9601ca75b26dc98b00d89c22f986de1d728292ec
[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 formatted 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 // Escape given character
122 //
123
124 void String::EscapeCharacter(int ch, int esc)
125 {
126 int nCount;
127 DWORD i;
128
129 if (m_pszBuffer == NULL)
130 return;
131
132 nCount = NumChars(m_pszBuffer, ch);
133 if (nCount == 0)
134 return;
135
136 m_dwBufSize += nCount;
137 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, m_dwBufSize * sizeof(TCHAR));
138 for(i = 0; m_pszBuffer[i] != 0; i++)
139 {
140 if (m_pszBuffer[i] == ch)
141 {
142 memmove(&m_pszBuffer[i + 1], &m_pszBuffer[i], (m_dwBufSize - i - 1) * sizeof(TCHAR));
143 m_pszBuffer[i] = esc;
144 i++;
145 }
146 }
147 }
148
149
150 //
151 // Set dynamically allocated string as a new buffer
152 //
153
154 void String::SetBuffer(TCHAR *pszBuffer)
155 {
156 safe_free(m_pszBuffer);
157 m_pszBuffer = pszBuffer;
158 m_dwBufSize = (m_pszBuffer != NULL) ? (DWORD)_tcslen(m_pszBuffer) + 1 : 1;
159 }
160
161
162 //
163 // Translate given substring
164 //
165
166 void String::Translate(const TCHAR *pszSrc, const TCHAR *pszDst)
167 {
168 DWORD i, dwLenSrc, dwLenDst, dwDelta;
169
170 if (m_pszBuffer == NULL)
171 return;
172
173 dwLenSrc = (DWORD)_tcslen(pszSrc);
174 dwLenDst = (DWORD)_tcslen(pszDst);
175
176 if (m_dwBufSize <= dwLenSrc)
177 return;
178
179 for(i = 0; i < m_dwBufSize - dwLenSrc; i++)
180 {
181 if (!memcmp(pszSrc, &m_pszBuffer[i], dwLenSrc * sizeof(TCHAR)))
182 {
183 if (dwLenSrc == dwLenDst)
184 {
185 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
186 i += dwLenDst - 1;
187 }
188 else if (dwLenSrc > dwLenDst)
189 {
190 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
191 i += dwLenDst;
192 dwDelta = dwLenSrc - dwLenDst;
193 m_dwBufSize -= dwDelta;
194 memmove(&m_pszBuffer[i], &m_pszBuffer[i + dwDelta], (m_dwBufSize - i) * sizeof(TCHAR));
195 i--;
196 }
197 else
198 {
199 dwDelta = dwLenDst - dwLenSrc;
200 m_pszBuffer = (TCHAR *)realloc(m_pszBuffer, (m_dwBufSize + dwDelta) * sizeof(TCHAR));
201 memmove(&m_pszBuffer[i + dwLenDst], &m_pszBuffer[i + dwLenSrc], (m_dwBufSize - i - dwLenSrc) * sizeof(TCHAR));
202 m_dwBufSize += dwDelta;
203 memcpy(&m_pszBuffer[i], pszDst, dwLenDst * sizeof(TCHAR));
204 i += dwLenDst - 1;
205 }
206 }
207 }
208 }
209
210
211 //
212 // Extract substring into buffer
213 //
214
215 TCHAR *String::SubStr(int nStart, int nLen, TCHAR *pszBuffer)
216 {
217 int nCount;
218 TCHAR *pszOut;
219
220 if ((nStart < (int)m_dwBufSize - 1) && (nStart >= 0))
221 {
222 if (nLen == -1)
223 {
224 nCount = (int)m_dwBufSize - nStart - 1;
225 }
226 else
227 {
228 nCount = min(nLen, (int)m_dwBufSize - nStart - 1);
229 }
230 pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc((nCount + 1) * sizeof(TCHAR));
231 memcpy(pszOut, &m_pszBuffer[nStart], nCount * sizeof(TCHAR));
232 pszOut[nCount] = 0;
233 }
234 else
235 {
236 pszOut = (pszBuffer != NULL) ? pszBuffer : (TCHAR *)malloc(sizeof(TCHAR));
237 *pszOut = 0;
238 }
239 return pszOut;
240 }
241
242
243 //
244 // Find substring in a string
245 //
246
247 int String::Find(const TCHAR *pszStr, int nStart)
248 {
249 TCHAR *p;
250
251 if ((nStart >= (int)m_dwBufSize - 1) || (nStart < 0))
252 return npos;
253
254 p = _tcsstr(&m_pszBuffer[nStart], pszStr);
255 return (p != NULL) ? (int)(((char *)p - (char *)m_pszBuffer) / sizeof(TCHAR)) : npos;
256 }
257
258
259 //
260 // Strip leading and trailing spaces
261 //
262
263 void String::Strip()
264 {
265 if (m_pszBuffer != NULL)
266 {
267 StrStrip(m_pszBuffer);
268 m_dwBufSize = (DWORD)_tcslen(m_pszBuffer) + 1;
269 }
270 }
271
272
273 //
274 // Shring string by removing trailing characters
275 //
276
277 void String::Shrink(int chars)
278 {
279 if (m_dwBufSize > 1)
280 {
281 m_dwBufSize -= min(m_dwBufSize - 1, (DWORD)chars);
282 if (m_pszBuffer != NULL)
283 m_pszBuffer[m_dwBufSize - 1] = 0;
284 }
285 }