VirtualBox

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

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

Main: Bstr makeover (third attempt) -- make Bstr(NULL) and Bstr() behave the same; resulting cleanup; make some more internal methods use Utf8Str instead of Bstr; fix a lot of CheckComArgNotNull??() usage

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