license headers in libnetxms changed to LGPL
[public/netxms.git] / src / libnetxms / table.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2010 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published
7 ** by the Free Software Foundation; either version 3 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU Lesser General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: table.cpp
20 **
21 **/
22
23 #include "libnetxms.h"
24
25
26 //
27 // Table constructor
28 //
29
30 Table::Table()
31 {
32 m_nNumRows = 0;
33 m_nNumCols = 0;
34 m_ppData = NULL;
35 m_ppColNames = NULL;
36 m_colFormats = NULL;
37 m_title = NULL;
38 }
39
40
41 //
42 // Create table from NXCP message
43 //
44
45 Table::Table(CSCPMessage *msg)
46 {
47 int i;
48 DWORD dwId;
49
50 m_nNumRows = msg->GetVariableLong(VID_TABLE_NUM_ROWS);
51 m_nNumCols = msg->GetVariableLong(VID_TABLE_NUM_COLS);
52 m_title = msg->GetVariableStr(VID_TABLE_TITLE);
53
54 m_ppColNames = (TCHAR **)malloc(sizeof(TCHAR *) * m_nNumCols);
55 m_colFormats = (LONG *)malloc(sizeof(LONG) * m_nNumCols);
56 for(i = 0, dwId = VID_TABLE_COLUMN_INFO_BASE; i < m_nNumCols; i++, dwId += 8)
57 {
58 m_ppColNames[i] = msg->GetVariableStr(dwId++);
59 m_colFormats[i] = (LONG)msg->GetVariableLong(dwId++);
60 }
61
62 m_ppData = (TCHAR **)malloc(sizeof(TCHAR *) * m_nNumCols * m_nNumRows);
63 for(i = 0, dwId = VID_TABLE_DATA_BASE; i < m_nNumCols * m_nNumRows; i++)
64 m_ppData[i] = msg->GetVariableStr(dwId++);
65 }
66
67
68 //
69 // Table destructor
70 //
71
72 Table::~Table()
73 {
74 int i;
75
76 for(i = 0; i < m_nNumCols; i++)
77 safe_free(m_ppColNames[i]);
78 safe_free(m_ppColNames);
79
80 safe_free(m_colFormats);
81
82 for(i = 0; i < m_nNumRows * m_nNumCols; i++)
83 safe_free(m_ppData[i]);
84 safe_free(m_ppData);
85
86 safe_free(m_title);
87 }
88
89
90 //
91 // Fill NXCP message with table data
92 //
93
94 int Table::fillMessage(CSCPMessage &msg, int offset, int rowLimit)
95 {
96 int i, row, col;
97 DWORD id;
98
99 msg.SetVariable(VID_TABLE_TITLE, CHECK_NULL_EX(m_title));
100
101 if (offset == 0)
102 {
103 msg.SetVariable(VID_TABLE_NUM_ROWS, (DWORD)m_nNumRows);
104 msg.SetVariable(VID_TABLE_NUM_COLS, (DWORD)m_nNumCols);
105
106 for(i = 0, id = VID_TABLE_COLUMN_INFO_BASE; i < m_nNumCols; i++, id += 8)
107 {
108 msg.SetVariable(id++, CHECK_NULL_EX(m_ppColNames[i]));
109 msg.SetVariable(id++, (DWORD)m_colFormats[i]);
110 }
111 }
112 msg.SetVariable(VID_TABLE_OFFSET, (DWORD)offset);
113
114 int stopRow = (rowLimit == -1) ? m_nNumRows : min(m_nNumRows, offset + rowLimit);
115 for(i = offset * m_nNumCols, row = offset, id = VID_TABLE_DATA_BASE; row < stopRow; row++)
116 {
117 for(col = 0; col < m_nNumCols; col++)
118 {
119 TCHAR *tmp = m_ppData[i++];
120 msg.SetVariable(id++, CHECK_NULL_EX(tmp));
121 }
122 }
123 msg.SetVariable(VID_NUM_ROWS, (DWORD)(row - offset));
124
125 if (row == m_nNumRows)
126 msg.SetEndOfSequence();
127 return row;
128 }
129
130
131 //
132 // Add new column
133 //
134
135 int Table::addColumn(const TCHAR *name, LONG format)
136 {
137 m_ppColNames = (TCHAR **)realloc(m_ppColNames, sizeof(TCHAR *) * (m_nNumCols + 1));
138 m_ppColNames[m_nNumCols] = _tcsdup(name);
139
140 m_colFormats = (LONG *)realloc(m_colFormats, sizeof(LONG) * (m_nNumCols + 1));
141 m_colFormats[m_nNumCols] = format;
142
143 if (m_nNumRows > 0)
144 {
145 TCHAR **ppNewData;
146 int i, nPosOld, nPosNew;
147
148 ppNewData = (TCHAR **)malloc(sizeof(TCHAR *) * m_nNumRows * (m_nNumCols + 1));
149 for(i = 0, nPosOld = 0, nPosNew = 0; i < m_nNumRows; i++)
150 {
151 memcpy(&ppNewData[nPosNew], &m_ppData[nPosOld], sizeof(TCHAR *) * m_nNumCols);
152 ppNewData[nPosNew + m_nNumCols] = NULL;
153 nPosOld += m_nNumCols;
154 nPosNew += m_nNumCols + 1;
155 }
156 safe_free(m_ppData);
157 m_ppData = ppNewData;
158 }
159
160 m_nNumCols++;
161 return m_nNumCols - 1;
162 }
163
164
165 //
166 // Add new row
167 //
168
169 int Table::addRow()
170 {
171 if (m_nNumCols > 0)
172 {
173 m_ppData = (TCHAR **)realloc(m_ppData, sizeof(TCHAR *) * (m_nNumRows + 1) * m_nNumCols);
174 memset(&m_ppData[m_nNumRows * m_nNumCols], 0, sizeof(TCHAR *) * m_nNumCols);
175 }
176 m_nNumRows++;
177 return m_nNumRows - 1;
178 }
179
180
181 //
182 // Set data at position
183 //
184
185 void Table::setAt(int nRow, int nCol, const TCHAR *pszData)
186 {
187 if ((nRow < 0) || (nRow >= m_nNumRows) ||
188 (nCol < 0) || (nCol >= m_nNumCols))
189 return;
190
191 safe_free(m_ppData[nRow * m_nNumCols + nCol]);
192 m_ppData[nRow * m_nNumCols + nCol] = _tcsdup(pszData);
193 }
194
195 void Table::setPreallocatedAt(int nRow, int nCol, TCHAR *pszData)
196 {
197 if ((nRow < 0) || (nRow >= m_nNumRows) ||
198 (nCol < 0) || (nCol >= m_nNumCols))
199 return;
200
201 safe_free(m_ppData[nRow * m_nNumCols + nCol]);
202 m_ppData[nRow * m_nNumCols + nCol] = pszData;
203 }
204
205 void Table::setAt(int nRow, int nCol, LONG nData)
206 {
207 TCHAR szBuffer[32];
208
209 _sntprintf(szBuffer, 32, _T("%d"), nData);
210 setAt(nRow, nCol, szBuffer);
211 }
212
213 void Table::setAt(int nRow, int nCol, DWORD dwData)
214 {
215 TCHAR szBuffer[32];
216
217 _sntprintf(szBuffer, 32, _T("%u"), dwData);
218 setAt(nRow, nCol, szBuffer);
219 }
220
221 void Table::setAt(int nRow, int nCol, INT64 nData)
222 {
223 TCHAR szBuffer[32];
224
225 _sntprintf(szBuffer, 32, INT64_FMT, nData);
226 setAt(nRow, nCol, szBuffer);
227 }
228
229 void Table::setAt(int nRow, int nCol, QWORD qwData)
230 {
231 TCHAR szBuffer[32];
232
233 _sntprintf(szBuffer, 32, UINT64_FMT, qwData);
234 setAt(nRow, nCol, szBuffer);
235 }
236
237 void Table::setAt(int nRow, int nCol, double dData)
238 {
239 TCHAR szBuffer[32];
240
241 _sntprintf(szBuffer, 32, _T("%f"), dData);
242 setAt(nRow, nCol, szBuffer);
243 }
244
245
246 //
247 // Get data from position
248 //
249
250 const TCHAR *Table::getAsString(int nRow, int nCol)
251 {
252 if ((nRow < 0) || (nRow >= m_nNumRows) ||
253 (nCol < 0) || (nCol >= m_nNumCols))
254 return NULL;
255
256 return m_ppData[nRow * m_nNumCols + nCol];
257 }
258
259 LONG Table::getAsInt(int nRow, int nCol)
260 {
261 const TCHAR *pszVal;
262
263 pszVal = getAsString(nRow, nCol);
264 return pszVal != NULL ? _tcstol(pszVal, NULL, 0) : 0;
265 }
266
267 DWORD Table::getAsUInt(int nRow, int nCol)
268 {
269 const TCHAR *pszVal;
270
271 pszVal = getAsString(nRow, nCol);
272 return pszVal != NULL ? _tcstoul(pszVal, NULL, 0) : 0;
273 }
274
275 INT64 Table::getAsInt64(int nRow, int nCol)
276 {
277 const TCHAR *pszVal;
278
279 pszVal = getAsString(nRow, nCol);
280 return pszVal != NULL ? _tcstoll(pszVal, NULL, 0) : 0;
281 }
282
283 QWORD Table::getAsUInt64(int nRow, int nCol)
284 {
285 const TCHAR *pszVal;
286
287 pszVal = getAsString(nRow, nCol);
288 return pszVal != NULL ? _tcstoull(pszVal, NULL, 0) : 0;
289 }
290
291 double Table::getAsDouble(int nRow, int nCol)
292 {
293 const TCHAR *pszVal;
294
295 pszVal = getAsString(nRow, nCol);
296 return pszVal != NULL ? _tcstod(pszVal, NULL) : 0;
297 }