VirtualBox

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

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

IPRT, Main: make ministring throw std::bad_alloc on allocation failure; remove isEmpty() and isNull(), change Main code to using length() instead

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 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
39/**
40 * "ministring" is a small C++ string class that does not depend on anything
41 * else except IPRT memory management functions. This is used as the base of
42 * both the Utf8Str class that COM uses as well as C++ code in IPRT that
43 * prefers to have a string class, like in xml.cpp.
44 *
45 * Semantics are like in std::string, except it can do a lot less.
46 *
47 * Much of the code in here used to be in com::Utf8Str so that com::Utf8Str
48 * can now derive from ministring and only contain code that is COM-specific,
49 * such as com::Bstr conversions. Compared to the old Utf8Str though, ministring
50 * always knows the length of its member string and the size of the buffer
51 * so it can use memcpy() instead of strdup().
52 */
53
54class RT_DECL_CLASS ministring
55{
56public:
57 /**
58 * Creates an empty string that has no memory allocated.
59 */
60 ministring()
61 : m_psz(NULL),
62 m_cbLength(0),
63 m_cbAllocated(0)
64 {
65 }
66
67 /**
68 * Creates a copy of another ministring. This allocates
69 * s.length() + 1 bytes for the new instance.
70 * @param s
71 */
72 ministring(const ministring &s)
73#ifdef RT_EXCEPTIONS_ENABLED
74 throw(std::bad_alloc)
75#endif
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#ifdef RT_EXCEPTIONS_ENABLED
87 throw(std::bad_alloc)
88#endif
89 {
90 copyFrom(pcsz);
91 }
92
93 /**
94 * Destructor.
95 */
96 virtual ~ministring()
97 {
98 cleanup();
99 }
100
101 /**
102 * Returns the length of the member string. This is always cached
103 * so calling this is cheap and requires no strlen() invocation.
104 * @return
105 */
106 size_t length() const
107 {
108 return m_cbLength;
109 }
110
111 /**
112 * Returns the number of bytes allocated in the internal string buffer,
113 * which is at least length() + 1 if length() > 0.
114 * @return
115 */
116 size_t capacity() const
117 {
118 return m_cbAllocated;
119 }
120
121 /**
122 * Requests that the contained memory buffer have at least cb bytes allocated.
123 * This may expand or shrink the string's storage, but will never truncate the
124 * contained string. In other words, cb will be ignored if it's smaller than
125 * length() + 1.
126 * @param cb new minimum size of member memory buffer
127 */
128 void reserve(size_t cb)
129#ifdef RT_EXCEPTIONS_ENABLED
130 throw(std::bad_alloc)
131#endif
132 {
133 if ( (cb != m_cbAllocated)
134 && (cb > m_cbLength + 1)
135 )
136 {
137 m_psz = (char*)RTMemRealloc(m_psz, cb);
138#ifdef RT_EXCEPTIONS_ENABLED
139 if (!m_psz)
140 throw std::bad_alloc();
141#endif
142 m_cbAllocated = cb;
143 }
144 }
145
146 /**
147 * Deallocates all memory.
148 */
149 inline void setNull()
150 {
151 cleanup();
152 }
153
154 /**
155 * Returns a non-const raw pointer that allows to modify the string directly.
156 * @warning
157 * 1) Be sure not to modify data beyond the allocated memory! Call
158 * capacity() to find out how large that buffer is.
159 * 2) After any operation that modifies the length of the string,
160 * you _must_ call ministring::jolt(), or subsequent copy operations
161 * may go nowhere. Better not use mutableRaw() at all.
162 */
163 char* mutableRaw()
164 {
165 return m_psz;
166 }
167
168 /**
169 * Intended to be called after something has messed with the internal string
170 * buffer (e.g. after using mutableRaw() or Utf8Str::asOutParam()). Resets
171 * the internal lengths correctly. Otherwise subsequent copy operations may
172 * go nowhere.
173 */
174 void jolt()
175 {
176 if (m_psz)
177 {
178 m_cbLength = strlen(m_psz);
179 m_cbAllocated = m_cbLength + 1;
180 }
181 else
182 {
183 m_cbLength = 0;
184 m_cbAllocated = 0;
185 }
186 }
187
188 /**
189 * Assigns a copy of pcsz to "this".
190 * @param pcsz
191 * @return
192 */
193 ministring& operator=(const char *pcsz)
194#ifdef RT_EXCEPTIONS_ENABLED
195 throw(std::bad_alloc)
196#endif
197 {
198 if (m_psz != pcsz)
199 {
200 cleanup();
201 copyFrom(pcsz);
202 }
203 return *this;
204 }
205
206 /**
207 * Assigns a copy of s to "this".
208 * @param s
209 * @return
210 */
211 ministring& operator=(const ministring &s)
212#ifdef RT_EXCEPTIONS_ENABLED
213 throw(std::bad_alloc)
214#endif
215 {
216 if (this != &s)
217 {
218 cleanup();
219 copyFrom(s);
220 }
221 return *this;
222 }
223
224 /**
225 * Appends a copy of @a that to "this".
226 * @param that
227 */
228 void append(const ministring &that)
229 {
230 size_t cbThis = length();
231 size_t cbThat = that.length();
232
233 if (cbThat)
234 {
235 size_t cbBoth = cbThis + cbThat + 1;
236
237 reserve(cbBoth);
238 // calls realloc(cbBoth) and sets m_cbAllocated
239
240 memcpy(m_psz + cbThis, that.m_psz, cbThat);
241 m_psz[cbThis + cbThat] = '\0';
242 m_cbLength = cbBoth - 1;
243 }
244 }
245
246 /**
247 * Returns the contained string as a C-style const char* pointer.
248 * @return
249 */
250 inline const char* c_str() const
251 {
252 return m_psz;
253 }
254
255 /**
256 * Like c_str(), for compatibility with lots of VirtualBox Main code.
257 * @return
258 */
259 inline const char* raw() const
260 {
261 return m_psz;
262 }
263
264 /** Intended to to pass instances as input (|char *|) parameters to methods. */
265 inline operator const char*() const
266 {
267 return c_str();
268 }
269
270 enum CaseSensitivity
271 {
272 CaseSensitive,
273 CaseInsensitive
274 };
275
276 /**
277 * Compares the member string to pcsz.
278 * @param pcsz
279 * @param cs Whether comparison should be case-sensitive.
280 * @return
281 */
282 int compare(const char *pcsz, CaseSensitivity cs = CaseSensitive) const
283 {
284 if (m_psz == pcsz)
285 return 0;
286 if (m_psz == NULL)
287 return -1;
288 if (pcsz == NULL)
289 return 1;
290
291 if (cs == CaseSensitive)
292 return ::RTStrCmp(m_psz, pcsz);
293 else
294 return ::RTStrICmp(m_psz, pcsz);
295 }
296
297 int compare(const ministring &that, CaseSensitivity cs = CaseSensitive) const
298 {
299 return compare(that.m_psz, cs);
300 }
301
302 bool operator==(const ministring &that) const { return !compare(that); }
303 bool operator!=(const ministring &that) const { return !!compare(that); }
304 bool operator<(const ministring &that) const { return compare(that) < 0; }
305 bool operator>(const ministring &that) const { return compare(that) > 0; }
306
307 bool operator==(const char *that) const { return !compare(that); }
308 bool operator!=(const char *that) const { return !!compare(that); }
309 bool operator<(const char *that) const { return compare(that) < 0; }
310 bool operator>(const char *that) const { return compare(that) > 0; }
311
312protected:
313
314 /**
315 * Hide operator bool() to force people to use isEmpty() explicitly.
316 */
317 operator bool() const { return false; }
318
319 /**
320 * Destructor implementation, also used to clean up in operator=()
321 * before assigning a new string.
322 */
323 void cleanup()
324 {
325 if (m_psz)
326 {
327 RTMemFree(m_psz);
328 m_psz = NULL;
329 m_cbLength = 0;
330 m_cbAllocated = 0;
331 }
332 }
333
334 /**
335 * Protected internal helper.
336 * copyFrom() unconditionally sets the members to a copy of the
337 * given other strings and makes no assumptions about previous
338 * contents. Can therefore be used both in copy constructors,
339 * when member variables have no defined value, and in assignments
340 * after having called cleanup().
341 *
342 * This variant copies from another ministring and is fast since
343 * the length of source string is known.
344 *
345 * @param s
346 */
347 void copyFrom(const ministring &s)
348#ifdef RT_EXCEPTIONS_ENABLED
349 throw(std::bad_alloc)
350#endif
351 {
352 if ((m_cbLength = s.m_cbLength))
353 {
354 m_cbAllocated = m_cbLength + 1;
355 m_psz = (char*)RTMemAlloc(m_cbAllocated);
356#ifdef RT_EXCEPTIONS_ENABLED
357 if (!m_psz)
358 throw std::bad_alloc();
359#endif
360 memcpy(m_psz, s.m_psz, m_cbAllocated); // include 0 terminator
361 }
362 else
363 {
364 m_cbAllocated = 0;
365 m_psz = NULL;
366 }
367 }
368
369 /**
370 * Protected internal helper.
371 * See copyFrom() above.
372 *
373 * This variant copies from a C string and needs to call strlen()
374 * on it. It's therefore slower than the one above.
375 *
376 * @param pcsz
377 */
378 void copyFrom(const char *pcsz)
379#ifdef RT_EXCEPTIONS_ENABLED
380 throw(std::bad_alloc)
381#endif
382 {
383 if (pcsz)
384 {
385 m_cbLength = strlen(pcsz);
386 m_cbAllocated = m_cbLength + 1;
387 m_psz = (char*)RTMemAlloc(m_cbAllocated);
388#ifdef RT_EXCEPTIONS_ENABLED
389 if (!m_psz)
390 throw std::bad_alloc();
391#endif
392 memcpy(m_psz, pcsz, m_cbAllocated); // include 0 terminator
393 }
394 else
395 {
396 m_cbLength = 0;
397 m_cbAllocated = 0;
398 m_psz = NULL;
399 }
400 }
401
402 char *m_psz;
403 size_t m_cbLength; // strlen(m_psz)
404 size_t m_cbAllocated; // size of buffer that m_psz points to; at least m_cbLength + 1
405};
406
407#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