8c3db5f9ce76083d7f8938fd66cd3d14a8033e2d
[public/netxms.git] / src / libnxsl / library.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Scripting Language Interpreter
4 ** Copyright (C) 2003-2014 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: library.cpp
21 **
22 **/
23
24 #include "libnxsl.h"
25
26 /**
27 * Constructor
28 */
29 NXSL_Library::NXSL_Library()
30 {
31 m_mutex = MutexCreate();
32 m_dwNumScripts = 0;
33 m_ppScriptList = NULL;
34 m_ppszNames = NULL;
35 m_pdwIdList = NULL;
36 }
37
38 /**
39 * Destructor
40 */
41 NXSL_Library::~NXSL_Library()
42 {
43 for(UINT32 i = 0; i < m_dwNumScripts; i++)
44 {
45 delete m_ppScriptList[i];
46 free(m_ppszNames[i]);
47 }
48 safe_free(m_ppScriptList);
49 safe_free(m_ppszNames);
50 safe_free(m_pdwIdList);
51 MutexDestroy(m_mutex);
52 }
53
54 /**
55 * Add script to library
56 */
57 BOOL NXSL_Library::addScript(UINT32 dwId, const TCHAR *pszName, NXSL_Program *pScript)
58 {
59 UINT32 i;
60
61 for(i = 0; i < m_dwNumScripts; i++)
62 if (!_tcsicmp(m_ppszNames[i], pszName))
63 return FALSE;
64
65 m_dwNumScripts++;
66 m_ppScriptList = (NXSL_Program **)realloc(m_ppScriptList, sizeof(NXSL_Program *) * m_dwNumScripts);
67 m_ppszNames = (TCHAR **)realloc(m_ppszNames, sizeof(TCHAR *) * m_dwNumScripts);
68 m_pdwIdList = (UINT32 *)realloc(m_pdwIdList, sizeof(UINT32) * m_dwNumScripts);
69 m_ppScriptList[i] = pScript;
70 m_ppszNames[i] = _tcsdup(pszName);
71 m_pdwIdList[i] = dwId;
72 return TRUE;
73 }
74
75 /**
76 * Delete script from library
77 */
78 void NXSL_Library::deleteInternal(int nIndex)
79 {
80 delete m_ppScriptList[nIndex];
81 free(m_ppszNames[nIndex]);
82 m_dwNumScripts--;
83 memmove(&m_ppScriptList[nIndex], &m_ppScriptList[nIndex + 1],
84 sizeof(NXSL_Program *) * (m_dwNumScripts - nIndex));
85 memmove(&m_ppszNames[nIndex], &m_ppszNames[nIndex + 1],
86 sizeof(char *) * (m_dwNumScripts - nIndex));
87 memmove(&m_pdwIdList[nIndex], &m_pdwIdList[nIndex + 1],
88 sizeof(UINT32) * (m_dwNumScripts - nIndex));
89 }
90
91 void NXSL_Library::deleteScript(const TCHAR *pszName)
92 {
93 UINT32 i;
94
95 for(i = 0; i < m_dwNumScripts; i++)
96 if (!_tcsicmp(m_ppszNames[i], pszName))
97 {
98 deleteInternal(i);
99 break;
100 }
101 }
102
103 void NXSL_Library::deleteScript(UINT32 dwId)
104 {
105 UINT32 i;
106
107 for(i = 0; i < m_dwNumScripts; i++)
108 if (m_pdwIdList[i] == dwId)
109 {
110 deleteInternal(i);
111 break;
112 }
113 }
114
115 /**
116 * Find script by name
117 */
118 NXSL_Program *NXSL_Library::findScript(const TCHAR *name)
119 {
120 UINT32 i;
121
122 for(i = 0; i < m_dwNumScripts; i++)
123 if (!_tcsicmp(m_ppszNames[i], name))
124 {
125 return m_ppScriptList[i];
126 }
127 return NULL;
128 }
129
130 /**
131 * Create ready to run VM for given script. This method will do library lock internally.
132 * VM must be deleted by caller when no longer needed.
133 */
134 NXSL_VM *NXSL_Library::createVM(const TCHAR *name, NXSL_Environment *env)
135 {
136 NXSL_VM *vm = NULL;
137 lock();
138 NXSL_Program *p = findScript(name);
139 if (p != NULL)
140 {
141 vm = new NXSL_VM(env);
142 if (!vm->load(p))
143 {
144 delete vm;
145 vm = NULL;
146 }
147 }
148 else
149 {
150 delete env;
151 }
152 unlock();
153 return vm;
154 }
155
156 /**
157 * Fill NXCP message with script data
158 */
159 void NXSL_Library::fillMessage(NXCPMessage *pMsg)
160 {
161 UINT32 i, dwId;
162
163 pMsg->setField(VID_NUM_SCRIPTS, m_dwNumScripts);
164 for(i = 0, dwId = VID_SCRIPT_LIST_BASE; i < m_dwNumScripts; i++)
165 {
166 pMsg->setField(dwId++, m_pdwIdList[i]);
167 pMsg->setField(dwId++, m_ppszNames[i]);
168 }
169 }