VirtualBox

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

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

com/string: Windows build fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.6 KB
Line 
1/* $Id: string.h 32727 2010-09-23 14:31:31Z vboxsync $ */
2
3/** @file
4 * MS COM / XPCOM Abstraction Layer:
5 * Smart string classes declaration
6 */
7
8/*
9 * Copyright (C) 2006-2010 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#if defined(VBOX_WITH_XPCOM)
215 /**
216 * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
217 * returns a pointer to a global variable containing an empty BSTR with a proper zero
218 * length prefix so that Windows is happy.
219 */
220 CBSTR raw() const
221 {
222 if (m_bstr)
223 return m_bstr;
224
225 return g_bstrEmpty;
226 }
227#else
228 /**
229 * Windows-only hack, as the automatically generated headers use BSTR.
230 * So if we don't want to cast like crazy we have to be more loose than
231 * on XPCOM.
232 *
233 * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
234 * returns a pointer to a global variable containing an empty BSTR with a proper zero
235 * length prefix so that Windows is happy.
236 */
237 BSTR raw() const
238 {
239 if (m_bstr)
240 return m_bstr;
241
242 return g_bstrEmpty;
243 }
244#endif
245
246 /**
247 * Returns a non-const raw pointer that allows to modify the string directly.
248 * As opposed to raw(), this DOES return NULL if the member string is empty
249 * because we cannot return a mutable pointer to the global variable with the
250 * empty string.
251 *
252 * @warning
253 * Be sure not to modify data beyond the allocated memory! The
254 * guaranteed size of the allocated memory is at least #length()
255 * bytes after creation and after every assignment operation.
256 */
257 BSTR mutableRaw() { return m_bstr; }
258
259 /**
260 * Intended to assign copies of instances to |BSTR| out parameters from
261 * within the interface method. Transfers the ownership of the duplicated
262 * string to the caller.
263 *
264 * If the member string is empty, this allocates an empty BSTR in *pstr
265 * (i.e. makes it point to a new buffer with a null byte).
266 */
267 void cloneTo(BSTR *pstr) const
268 {
269 if (pstr)
270 {
271 *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
272#ifdef RT_EXCEPTIONS_ENABLED
273 if (!*pstr)
274 throw std::bad_alloc();
275#endif
276 }
277 }
278
279 /**
280 * Intended to assign instances to |BSTR| out parameters from within the
281 * interface method. Transfers the ownership of the original string to the
282 * caller and resets the instance to null.
283 *
284 * As opposed to cloneTo(), this method doesn't create a copy of the
285 * string.
286 *
287 * If the member string is empty, this allocates an empty BSTR in *pstr
288 * (i.e. makes it point to a new buffer with a null byte).
289 */
290 void detachTo(BSTR *pstr)
291 {
292 if (m_bstr)
293 *pstr = m_bstr;
294 else
295 {
296 // allocate null BSTR
297 *pstr = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
298#ifdef RT_EXCEPTIONS_ENABLED
299 if (!*pstr)
300 throw std::bad_alloc();
301#endif
302 }
303 m_bstr = NULL;
304 }
305
306 /**
307 * Intended to pass instances as |BSTR| out parameters to methods.
308 * Takes the ownership of the returned data.
309 */
310 BSTR* asOutParam()
311 {
312 cleanup();
313 return &m_bstr;
314 }
315
316 /**
317 * Static immutable empty-string object. May be used for comparison purposes.
318 */
319 static const Bstr Empty;
320
321protected:
322
323 void cleanup()
324 {
325 if (m_bstr)
326 {
327 ::SysFreeString(m_bstr);
328 m_bstr = NULL;
329 }
330 }
331
332 /**
333 * Protected internal helper to copy a string. This ignores the previous object
334 * state, so either call this from a constructor or call cleanup() first.
335 *
336 * This variant copies from a zero-terminated UTF-16 string (which need not
337 * be a BSTR, i.e. need not have a length prefix).
338 *
339 * If the source is empty, this sets the member string to NULL.
340 * @param rs
341 */
342 void copyFrom(const OLECHAR *rs)
343 {
344 if (rs && *rs)
345 {
346 m_bstr = ::SysAllocString(rs);
347#ifdef RT_EXCEPTIONS_ENABLED
348 if (!m_bstr)
349 throw std::bad_alloc();
350#endif
351 }
352 else
353 m_bstr = NULL;
354 }
355
356 /**
357 * Protected internal helper to copy a string. This ignores the previous object
358 * state, so either call this from a constructor or call cleanup() first.
359 *
360 * This variant copies and converts from a zero-terminated UTF-8 string.
361 *
362 * If the source is empty, this sets the member string to NULL.
363 * @param rs
364 */
365 void copyFrom(const char *rs)
366 {
367 if (rs && *rs)
368 {
369 PRTUTF16 s = NULL;
370 ::RTStrToUtf16(rs, &s);
371#ifdef RT_EXCEPTIONS_ENABLED
372 if (!s)
373 throw std::bad_alloc();
374#endif
375 copyFrom((const OLECHAR *)s); // allocates BSTR from zero-terminated input string
376 ::RTUtf16Free(s);
377 }
378 else
379 m_bstr = NULL;
380 }
381
382 BSTR m_bstr;
383
384 friend class Utf8Str; /* to access our raw_copy() */
385};
386
387/* symmetric compare operators */
388inline bool operator==(CBSTR l, const Bstr &r) { return r.operator==(l); }
389inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!=(l); }
390inline bool operator==(BSTR l, const Bstr &r) { return r.operator==(l); }
391inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!=(l); }
392
393
394////////////////////////////////////////////////////////////////////////////////
395
396/**
397 * String class used universally in Main for UTF-8 strings.
398 *
399 * This is based on iprt::MiniString, to which some functionality has been
400 * moved. Here we keep things that are specific to Main, such as conversions
401 * with UTF-16 strings (Bstr).
402 *
403 * Like iprt::MiniString, Utf8Str does not differentiate between NULL strings
404 * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL)
405 * behave the same. In both cases, MiniString allocates no memory, reports
406 * a zero length and zero allocated bytes for both, and returns an empty
407 * C string from c_str().
408 */
409class Utf8Str : public iprt::MiniString
410{
411public:
412
413 Utf8Str() {}
414
415 Utf8Str(const MiniString &that)
416 : MiniString(that)
417 {}
418
419 Utf8Str(const char *that)
420 : MiniString(that)
421 {}
422
423 Utf8Str(const Bstr &that)
424 {
425 copyFrom(that.raw());
426 }
427
428 Utf8Str(CBSTR that)
429 {
430 copyFrom(that);
431 }
432
433 Utf8Str& operator=(const MiniString &that)
434 {
435 MiniString::operator=(that);
436 return *this;
437 }
438
439 Utf8Str& operator=(const char *that)
440 {
441 MiniString::operator=(that);
442 return *this;
443 }
444
445 Utf8Str& operator=(const Bstr &that)
446 {
447 cleanup();
448 copyFrom(that.raw());
449 return *this;
450 }
451
452 Utf8Str& operator=(CBSTR that)
453 {
454 cleanup();
455 copyFrom(that);
456 return *this;
457 }
458
459#if defined(VBOX_WITH_XPCOM)
460 /**
461 * Intended to assign instances to |char *| out parameters from within the
462 * interface method. Transfers the ownership of the duplicated string to the
463 * caller.
464 *
465 * This allocates a single 0 byte in the target if the member string is empty.
466 *
467 * This uses XPCOM memory allocation and thus only works on XPCOM. MSCOM doesn't
468 * like char* strings anyway.
469 */
470 void cloneTo(char **pstr) const;
471#endif
472
473 /**
474 * Intended to assign instances to |BSTR| out parameters from within the
475 * interface method. Transfers the ownership of the duplicated string to the
476 * caller.
477 */
478 void cloneTo(BSTR *pstr) const
479 {
480 if (pstr)
481 {
482 Bstr bstr(*this);
483 bstr.cloneTo(pstr);
484 }
485 }
486
487 /**
488 * Converts "this" to lower case by calling RTStrToLower().
489 * @return
490 */
491 Utf8Str& toLower();
492
493 /**
494 * Converts "this" to upper case by calling RTStrToUpper().
495 * @return
496 */
497 Utf8Str& toUpper();
498
499 /**
500 * Removes a trailing slash from the member string, if present.
501 * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
502 */
503 void stripTrailingSlash();
504
505 /**
506 * Removes a trailing filename from the member string, if present.
507 * Calls RTPathStripFilename() without having to mess with mutableRaw().
508 */
509 void stripFilename();
510
511 /**
512 * Removes a trailing file name extension from the member string, if present.
513 * Calls RTPathStripExt() without having to mess with mutableRaw().
514 */
515 void stripExt();
516
517 /**
518 * Attempts to convert the member string into a 32-bit integer.
519 *
520 * @returns 32-bit unsigned number on success.
521 * @returns 0 on failure.
522 */
523 int toInt32() const
524 {
525 return RTStrToInt32(m_psz);
526 }
527
528 /**
529 * Attempts to convert the member string into an unsigned 32-bit integer.
530 *
531 * @returns 32-bit unsigned number on success.
532 * @returns 0 on failure.
533 */
534 int toUInt32() const
535 {
536 return RTStrToUInt32(m_psz);
537 }
538
539 /**
540 * Static immutable empty-string object. May be used for comparison purposes.
541 */
542 static const Utf8Str Empty;
543
544protected:
545
546 void copyFrom(CBSTR s);
547
548 friend class Bstr; /* to access our raw_copy() */
549};
550
551/**
552 * This class is a printf-like formatter for Utf8Str strings. Its purpose is
553 * to construct Utf8Str objects from a format string and a list of arguments
554 * for the format string.
555 *
556 * The usage of this class is like the following:
557 * <code>
558 * Utf8StrFmt string("program name = %s", argv[0]);
559 * </code>
560 */
561class Utf8StrFmt : public Utf8Str
562{
563public:
564
565 /**
566 * Constructs a new string given the format string and the list
567 * of the arguments for the format string.
568 *
569 * @param format printf-like format string (in UTF-8 encoding)
570 * @param ... list of the arguments for the format string
571 */
572 explicit Utf8StrFmt(const char *format, ...)
573 {
574 va_list args;
575 va_start(args, format);
576 init(format, args);
577 va_end(args);
578 }
579
580protected:
581 Utf8StrFmt()
582 { }
583
584 void init(const char *format, va_list args);
585
586private:
587};
588
589/**
590 * This class is a vprintf-like formatter for Utf8Str strings. It is
591 * identical to Utf8StrFmt except that its constructor takes a va_list
592 * argument instead of ellipsis.
593 *
594 * Note that a separate class is necessary because va_list is defined as
595 * |char *| on most platforms. For this reason, if we had two overloaded
596 * constructors in Utf8StrFmt (one taking ellipsis and another one taking
597 * va_list) then composing a constructor call using exactly two |char *|
598 * arguments would cause the compiler to use the va_list overload instead of
599 * the ellipsis one which is obviously wrong. The compiler would choose
600 * va_list because ellipsis has the lowest rank when it comes to resolving
601 * overloads, as opposed to va_list which is an exact match for |char *|.
602 */
603class Utf8StrFmtVA : public Utf8StrFmt
604{
605public:
606
607 /**
608 * Constructs a new string given the format string and the list
609 * of the arguments for the format string.
610 *
611 * @param format printf-like format string (in UTF-8 encoding)
612 * @param args list of arguments for the format string
613 */
614 Utf8StrFmtVA(const char *format, va_list args) { init(format, args); }
615};
616
617/**
618 * The BstrFmt class is a shortcut to <tt>Bstr(Utf8StrFmt(...))</tt>.
619 */
620class BstrFmt : public Bstr
621{
622public:
623
624 /**
625 * Constructs a new string given the format string and the list of the
626 * arguments for the format string.
627 *
628 * @param aFormat printf-like format string (in UTF-8 encoding).
629 * @param ... List of the arguments for the format string.
630 */
631 explicit BstrFmt(const char *aFormat, ...)
632 {
633 va_list args;
634 va_start(args, aFormat);
635 copyFrom(Utf8StrFmtVA(aFormat, args).c_str());
636 va_end(args);
637 }
638};
639
640/**
641 * The BstrFmtVA class is a shortcut to <tt>Bstr(Utf8StrFmtVA(...))</tt>.
642 */
643class BstrFmtVA : public Bstr
644{
645public:
646
647 /**
648 * Constructs a new string given the format string and the list of the
649 * arguments for the format string.
650 *
651 * @param aFormat printf-like format string (in UTF-8 encoding).
652 * @param aArgs List of arguments for the format string
653 */
654 BstrFmtVA(const char *aFormat, va_list aArgs)
655 {
656 copyFrom(Utf8StrFmtVA(aFormat, aArgs).c_str());
657 }
658};
659
660} /* namespace com */
661
662#endif /* !___VBox_com_string_h */
663
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