VirtualBox

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

Last change on this file since 4337 was 4134, checked in by vboxsync, 17 years ago

Main: Add Utf8StrFmtVA to resolve the dangerous ambiguity of ellipsis and va_list.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 KB
Line 
1/** @file
2 * MS COM / XPCOM Abstraction Layer:
3 * Smart string classes declaration
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ___VBox_com_string_h
19#define ___VBox_com_string_h
20
21#if !defined(RT_OS_WINDOWS)
22#include <nsMemory.h>
23#endif
24
25#include "VBox/com/defs.h"
26#include "VBox/com/assert.h"
27
28#include <iprt/string.h>
29#include <iprt/alloc.h>
30
31namespace com
32{
33
34class Utf8Str;
35
36/**
37 * Helper class that represents the |BSTR| type and hides platform-specific
38 * implementation details.
39 *
40 * This class uses COM/XPCOM-provided memory management routines to allocate
41 * and free string buffers. This makes it possible to:
42 * - use it as a type of member variables of COM/XPCOM components and pass
43 * their values to callers through component methods' output parameters
44 * using the #cloneTo() operation;
45 * - adopt (take ownership of) string buffers returned in output parameters
46 * of COM methods using the #asOutParam() operation and correctly free them
47 * afterwards.
48 */
49class Bstr
50{
51public:
52
53 typedef BSTR String;
54 typedef const BSTR ConstString;
55
56 Bstr () : bstr (NULL) {}
57
58 Bstr (const Bstr &that) : bstr (NULL) { raw_copy (bstr, that.bstr); }
59 Bstr (const BSTR that) : bstr (NULL) { raw_copy (bstr, that); }
60 Bstr (const wchar_t *that) : bstr (NULL)
61 {
62 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
63 raw_copy (bstr, (const BSTR) that);
64 }
65
66 Bstr (const Utf8Str &that);
67 Bstr (const char *that);
68
69 /** Shortcut that calls #alloc(aSize) right after object creation. */
70 Bstr (size_t aSize) : bstr (NULL) { alloc (aSize); }
71
72 ~Bstr () { setNull(); }
73
74 Bstr &operator = (const Bstr &that) { safe_assign (that.bstr); return *this; }
75 Bstr &operator = (const BSTR that) { safe_assign (that); return *this; }
76
77 Bstr &operator = (const Utf8Str &that);
78 Bstr &operator = (const char *that);
79
80 Bstr &setNull()
81 {
82 if (bstr)
83 {
84 ::SysFreeString (bstr);
85 bstr = NULL;
86 }
87 return *this;
88 }
89
90 Bstr &setNullIfEmpty()
91 {
92 if (bstr && *bstr == 0)
93 {
94 ::SysFreeString (bstr);
95 bstr = NULL;
96 }
97 return *this;
98 }
99
100 /**
101 * Allocates memory for a string capable to store \a aSize - 1 characters
102 * plus the terminating zero character. If \a aSize is zero, or if a
103 * memory allocation error occurs, this object will become null.
104 */
105 Bstr &alloc (size_t aSize)
106 {
107 setNull();
108 if (aSize)
109 {
110 unsigned int size = (unsigned int) aSize; Assert (size == aSize);
111 bstr = ::SysAllocStringLen (NULL, size - 1);
112 if (bstr)
113 bstr [0] = 0;
114 }
115 return *this;
116 }
117
118 int compare (const BSTR str) const
119 {
120 return ::RTStrUcs2Cmp ((PRTUCS2) bstr, (PRTUCS2) str);
121 }
122
123 bool operator == (const Bstr &that) const { return !compare (that.bstr); }
124 bool operator != (const Bstr &that) const { return !!compare (that.bstr); }
125 bool operator == (const BSTR that) const { return !compare (that); }
126 bool operator != (const wchar_t *that) const
127 {
128 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
129 return !!compare ((const BSTR) that);
130 }
131 bool operator == (const wchar_t *that) const
132 {
133 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
134 return !compare ((const BSTR) that);
135 }
136 bool operator != (const BSTR that) const { return !!compare (that); }
137 bool operator < (const Bstr &that) const { return compare (that.bstr) < 0; }
138 bool operator < (const BSTR that) const { return compare (that) < 0; }
139 bool operator < (const wchar_t *that) const
140 {
141 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
142 return compare ((const BSTR) that) < 0;
143 }
144
145 int compareIgnoreCase (const BSTR str) const
146 {
147 return ::RTUtf16LocaleICmp (bstr, str);
148 }
149
150 bool isNull() const { return bstr == NULL; }
151 operator bool() const { return !isNull(); }
152
153 bool isEmpty() const { return isNull() || *bstr == 0; }
154
155 size_t length() const { return isNull() ? 0 : ::RTStrUcs2Len ((PRTUCS2) bstr); }
156
157 /** Intended to to pass instances as |BSTR| input parameters to methods. */
158 operator const BSTR () const { return bstr; }
159
160 /** The same as operator const BSTR(), but for situations where the compiler
161 cannot typecast implicitly (for example, in printf() argument list). */
162 const BSTR raw() const { return bstr; }
163
164 /**
165 * Returns a non-const raw pointer that allows to modify the string directly.
166 * @warning
167 * Be sure not to modify data beyond the allocated memory! The
168 * guaranteed size of the allocated memory is at least #length()
169 * bytes after creation and after every assignment operation.
170 */
171 BSTR mutableRaw() { return bstr; }
172
173 /**
174 * Intended to assign instances to |BSTR| out parameters from within the
175 * interface method. Transfers the ownership of the duplicated string to
176 * the caller.
177 */
178 const Bstr &cloneTo (BSTR *pstr) const
179 {
180 if (pstr)
181 {
182 *pstr = NULL;
183 raw_copy (*pstr, bstr);
184 }
185 return *this;
186 }
187
188 /**
189 * Intended to assign instances to |char *| out parameters from within the
190 * interface method. Transfers the ownership of the duplicated string to
191 * the caller.
192 */
193 const Bstr &cloneTo (char **pstr) const;
194
195 /**
196 * Intended to pass instances as |BSTR| out parameters to methods.
197 * Takes the ownership of the returned data.
198 */
199 BSTR *asOutParam() { setNull(); return &bstr; }
200
201private:
202
203 void safe_assign (const BSTR str)
204 {
205 if (bstr != str)
206 {
207 setNull();
208 raw_copy (bstr, str);
209 }
210 }
211
212 inline static void raw_copy (BSTR &ls, const BSTR rs)
213 {
214 if (rs)
215 ls = ::SysAllocString ((const OLECHAR *) rs);
216 }
217
218 inline static void raw_copy (BSTR &ls, const char *rs)
219 {
220 if (rs)
221 {
222 PRTUCS2 s = NULL;
223 ::RTStrUtf8ToUcs2 (&s, rs);
224 raw_copy (ls, (BSTR) s);
225 ::RTStrUcs2Free (s);
226 }
227 }
228
229 BSTR bstr;
230
231 friend class Utf8Str; // to access our raw_copy()
232};
233
234// symmetric compare operators
235inline bool operator== (const BSTR l, const Bstr &r) { return r.operator== (l); }
236inline bool operator!= (const BSTR l, const Bstr &r) { return r.operator!= (l); }
237
238////////////////////////////////////////////////////////////////////////////////
239
240/**
241 * Helper class that represents UTF8 (|char *|) strings. Useful in
242 * conjunction with Bstr to simplify conversions beetween UCS2 (|BSTR|)
243 * and UTF8.
244 *
245 * This class uses COM/XPCOM-provided memory management routines to allocate
246 * and free string buffers. This makes it possible to:
247 * - use it as a type of member variables of COM/XPCOM components and pass
248 * their values to callers through component methods' output parameters
249 * using the #cloneTo() operation;
250 * - adopt (take ownership of) string buffers returned in output parameters
251 * of COM methods using the #asOutParam() operation and correctly free them
252 * afterwards.
253 */
254class Utf8Str
255{
256public:
257
258 typedef char *String;
259 typedef const char *ConstString;
260
261 Utf8Str () : str (NULL) {}
262
263 Utf8Str (const Utf8Str &that) : str (NULL) { raw_copy (str, that.str); }
264 Utf8Str (const char *that) : str (NULL) { raw_copy (str, that); }
265
266 Utf8Str (const Bstr &that) : str (NULL) { raw_copy (str, that); }
267 Utf8Str (const BSTR that) : str (NULL) { raw_copy (str, that); }
268
269 /** Shortcut that calls #alloc(aSize) right after object creation. */
270 Utf8Str (size_t aSize) : str (NULL) { alloc(aSize); }
271
272 virtual ~Utf8Str () { setNull(); }
273
274 Utf8Str &operator = (const Utf8Str &that) { safe_assign (that.str); return *this; }
275 Utf8Str &operator = (const char *that) { safe_assign (that); return *this; }
276
277 Utf8Str &operator = (const Bstr &that)
278 {
279 setNull();
280 raw_copy (str, that);
281 return *this;
282 }
283 Utf8Str &operator = (const BSTR that)
284 {
285 setNull();
286 raw_copy (str, that);
287 return *this;
288 }
289
290 Utf8Str &setNull()
291 {
292 if (str)
293 {
294#if defined (RT_OS_WINDOWS)
295 ::RTStrFree (str);
296#else
297 nsMemory::Free (str);
298#endif
299 str = NULL;
300 }
301 return *this;
302 }
303
304 Utf8Str &setNullIfEmpty()
305 {
306 if (str && *str == 0)
307 {
308#if defined (RT_OS_WINDOWS)
309 ::RTStrFree (str);
310#else
311 nsMemory::Free (str);
312#endif
313 str = NULL;
314 }
315 return *this;
316 }
317
318 /**
319 * Allocates memory for a string capable to store \a aSize - 1 characters
320 * plus the terminating zero character. If \a aSize is zero, or if a
321 * memory allocation error occurs, this object will become null.
322 */
323 Utf8Str &alloc (size_t aSize)
324 {
325 setNull();
326 if (aSize)
327 {
328#if defined (RT_OS_WINDOWS)
329 str = (char *) ::RTMemTmpAlloc (aSize);
330#else
331 str = (char *) nsMemory::Alloc (aSize);
332#endif
333 if (str)
334 str [0] = 0;
335 }
336 return *this;
337 }
338
339 int compare (const char *s) const
340 {
341 return str == s ? 0 : ::strcmp (str, s);
342 }
343
344 bool operator == (const Utf8Str &that) const { return !compare (that.str); }
345 bool operator != (const Utf8Str &that) const { return !!compare (that.str); }
346 bool operator == (const char *that) const { return !compare (that); }
347 bool operator != (const char *that) const { return !!compare (that); }
348 bool operator < (const Utf8Str &that) const { return compare (that.str) < 0; }
349 bool operator < (const char *that) const { return compare (that) < 0; }
350
351 bool isNull() const { return str == NULL; }
352 operator bool() const { return !isNull(); }
353
354 bool isEmpty() const { return isNull() || *str == 0; }
355
356 size_t length() const { return isNull() ? 0 : ::strlen (str); }
357
358 /** Intended to to pass instances as input (|char *|) parameters to methods. */
359 operator const char *() const { return str; }
360
361 /** The same as operator const char *(), but for situations where the compiler
362 cannot typecast implicitly (for example, in printf() argument list). */
363 const char *raw() const { return str; }
364
365 /**
366 * Returns a non-const raw pointer that allows to modify the string directly.
367 * @warning
368 * Be sure not to modify data beyond the allocated memory! The
369 * guaranteed size of the allocated memory is at least #length()
370 * bytes after creation and after every assignment operation.
371 */
372 char *mutableRaw() { return str; }
373
374 /**
375 * Intended to assign instances to |char *| out parameters from within the
376 * interface method. Transfers the ownership of the duplicated string to the
377 * caller.
378 */
379 const Utf8Str &cloneTo (char **pstr) const
380 {
381 if (pstr)
382 {
383 *pstr = NULL;
384 raw_copy (*pstr, str);
385 }
386 return *this;
387 }
388
389 /**
390 * Intended to assign instances to |BSTR| out parameters from within the
391 * interface method. Transfers the ownership of the duplicated string to the
392 * caller.
393 */
394 const Utf8Str &cloneTo (BSTR *pstr) const
395 {
396 if (pstr)
397 {
398 *pstr = NULL;
399 Bstr::raw_copy (*pstr, str);
400 }
401 return *this;
402 }
403
404 /**
405 * Intended to pass instances as out (|char **|) parameters to methods.
406 * Takes the ownership of the returned data.
407 */
408 char **asOutParam() { setNull(); return &str; }
409
410private:
411
412 void safe_assign (const char *s)
413 {
414 if (str != s)
415 {
416 setNull();
417 raw_copy (str, s);
418 }
419 }
420
421 inline static void raw_copy (char *&ls, const char *rs)
422 {
423 if (rs)
424#if defined (RT_OS_WINDOWS)
425 ::RTStrDupEx (&ls, rs);
426#else
427 ls = (char *) nsMemory::Clone (rs, strlen (rs) + 1);
428#endif
429 }
430
431 inline static void raw_copy (char *&ls, const BSTR rs)
432 {
433 if (rs)
434 {
435#if defined (RT_OS_WINDOWS)
436 ::RTStrUcs2ToUtf8 (&ls, (PRTUCS2) rs);
437#else
438 char *s = NULL;
439 ::RTStrUcs2ToUtf8 (&s, (PRTUCS2) rs);
440 raw_copy (ls, s);
441 ::RTStrFree (s);
442#endif
443 }
444 }
445
446 char *str;
447
448 friend class Bstr; // to access our raw_copy()
449};
450
451// symmetric compare operators
452inline bool operator== (const char *l, const Utf8Str &r) { return r.operator== (l); }
453inline bool operator!= (const char *l, const Utf8Str &r) { return r.operator!= (l); }
454
455// work around error C2593 of the stupid MSVC 7.x ambiguity resolver
456WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP (Bstr)
457WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP (Utf8Str)
458
459////////////////////////////////////////////////////////////////////////////////
460
461// inlined Bstr members that depend on Utf8Str
462
463inline Bstr::Bstr (const Utf8Str &that) : bstr (NULL) { raw_copy (bstr, that); }
464inline Bstr::Bstr (const char *that) : bstr (NULL) { raw_copy (bstr, that); }
465
466inline Bstr &Bstr::operator = (const Utf8Str &that)
467{
468 setNull();
469 raw_copy (bstr, that);
470 return *this;
471}
472inline Bstr &Bstr::operator = (const char *that)
473{
474 setNull();
475 raw_copy (bstr, that);
476 return *this;
477}
478
479inline const Bstr &Bstr::cloneTo (char **pstr) const
480{
481 if (pstr) {
482 *pstr = NULL;
483 Utf8Str::raw_copy (*pstr, bstr);
484 }
485 return *this;
486}
487
488////////////////////////////////////////////////////////////////////////////////
489
490/**
491 * This class is a printf-like formatter for Utf8Str strings. Its purpose is
492 * to construct Utf8Str objects from a format string and a list of arguments
493 * for the format string.
494 *
495 * The usage of this class is like the following:
496 * <code>
497 * Utf8StrFmt string ("program name = %s", argv[0]);
498 * </code>
499 */
500class Utf8StrFmt : public Utf8Str
501{
502public:
503
504 /**
505 * Constructs a new string given the format string and the list
506 * of the arguments for the format string.
507 *
508 * @param format printf-like format string (in UTF-8 encoding)
509 * @param ... list of the arguments for the format string
510 */
511 explicit Utf8StrFmt (const char *format, ...)
512 {
513 va_list args;
514 va_start (args, format);
515 init (format, args);
516 va_end (args);
517 }
518
519protected:
520
521 Utf8StrFmt() {}
522
523 void init (const char *format, va_list args);
524
525private:
526
527 static DECLCALLBACK(size_t) strOutput (void *pvArg, const char *pachChars,
528 size_t cbChars);
529};
530
531/**
532 * This class is a vprintf-like formatter for Utf8Str strings. It is
533 * identical to Utf8StrFmt except that its constructor takes a va_list
534 * argument instead of ellipsis.
535 *
536 * Note that a separate class is necessary because va_list is defined as
537 * |char *| on most platforms. For this reason, if we had two overloaded
538 * constructors in Utf8StrFmt (one taking ellipsis and another one taking
539 * va_list) then composing a constructor call using exactly two |char *|
540 * arguments would cause the compiler to use the va_list overload instead of
541 * the ellipsis one which is obviously wrong. The compiler would choose
542 * va_list because ellipsis has the lowest rank when it comes to resolving
543 * overloads, as opposed to va_list which is an exact match for |char *|.
544 */
545class Utf8StrFmtVA : public Utf8StrFmt
546{
547public:
548
549 /**
550 * Constructs a new string given the format string and the list
551 * of the arguments for the format string.
552 *
553 * @param format printf-like format string (in UTF-8 encoding)
554 * @param args list of arguments for the format string
555 */
556 Utf8StrFmtVA (const char *format, va_list args) { init (format, args); }
557};
558
559} // namespace com
560
561#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