Changeset 26553 in vbox for trunk/include/VBox
- Timestamp:
- Feb 15, 2010 5:34:29 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 57732
- Location:
- trunk/include/VBox/com
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/Guid.h
r26550 r26553 97 97 { 98 98 ::RTUuidClear (&uuid); 99 if (!that.is Empty())99 if (!that.isNull()) 100 100 ::RTUuidFromUtf16(&uuid, that.raw()); 101 101 refresh(); … … 145 145 } 146 146 147 Bstr toUtf16 () const147 Bstr toUtf16 () const 148 148 { 149 149 if (isEmpty()) -
trunk/include/VBox/com/string.h
r26552 r26553 3 3 /** @file 4 4 * MS COM / XPCOM Abstraction Layer: 5 * UTF-8 and UTF-16 string classes5 * Smart string classes declaration 6 6 */ 7 7 … … 59 59 60 60 /** 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(). 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. 89 72 */ 90 73 class Bstr … … 92 75 public: 93 76 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 } 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); } 129 84 130 85 #if defined (VBOX_WITH_XPCOM) 131 Bstr(const wchar_t * pw)86 Bstr(const wchar_t *that) : bstr(NULL) 132 87 { 133 88 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR)); 134 copyFrom((CBSTR)pw);89 raw_copy(bstr, (CBSTR)that); 135 90 } 136 91 #endif 137 92 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 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); } 244 157 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) const 162 { 163 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR)); 164 return !!compare((CBSTR) that); 165 } 166 bool operator==(const wchar_t *that) const 167 { 168 AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR)); 169 return !compare((CBSTR) that); 170 } 171 #endif 172 245 173 bool operator!=(CBSTR that) const { return !!compare(that); } 246 bool operator<( CBSTR that) const { return compare(that) < 0; } 247 bool operator>( CBSTR that) const { return compare(that) > 0; } 248 249 /** @} */ 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); } 250 197 251 198 /** Intended to to pass instances as |CBSTR| input parameters to methods. */ 252 operator CBSTR() const { return raw(); }199 operator CBSTR() const { return bstr; } 253 200 254 201 /** … … 257 204 * input BSTR parameters of interface methods are not const. 258 205 */ 259 operator BSTR() { return (BSTR)raw(); } 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; } 260 222 261 223 /** … … 263 225 * within the interface method. Transfers the ownership of the duplicated 264 226 * string to the caller. 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 227 */ 228 const Bstr &cloneTo(BSTR *pstr) const 269 229 { 270 230 if (pstr) 271 *pstr = ::SysAllocString((const OLECHAR*)raw()); 272 // raw() never returns NULL, so we always allocate something here 231 { 232 *pstr = NULL; 233 raw_copy(*pstr, bstr); 234 } 273 235 return *this; 274 236 } … … 281 243 * As opposed to cloneTo(), this method doesn't create a copy of the 282 244 * string. 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; 290 return *this; 291 } 245 */ 246 Bstr &detachTo(BSTR *pstr) 247 { 248 *pstr = bstr; 249 bstr = NULL; 250 return *this; 251 } 252 253 /** 254 * Intended to assign copies of instances to |char *| out parameters from 255 * within the interface method. Transfers the ownership of the duplicated 256 * string to the caller. 257 */ 258 const Bstr &cloneTo(char **pstr) const; 292 259 293 260 /** … … 295 262 * Takes the ownership of the returned data. 296 263 */ 297 BSTR* asOutParam() 298 { 299 cleanup(); 300 return &m_bstr; 301 } 264 BSTR *asOutParam() { setNull(); return &bstr; } 302 265 303 266 /** … … 308 271 protected: 309 272 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) 317 { 318 ::SysFreeString(m_bstr); 319 m_bstr = NULL; 320 } 321 } 322 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) 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 273 void safe_assign(CBSTR str) 274 { 275 if (bstr != str) 276 { 277 setNull(); 278 raw_copy(bstr, str); 279 } 280 } 281 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) 291 { 411 292 PRTUTF16 s = NULL; 412 ::RTStrToUtf16( pcsz, &s);413 copyFrom((BSTR)s); // @todo r=dj this is not exception safe293 ::RTStrToUtf16(rs, &s); 294 raw_copy(ls, (BSTR)s); 414 295 ::RTUtf16Free(s); 415 296 } 416 else417 m_bstr = NULL; 418 }419 420 BSTR m_bstr; /**< The string buffer.*/297 } 298 299 BSTR bstr; 300 301 friend class Utf8Str; /* to access our raw_copy() */ 421 302 }; 422 303 … … 430 311 431 312 /** 432 * String class used universally in Main for Utf-8 strings. 433 * 434 * This is based on iprt::MiniString, to which some functionality has been 435 * moved. Here we keep things that are specific to Main, such as conversions 436 * with UTF-16 strings (Bstr). 437 * 438 * Like iprt::MiniString, Utf8Str does not differentiate between NULL strings 439 * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) 440 * behave the same. In both cases, MiniString allocates no memory, reports 441 * a zero length and zero allocated bytes for both, and returns an empty 442 * C string from c_str(). 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. 443 325 */ 444 326 class Utf8Str : public iprt::MiniString … … 458 340 Utf8Str(const Bstr &that) 459 341 { 460 copyFrom(that .raw());342 copyFrom(that); 461 343 } 462 344 … … 481 363 { 482 364 cleanup(); 483 copyFrom(that .raw());365 copyFrom(that); 484 366 return *this; 485 367 } … … 497 379 * caller. 498 380 * 499 * This allocates a single 0 byte in the target if the member string is empty.500 *501 381 * @remarks The returned string must be freed by RTStrFree, not RTMemFree. 502 382 */ 503 383 const Utf8Str& cloneTo(char **pstr) const 504 384 { 505 if (pstr) 506 { 507 *pstr = RTStrDup(raw()); 508 #ifdef RT_EXCEPTIONS_ENABLED 509 if (!*pstr) 510 throw std::bad_alloc(); 511 #endif 512 } 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; 513 404 return *this; 514 405 } … … 518 409 * interface method. Transfers the ownership of the duplicated string to the 519 410 * caller. 520 *521 * This allocates a single 0 byte in the target if the member string is empty.522 411 */ 523 412 const Utf8Str& cloneTo(BSTR *pstr) const … … 525 414 if (pstr) 526 415 { 527 Bstr bstr(c_str());528 416 *pstr = NULL; 529 bstr.detachTo(pstr);417 Bstr::raw_copy(*pstr, m_psz); 530 418 } 531 419 return *this; … … 619 507 if (s) 620 508 { 621 RTUtf16ToUtf8((PRTUTF16)s, &m_psz); /** @todo r=bird: This technically requires using RTStrFree, ministring::cleanup() uses RTMemFree. */ 622 #ifdef RT_EXCEPTIONS_ENABLED 623 if (!m_psz) 624 throw std::bad_alloc(); 625 #endif 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. */ 626 511 m_cbLength = strlen(m_psz); /** @todo optimize by using a different RTUtf* function */ 627 512 m_cbAllocated = m_cbLength + 1; … … 640 525 // work around error C2593 of the stupid MSVC 7.x ambiguity resolver 641 526 WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP(Bstr) 527 528 //////////////////////////////////////////////////////////////////////////////// 529 530 // inlined Bstr members that depend on Utf8Str 531 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) const 558 { 559 if (pstr) 560 { 561 Utf8Str ustr(*this); 562 ustr.detachTo(pstr); 563 } 564 return *this; 565 } 642 566 643 567 //////////////////////////////////////////////////////////////////////////////// … … 730 654 va_list args; 731 655 va_start(args, aFormat); 732 copyFrom(Utf8StrFmtVA(aFormat, args).c_str());656 raw_copy(bstr, Utf8StrFmtVA(aFormat, args).c_str()); 733 657 va_end(args); 734 658 } … … 751 675 BstrFmtVA(const char *aFormat, va_list aArgs) 752 676 { 753 copyFrom(Utf8StrFmtVA(aFormat, aArgs).c_str());677 raw_copy(bstr, Utf8StrFmtVA(aFormat, aArgs).c_str()); 754 678 } 755 679 };
Note:
See TracChangeset
for help on using the changeset viewer.