XML configs implemented
[public/netxms.git] / src / libnetxms / string.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003, 2004, 2005, 2006, 2007 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: string.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25
26
27 //
28 // Static members
29 //
30
31 const int String::npos = -1;
32
33
34 //
35 // Constructor
36 //
37
38 String::String()
39 {
40 m_dwBufSize = 1;
41 m_pszBuffer = NULL;
42 }
43
44
45 //
46 // Destructor
47 //
48
49 String::~String()
50 {
51 safe_free(m_pszBuffer);
52 }
53
54
55 //
56 // Operator =
57 //
58
59 const String& String::operator =(const TCHAR *pszStr)
60 {
61 safe_free(m_pszBuffer);
62 m_pszBuffer = _tcsdup(CHECK_NULL_EX(pszStr));
63 m_dwBufSize = (DWORD)_tcslen(CHECK_NULL_EX(pszStr)) + 1;
64 return *this;
65 }
66
67
68 //
69 // Operator +=
70 //
71
72 const String& String::operator +=(const TCHAR *pszStr)
73 {
74 DWORD dwLen;
75
76 if (pszStr != NULL)
77 {
78 dwLen = (DWORD)_tcslen(pszStr);
79 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwLen) * sizeof(TCHAR));
80 _tcscpy(&m_pszBuffer[m_dwBufSize - 1], pszStr);
81 m_dwBufSize += dwLen;
82 }
83 return *this;
84 }
85
86
87 //
88 // Add formatted string to the end of buffer
89 //
90
91 void String::AddFormattedString(const TCHAR *pszFormat, ...)
92 {
93 int nLen;
94 va_list args;
95 TCHAR *pszBuffer;
96
97 nLen = (int)_tcslen(pszFormat) + NumChars(pszFormat, _T('%')) * 1024;
98 pszBuffer = (TCHAR *)malloc(nLen * sizeof(TCHAR));
99 va_start(args, pszFormat);
100 _vsntprintf(pszBuffer, nLen, pszFormat, args);
101 va_end(args);
102 *this += pszBuffer;
103 free(pszBuffer);
104 }
105
106
107 //
108 // Add string to the end of buffer
109 //
110
111 void String::AddString(const TCHAR *pStr, DWORD dwSize)
112 {
113 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
114 memcpy(&m_pszBuffer[m_dwBufSize - 1], pStr, dwSize * sizeof(TCHAR));
115 m_dwBufSize += dwSize;
116 m_pszBuffer[m_dwBufSize - 1] = 0;
117 }
118
119
120 //
121 // Add multibyte string to the end of buffer
122 //
123
124 void String::AddMultiByteString(const char *pStr, DWORD dwSize, int nCodePage)
125 {
126 #ifdef UNICODE
127 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
128 MultiByteToWideChar(nCodePage, (nCodePage == CP_UTF8) ? 0 : MB_PRECOMPOSED, pStr, dwSize, &m_pszBuffer[m_dwBufSize - 1], dwSize);
129 m_dwBufSize += dwSize;
130 m_pszBuffer[m_dwBufSize - 1] = 0;
131 #else
132 AddString(pStr, dwSize);
133 #endif
134 }
135
136
137 //
138 // Add widechar string to the end of buffer
139 //
140
141 void String::AddWideCharString(const WCHAR *pStr, DWORD dwSize)
142 {
143 #ifdef UNICODE
144 AddString(pStr, dwSize);
145 #else
146 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
147 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, pStr, dwSize, &m_pszBuffer[m_dwBufSize - 1], dwSize, NULL, NULL);
148 m_dwBufSize += dwSize;
149 m_pszBuffer[m_dwBufSize - 1] = 0;
150 #endif
151 }
152
153
154 //
155 // Escape given character
156 //
157
158 void String::EscapeCharacter(int ch, int esc)
159 {
160 int nCount;
161 DWORD i;
162
163 if (m_pszBuffer == NULL)
164 return;
165
166 nCount = NumChars(m_pszBuffer, ch);
167 if (nCount == 0)
168 return;
169
170 m_dwBufSize += nCount;
171 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, m_dwBufSize * sizeof(TCHAR));
172 for(i = 0; m_pszBuffer[i] != 0; i++)
173 {
174 if (m_pszBuffer[i] == ch)
175 {
176 memmove(&m_pszBuffer[i + 1], &m_pszBuffer[i], (m_dwBufSize - i - 1) * sizeof(TCHAR));
177 m_pszBuffer[i] = esc;
178 i++;
179 }
180 }
181 }
182
183
184 //
185 // Set dynamically allocated string as a new buffer
186 //
187
188 void String::SetBuffer(TCHAR *pszBuffer)
189 {
190 safe_free(m_pszBuffer);
191 m_pszBuffer = pszBuffer;
192 m_dwBufSize = (m_pszBuffer != NULL) ? (DWORD)_tcslen(m_pszBuffer) + 1 : 1;
193 }
194
195
196 //
197 // Translate given substring
198 //
199
200 void String::Translate(const TCHAR *pszSrc, const TCHAR *pszDst)
201 {
202 DWORD i, dwLenSrc, dwLenDst, dwDelta;
203
204 if (m_pszBuffer == NULL)
205 return;
206
207 dwLenSrc = (DWORD)_tcslen(pszSrc);
208 dwLenDst = (DWORD)_tcslen(pszDst);
209
210 if (m_dwBufSize <= dwLenSrc)
211 return;
212
213 for(i = 0; i < m_dwBufSize - dwLenSrc; i++)
214 {
215 if (!memcmp(pszSrc, &m_pszBuffer[i], dwLenSrc * sizeof(TCHAR)))
216 {
217 if (dwLenSrc == dwLenDst)
218 {
219 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
220 i += dwLenDst - 1;
221 }
222 else if (dwLenSrc > dwLenDst)
223 {
224 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
225 i += dwLenDst;
226 dwDelta = dwLenSrc - dwLenDst;
227 m_dwBufSize -= dwDelta;
228 memmove(&m_pszBuffer[i], &m_pszBuffer[i + dwDelta], (m_dwBufSize - i) * sizeof(TCHAR));
229 i--;
230 }
231 else
232 {
233 dwDelta = dwLenDst - dwLenSrc;
234 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwDelta) * sizeof(TCHAR));
235 memmove(&m_pszBuffer[i + dwLenDst], &m_pszBuffer[i + dwLenSrc], (m_dwBufSize - i - dwLenSrc) * sizeof(TCHAR));
236 m_dwBufSize += dwDelta;
237 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
238 i += dwLenDst - 1;
239 }
240 }
241 }
242 }
243
244
245 //
246 // Extract substring into buffer
247 //
248
249 TCHAR *String::SubStr(int nStart, int nLen, TCHAR *pszBuffer)
250 {
251 int nCount;
252 TCHAR *pszOut;
253
254 if ((nStart < (int)m_dwBufSize - 1) && (nStart >= 0))
255 {
256 if (nLen == -1)
257 {
258 nCount = (int)m_dwBufSize - nStart - 1;
259 }
260 else
261 {
262 nCount = min(nLen, (int)m_dwBufSize - nStart - 1);
263 }
264 pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc((nCount + 1) * sizeof(TCHAR));
265 memcpy(pszOut, &m_pszBuffer[nStart], nCount * sizeof(TCHAR));
266 pszOut[nCount] = 0;
267 }
268 else
269 {
270 pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc(sizeof(TCHAR));
271 *pszOut = 0;
272 }
273 return pszOut;
274 }
275
276
277 //
278 // Find substring in a string
279 //
280
281 int String::Find(const TCHAR *pszStr, int nStart)
282 {
283 TCHAR *p;
284
285 if ((nStart >= (int)m_dwBufSize - 1) || (nStart < 0))
286 return npos;
287
288 p = _tcsstr(&m_pszBuffer[nStart], pszStr);
289 return (p != NULL) ? (int)(((char *)p - (char *)m_pszBuffer) / sizeof(TCHAR)) : npos;
290 }
291
292
293 //
294 // Strip leading and trailing spaces
295 //
296
297 void String::Strip()
298 {
299 if (m_pszBuffer != NULL)
300 {
301 StrStrip(m_pszBuffer);
302 m_dwBufSize = (DWORD)_tcslen(m_pszBuffer) + 1;
303 }
304 }
305
306
307 //
308 // Shring string by removing trailing characters
309 //
310
311 void String::Shrink(int chars)
312 {
313 if (m_dwBufSize > 1)
314 {
315 m_dwBufSize -= min(m_dwBufSize - 1, (DWORD)chars);
316 if (m_pszBuffer != NULL)
317 m_pszBuffer[m_dwBufSize - 1] = 0;
318 }
319 }