VirtualBox

source: vbox/trunk/include/VBox/com/string.h@ 32718

Last change on this file since 32718 was 32718, checked in by vboxsync, 14 years ago

com/string: Remove bool conversion operator and other convenience error operators. They are hiding programming errors (like incorrect empty string checks, and in one case a free of the wrong pointer).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.0 KB
Line 
1/* $Id: string.h 32718 2010-09-23 12:57:52Z vboxsync $ */
2
3/** @file
4 * MS COM / XPCOM Abstraction Layer:
5 * Smart string classes declaration
6 */
7
8/*
9 * Copyright (C) 2006-2009 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * The contents of this file may alternatively be used under the terms
20 * of the Common Development and Distribution License Version 1.0
21 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
22 * VirtualBox OSE distribution, in which case the provisions of the
23 * CDDL are applicable instead of those of the GPL.
24 *
25 * You may elect to license modified versions of this file under the
26 * terms and conditions of either the GPL or the CDDL or both.
27 */
28
29#ifndef ___VBox_com_string_h
30#define ___VBox_com_string_h
31
32/* Make sure all the stdint.h macros are included - must come first! */
33#ifndef __STDC_LIMIT_MACROS
34# define __STDC_LIMIT_MACROS
35#endif
36#ifndef __STDC_CONSTANT_MACROS
37# define __STDC_CONSTANT_MACROS
38#endif
39
40#if defined (VBOX_WITH_XPCOM)
41# include <nsMemory.h>
42#endif
43
44#include "VBox/com/defs.h"
45#include "VBox/com/assert.h"
46
47#include <iprt/alloc.h>
48#include <iprt/cpp/ministring.h>
49
50namespace com
51{
52
53class Utf8Str;
54
55// global constant in glue/string.cpp that represents an empty BSTR
56extern const BSTR g_bstrEmpty;
57
58/**
59 * String class used universally in Main for COM-style Utf-16 strings.
60 * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions
61 * back and forth since most of VirtualBox and our libraries use UTF-8.
62 *
63 * To make things more obscure, on Windows, a COM-style BSTR is not just a
64 * pointer to a null-terminated wide character array, but the four bytes
65 * (32 bits) BEFORE the memory that the pointer points to are a length
66 * DWORD. One must therefore avoid pointer arithmetic and always use
67 * SysAllocString and the like to deal with BSTR pointers, which manage
68 * that DWORD correctly.
69 *
70 * For platforms other than Windows, we provide our own versions of the
71 * Sys* functions in Main/xpcom/helpers.cpp which do NOT use length
72 * prefixes though to be compatible with how XPCOM allocates string
73 * parameters to public functions.
74 *
75 * The Bstr class hides all this handling behind a std::string-like interface
76 * and also provides automatic conversions to MiniString and Utf8Str instances.
77 *
78 * The one advantage of using the SysString* routines is that this makes it
79 * possible to use it as a type of member variables of COM/XPCOM components
80 * and pass their values to callers through component methods' output parameters
81 * using the #cloneTo() operation. Also, the class can adopt (take ownership of)
82 * string buffers returned in output parameters of COM methods using the
83 * #asOutParam() operation and correctly free them afterwards.
84 *
85 * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates
86 * between NULL strings and empty strings. In other words, Bstr("") and
87 * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory,
88 * reports a zero length and zero allocated bytes for both, and returns an
89 * empty C wide string from raw().
90 */
91class Bstr
92{
93public:
94
95 Bstr()
96 : m_bstr(NULL)
97 { }
98
99 Bstr(const Bstr &that)
100 {
101 copyFrom((const OLECHAR *)that.m_bstr);
102 }
103
104 Bstr(CBSTR that)
105 {
106 copyFrom((const OLECHAR *)that);
107 }
108
109#if defined (VBOX_WITH_XPCOM)
110 Bstr(const wchar_t *that)
111 {
112 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR));
113 copyFrom((const OLECHAR *)that);
114 }
115#endif
116
117 Bstr(const iprt::MiniString &that)
118 {
119 copyFrom(that.c_str());
120 }
121
122 Bstr(const char *that)
123 {
124 copyFrom(that);
125 }
126
127 ~Bstr()
128 {
129 setNull();
130 }
131
132 Bstr& operator=(const Bstr &that)
133 {
134 cleanup();
135 copyFrom((const OLECHAR *)that.m_bstr);
136 return *this;
137 }
138
139 Bstr& operator=(CBSTR that)
140 {
141 cleanup();
142 copyFrom((const OLECHAR *)that);
143 return *this;
144 }
145
146#if defined (VBOX_WITH_XPCOM)
147 Bstr& operator=(const wchar_t *that)
148 {
149 cleanup();
150 copyFrom((const OLECHAR *)that);
151 return *this;
152 }
153#endif
154
155 Bstr& setNull()
156 {
157 cleanup();
158 return *this;
159 }
160
161 /** Case sensitivity selector. */
162 enum CaseSensitivity
163 {
164 CaseSensitive,
165 CaseInsensitive
166 };
167
168 /**
169 * Compares the member string to str.
170 * @param str
171 * @param cs Whether comparison should be case-sensitive.
172 * @return
173 */
174 int compare(CBSTR str, CaseSensitivity cs = CaseSensitive) const
175 {
176 if (cs == CaseSensitive)
177 return ::RTUtf16Cmp((PRTUTF16)m_bstr, (PRTUTF16)str);
178 return ::RTUtf16LocaleICmp((PRTUTF16)m_bstr, (PRTUTF16)str);
179 }
180
181 int compare(BSTR str, CaseSensitivity cs = CaseSensitive) const
182 {
183 return compare((CBSTR)str, cs);
184 }
185
186 int compare(const Bstr &that, CaseSensitivity cs = CaseSensitive) const
187 {
188 return compare(that.m_bstr, cs);
189 }
190
191 bool operator==(const Bstr &that) const { return !compare(that.m_bstr); }
192 bool operator!=(const Bstr &that) const { return !!compare(that.m_bstr); }
193 bool operator==(CBSTR that) const { return !compare(that); }
194 bool operator==(BSTR that) const { return !compare(that); }
195
196 bool operator!=(CBSTR that) const { return !!compare(that); }
197 bool operator!=(BSTR that) const { return !!compare(that); }
198 bool operator<(const Bstr &that) const { return compare(that.m_bstr) < 0; }
199 bool operator<(CBSTR that) const { return compare(that) < 0; }
200 bool operator<(BSTR that) const { return compare(that) < 0; }
201
202 /**
203 * Returns true if the member string has no length.
204 * This is true for instances created from both NULL and "" input strings.
205 *
206 * @note Always use this method to check if an instance is empty. Do not
207 * use length() because that may need to run through the entire string
208 * (Bstr does not cache string lengths).
209 */
210 bool isEmpty() const { return m_bstr == NULL || *m_bstr == 0; }
211
212 size_t length() const { return isEmpty() ? 0 : ::RTUtf16Len((PRTUTF16)m_bstr); }
213
214 /**
215 * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
216 * returns a pointer to a global variable containing an empty BSTR with a proper zero
217 * length prefix so that Windows is happy.
218 */
219 CBSTR raw() const
220 {
221 if (m_bstr)
222 return m_bstr;
223
224 return g_bstrEmpty;
225 }
226
227 /**
228 * Returns a non-const raw pointer that allows to modify the string directly.
229 * As opposed to raw(), this DOES return NULL if the member string is empty
230 * because we cannot return a mutable pointer to the global variable with the
231 * empty string.
232 *
233 * @warning
234 * Be sure not to modify data beyond the allocated memory! The
235 * guaranteed size of the allocated memory is at least #length()
236 * bytes after creation and after every assignment operation.
237 */
238 BSTR mutableRaw() { return m_bstr; }
239
240 /**
241 * Intended to assign copies of instances to |BSTR| out parameters from
242 * within the interface method. Transfers the ownership of the duplicated
243 * string to the caller.
244 *
245 * If the member string is empty, this allocates an empty BSTR in *pstr
246 * (i.e. makes it point to a new buffer with a null byte).
247 */
248 void cloneTo(BSTR *pstr) const
249 {
250 if (pstr)
251 {
252 *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
253#ifdef RT_EXCEPTIONS_ENABLED
254 if (!*pstr)
255 throw std::bad_alloc();
256#endif
257 }
258 }
259
260 /**
261 * Intended to assign instances to |BSTR| out parameters from within the
262 * interface method. Transfers the ownership of the original string to the
263 * caller and resets the instance to null.
264 *
265 * As opposed to cloneTo(), this method doesn't create a copy of the
266 * string.
267 *
268 * If the member string is empty, this allocates an empty BSTR in *pstr
269 * (i.e. makes it point to a new buffer with a null byte).
270 */
271 void detachTo(BSTR *pstr)
272 {
273 if (m_bstr)
274 *pstr = m_bstr;
275 else
276 {
277 // allocate null BSTR
278 *pstr = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
279#ifdef RT_EXCEPTIONS_ENABLED
280 if (!*pstr)
281 throw std::bad_alloc();
282#endif
283 }
284 m_bstr = NULL;
285 }
286
287 /**
288 * Intended to pass instances as |BSTR| out parameters to methods.
289 * Takes the ownership of the returned data.
290 */
291 BSTR* asOutParam()
292 {
293 cleanup();
294 return &m_bstr;
295 }
296
297 /**
298 * Static immutable empty-string object. May be used for comparison purposes.
299 */
300 static const Bstr Empty;
301
302protected:
303
304 void cleanup()
305 {
306 if (m_bstr)
307 {
308 ::SysFreeString(m_bstr);
309 m_bstr = NULL;
310 }
311 }
312
313 /**
314 * Protected internal helper to copy a string. This ignores the previous object
315 * state, so either call this from a constructor or call cleanup() first.
316 *
317 * This variant copies from a zero-terminated UTF-16 string (which need not
318 * be a BSTR, i.e. need not have a length prefix).
319 *
320 * If the source is empty, this sets the member string to NULL.
321 * @param rs
322 */
323 void copyFrom(const OLECHAR *rs)
324 {
325 if (rs && *rs)
326 {
327 m_bstr = ::SysAllocString(rs);
328#ifdef RT_EXCEPTIONS_ENABLED
329 if (!m_bstr)
330 throw std::bad_alloc();
331#endif
332 }
333 else
334 m_bstr = NULL;
335 }
336
337 /**
338 * Protected internal helper to copy a string. This ignores the previous object
339 * state, so either call this from a constructor or call cleanup() first.
340 *
341 * This variant copies and converts from a zero-terminated UTF-8 string.
342 *
343 * If the source is empty, this sets the member string to NULL.
344 * @param rs
345 */
346 void copyFrom(const char *rs)
347 {
348 if (rs && *rs)
349 {
350 PRTUTF16 s = NULL;
351 ::RTStrToUtf16(rs, &s);
352#ifdef RT_EXCEPTIONS_ENABLED
353 if (!s)
354 throw std::bad_alloc();
355#endif
356 copyFrom((const OLECHAR *)s); // allocates BSTR from zero-terminated input string
357 ::RTUtf16Free(s);
358 }
359 else
360 m_bstr = NULL;
361 }
362
363 BSTR m_bstr;
364
365 friend class Utf8Str; /* to access our raw_copy() */
366};
367
368/* symmetric compare operators */
369inline bool operator==(CBSTR l, const Bstr &r) { return r.operator==(l); }
370inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!=(l); }
371inline bool operator==(BSTR l, const Bstr &r) { return r.operator==(l); }
372inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!=(l); }
373
374
375////////////////////////////////////////////////////////////////////////////////
376
377/**
378 * String class used universally in Main for UTF-8 strings.
379 *
380 * This is based on iprt::MiniString, to which some functionality has been
381 * moved. Here we keep things that are specific to Main, such as conversions
382 * with UTF-16 strings (Bstr).
383 *
384 * Like iprt::MiniString, Utf8Str does not differentiate between NULL strings
385 * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL)
386 * behave the same. In both cases, MiniString allocates no memory, reports
387 * a zero length and zero allocated bytes for both, and returns an empty
388 * C string from c_str().
389 */
390class Utf8Str : public iprt::MiniString
391{
392public:
393
394 Utf8Str() {}
395
396 Utf8Str(const MiniString &that)
397 : MiniString(that)
398 {}
399
400 Utf8Str(const char *that)
401 : MiniString(that)
402 {}
403
404 Utf8Str(const Bstr &that)
405 {
406 copyFrom(that.raw());
407 }
408
409 Utf8Str(CBSTR that)
410 {
411 copyFrom(that);
412 }
413
414 Utf8Str& operator=(const MiniString &that)
415 {
416 MiniString::operator=(that);
417 return *this;
418 }
419
420 Utf8Str& operator=(const char *that)
421 {
422 MiniString::operator=(that);
423 return *this;
424 }
425
426 Utf8Str& operator=(const Bstr &that)
427 {
428 cleanup();
429 copyFrom(that.raw());
430 return *this;
431 }
432
433 Utf8Str& operator=(CBSTR that)
434 {
435 cleanup();
436 copyFrom(that);
437 return *this;
438 }
439
440#if defined (VBOX_WITH_XPCOM)
441 /**
442 * Intended to assign instances to |char *| out parameters from within the
443 * interface method. Transfers the ownership of the duplicated string to the
444 * caller.
445 *
446 * This allocates a single 0 byte in the target if the member string is empty.
447 *
448 * This uses XPCOM memory allocation and thus only works on XPCOM. MSCOM doesn't
449 * like char* strings anyway.
450 */
451 void cloneTo(char **pstr) const;
452#endif
453
454 /**
455 * Intended to assign instances to |BSTR| out parameters from within the
456 * interface method. Transfers the ownership of the duplicated string to the
457 * caller.
458 */
459 void cloneTo(BSTR *pstr) const
460 {
461 if (pstr)
462 {
463 Bstr bstr(*this);
464 bstr.cloneTo(pstr);
465 }
466 }
467
468 /**
469 * Converts "this" to lower case by calling RTStrToLower().
470 * @return
471 */
472 Utf8Str& toLower();
473
474 /**
475 * Converts "this" to upper case by calling RTStrToUpper().
476 * @return
477 */
478 Utf8Str& toUpper();
479
480 /**
481 * Removes a trailing slash from the member string, if present.
482 * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
483 */
484 void stripTrailingSlash();
485
486 /**
487 * Removes a trailing filename from the member string, if present.
488 * Calls RTPathStripFilename() without having to mess with mutableRaw().
489 */
490 void stripFilename();
491
492 /**
493 * Removes a trailing file name extension from the member string, if present.
494 * Calls RTPathStripExt() without having to mess with mutableRaw().
495 */
496 void stripExt();
497
498 /**
499 * Attempts to convert the member string into a 32-bit integer.
500 *
501 * @returns 32-bit unsigned number on success.
502 * @returns 0 on failure.
503 */
504 int toInt32() const
505 {
506 return RTStrToInt32(m_psz);
507 }
508
509 /**
510 * Attempts to convert the member string into an unsigned 32-bit integer.
511 *
512 * @returns 32-bit unsigned number on success.
513 * @returns 0 on failure.
514 */
515 int toUInt32() const
516 {
517 return RTStrToUInt32(m_psz);
518 }
519
520 /**
521 * Static immutable empty-string object. May be used for comparison purposes.
522 */
523 static const Utf8Str Empty;
524
525protected:
526
527 void copyFrom(CBSTR s);
528
529 friend class Bstr; /* to access our raw_copy() */
530};
531
532/**
533 * This class is a printf-like formatter for Utf8Str strings. Its purpose is
534 * to construct Utf8Str objects from a format string and a list of arguments
535 * for the format string.
536 *
537 * The usage of this class is like the following:
538 * <code>
539 * Utf8StrFmt string ("program name = %s", argv[0]);
540 * </code>
541 */
542class Utf8StrFmt : public Utf8Str
543{
544public:
545
546 /**
547 * Constructs a new string given the format string and the list
548 * of the arguments for the format string.
549 *
550 * @param format printf-like format string (in UTF-8 encoding)
551 * @param ... list of the arguments for the format string
552 */
553 explicit Utf8StrFmt(const char *format, ...)
554 {
555 va_list args;
556 va_start(args, format);
557 init(format, args);
558 va_end(args);
559 }
560
561protected:
562 Utf8StrFmt()
563 { }
564
565 void init(const char *format, va_list args);
566
567private:
568};
569
570/**
571 * This class is a vprintf-like formatter for Utf8Str strings. It is
572 * identical to Utf8StrFmt except that its constructor takes a va_list
573 * argument instead of ellipsis.
574 *
575 * Note that a separate class is necessary because va_list is defined as
576 * |char *| on most platforms. For this reason, if we had two overloaded
577 * constructors in Utf8StrFmt (one taking ellipsis and another one taking
578 * va_list) then composing a constructor call using exactly two |char *|
579 * arguments would cause the compiler to use the va_list overload instead of
580 * the ellipsis one which is obviously wrong. The compiler would choose
581 * va_list because ellipsis has the lowest rank when it comes to resolving
582 * overloads, as opposed to va_list which is an exact match for |char *|.
583 */
584class Utf8StrFmtVA : public Utf8StrFmt
585{
586public:
587
588 /**
589 * Constructs a new string given the format string and the list
590 * of the arguments for the format string.
591 *
592 * @param format printf-like format string (in UTF-8 encoding)
593 * @param args list of arguments for the format string
594 */
595 Utf8StrFmtVA(const char *format, va_list args) { init(format, args); }
596};
597
598/**
599 * The BstrFmt class is a shortcut to <tt>Bstr(Utf8StrFmt(...))</tt>.
600 */
601class BstrFmt : public Bstr
602{
603public:
604
605 /**
606 * Constructs a new string given the format string and the list of the
607 * arguments for the format string.
608 *
609 * @param aFormat printf-like format string (in UTF-8 encoding).
610 * @param ... List of the arguments for the format string.
611 */
612 explicit BstrFmt(const char *aFormat, ...)
613 {
614 va_list args;
615 va_start(args, aFormat);
616 copyFrom(Utf8StrFmtVA(aFormat, args).c_str());
617 va_end(args);
618 }
619};
620
621/**
622 * The BstrFmtVA class is a shortcut to <tt>Bstr(Utf8StrFmtVA(...))</tt>.
623 */
624class BstrFmtVA : public Bstr
625{
626public:
627
628 /**
629 * Constructs a new string given the format string and the list of the
630 * arguments for the format string.
631 *
632 * @param aFormat printf-like format string (in UTF-8 encoding).
633 * @param aArgs List of arguments for the format string
634 */
635 BstrFmtVA(const char *aFormat, va_list aArgs)
636 {
637 copyFrom(Utf8StrFmtVA(aFormat, aArgs).c_str());
638 }
639};
640
641} /* namespace com */
642
643#endif /* !___VBox_com_string_h */
644
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