VirtualBox

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

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

API: big medium handling change and lots of assorted other cleanups and fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 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 MiniString& append(const MiniString &that);
215 MiniString& append(char c);
216
217 /**
218 * Returns the byte at the given index, or a null byte if
219 * the index is not smaller than length(). This does _not_
220 * count UTF-8 characters but simply points into the
221 * member C string.
222 * @param i
223 * @return
224 */
225 inline char operator[](size_t i) const
226 {
227 if (i < length())
228 return m_psz[i];
229 return '\0';
230 }
231
232 /**
233 * Returns the contained string as a C-style const char* pointer.
234 * @return
235 */
236 inline const char* c_str() const
237 {
238 return m_psz;
239 }
240
241 /**
242 * Like c_str(), for compatibility with lots of VirtualBox Main code.
243 * @return
244 */
245 inline const char* raw() const
246 {
247 return m_psz;
248 }
249
250 /**
251 * Returns true if the member string has no length. This states nothing about
252 * how much memory might be allocated.
253 * @return
254 */
255 bool isEmpty() const
256 {
257 return length() == 0;
258 }
259
260 enum CaseSensitivity
261 {
262 CaseSensitive,
263 CaseInsensitive
264 };
265
266 /**
267 * Compares the member string to pcsz.
268 * @param pcsz
269 * @param cs Whether comparison should be case-sensitive.
270 * @return
271 */
272 int compare(const char *pcsz, CaseSensitivity cs = CaseSensitive) const
273 {
274 if (m_psz == pcsz)
275 return 0;
276 if (m_psz == NULL)
277 return -1;
278 if (pcsz == NULL)
279 return 1;
280
281 if (cs == CaseSensitive)
282 return ::RTStrCmp(m_psz, pcsz);
283 else
284 return ::RTStrICmp(m_psz, pcsz);
285 }
286
287 int compare(const MiniString &that, CaseSensitivity cs = CaseSensitive) const
288 {
289 return compare(that.m_psz, cs);
290 }
291
292 bool operator==(const MiniString &that) const { return !compare(that); }
293 bool operator!=(const MiniString &that) const { return !!compare(that); }
294 bool operator<(const MiniString &that) const { return compare(that) < 0; }
295 bool operator>(const MiniString &that) const { return compare(that) > 0; }
296
297 bool operator==(const char *that) const { return !compare(that); }
298 bool operator!=(const char *that) const { return !!compare(that); }
299 bool operator<(const char *that) const { return compare(that) < 0; }
300 bool operator>(const char *that) const { return compare(that) > 0; }
301
302 static const size_t npos;
303
304 /**
305 * Looks for pcszFind in "this" starting at "pos" and returns its position,
306 * counting from the beginning of "this" at 0. Returns npos if not found.
307 */
308 size_t find(const char *pcszFind, size_t pos = 0) const;
309
310 /**
311 * Returns a substring of "this" as a new Utf8Str. Works exactly like
312 * its equivalent in std::string except that this interprets pos and n
313 * as UTF-8 codepoints instead of bytes. With the default parameters "0"
314 * and "npos", this always copies the entire string.
315 * @param pos Index of first codepoint to copy from "this", counting from 0.
316 * @param n Number of codepoints to copy, starting with the one at "pos".
317 */
318 iprt::MiniString substr(size_t pos = 0, size_t n = npos) const;
319
320 /**
321 * Returns true if "this" ends with "that".
322 * @param that
323 * @param cs
324 * @return
325 */
326 bool endsWith(const iprt::MiniString &that, CaseSensitivity cs = CaseSensitive) const;
327
328 /**
329 * Returns true if "this" begins with "that".
330 * @return
331 */
332 bool startsWith(const iprt::MiniString &that, CaseSensitivity cs = CaseSensitive) const;
333
334 /**
335 * Returns true if "this" contains "that" (strstr).
336 * @param that
337 * @param cs
338 * @return
339 */
340 bool contains(const iprt::MiniString &that, CaseSensitivity cs = CaseSensitive) const;
341
342 /**
343 * Attempts to convert the member string into an 64-bit integer.
344 *
345 * @returns 64-bit unsigned number on success.
346 * @returns 0 on failure.
347 */
348 int64_t toInt64() const
349 {
350 return RTStrToInt64(m_psz);
351 }
352
353 /**
354 * Attempts to convert the member string into an unsigned 64-bit integer.
355 *
356 * @returns 64-bit unsigned number on success.
357 * @returns 0 on failure.
358 */
359 uint64_t toUInt64() const
360 {
361 return RTStrToUInt64(m_psz);
362 }
363
364 /**
365 * Attempts to convert the member string into an unsigned 64-bit integer.
366 * @return IPRT error code.
367 * @param i Output buffer.
368 */
369 int toInt(uint64_t &i) const;
370
371 /**
372 * Attempts to convert the member string into an unsigned 32-bit integer.
373 * @return IPRT error code.
374 * @param i Output buffer.
375 */
376 int toInt(uint32_t &i) const;
377
378protected:
379
380 /**
381 * Hide operator bool() to force people to use isEmpty() explicitly.
382 */
383 operator bool() const { return false; }
384
385 /**
386 * Destructor implementation, also used to clean up in operator=()
387 * before assigning a new string.
388 */
389 void cleanup()
390 {
391 if (m_psz)
392 {
393 RTMemFree(m_psz);
394 m_psz = NULL;
395 m_cbLength = 0;
396 m_cbAllocated = 0;
397 }
398 }
399
400 /**
401 * Protected internal helper.
402 * copyFrom() unconditionally sets the members to a copy of the
403 * given other strings and makes no assumptions about previous
404 * contents. Can therefore be used both in copy constructors,
405 * when member variables have no defined value, and in assignments
406 * after having called cleanup().
407 *
408 * This variant copies from another MiniString and is fast since
409 * the length of source string is known.
410 *
411 * @param s
412 */
413 void copyFrom(const MiniString &s)
414 {
415 if ((m_cbLength = s.m_cbLength))
416 {
417 m_cbAllocated = m_cbLength + 1;
418 m_psz = (char*)RTMemAlloc(m_cbAllocated);
419#ifdef RT_EXCEPTIONS_ENABLED
420 if (!m_psz)
421 throw std::bad_alloc();
422#endif
423 memcpy(m_psz, s.m_psz, m_cbAllocated); // include 0 terminator
424 }
425 else
426 {
427 m_cbAllocated = 0;
428 m_psz = NULL;
429 }
430 }
431
432 /**
433 * Protected internal helper.
434 * See copyFrom() above.
435 *
436 * This variant copies from a C string and needs to call strlen()
437 * on it. It's therefore slower than the one above.
438 *
439 * @param pcsz
440 */
441 void copyFrom(const char *pcsz)
442 {
443 if (pcsz)
444 {
445 m_cbLength = strlen(pcsz);
446 m_cbAllocated = m_cbLength + 1;
447 m_psz = (char*)RTMemAlloc(m_cbAllocated);
448#ifdef RT_EXCEPTIONS_ENABLED
449 if (!m_psz)
450 throw std::bad_alloc();
451#endif
452 memcpy(m_psz, pcsz, m_cbAllocated); // include 0 terminator
453 }
454 else
455 {
456 m_cbLength = 0;
457 m_cbAllocated = 0;
458 m_psz = NULL;
459 }
460 }
461
462 char *m_psz;
463 size_t m_cbLength; // strlen(m_psz)
464 size_t m_cbAllocated; // size of buffer that m_psz points to; at least m_cbLength + 1
465};
466
467} // namespace iprt
468
469#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