Changeset 26550 in vbox for trunk/include/VBox/com
- Timestamp:
- Feb 15, 2010 5:14:18 PM (15 years ago)
- Location:
- trunk/include/VBox/com
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/Guid.h
r26177 r26550 97 97 { 98 98 ::RTUuidClear (&uuid); 99 if (!that.is Null())99 if (!that.isEmpty()) 100 100 ::RTUuidFromUtf16(&uuid, that.raw()); 101 101 refresh(); … … 145 145 } 146 146 147 Bstr toUtf16 147 Bstr toUtf16() const 148 148 { 149 149 if (isEmpty()) -
trunk/include/VBox/com/string.h
r26239 r26550 3 3 /** @file 4 4 * MS COM / XPCOM Abstraction Layer: 5 * Smart string classes declaration5 * UTF-8 and UTF-16 string classes 6 6 */ 7 7 … … 59 59 60 60 /** 61 * Helper class that represents the |BSTR| type and hides platform-specific 62 * implementation details. 63 * 64 * This class uses COM/XPCOM-provided memory management routines to allocate 65 * and free string buffers. This makes it possible to: 66 * - use it as a type of member variables of COM/XPCOM components and pass 67 * their values to callers through component methods' output parameters 68 * using the #cloneTo() operation; 69 * - adopt (take ownership of) string buffers returned in output parameters 70 * of COM methods using the #asOutParam() operation and correctly free them 71 * afterwards. 61 * String class used universally in Main for COM-style Utf-16 strings. 62 * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions 63 * back and forth since most of VirtualBox and our libraries use UTF-8. 64 * The Bstr class makes such conversions easier. 65 * 66 * Whereas the BSTR identifier is a typedef for a pointer to a wide character 67 * array (const char *uint_16 effectively, depending on the platform), 68 * the Bstr class is a fully featured string class with memory management 69 * for such strings. 70 * 71 * Bstr uses COM/XPCOM-provided memory management routines (SysAlloc* etc.) 72 * to allocate and free string buffers. This makes it possible to use it as 73 * a type of member variables of COM/XPCOM components and pass their values 74 * to callers through component methods' output parameters using the #cloneTo() 75 * operation. Also, the class can adopt (take ownership of) string buffers 76 * returned in output parameters of COM methods using the #asOutParam() 77 * operation and correctly free them afterwards. 78 * 79 * As opposed to the Ut8Str class, which is very efficient, Bstr does not 80 * cache the length of its member string. As a result, copying Bstr's is 81 * more expensive, and Bstr really should only be used to capture arguments 82 * from and return data to public COM methods. 83 * 84 * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates 85 * between NULL strings and empty strings. In other words, Bstr("") and 86 * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory, 87 * reports a zero length and zero allocated bytes for both, and returns an 88 * empty C wide string from raw(). 72 89 */ 73 90 class Bstr … … 75 92 public: 76 93 77 typedef BSTR String; 78 typedef CBSTR ConstString; 79 80 Bstr() : bstr(NULL) {} 81 82 Bstr(const Bstr &that) : bstr(NULL) { raw_copy(bstr, that.bstr); } 83 Bstr(CBSTR that) : bstr(NULL) { raw_copy(bstr, that); } 94 /** 95 * Creates an empty string that has no memory allocated. 96 */ 97 Bstr() 98 : m_bstr(NULL) 99 { 100 } 101 102 /** 103 * Creates a copy of another Bstr. 104 * 105 * This allocates s.length() + 1 wide characters for the new instance, unless s is empty. 106 * 107 * @param s The source string. 108 * 109 * @throws std::bad_alloc 110 */ 111 Bstr(const Bstr &s) 112 { 113 copyFrom(s); 114 } 115 116 /** 117 * Creates a copy of a wide char string buffer. 118 * 119 * This allocates SysStringLen(pw) + 1 wide characters for the new instance, unless s is empty. 120 * 121 * @param pcsz The source string. 122 * 123 * @throws std::bad_alloc 124 */ 125 Bstr(CBSTR pw) 126 { 127 copyFrom(pw); 128 } 84 129 85 130 #if defined (VBOX_WITH_XPCOM) 86 Bstr(const wchar_t * that) : bstr(NULL)131 Bstr(const wchar_t *pw) 87 132 { 88 133 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR)); 89 raw_copy(bstr, (CBSTR)that);134 copyFrom((CBSTR)pw); 90 135 } 91 136 #endif 92 137 93 Bstr(const iprt::MiniString &that); 94 Bstr(const char *that); 95 96 /** Shortcut that calls #alloc(aSize) right after object creation. */ 97 Bstr(size_t aSize) : bstr(NULL) { alloc(aSize); } 98 99 ~Bstr() { setNull(); } 100 101 Bstr &operator=(const Bstr &that) { safe_assign(that.bstr); return *this; } 102 Bstr &operator=(CBSTR that) { safe_assign(that); return *this; } 103 104 Bstr &operator=(const Utf8Str &that); 105 Bstr &operator=(const char *that); 106 107 Bstr &setNull() 108 { 109 if (bstr) 110 { 111 ::SysFreeString(bstr); 112 bstr = NULL; 113 } 114 return *this; 115 } 116 117 Bstr &setNullIfEmpty() 118 { 119 if (bstr && *bstr == 0) 120 { 121 ::SysFreeString(bstr); 122 bstr = NULL; 123 } 124 return *this; 125 } 126 127 /** 128 * Allocates memory for a string capable to store \a aSize - 1 characters; 129 * in other words, aSize includes the terminating zero character. If \a aSize 130 * is zero, or if a memory allocation error occurs, this object will become null. 131 */ 132 Bstr &alloc(size_t aSize) 133 { 134 setNull(); 135 if (aSize) 136 { 137 unsigned int size = (unsigned int) aSize; Assert(size == aSize); 138 bstr = ::SysAllocStringLen(NULL, size - 1); 139 if (bstr) 140 bstr[0] = 0; 141 } 142 return *this; 143 } 144 145 int compare(CBSTR str) const 146 { 147 return ::RTUtf16Cmp((PRTUTF16) bstr, (PRTUTF16) str); 148 } 149 150 int compare(BSTR str) const 151 { 152 return ::RTUtf16Cmp((PRTUTF16) bstr, (PRTUTF16) str); 153 } 154 155 bool operator==(const Bstr &that) const { return !compare(that.bstr); } 156 bool operator!=(const Bstr &that) const { return !!compare(that.bstr); } 138 139 /** 140 * Creates a copy of an IPRT MiniString (which includes Utf8Str). 141 * 142 * This allocates s.length() + 1 wide characters for the new instance, unless s is empty. 143 * 144 * @param pcsz The source string. 145 * 146 * @throws std::bad_alloc 147 */ 148 Bstr(const iprt::MiniString &s) 149 { 150 copyFrom(s.c_str()); // @todo the source string length is know, we can probably speed this up 151 } 152 153 /** 154 * Creates a copy of a C string. 155 * 156 * This allocates strlen(pcsz) + 1 bytes for the new instance, unless s is empty. 157 * 158 * @param pcsz The source string. 159 * 160 * @throws std::bad_alloc 161 */ 162 Bstr(const char *pcsz) 163 { 164 copyFrom(pcsz); 165 } 166 167 /** 168 * String length in wide characters. 169 * 170 * Returns the length of the member string, which is equal to SysStringLen(raw()). 171 * In other words, this returns neither bytes nor the number of unicode codepoints. 172 * 173 * As opposed to Utf8Str::length(), this is _not_ cached and expensive. 174 */ 175 size_t length() const 176 { 177 return ::SysStringLen(m_bstr); 178 } 179 180 /** 181 * Deallocates all memory. 182 */ 183 inline void setNull() 184 { 185 cleanup(); 186 } 187 188 /** 189 * Returns a const pointer to the member string. If the member string is empty, 190 * returns a pointer to a static null character. 191 * @return 192 */ 193 CBSTR raw() const 194 { 195 return (m_bstr) ? m_bstr : (CBSTR)L""; 196 } 197 198 /** 199 * Empty string or not? 200 * 201 * Returns true if the member string has no length. 202 * 203 * @returns true if empty, false if not. 204 */ 205 bool isEmpty() const 206 { 207 return (m_bstr == NULL); 208 } 209 210 /** Case sensitivity selector. */ 211 enum CaseSensitivity 212 { 213 CaseSensitive, 214 CaseInsensitive 215 }; 216 217 int compare(CBSTR str, CaseSensitivity cs = CaseSensitive) const 218 { 219 if (m_bstr == str) 220 return 0; 221 if (m_bstr == NULL) 222 return -1; 223 if (str == NULL) 224 return 1; 225 226 if (cs == CaseSensitive) 227 return ::RTUtf16Cmp((PRTUTF16)m_bstr, (PRTUTF16)str); 228 else 229 return ::RTUtf16ICmp((PRTUTF16)m_bstr, (PRTUTF16)str); 230 } 231 232 int compare(const Bstr &bstr, CaseSensitivity cs = CaseSensitive) const 233 { 234 return compare(bstr.raw(), cs); 235 } 236 237 /** @name Comparison operators. 238 * @{ */ 239 bool operator==(const Bstr &that) const { return !compare(that.raw()); } 240 bool operator!=(const Bstr &that) const { return !!compare(that.raw()); } 241 bool operator<( const Bstr &that) const { return compare(that.raw()) < 0; } 242 bool operator>( const Bstr &that) const { return compare(that.raw()) > 0; } 243 157 244 bool operator==(CBSTR that) const { return !compare(that); } 158 bool operator==(BSTR that) const { return !compare(that); }159 160 #if defined (VBOX_WITH_XPCOM)161 bool operator!=(const wchar_t *that) const162 {163 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR));164 return !!compare((CBSTR) that);165 }166 bool operator==(const wchar_t *that) const167 {168 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR));169 return !compare((CBSTR) that);170 }171 #endif172 173 245 bool operator!=(CBSTR that) const { return !!compare(that); } 174 bool operator!=(BSTR that) const { return !!compare(that); } 175 bool operator<(const Bstr &that) const { return compare(that.bstr) < 0; } 176 bool operator<(CBSTR that) const { return compare(that) < 0; } 177 bool operator<(BSTR that) const { return compare(that) < 0; } 178 #if defined (VBOX_WITH_XPCOM) 179 bool operator<(const wchar_t *that) const 180 { 181 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR)); 182 return compare((CBSTR) that) < 0; 183 } 184 #endif 185 186 int compareIgnoreCase(CBSTR str) const 187 { 188 return ::RTUtf16LocaleICmp(bstr, str); 189 } 190 191 bool isNull() const { return bstr == NULL; } 192 operator bool() const { return !isNull(); } 193 194 bool isEmpty() const { return isNull() || *bstr == 0; } 195 196 size_t length() const { return isNull() ? 0 : ::RTUtf16Len((PRTUTF16) bstr); } 246 bool operator<( CBSTR that) const { return compare(that) < 0; } 247 bool operator>( CBSTR that) const { return compare(that) > 0; } 248 249 /** @} */ 197 250 198 251 /** Intended to to pass instances as |CBSTR| input parameters to methods. */ 199 operator CBSTR() const { return bstr; }252 operator CBSTR() const { return raw(); } 200 253 201 254 /** … … 204 257 * input BSTR parameters of interface methods are not const. 205 258 */ 206 operator BSTR() { return bstr; } 207 208 /** 209 * The same as operator CBSTR(), but for situations where the compiler 210 * cannot typecast implicitly (for example, in printf() argument list). 211 */ 212 CBSTR raw() const { return bstr; } 213 214 /** 215 * Returns a non-const raw pointer that allows to modify the string directly. 216 * @warning 217 * Be sure not to modify data beyond the allocated memory! The 218 * guaranteed size of the allocated memory is at least #length() 219 * bytes after creation and after every assignment operation. 220 */ 221 BSTR mutableRaw() { return bstr; } 259 operator BSTR() { return (BSTR)raw(); } 222 260 223 261 /** … … 225 263 * within the interface method. Transfers the ownership of the duplicated 226 264 * string to the caller. 227 */ 228 const Bstr &cloneTo(BSTR *pstr) const 265 * 266 * This allocates a single 0 byte in the target if the member string is empty. 267 */ 268 const Bstr& cloneTo(BSTR *pstr) const 229 269 { 230 270 if (pstr) 231 { 232 *pstr = NULL; 233 raw_copy(*pstr, bstr); 234 } 271 *pstr = ::SysAllocString((const OLECHAR*)raw()); 272 // raw() never returns NULL, so we always allocate something here 235 273 return *this; 236 274 } … … 243 281 * As opposed to cloneTo(), this method doesn't create a copy of the 244 282 * string. 245 */ 246 Bstr &detachTo(BSTR *pstr) 247 { 248 *pstr = bstr; 249 bstr = NULL; 283 * 284 * This allocates a single 0 byte in the target if the member string is empty. 285 */ 286 Bstr& detachTo(BSTR *pstr) 287 { 288 *pstr = (m_bstr) ? m_bstr : ::SysAllocString((const OLECHAR*)""); 289 m_bstr = NULL; 250 290 return *this; 251 291 } 252 253 /**254 * Intended to assign copies of instances to |char *| out parameters from255 * within the interface method. Transfers the ownership of the duplicated256 * string to the caller.257 */258 const Bstr &cloneTo(char **pstr) const;259 292 260 293 /** … … 262 295 * Takes the ownership of the returned data. 263 296 */ 264 BSTR *asOutParam() { setNull(); return &bstr; } 297 BSTR* asOutParam() 298 { 299 cleanup(); 300 return &m_bstr; 301 } 265 302 266 303 /** … … 271 308 protected: 272 309 273 void safe_assign(CBSTR str) 274 { 275 if (bstr != str) 310 /** 311 * Destructor implementation, also used to clean up in operator=() before 312 * assigning a new string. 313 */ 314 void cleanup() 315 { 316 if (m_bstr) 276 317 { 277 setNull();278 raw_copy(bstr, str);318 ::SysFreeString(m_bstr); 319 m_bstr = NULL; 279 320 } 280 321 } 281 322 282 inline static void raw_copy(BSTR &ls, CBSTR rs) 283 { 284 if (rs) 285 ls = ::SysAllocString((const OLECHAR *) rs); 286 } 287 288 inline static void raw_copy(BSTR &ls, const char *rs) 289 { 290 if (rs) 323 /** 324 * Protected internal helper which allocates memory for a string capable of 325 * storing \a aSize - 1 characters (not bytes, not codepoints); in other words, 326 * aSize includes the terminating null character. 327 * 328 * Does NOT call cleanup() before allocating! 329 * 330 * @throws std::bad_alloc On allocation failure. The object is left describing 331 * a NULL string. 332 */ 333 void alloc(size_t cw) 334 { 335 if (cw) 291 336 { 337 m_bstr = ::SysAllocStringLen(NULL, (unsigned int)cw - 1); 338 #ifdef RT_EXCEPTIONS_ENABLED 339 if (!m_bstr) 340 throw std::bad_alloc(); 341 #endif 342 } 343 } 344 345 /** 346 * Protected internal helper to copy a string, ignoring the previous object state. 347 * 348 * copyFrom() unconditionally sets the members to a copy of the given other 349 * strings and makes no assumptions about previous contents. Can therefore be 350 * used both in copy constructors, when member variables have no defined value, 351 * and in assignments after having called cleanup(). 352 * 353 * This variant copies from another Bstr. Since Bstr does _not_ cache string lengths, 354 * this is not fast. 355 * 356 * @param s The source string. 357 * 358 * @throws std::bad_alloc On allocation failure. The object is left describing 359 * a NULL string. 360 */ 361 void copyFrom(const Bstr &s) 362 { 363 copyFrom(s.raw()); 364 } 365 366 /** 367 * Protected internal helper to copy a string, ignoring the previous object state. 368 * 369 * See copyFrom() above. 370 * 371 * This variant copies from a wide char C string. 372 * 373 * @param pcsz The source string. 374 * 375 * @throws std::bad_alloc On allocation failure. The object is left describing 376 * a NULL string. 377 */ 378 void copyFrom(CBSTR pw) 379 { 380 size_t cwLength; 381 if ( (pw) 382 && ((cwLength = ::SysStringLen((BSTR)pw))) 383 ) 384 { 385 size_t cwAllocated = cwLength + 1; 386 alloc(cwAllocated); 387 memcpy(m_bstr, pw, cwAllocated * sizeof(OLECHAR)); // include 0 terminator 388 } 389 else 390 m_bstr = NULL; 391 } 392 393 /** 394 * Protected internal helper to copy a string, ignoring the previous object state. 395 * 396 * See copyFrom() above. 397 * 398 * This variant converts from a Utf-8 C string. 399 * 400 * @param pcsz The source string. 401 * 402 * @throws std::bad_alloc On allocation failure. The object is left describing 403 * a NULL string. 404 */ 405 void copyFrom(const char *pcsz) 406 { 407 if (pcsz && *pcsz) 408 { 409 // @todo r=dj apparently this was copied twice in the original because our buffers 410 // use memory from SysAllocMem and IPRT doesn't, but check if this can be made faster 292 411 PRTUTF16 s = NULL; 293 ::RTStrToUtf16( rs, &s);294 raw_copy(ls, (BSTR)s);412 ::RTStrToUtf16(pcsz, &s); 413 copyFrom((BSTR)s); // @todo r=dj this is not exception safe 295 414 ::RTUtf16Free(s); 296 415 } 297 }298 299 BSTR bstr;300 301 friend class Utf8Str; /* to access our raw_copy()*/416 else 417 m_bstr = NULL; 418 } 419 420 BSTR m_bstr; /**< The string buffer. */ 302 421 }; 303 422 304 /* symmetric compare operators */305 inline bool operator==(CBSTR l, const Bstr &r) { return r.operator==(l); }306 inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!=(l); }307 inline bool operator==(BSTR l, const Bstr &r) { return r.operator==(l); }308 inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!=(l); }309 310 423 //////////////////////////////////////////////////////////////////////////////// 311 424 312 425 /** 313 * Helper class that represents UTF8 (|char *|) strings. Useful in 314 * conjunction with Bstr to simplify conversions between UTF16 (|BSTR|) 315 * and UTF8. 316 * 317 * This class uses COM/XPCOM-provided memory management routines to allocate 318 * and free string buffers. This makes it possible to: 319 * - use it as a type of member variables of COM/XPCOM components and pass 320 * their values to callers through component methods' output parameters 321 * using the #cloneTo() operation; 322 * - adopt (take ownership of) string buffers returned in output parameters 323 * of COM methods using the #asOutParam() operation and correctly free them 324 * afterwards. 426 * String class used universally in Main for Utf-8 strings. 427 * 428 * This is based on iprt::MiniString, to which some functionality has been 429 * moved. Here we keep things that are specific to Main, such as conversions 430 * with UTF-16 strings (Bstr). 431 * 432 * Like iprt::MiniString, Utf8Str does not differentiate between NULL strings 433 * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) 434 * behave the same. In both cases, MiniString allocates no memory, reports 435 * a zero length and zero allocated bytes for both, and returns an empty 436 * C string from c_str(). 325 437 */ 326 438 class Utf8Str : public iprt::MiniString … … 340 452 Utf8Str(const Bstr &that) 341 453 { 342 copyFrom(that );454 copyFrom(that.raw()); 343 455 } 344 456 … … 361 473 362 474 Utf8Str& operator=(const Bstr &that) 475 { 476 cleanup(); 477 copyFrom(that.raw()); 478 return *this; 479 } 480 481 Utf8Str& operator=(CBSTR that) 363 482 { 364 483 cleanup(); … … 367 486 } 368 487 369 Utf8Str& operator=(CBSTR that)370 {371 cleanup();372 copyFrom(that);373 return *this;374 }375 376 488 /** 377 489 * Intended to assign instances to |char *| out parameters from within the … … 379 491 * caller. 380 492 * 493 * This allocates a single 0 byte in the target if the member string is empty. 494 * 381 495 * @remarks The returned string must be freed by RTStrFree, not RTMemFree. 382 496 */ 383 497 const Utf8Str& cloneTo(char **pstr) const 384 498 { 385 if (pstr) /** @todo r=bird: This needs to if m_psz is NULL. Shouldn't it also throw std::bad_alloc? */ 386 *pstr = RTStrDup(m_psz); 387 return *this; 388 } 389 390 /** 391 * Intended to assign instances to |char *| out parameters from within the 392 * interface method. Transfers the ownership of the original string to the 393 * caller and resets the instance to null. 394 * 395 * As opposed to cloneTo(), this method doesn't create a copy of the 396 * string. 397 */ 398 Utf8Str& detachTo(char **pstr) 399 { 400 *pstr = m_psz; 401 m_psz = NULL; 402 m_cbAllocated = 0; 403 m_cbLength = 0; 499 if (pstr) 500 { 501 *pstr = RTStrDup(raw()); 502 #ifdef RT_EXCEPTIONS_ENABLED 503 if (!*pstr) 504 throw std::bad_alloc(); 505 #endif 506 } 404 507 return *this; 405 508 } … … 409 512 * interface method. Transfers the ownership of the duplicated string to the 410 513 * caller. 514 * 515 * This allocates a single 0 byte in the target if the member string is empty. 411 516 */ 412 517 const Utf8Str& cloneTo(BSTR *pstr) const … … 414 519 if (pstr) 415 520 { 521 Bstr bstr(c_str()); 416 522 *pstr = NULL; 417 Bstr::raw_copy(*pstr, m_psz);523 bstr.detachTo(pstr); 418 524 } 419 525 return *this; … … 507 613 if (s) 508 614 { 509 RTUtf16ToUtf8((PRTUTF16)s, &m_psz); /** @todo r=bird: This isn't throwing std::bad_alloc / handling return codes. 510 * Also, this technically requires using RTStrFree, ministring::cleanup() uses RTMemFree. */ 615 RTUtf16ToUtf8((PRTUTF16)s, &m_psz); /** @todo r=bird: This technically requires using RTStrFree, ministring::cleanup() uses RTMemFree. */ 616 #ifdef RT_EXCEPTIONS_ENABLED 617 if (!m_psz) 618 throw std::bad_alloc(); 619 #endif 511 620 m_cbLength = strlen(m_psz); /** @todo optimize by using a different RTUtf* function */ 512 621 m_cbAllocated = m_cbLength + 1; … … 525 634 // work around error C2593 of the stupid MSVC 7.x ambiguity resolver 526 635 WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP(Bstr) 527 528 ////////////////////////////////////////////////////////////////////////////////529 530 // inlined Bstr members that depend on Utf8Str531 532 inline Bstr::Bstr(const iprt::MiniString &that)533 : bstr(NULL)534 {535 raw_copy(bstr, that.c_str());536 }537 538 inline Bstr::Bstr(const char *that)539 : bstr(NULL)540 {541 raw_copy(bstr, that);542 }543 544 inline Bstr &Bstr::operator=(const Utf8Str &that)545 {546 setNull();547 raw_copy(bstr, that.c_str());548 return *this;549 }550 inline Bstr &Bstr::operator=(const char *that)551 {552 setNull();553 raw_copy(bstr, that);554 return *this;555 }556 557 inline const Bstr& Bstr::cloneTo(char **pstr) const558 {559 if (pstr)560 {561 Utf8Str ustr(*this);562 ustr.detachTo(pstr);563 }564 return *this;565 }566 636 567 637 //////////////////////////////////////////////////////////////////////////////// … … 654 724 va_list args; 655 725 va_start(args, aFormat); 656 raw_copy(bstr,Utf8StrFmtVA(aFormat, args).c_str());726 copyFrom(Utf8StrFmtVA(aFormat, args).c_str()); 657 727 va_end(args); 658 728 } … … 675 745 BstrFmtVA(const char *aFormat, va_list aArgs) 676 746 { 677 raw_copy(bstr,Utf8StrFmtVA(aFormat, aArgs).c_str());747 copyFrom(Utf8StrFmtVA(aFormat, aArgs).c_str()); 678 748 } 679 749 };
Note:
See TracChangeset
for help on using the changeset viewer.