VirtualBox

source: vbox/trunk/include/iprt/ministring_cpp.h@ 22650

Last change on this file since 22650 was 22173, checked in by vboxsync, 15 years ago

Main: the big XML settings rework. Move XML reading/writing out of interface implementation code into separate layer so it can handle individual settings versions in the future.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1/** @file
2 * VirtualBox mini C++ string class. This is a base for both Utf8Str and
3 * other places where IPRT may want to use a lean C++ string class.
4 */
5
6/*
7 * Copyright (C) 2007-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31#ifndef ___VBox_ministring_h
32#define ___VBox_ministring_h
33
34#include <iprt/mem.h>
35#include <iprt/string.h>
36
37#include <new>
38
39namespace iprt
40{
41
42/**
43 * "MiniString" is a small C++ string class that does not depend on anything
44 * else except IPRT memory management functions. This is used as the base of
45 * both the Utf8Str class that COM uses as well as C++ code in IPRT that
46 * prefers to have a string class, like in xml.cpp.
47 *
48 * Semantics are like in std::string, except it can do a lot less.
49 *
50 * Much of the code in here used to be in com::Utf8Str so that com::Utf8Str
51 * can now derive from MiniString and only contain code that is COM-specific,
52 * such as com::Bstr conversions. Compared to the old Utf8Str though, MiniString
53 * always knows the length of its member string and the size of the buffer
54 * so it can use memcpy() instead of strdup().
55 */
56
57class RT_DECL_CLASS MiniString
58{
59public:
60 /**
61 * Creates an empty string that has no memory allocated.
62 */
63 MiniString()
64 : m_psz(NULL),
65 m_cbLength(0),
66 m_cbAllocated(0)
67 {
68 }
69
70 /**
71 * Creates a copy of another MiniString. This allocates
72 * s.length() + 1 bytes for the new instance.
73 * @param s
74 */
75 MiniString(const MiniString &s)
76 {
77 copyFrom(s);
78 }
79
80 /**
81 * Creates a copy of another MiniString. This allocates
82 * strlen(pcsz) + 1 bytes for the new instance.
83 * @param pcsz
84 */
85 MiniString(const char *pcsz)
86 {
87 copyFrom(pcsz);
88 }
89
90 /**
91 * Destructor.
92 */
93 virtual ~MiniString()
94 {
95 cleanup();
96 }
97
98 /**
99 * Returns the length of the member string, which is equal to
100 * strlen(c_str()). In other words, this does not count UTF-8 characters
101 * but returns the number of bytes. This is always cached
102 * so calling this is cheap and requires no strlen() invocation.
103 * @return
104 */
105 size_t length() const
106 {
107 return m_cbLength;
108 }
109
110 /**
111 * Returns the number of bytes allocated in the internal string buffer,
112 * which is at least length() + 1 if length() > 0.
113 * @return
114 */
115 size_t capacity() const
116 {
117 return m_cbAllocated;
118 }
119
120 /**
121 * Requests that the contained memory buffer have at least cb bytes allocated.
122 * This may expand or shrink the string's storage, but will never truncate the
123 * contained string. In other words, cb will be ignored if it's smaller than
124 * length() + 1.
125 * @param cb new minimum size of member memory buffer
126 */
127 void reserve(size_t cb)
128 {
129 if ( (cb != m_cbAllocated)
130 && (cb > m_cbLength + 1)
131 )
132 {
133 m_psz = (char*)RTMemRealloc(m_psz, cb);
134#ifdef RT_EXCEPTIONS_ENABLED
135 if (!m_psz)
136 throw std::bad_alloc();
137#endif
138 m_cbAllocated = cb;
139 }
140 }
141
142 /**
143 * Deallocates all memory.
144 */
145 inline void setNull()
146 {
147 cleanup();
148 }
149
150 /**
151 * Returns a non-const raw pointer that allows to modify the string directly.
152 * @warning
153 * 1) Be sure not to modify data beyond the allocated memory! Call
154 * capacity() to find out how large that buffer is.
155 * 2) After any operation that modifies the length of the string,
156 * you _must_ call MiniString::jolt(), or subsequent copy operations
157 * may go nowhere. Better not use mutableRaw() at all.
158 */
159 char* mutableRaw()
160 {
161 return m_psz;
162 }
163
164 /**
165 * Intended to be called after something has messed with the internal string
166 * buffer (e.g. after using mutableRaw() or Utf8Str::asOutParam()). Resets
167 * the internal lengths correctly. Otherwise subsequent copy operations may
168 * go nowhere.
169 */
170 void jolt()
171 {
172 if (m_psz)
173 {
174 m_cbLength = strlen(m_psz);
175 m_cbAllocated = m_cbLength + 1;
176 }
177 else
178 {
179 m_cbLength = 0;
180 m_cbAllocated = 0;
181 }
182 }
183
184 /**
185 * Assigns a copy of pcsz to "this".
186 * @param pcsz
187 * @return
188 */
189 MiniString& operator=(const char *pcsz)
190 {
191 if (m_psz != pcsz)
192 {
193 cleanup();
194 copyFrom(pcsz);
195 }
196 return *this;
197 }
198
199 /**
200 * Assigns a copy of s to "this".
201 * @param s
202 * @return
203 */
204 MiniString& operator=(const MiniString &s)
205 {
206 if (this != &s)
207 {
208 cleanup();
209 copyFrom(s);
210 }
211 return *this;
212 }
213
214 /**
215 * Appends a copy of @a that to "this".
216 * @param that
217 */
218 MiniString& append(const MiniString &that)
219 {
220 size_t cbThis = length();
221 size_t cbThat = that.length();
222
223 if (cbThat)
224 {
225 size_t cbBoth = cbThis + cbThat + 1;
226
227 reserve(cbBoth);
228 // calls realloc(cbBoth) and sets m_cbAllocated
229
230 memcpy(m_psz + cbThis, that.m_psz, cbThat);
231 m_psz[cbThis + cbThat] = '\0';
232 m_cbLength = cbBoth - 1;
233 }
234 return *this;
235 }
236
237 /**
238 * Returns the byte at the given index, or a null byte if
239 * the index is not smaller than length(). This does _not_
240 * count UTF-8 characters but simply points into the
241 * member C string.
242 * @param i
243 * @return
244 */
245 inline char operator[](size_t i) const
246 {
247 if (i < length())
248 return m_psz[i];
249 return '\0';
250 }
251
252 /**
253 * Returns the contained string as a C-style const char* pointer.
254 * @return
255 */
256 inline const char* c_str() const
257 {
258 return m_psz;
259 }
260
261 /**
262 * Like c_str(), for compatibility with lots of VirtualBox Main code.
263 * @return
264 */
265 inline const char* raw() const
266 {
267 return m_psz;
268 }
269
270 /**
271 * Returns true if the member string has no length. This states nothing about
272 * how much memory might be allocated.
273 * @return
274 */
275 bool isEmpty() const
276 {
277 return length() == 0;
278 }
279
280 enum CaseSensitivity
281 {
282 CaseSensitive,
283 CaseInsensitive
284 };
285
286 /**
287 * Compares the member string to pcsz.
288 * @param pcsz
289 * @param cs Whether comparison should be case-sensitive.
290 * @return
291 */
292 int compare(const char *pcsz, CaseSensitivity cs = CaseSensitive) const
293 {
294 if (m_psz == pcsz)
295 return 0;
296 if (m_psz == NULL)
297 return -1;
298 if (pcsz == NULL)
299 return 1;
300
301 if (cs == CaseSensitive)
302 return ::RTStrCmp(m_psz, pcsz);
303 else
304 return ::RTStrICmp(m_psz, pcsz);
305 }
306
307 int compare(const MiniString &that, CaseSensitivity cs = CaseSensitive) const
308 {
309 return compare(that.m_psz, cs);
310 }
311
312 bool operator==(const MiniString &that) const { return !compare(that); }
313 bool operator!=(const MiniString &that) const { return !!compare(that); }
314 bool operator<(const MiniString &that) const { return compare(that) < 0; }
315 bool operator>(const MiniString &that) const { return compare(that) > 0; }
316
317 bool operator==(const char *that) const { return !compare(that); }
318 bool operator!=(const char *that) const { return !!compare(that); }
319 bool operator<(const char *that) const { return compare(that) < 0; }
320 bool operator>(const char *that) const { return compare(that) > 0; }
321
322 static const size_t npos;
323
324 /**
325 * Looks for pcszFind in "this" starting at "pos" and returns its position,
326 * counting from the beginning of "this" at 0. Returns npos if not found.
327 */
328 size_t find(const char *pcszFind, size_t pos = 0) const;
329
330 /**
331 * Returns a substring of "this" as a new Utf8Str. Works exactly like
332 * its equivalent in std::string except that this interprets pos and n
333 * as UTF-8 codepoints instead of bytes. With the default parameters "0"
334 * and "npos", this always copies the entire string.
335 * @param pos Index of first codepoint to copy from "this", counting from 0.
336 * @param n Number of codepoints to copy, starting with the one at "pos".
337 */
338 iprt::MiniString substr(size_t pos = 0, size_t n = npos) const;
339
340 /**
341 * Returns true if "this" ends with "that".
342 * @param that
343 * @param cs
344 * @return
345 */
346 bool endsWith(const iprt::MiniString &that, CaseSensitivity cs = CaseSensitive) const;
347
348 /**
349 * Returns true if "this" begins with "that".
350 * @return
351 */
352 bool startsWith(const iprt::MiniString &that, CaseSensitivity cs = CaseSensitive) const;
353
354 /**
355 * Returns true if "this" contains "that" (strstr).
356 * @param that
357 * @param cs
358 * @return
359 */
360 bool contains(const iprt::MiniString &that, CaseSensitivity cs = CaseSensitive) const;
361
362 /**
363 * Attempts to convert the member string into an 64-bit integer.
364 *
365 * @returns 64-bit unsigned number on success.
366 * @returns 0 on failure.
367 */
368 int64_t toInt64() const
369 {
370 return RTStrToInt64(m_psz);
371 }
372
373 /**
374 * Attempts to convert the member string into an unsigned 64-bit integer.
375 *
376 * @returns 64-bit unsigned number on success.
377 * @returns 0 on failure.
378 */
379 uint64_t toUInt64() const
380 {
381 return RTStrToUInt64(m_psz);
382 }
383
384 /**
385 * Attempts to convert the member string into an unsigned 64-bit integer.
386 * @return IPRT error code.
387 * @param i Output buffer.
388 */
389 int toInt(uint64_t &i) const;
390
391 /**
392 * Attempts to convert the member string into an unsigned 32-bit integer.
393 * @return IPRT error code.
394 * @param i Output buffer.
395 */
396 int toInt(uint32_t &i) const;
397
398protected:
399
400 /**
401 * Hide operator bool() to force people to use isEmpty() explicitly.
402 */
403 operator bool() const { return false; }
404
405 /**
406 * Destructor implementation, also used to clean up in operator=()
407 * before assigning a new string.
408 */
409 void cleanup()
410 {
411 if (m_psz)
412 {
413 RTMemFree(m_psz);
414 m_psz = NULL;
415 m_cbLength = 0;
416 m_cbAllocated = 0;
417 }
418 }
419
420 /**
421 * Protected internal helper.
422 * copyFrom() unconditionally sets the members to a copy of the
423 * given other strings and makes no assumptions about previous
424 * contents. Can therefore be used both in copy constructors,
425 * when member variables have no defined value, and in assignments
426 * after having called cleanup().
427 *
428 * This variant copies from another MiniString and is fast since
429 * the length of source string is known.
430 *
431 * @param s
432 */
433 void copyFrom(const MiniString &s)
434 {
435 if ((m_cbLength = s.m_cbLength))
436 {
437 m_cbAllocated = m_cbLength + 1;
438 m_psz = (char*)RTMemAlloc(m_cbAllocated);
439#ifdef RT_EXCEPTIONS_ENABLED
440 if (!m_psz)
441 throw std::bad_alloc();
442#endif
443 memcpy(m_psz, s.m_psz, m_cbAllocated); // include 0 terminator
444 }
445 else
446 {
447 m_cbAllocated = 0;
448 m_psz = NULL;
449 }
450 }
451
452 /**
453 * Protected internal helper.
454 * See copyFrom() above.
455 *
456 * This variant copies from a C string and needs to call strlen()
457 * on it. It's therefore slower than the one above.
458 *
459 * @param pcsz
460 */
461 void copyFrom(const char *pcsz)
462 {
463 if (pcsz)
464 {
465 m_cbLength = strlen(pcsz);
466 m_cbAllocated = m_cbLength + 1;
467 m_psz = (char*)RTMemAlloc(m_cbAllocated);
468#ifdef RT_EXCEPTIONS_ENABLED
469 if (!m_psz)
470 throw std::bad_alloc();
471#endif
472 memcpy(m_psz, pcsz, m_cbAllocated); // include 0 terminator
473 }
474 else
475 {
476 m_cbLength = 0;
477 m_cbAllocated = 0;
478 m_psz = NULL;
479 }
480 }
481
482 char *m_psz;
483 size_t m_cbLength; // strlen(m_psz)
484 size_t m_cbAllocated; // size of buffer that m_psz points to; at least m_cbLength + 1
485};
486
487} // namespace iprt
488
489#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette