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