fixed problems with IPSO build
[public/netxms.git] / src / libnetxms / string.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
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: 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 // Constructors
36 //
37
38 String::String()
39 {
40 m_dwBufSize = 1;
41 m_pszBuffer = NULL;
42 }
43
44 String::String(const String &src)
45 {
46 m_dwBufSize = src.m_dwBufSize;
47 m_pszBuffer = (src.m_pszBuffer != NULL) ? (TCHAR *)nx_memdup(src.m_pszBuffer, src.m_dwBufSize * sizeof(TCHAR)) : NULL;
48 }
49
50 String::String(const TCHAR *init)
51 {
52 m_dwBufSize = (DWORD)_tcslen(init) + 1;
53 m_pszBuffer = _tcsdup(init);
54 }
55
56
57 //
58 // Destructor
59 //
60
61 String::~String()
62 {
63 safe_free(m_pszBuffer);
64 }
65
66
67 //
68 // Operator =
69 //
70
71 const String& String::operator =(const TCHAR *pszStr)
72 {
73 safe_free(m_pszBuffer);
74 m_pszBuffer = _tcsdup(CHECK_NULL_EX(pszStr));
75 m_dwBufSize = (DWORD)_tcslen(CHECK_NULL_EX(pszStr)) + 1;
76 return *this;
77 }
78
79
80 //
81 // Operator +=
82 //
83
84 const String& String::operator +=(const TCHAR *pszStr)
85 {
86 DWORD dwLen;
87
88 if (pszStr != NULL)
89 {
90 dwLen = (DWORD)_tcslen(pszStr);
91 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwLen) * sizeof(TCHAR));
92 _tcscpy(&m_pszBuffer[m_dwBufSize - 1], pszStr);
93 m_dwBufSize += dwLen;
94 }
95 return *this;
96 }
97
98
99 //
100 // Add formatted string to the end of buffer
101 //
102
103 void String::addFormattedString(const TCHAR *format, ...)
104 {
105 va_list args;
106
107 va_start(args, format);
108 addFormattedStringV(format, args);
109 va_end(args);
110 }
111
112 void String::addFormattedStringV(const TCHAR *format, va_list args)
113 {
114 int len;
115 TCHAR *buffer;
116
117 #ifdef UNICODE
118
119 #if HAVE_VASWPRINTF
120 vaswprintf(&buffer, format, args);
121 #elif HAVE_VSCWPRINTF && HAVE_DECL_VA_COPY
122 va_list argsCopy;
123 va_copy(argsCopy, args);
124
125 len = (int)vscwprintf(format, args) + 1;
126 buffer = (WCHAR *)malloc(len * sizeof(WCHAR));
127
128 vsnwprintf(buffer, len, format, argsCopy);
129 va_end(argsCopy);
130 #else
131 // No way to determine required buffer size, guess
132 len = wcslen(format) + CharCount(format, L'%') * 1000 + 1;
133 buffer = (WCHAR *)malloc(len * sizeof(WCHAR));
134
135 vsnwprintf(buffer, len, format, args);
136 #endif
137
138 #else /* UNICODE */
139
140 #if HAVE_VASPRINTF && !defined(_IPSO)
141 vasprintf(&buffer, format, args);
142 #elif HAVE_VSCPRINTF && HAVE_DECL_VA_COPY
143 va_list argsCopy;
144 va_copy(argsCopy, args);
145
146 len = (int)vscprintf(format, args) + 1;
147 buffer = (char *)malloc(len);
148
149 vsnprintf(buffer, len, format, argsCopy);
150 va_end(argsCopy);
151 #elif SNPRINTF_RETURNS_REQUIRED_SIZE && HAVE_DECL_VA_COPY
152 va_list argsCopy;
153 va_copy(argsCopy, args);
154
155 len = (int)snprintf(NULL, 0, format, args) + 1;
156 buffer = (char *)malloc(len);
157
158 vsnprintf(buffer, len, format, argsCopy);
159 va_end(argsCopy);
160 #else
161 // No way to determine required buffer size, guess
162 len = strlen(format) + NumChars(format, '%') * 1000 + 1;
163 buffer = (char *)malloc(len);
164
165 vsnprintf(buffer, len, format, args);
166 #endif
167
168 #endif /* UNICODE */
169
170 *this += buffer;
171 free(buffer);
172 }
173
174
175 //
176 // Add string to the end of buffer
177 //
178
179 void String::addString(const TCHAR *pStr, DWORD dwSize)
180 {
181 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
182 memcpy(&m_pszBuffer[m_dwBufSize - 1], pStr, dwSize * sizeof(TCHAR));
183 m_dwBufSize += dwSize;
184 m_pszBuffer[m_dwBufSize - 1] = 0;
185 }
186
187
188 //
189 // Add multibyte string to the end of buffer
190 //
191
192 void String::addMultiByteString(const char *pStr, DWORD dwSize, int nCodePage)
193 {
194 #ifdef UNICODE
195 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
196 MultiByteToWideChar(nCodePage, (nCodePage == CP_UTF8) ? 0 : MB_PRECOMPOSED, pStr, dwSize, &m_pszBuffer[m_dwBufSize - 1], dwSize);
197 m_dwBufSize += dwSize;
198 m_pszBuffer[m_dwBufSize - 1] = 0;
199 #else
200 addString(pStr, dwSize);
201 #endif
202 }
203
204
205 //
206 // Add widechar string to the end of buffer
207 //
208
209 void String::addWideCharString(const WCHAR *pStr, DWORD dwSize)
210 {
211 #ifdef UNICODE
212 addString(pStr, dwSize);
213 #else
214 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwSize) * sizeof(TCHAR));
215 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, pStr, dwSize, &m_pszBuffer[m_dwBufSize - 1], dwSize, NULL, NULL);
216 m_dwBufSize += dwSize;
217 m_pszBuffer[m_dwBufSize - 1] = 0;
218 #endif
219 }
220
221
222 //
223 // Escape given character
224 //
225
226 void String::escapeCharacter(int ch, int esc)
227 {
228 int nCount;
229 DWORD i;
230
231 if (m_pszBuffer == NULL)
232 return;
233
234 nCount = NumChars(m_pszBuffer, ch);
235 if (nCount == 0)
236 return;
237
238 m_dwBufSize += nCount;
239 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, m_dwBufSize * sizeof(TCHAR));
240 for(i = 0; m_pszBuffer[i] != 0; i++)
241 {
242 if (m_pszBuffer[i] == ch)
243 {
244 memmove(&m_pszBuffer[i + 1], &m_pszBuffer[i], (m_dwBufSize - i - 1) * sizeof(TCHAR));
245 m_pszBuffer[i] = esc;
246 i++;
247 }
248 }
249 }
250
251
252 //
253 // Set dynamically allocated string as a new buffer
254 //
255
256 void String::setBuffer(TCHAR *pszBuffer)
257 {
258 safe_free(m_pszBuffer);
259 m_pszBuffer = pszBuffer;
260 m_dwBufSize = (m_pszBuffer != NULL) ? (DWORD)_tcslen(m_pszBuffer) + 1 : 1;
261 }
262
263
264 //
265 // Translate given substring
266 //
267
268 void String::translate(const TCHAR *pszSrc, const TCHAR *pszDst)
269 {
270 DWORD i, dwLenSrc, dwLenDst, dwDelta;
271
272 if (m_pszBuffer == NULL)
273 return;
274
275 dwLenSrc = (DWORD)_tcslen(pszSrc);
276 dwLenDst = (DWORD)_tcslen(pszDst);
277
278 if (m_dwBufSize <= dwLenSrc)
279 return;
280
281 for(i = 0; i < m_dwBufSize - dwLenSrc; i++)
282 {
283 if (!memcmp(pszSrc, &m_pszBuffer[i], dwLenSrc * sizeof(TCHAR)))
284 {
285 if (dwLenSrc == dwLenDst)
286 {
287 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
288 i += dwLenDst - 1;
289 }
290 else if (dwLenSrc > dwLenDst)
291 {
292 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
293 i += dwLenDst;
294 dwDelta = dwLenSrc - dwLenDst;
295 m_dwBufSize -= dwDelta;
296 memmove(&m_pszBuffer[i], &m_pszBuffer[i + dwDelta], (m_dwBufSize - i) * sizeof(TCHAR));
297 i--;
298 }
299 else
300 {
301 dwDelta = dwLenDst - dwLenSrc;
302 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwDelta) * sizeof(TCHAR));
303 memmove(&m_pszBuffer[i + dwLenDst], &m_pszBuffer[i + dwLenSrc], (m_dwBufSize - i - dwLenSrc) * sizeof(TCHAR));
304 m_dwBufSize += dwDelta;
305 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
306 i += dwLenDst - 1;
307 }
308 }
309 }
310 }
311
312
313 //
314 // Extract substring into buffer
315 //
316
317 TCHAR *String::subStr(int nStart, int nLen, TCHAR *pszBuffer)
318 {
319 int nCount;
320 TCHAR *pszOut;
321
322 if ((nStart < (int)m_dwBufSize - 1) && (nStart >= 0))
323 {
324 if (nLen == -1)
325 {
326 nCount = (int)m_dwBufSize - nStart - 1;
327 }
328 else
329 {
330 nCount = min(nLen, (int)m_dwBufSize - nStart - 1);
331 }
332 pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc((nCount + 1) * sizeof(TCHAR));
333 memcpy(pszOut, &m_pszBuffer[nStart], nCount * sizeof(TCHAR));
334 pszOut[nCount] = 0;
335 }
336 else
337 {
338 pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc(sizeof(TCHAR));
339 *pszOut = 0;
340 }
341 return pszOut;
342 }
343
344
345 //
346 // Find substring in a string
347 //
348
349 int String::find(const TCHAR *pszStr, int nStart)
350 {
351 TCHAR *p;
352
353 if ((nStart >= (int)m_dwBufSize - 1) || (nStart < 0))
354 return npos;
355
356 p = _tcsstr(&m_pszBuffer[nStart], pszStr);
357 return (p != NULL) ? (int)(((char *)p - (char *)m_pszBuffer) / sizeof(TCHAR)) : npos;
358 }
359
360
361 //
362 // Strip leading and trailing spaces, tabs, newlines
363 //
364
365 void String::trim()
366 {
367 if (m_pszBuffer != NULL)
368 {
369 Trim(m_pszBuffer);
370 m_dwBufSize = (DWORD)_tcslen(m_pszBuffer) + 1;
371 }
372 }
373
374
375 //
376 // Shring string by removing trailing characters
377 //
378
379 void String::shrink(int chars)
380 {
381 if (m_dwBufSize > 1)
382 {
383 m_dwBufSize -= min(m_dwBufSize - 1, (DWORD)chars);
384 if (m_pszBuffer != NULL)
385 m_pszBuffer[m_dwBufSize - 1] = 0;
386 }
387 }