Changeset 21073 in vbox
- Timestamp:
- Jun 30, 2009 3:01:09 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Config.kmk
r21067 r21073 490 490 ## Use the new version of liblzf. Remove with the old liblzf. 491 491 #VBOX_WITH_NEW_LIBLZF = 1 492 ## For experimenting with linking libxml2 into VBoxRT.493 VBOX_WITH_LIBXML2_IN_VBOXRT = 1494 492 495 493 ## For experimenting with disabling preemption instead of interrupts … … 1799 1797 # 1800 1798 SDK_VBOX_LIBXML2 = . 1801 #if1of ($(KBUILD_TARGET),win os2 solaris) 1802 SDK_VBOX_LIBXML2_INCS ?= $(PATH_ROOT)/src/libs/libxml2-2.6.30/include 1803 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 1804 SDK_VBOX_LIBXML2_DEFS ?= _REENTRANT 1805 else 1806 SDK_VBOX_LIBXML2_DEFS ?= LIBXML_STATIC _REENTRANT 1807 SDK_VBOX_LIBXML2_LIBS ?= $(PATH_LIB)/VBox-libxml2$(VBOX_SUFF_LIB) 1808 endif 1809 SDK_VBOX_LIBXML2_DEFS.win += WIN32 _WINDOWS _MBCS 1810 #else if1of ($(KBUILD_TARGET),linux) 1811 # SDK_VBOX_LIBXML2_INCS ?= 1812 # SDK_VBOX_LIBXML2_LIBS ?= 1813 # SDK_VBOX_LIBXML2_CFLAGS ?= $(shell pkg-config libxml-2.0 --cflags) 1814 # SDK_VBOX_LIBXML2_CXXFLAGS ?= $(SDK_VBOX_LIBXML2_CFLAGS) 1815 # SDK_VBOX_LIBXML2_LDFLAGS ?= $(shell pkg-config libxml-2.0 --libs) 1816 #else 1817 # SDK_VBOX_LIBXML2_INCS ?= 1818 # SDK_VBOX_LIBXML2_LIBS ?= xml2 1819 #endif 1799 SDK_VBOX_LIBXML2_INCS ?= $(PATH_ROOT)/src/libs/libxml2-2.6.30/include 1800 SDK_VBOX_LIBXML2_DEFS ?= _REENTRANT 1801 SDK_VBOX_LIBXML2_DEFS.win += WIN32 _WINDOWS _MBCS 1802 # note: no linking to LIB here, we do that explicitly in src/VBox/Runtime/Makefile.kmk to link 1803 # libxml against VBoxRT 1820 1804 1821 1805 SDK_VBOX_LIBXSLT = . … … 1853 1837 SDK_VBOX_OPENSSL_INCS ?= $(SDK_VBOX_OPENSSL_VBOX_DEFAULT_INCS) 1854 1838 SDK_VBOX_OPENSSL_ORDERDEPS ?= $(crypto-headers_1_TARGET) 1855 ifndef VBOX_WITH_LIBXML2_IN_VBOXRT 1856 SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB) 1857 endif 1839 SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB) 1858 1840 # Build entire openssl library, not just the minimal subset. 1859 1841 if1of ($(KBUILD_TARGET), linux solaris) -
trunk/include/VBox/com/string.h
r18589 r21073 49 49 #include "VBox/com/assert.h" 50 50 51 #include <iprt/string.h>52 51 #include <iprt/cpputils.h> 53 52 #include <iprt/alloc.h> 53 #include <iprt/ministring_cpp.h> 54 54 55 55 namespace com … … 153 153 } 154 154 155 bool operator ==(const Bstr &that) const { return !compare (that.bstr); }156 bool operator !=(const Bstr &that) const { return !!compare (that.bstr); }157 bool operator ==(CBSTR that) const { return !compare (that); }158 bool operator ==(BSTR that) const { return !compare (that); }155 bool operator==(const Bstr &that) const { return !compare (that.bstr); } 156 bool operator!=(const Bstr &that) const { return !!compare (that.bstr); } 157 bool operator==(CBSTR that) const { return !compare (that); } 158 bool operator==(BSTR that) const { return !compare (that); } 159 159 160 160 #if defined (VBOX_WITH_XPCOM) 161 bool operator !=(const wchar_t *that) const161 bool operator!=(const wchar_t *that) const 162 162 { 163 163 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR)); 164 164 return !!compare ((CBSTR) that); 165 165 } 166 bool operator ==(const wchar_t *that) const166 bool operator==(const wchar_t *that) const 167 167 { 168 168 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR)); … … 171 171 #endif 172 172 173 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; }173 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 178 #if defined (VBOX_WITH_XPCOM) 179 bool operator <(const wchar_t *that) const179 bool operator<(const wchar_t *that) const 180 180 { 181 181 AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR)); … … 303 303 304 304 /* symmetric compare operators */ 305 inline bool operator== 306 inline bool operator!= 307 inline bool operator== 308 inline bool operator!= 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 309 310 310 //////////////////////////////////////////////////////////////////////////////// … … 324 324 * afterwards. 325 325 */ 326 class Utf8Str 326 class Utf8Str : public ministring 327 327 { 328 328 public: 329 329 330 enum CaseSensitivity 331 { 332 CaseSensitive, 333 CaseInsensitive 334 }; 335 336 typedef char *String; 337 typedef const char *ConstString; 338 339 Utf8Str () : str (NULL) {} 340 341 Utf8Str (const Utf8Str &that) : str (NULL) { raw_copy (str, that.str); } 342 Utf8Str (const char *that) : str (NULL) { raw_copy (str, that); } 343 344 Utf8Str (const Bstr &that) : str (NULL) { raw_copy (str, that); } 345 Utf8Str (CBSTR that) : str (NULL) { raw_copy (str, that); } 346 347 /** Shortcut that calls #alloc(aSize) right after object creation. */ 348 Utf8Str (size_t aSize) : str (NULL) { alloc(aSize); } 349 350 virtual ~Utf8Str () { setNull(); } 351 352 Utf8Str &operator = (const Utf8Str &that) { safe_assign (that.str); return *this; } 353 Utf8Str &operator = (const char *that) { safe_assign (that); return *this; } 354 355 Utf8Str &operator = (const Bstr &that) 356 { 357 setNull(); 358 raw_copy (str, that); 359 return *this; 360 } 361 Utf8Str &operator = (CBSTR that) 362 { 363 setNull(); 364 raw_copy (str, that); 365 return *this; 366 } 367 368 Utf8Str &setNull() 369 { 370 if (str) 371 { 372 #if !defined (VBOX_WITH_XPCOM) 373 ::RTStrFree (str); 374 #else 375 nsMemory::Free (str); 376 #endif 377 str = NULL; 378 } 379 return *this; 380 } 381 382 Utf8Str &setNullIfEmpty() 383 { 384 if (str && *str == 0) 385 { 386 #if !defined (VBOX_WITH_XPCOM) 387 ::RTStrFree (str); 388 #else 389 nsMemory::Free (str); 390 #endif 391 str = NULL; 392 } 393 return *this; 394 } 395 396 /** 397 * Allocates memory for a string capable to store \a aSize - 1 bytes (not characters!); 398 * in other words, aSize includes the terminating zero character. If \a aSize 399 * is zero, or if a memory allocation error occurs, this object will become null. 400 */ 401 Utf8Str &alloc (size_t aSize) 402 { 403 setNull(); 404 if (aSize) 405 { 406 #if !defined (VBOX_WITH_XPCOM) 407 str = (char *) ::RTMemTmpAlloc (aSize); 408 #else 409 str = (char *) nsMemory::Alloc (aSize); 410 #endif 411 if (str) 412 str [0] = 0; 413 } 414 return *this; 415 } 416 417 void append(const Utf8Str &that) 418 { 419 size_t cbThis = length(); 420 size_t cbThat = that.length(); 421 422 if (cbThat) 423 { 424 size_t cbBoth = cbThis + cbThat + 1; 425 426 // @todo optimize with realloc() once the memory management is fixed 427 char *pszTemp; 428 #if !defined (VBOX_WITH_XPCOM) 429 pszTemp = (char*)::RTMemTmpAlloc(cbBoth); 430 #else 431 pszTemp = (char*)nsMemory::Alloc(cbBoth); 432 #endif 433 if (str) 434 { 435 memcpy(pszTemp, str, cbThis); 436 setNull(); 437 } 438 if (that.str) 439 memcpy(pszTemp + cbThis, that.str, cbThat); 440 pszTemp[cbThis + cbThat] = '\0'; 441 442 str = pszTemp; 443 } 444 } 445 446 int compare (const char *pcsz, CaseSensitivity cs = CaseSensitive) const 447 { 448 if (str == pcsz) 449 return 0; 450 if (str == NULL) 451 return -1; 452 if (pcsz == NULL) 453 return 1; 454 455 if (cs == CaseSensitive) 456 return ::RTStrCmp(str, pcsz); 457 else 458 return ::RTStrICmp(str, pcsz); 459 } 460 461 int compare (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const 462 { 463 return compare (that.str, cs); 464 } 465 466 bool operator == (const Utf8Str &that) const { return !compare (that); } 467 bool operator != (const Utf8Str &that) const { return !!compare (that); } 468 bool operator == (const char *that) const { return !compare (that); } 469 bool operator != (const char *that) const { return !!compare (that); } 470 bool operator < (const Utf8Str &that) const { return compare (that) < 0; } 471 bool operator < (const char *that) const { return compare (that) < 0; } 472 473 bool endsWith (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const 474 { 475 if (isNull() || that.isNull()) 476 return false; 477 478 size_t l1 = length(); 479 size_t l2 = that.length(); 480 if (l1 < l2) 481 return false; 482 483 size_t l = l1 - l2; 484 if (cs == CaseSensitive) 485 return ::RTStrCmp(&str[l], that.str) == 0; 486 else 487 return ::RTStrICmp(&str[l], that.str) == 0; 488 } 489 490 bool startsWith (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const 491 { 492 if (isNull() || that.isNull()) 493 return false; 494 495 size_t l1 = length(); 496 size_t l2 = that.length(); 497 if (l1 < l2) 498 return false; 499 500 if (cs == CaseSensitive) 501 return ::RTStrNCmp(str, that.str, l2) == 0; 502 else 503 return ::RTStrNICmp(str, that.str, l2) == 0; 504 } 505 506 bool contains (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const 507 { 508 if (cs == CaseSensitive) 509 return ::RTStrStr (str, that.str) != NULL; 510 else 511 return ::RTStrIStr (str, that.str) != NULL; 512 } 513 514 Utf8Str& toLower() 515 { 516 if (isEmpty()) 517 return *this; 518 519 ::RTStrToLower(str); 520 521 return *this; 522 } 523 524 Utf8Str& toUpper() 525 { 526 if (isEmpty()) 527 return *this; 528 529 ::RTStrToUpper(str); 530 531 return *this; 532 } 533 534 bool isNull() const { return str == NULL; } 535 operator bool() const { return !isNull(); } 536 537 bool isEmpty() const { return isNull() || *str == 0; } 538 539 size_t length() const { return isNull() ? 0 : ::strlen (str); } 540 541 /** Intended to to pass instances as input (|char *|) parameters to methods. */ 542 operator const char *() const { return str; } 543 544 /** The same as operator const char *(), but for situations where the compiler 545 cannot typecast implicitly (for example, in printf() argument list). */ 546 const char *raw() const { return str; } 547 548 /** The same as operator const char *(), but for situations where the compiler 549 cannot typecast implicitly (for example, in printf() argument list). */ 550 const char *c_str() const { return str; } 551 552 /** 553 * Returns a non-const raw pointer that allows to modify the string directly. 554 * @warning 555 * Be sure not to modify data beyond the allocated memory! The 556 * guaranteed size of the allocated memory is at least #length() 557 * bytes after creation and after every assignment operation. 558 */ 559 char *mutableRaw() { return str; } 330 Utf8Str() {} 331 332 Utf8Str(const Utf8Str &that) 333 : ministring(that) 334 {} 335 336 Utf8Str(const char *that) 337 : ministring(that) 338 {} 339 340 Utf8Str(const Bstr &that) 341 { 342 copyFrom(that); 343 } 344 345 Utf8Str(CBSTR that) 346 { 347 copyFrom(that); 348 } 349 350 Utf8Str& operator=(const Utf8Str &that) 351 { 352 ministring::operator=(that); 353 return *this; 354 } 355 356 Utf8Str& operator=(const char *that) 357 { 358 ministring::operator=(that); 359 return *this; 360 } 361 362 Utf8Str& operator=(const Bstr &that) 363 { 364 cleanup(); 365 copyFrom(that); 366 return *this; 367 } 368 369 Utf8Str& operator=(CBSTR that) 370 { 371 cleanup(); 372 copyFrom(that); 373 return *this; 374 } 560 375 561 376 /** … … 564 379 * caller. 565 380 */ 566 const Utf8Str &cloneTo(char **pstr) const381 const Utf8Str& cloneTo(char **pstr) const 567 382 { 568 383 if (pstr) 569 { 570 *pstr = NULL; 571 raw_copy (*pstr, str); 572 } 384 *pstr = RTStrDup(m_psz); 573 385 return *this; 574 386 } … … 582 394 * string. 583 395 */ 584 Utf8Str &detachTo (char **pstr) 585 { 586 *pstr = str; 587 str = NULL; 396 Utf8Str& detachTo(char **pstr) 397 { 398 *pstr = m_psz; 399 m_psz = NULL; 400 m_cbAllocated = 0; 401 m_cbLength = 0; 588 402 return *this; 589 403 } … … 594 408 * caller. 595 409 */ 596 const Utf8Str &cloneTo(BSTR *pstr) const410 const Utf8Str& cloneTo(BSTR *pstr) const 597 411 { 598 412 if (pstr) 599 413 { 600 414 *pstr = NULL; 601 Bstr::raw_copy (*pstr, str);415 Bstr::raw_copy(*pstr, m_psz); 602 416 } 603 417 return *this; … … 623 437 624 438 /** 625 * Attempts to convert the member string into an 32-bit integer. 439 * Returns true if "this" ends with "that". 440 * @param that 441 * @param cs 442 * @return 443 */ 444 bool endsWith(const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const; 445 446 /** 447 * Returns true if "this" begins with "that". 448 * @return 449 */ 450 bool startsWith(const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const; 451 452 /** 453 * Returns true if "this" contains "that" (strstr). 454 * @param that 455 * @param cs 456 * @return 457 */ 458 bool contains(const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const; 459 460 /** 461 * Converts "this" to lower case by calling RTStrToLower(). 462 * @return 463 */ 464 Utf8Str& toLower(); 465 466 /** 467 * Converts "this" to upper case by calling RTStrToUpper(). 468 * @return 469 */ 470 Utf8Str& toUpper(); 471 472 /** 473 * Removes a trailing slash from the member string, if present. 474 * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw(). 475 */ 476 void stripTrailingSlash(); 477 478 /** 479 * Removes a trailing filename from the member string, if present. 480 * Calls RTPathStripFilename() without having to mess with mutableRaw(). 481 */ 482 void stripFilename(); 483 484 /** 485 * Removes a trailing file name extension from the member string, if present. 486 * Calls RTPathStripExt() without having to mess with mutableRaw(). 487 */ 488 void stripExt(); 489 490 /** 491 * Attempts to convert the member string into a 32-bit integer. 626 492 * 627 493 * @returns 32-bit unsigned number on success. … … 630 496 int toInt32() const 631 497 { 632 return RTStrToInt32( str);498 return RTStrToInt32(m_psz); 633 499 } 634 500 … … 641 507 int toUInt32() const 642 508 { 643 return RTStrToUInt32( str);509 return RTStrToUInt32(m_psz); 644 510 } 645 511 … … 652 518 int64_t toInt64() const 653 519 { 654 return RTStrToInt64( str);520 return RTStrToInt64(m_psz); 655 521 } 656 522 … … 663 529 uint64_t toUInt64() const 664 530 { 665 return RTStrToUInt64( str);531 return RTStrToUInt64(m_psz); 666 532 } 667 533 … … 684 550 * Takes the ownership of the returned data. 685 551 */ 686 char **asOutParam() { setNull(); return &str; } 552 char **asOutParam() 553 { 554 cleanup(); 555 return &m_psz; 556 } 687 557 688 558 /** … … 693 563 protected: 694 564 695 void safe_assign (const char *s) 696 { 697 if (str != s) 698 { 699 setNull(); 700 raw_copy (str, s); 701 } 702 } 703 704 inline static void raw_copy (char *&ls, const char *rs) 705 { 706 if (rs) 707 #if !defined (VBOX_WITH_XPCOM) 708 ::RTStrDupEx (&ls, rs); 709 #else 710 ls = (char *) nsMemory::Clone (rs, strlen (rs) + 1); 711 #endif 712 } 713 714 inline static void raw_copy (char *&ls, CBSTR rs) 715 { 716 if (rs) 717 { 718 #if !defined (VBOX_WITH_XPCOM) 719 ::RTUtf16ToUtf8 ((PRTUTF16) rs, &ls); 720 #else 721 char *s = NULL; 722 ::RTUtf16ToUtf8 ((PRTUTF16) rs, &s); 723 raw_copy (ls, s); 724 ::RTStrFree (s); 725 #endif 726 } 727 } 728 729 char *str; 565 /** 566 * As with the ministring::copyFrom() variants, this unconditionally 567 * sets the members to a copy of the given other strings and makes 568 * no assumptions about previous contents. This can therefore be used 569 * both in copy constructors, when member variables have no defined 570 * value, and in assignments after having called cleanup(). 571 * 572 * This variant converts from a UTF-16 string, most probably from 573 * a Bstr assignment. 574 * 575 * @param rs 576 */ 577 void copyFrom(CBSTR s) 578 { 579 if (s) 580 { 581 RTUtf16ToUtf8((PRTUTF16)s, &m_psz); 582 m_cbLength = strlen(m_psz); // TODO optimize by using a different RTUtf* function 583 m_cbAllocated = m_cbLength + 1; 584 } 585 else 586 { 587 m_cbLength = 0; 588 m_cbAllocated = 0; 589 m_psz = NULL; 590 } 591 } 730 592 731 593 friend class Bstr; /* to access our raw_copy() */ 732 594 }; 733 734 // symmetric compare operators735 inline bool operator== (const char *l, const Utf8Str &r) { return r.operator== (l); }736 inline bool operator!= (const char *l, const Utf8Str &r) { return r.operator!= (l); }737 595 738 596 // work around error C2593 of the stupid MSVC 7.x ambiguity resolver … … 760 618 } 761 619 762 inline const Bstr &Bstr::cloneTo (char **pstr) const 763 { 764 if (pstr) { 765 *pstr = NULL; 766 Utf8Str::raw_copy (*pstr, bstr); 620 inline const Bstr& Bstr::cloneTo(char **pstr) const 621 { 622 if (pstr) 623 { 624 Utf8Str ustr(*this); 625 ustr.detachTo(pstr); 767 626 } 768 627 return *this; -
trunk/include/VBox/settings.h
r16560 r21073 31 31 #define ___VBox_settings_h 32 32 33 #include <limits> 34 33 35 #include <iprt/cdefs.h> 34 36 #include <iprt/cpputils.h> 35 #include <iprt/string.h>36 37 #include <list>38 #include <memory>39 #include <limits>40 41 37 #include <iprt/time.h> 38 #include <iprt/xml_cpp.h> 42 39 43 40 #include <VBox/com/Guid.h> 44 45 #include <VBox/xml.h>46 47 // #include <stdarg.h>48 41 49 42 /* these conflict with numeric_digits<>::min and max */ -
trunk/include/VBox/xml.h
r19530 r21073 1 /** @file2 * VirtualBox XML helper APIs.3 */4 5 /*6 * Copyright (C) 2007-2008 Sun Microsystems, Inc.7 *8 * This file is part of VirtualBox Open Source Edition (OSE), as9 * available from http://www.virtualbox.org. This file is free software;10 * you can redistribute it and/or modify it under the terms of the GNU11 * General Public License (GPL) as published by the Free Software12 * Foundation, in version 2 as it comes in the "COPYING" file of the13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.15 *16 * The contents of this file may alternatively be used under the terms17 * of the Common Development and Distribution License Version 1.018 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the19 * VirtualBox OSE distribution, in which case the provisions of the20 * CDDL are applicable instead of those of the GPL.21 *22 * You may elect to license modified versions of this file under the23 * terms and conditions of either the GPL or the CDDL or both.24 *25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa26 * Clara, CA 95054 USA or visit http://www.sun.com if you need27 * additional information or have any questions.28 */29 30 #ifndef ___VBox_vboxxml_h31 #define ___VBox_vboxxml_h32 33 #ifndef IN_RING334 # error "There are no XML APIs available in Ring-0 Context!"35 #else /* IN_RING3 */36 37 /** @def IN_VBOXXML_R338 * Used to indicate whether we're inside the same link module as the39 * XML Settings File Manipulation API.40 *41 * @todo should go to a separate common include together with VBOXXML2_CLASS42 * once there becomes more than one header in the VBoxXML2 library.43 */44 #ifdef DOXYGEN_RUNNING45 # define IN_VBOXXML_R346 #endif47 48 /** @def VBOXXML_CLASS49 * Class export/import wrapper. */50 #ifdef IN_VBOXXML_R351 # define VBOXXML_CLASS DECLEXPORT_CLASS52 #else53 # define VBOXXML_CLASS DECLIMPORT_CLASS54 #endif55 56 /*57 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a58 * result of private data member declarations of some classes below) need to59 * be exported too to in order to be accessible by clients.60 *61 * The alternative is to instantiate a template before the data member62 * declaration with the VBOXXML_CLASS prefix, but the standard disables63 * explicit instantiations in a foreign namespace. In other words, a declaration64 * like:65 *66 * template class VBOXXML_CLASS std::auto_ptr <Data>;67 *68 * right before the member declaration makes MSVC happy too, but this is not a69 * valid C++ construct (and G++ spits it out). So, for now we just disable the70 * warning and will come back to this problem one day later.71 *72 * We also disable another warning (4275) saying that a DLL-exported class73 * inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->74 * std::bad_alloc). I can't get how it can harm yet.75 */76 #if defined(_MSC_VER)77 #pragma warning (disable:4251)78 #pragma warning (disable:4275)79 #endif80 81 /* Forwards */82 typedef struct _xmlParserInput xmlParserInput;83 typedef xmlParserInput *xmlParserInputPtr;84 typedef struct _xmlParserCtxt xmlParserCtxt;85 typedef xmlParserCtxt *xmlParserCtxtPtr;86 typedef struct _xmlError xmlError;87 typedef xmlError *xmlErrorPtr;88 89 namespace xml90 {91 92 // Little string class for XML only93 //////////////////////////////////////////////////////////////////////////////94 95 class ministring96 {97 public:98 ministring()99 : m_psz(NULL)100 {101 }102 103 ministring(const ministring &s)104 : m_psz(NULL)105 {106 copyFrom(s.c_str());107 }108 109 ministring(const char *pcsz)110 : m_psz(NULL)111 {112 copyFrom(pcsz);113 }114 115 ~ministring()116 {117 cleanup();118 }119 120 void operator=(const char *pcsz)121 {122 cleanup();123 copyFrom(pcsz);124 }125 126 void operator=(const ministring &s)127 {128 cleanup();129 copyFrom(s.c_str());130 }131 132 const char* c_str() const133 {134 return m_psz;135 }136 137 private:138 void cleanup()139 {140 if (m_psz)141 {142 RTStrFree(m_psz);143 m_psz = NULL;144 }145 }146 147 void copyFrom(const char *pcsz)148 {149 if (pcsz)150 m_psz = RTStrDup(pcsz);151 }152 153 154 char *m_psz;155 };156 157 // Exceptions158 //////////////////////////////////////////////////////////////////////////////159 160 /**161 * Base exception class.162 */163 class VBOXXML_CLASS Error : public std::exception164 {165 public:166 167 Error(const char *pcszMessage)168 : m_pcsz(NULL)169 {170 copyFrom(pcszMessage);171 }172 173 Error(const Error &s)174 : std::exception(s)175 {176 copyFrom(s.what());177 }178 179 virtual ~Error() throw()180 {181 cleanup();182 }183 184 void operator=(const Error &s)185 {186 cleanup();187 copyFrom(s.what());188 }189 190 void setWhat(const char *pcszMessage)191 {192 cleanup();193 copyFrom(pcszMessage);194 }195 196 virtual const char* what() const throw()197 {198 return m_pcsz;199 }200 201 private:202 Error() {}; // hide the default constructor to make sure the extended one above is always used203 204 void cleanup()205 {206 if (m_pcsz)207 {208 RTStrFree(m_pcsz);209 m_pcsz = NULL;210 }211 }212 213 void copyFrom(const char *pcszMessage)214 {215 if (pcszMessage)216 m_pcsz = RTStrDup(pcszMessage);217 }218 219 char *m_pcsz;220 };221 222 class VBOXXML_CLASS LogicError : public Error223 {224 public:225 226 LogicError(const char *aMsg = NULL)227 : xml::Error(aMsg)228 {}229 230 LogicError(RT_SRC_POS_DECL);231 };232 233 class VBOXXML_CLASS RuntimeError : public Error234 {235 public:236 237 RuntimeError(const char *aMsg = NULL)238 : xml::Error(aMsg)239 {}240 };241 242 class VBOXXML_CLASS XmlError : public RuntimeError243 {244 public:245 XmlError(xmlErrorPtr aErr);246 247 static char *Format(xmlErrorPtr aErr);248 };249 250 // Logical errors251 //////////////////////////////////////////////////////////////////////////////252 253 class VBOXXML_CLASS ENotImplemented : public LogicError254 {255 public:256 ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {}257 ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}258 };259 260 class VBOXXML_CLASS EInvalidArg : public LogicError261 {262 public:263 EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {}264 EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}265 };266 267 class VBOXXML_CLASS EDocumentNotEmpty : public LogicError268 {269 public:270 EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}271 EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}272 };273 274 class VBOXXML_CLASS ENodeIsNotElement : public LogicError275 {276 public:277 ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {}278 ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}279 };280 281 // Runtime errors282 //////////////////////////////////////////////////////////////////////////////283 284 class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc285 {286 public:287 ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {}288 virtual ~ENoMemory() throw() {}289 };290 291 class VBOXXML_CLASS EIPRTFailure : public RuntimeError292 {293 public:294 295 EIPRTFailure (int aRC);296 297 int rc() const { return mRC; }298 299 private:300 int mRC;301 };302 303 304 /**305 * The Stream class is a base class for I/O streams.306 */307 class VBOXXML_CLASS Stream308 {309 public:310 311 virtual ~Stream() {}312 313 virtual const char *uri() const = 0;314 315 /**316 * Returns the current read/write position in the stream. The returned317 * position is a zero-based byte offset from the beginning of the file.318 *319 * Throws ENotImplemented if this operation is not implemented for the320 * given stream.321 */322 virtual uint64_t pos() const = 0;323 324 /**325 * Sets the current read/write position in the stream.326 *327 * @param aPos Zero-based byte offset from the beginning of the stream.328 *329 * Throws ENotImplemented if this operation is not implemented for the330 * given stream.331 */332 virtual void setPos (uint64_t aPos) = 0;333 };334 335 /**336 * The Input class represents an input stream.337 *338 * This input stream is used to read the settings tree from.339 * This is an abstract class that must be subclassed in order to fill it with340 * useful functionality.341 */342 class VBOXXML_CLASS Input : virtual public Stream343 {344 public:345 346 /**347 * Reads from the stream to the supplied buffer.348 *349 * @param aBuf Buffer to store read data to.350 * @param aLen Buffer length.351 *352 * @return Number of bytes read.353 */354 virtual int read (char *aBuf, int aLen) = 0;355 };356 357 /**358 *359 */360 class VBOXXML_CLASS Output : virtual public Stream361 {362 public:363 364 /**365 * Writes to the stream from the supplied buffer.366 *367 * @param aBuf Buffer to write data from.368 * @param aLen Buffer length.369 *370 * @return Number of bytes written.371 */372 virtual int write (const char *aBuf, int aLen) = 0;373 374 /**375 * Truncates the stream from the current position and upto the end.376 * The new file size will become exactly #pos() bytes.377 *378 * Throws ENotImplemented if this operation is not implemented for the379 * given stream.380 */381 virtual void truncate() = 0;382 };383 384 385 //////////////////////////////////////////////////////////////////////////////386 387 /**388 * The File class is a stream implementation that reads from and writes to389 * regular files.390 *391 * The File class uses IPRT File API for file operations. Note that IPRT File392 * API is not thread-safe. This means that if you pass the same RTFILE handle to393 * different File instances that may be simultaneously used on different394 * threads, you should care about serialization; otherwise you will get garbage395 * when reading from or writing to such File instances.396 */397 class VBOXXML_CLASS File : public Input, public Output398 {399 public:400 401 /**402 * Possible file access modes.403 */404 enum Mode { Mode_Read, Mode_WriteCreate, Mode_Overwrite, Mode_ReadWrite };405 406 /**407 * Opens a file with the given name in the given mode. If @a aMode is Read408 * or ReadWrite, the file must exist. If @a aMode is Write, the file must409 * not exist. Otherwise, an EIPRTFailure excetion will be thrown.410 *411 * @param aMode File mode.412 * @param aFileName File name.413 */414 File (Mode aMode, const char *aFileName);415 416 /**417 * Uses the given file handle to perform file operations. This file418 * handle must be already open in necessary mode (read, or write, or mixed).419 *420 * The read/write position of the given handle will be reset to the421 * beginning of the file on success.422 *423 * Note that the given file handle will not be automatically closed upon424 * this object destruction.425 *426 * @note It you pass the same RTFILE handle to more than one File instance,427 * please make sure you have provided serialization in case if these428 * instasnces are to be simultaneously used by different threads.429 * Otherwise you may get garbage when reading or writing.430 *431 * @param aHandle Open file handle.432 * @param aFileName File name (for reference).433 */434 File (RTFILE aHandle, const char *aFileName = NULL);435 436 /**437 * Destroys the File object. If the object was created from a file name438 * the corresponding file will be automatically closed. If the object was439 * created from a file handle, it will remain open.440 */441 virtual ~File();442 443 const char *uri() const;444 445 uint64_t pos() const;446 void setPos (uint64_t aPos);447 448 /**449 * See Input::read(). If this method is called in wrong file mode,450 * LogicError will be thrown.451 */452 int read (char *aBuf, int aLen);453 454 /**455 * See Output::write(). If this method is called in wrong file mode,456 * LogicError will be thrown.457 */458 int write (const char *aBuf, int aLen);459 460 /**461 * See Output::truncate(). If this method is called in wrong file mode,462 * LogicError will be thrown.463 */464 void truncate();465 466 private:467 468 /* Obscure class data */469 struct Data;470 std::auto_ptr <Data> m;471 472 /* auto_ptr data doesn't have proper copy semantics */473 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File)474 };475 476 /**477 * The MemoryBuf class represents a stream implementation that reads from the478 * memory buffer.479 */480 class VBOXXML_CLASS MemoryBuf : public Input481 {482 public:483 484 MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);485 486 virtual ~MemoryBuf();487 488 const char *uri() const;489 490 int read (char *aBuf, int aLen);491 uint64_t pos() const;492 void setPos (uint64_t aPos);493 494 private:495 /* Obscure class data */496 struct Data;497 std::auto_ptr <Data> m;498 499 /* auto_ptr data doesn't have proper copy semantics */500 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (MemoryBuf)501 };502 503 504 /*505 * GlobalLock506 *507 *508 */509 510 typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,511 const char *aID,512 xmlParserCtxt *aCtxt);513 typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;514 515 class VBOXXML_CLASS GlobalLock516 {517 public:518 GlobalLock();519 ~GlobalLock();520 521 void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc);522 523 static xmlParserInput* callDefaultLoader(const char *aURI,524 const char *aID,525 xmlParserCtxt *aCtxt);526 527 private:528 /* Obscure class data. */529 struct Data;530 struct Data *m;531 };532 533 /**534 * Node:535 * an XML node, which represents either an element or text content536 * or an attribute.537 *538 * For elements, getName() returns the element name, and getValue()539 * returns the text contents, if any.540 *541 * For attributes, getName() returns the attribute name, and getValue()542 * returns the attribute value, if any.543 *544 * Since the default constructor is private, one can create new nodes545 * only through factory methods provided by the XML classes. These are:546 *547 * -- xml::Document::createRootElement()548 * -- xml::Node::createChild()549 * -- xml::Node::addContent()550 * -- xml::Node::setAttribute()551 */552 553 class ElementNode;554 typedef std::list<const ElementNode*> ElementNodesList;555 556 class AttributeNode;557 558 class ContentNode;559 560 class VBOXXML_CLASS Node561 {562 public:563 ~Node();564 565 const char* getName() const;566 const char* getValue() const;567 bool copyValue(int32_t &i) const;568 bool copyValue(uint32_t &i) const;569 bool copyValue(int64_t &i) const;570 bool copyValue(uint64_t &i) const;571 572 int getLineNumber() const;573 574 int isElement()575 {576 return mType == IsElement;577 }578 579 protected:580 typedef enum {IsElement, IsAttribute, IsContent} EnumType;581 EnumType mType;582 583 // hide the default constructor so people use only our factory methods584 Node(EnumType type);585 Node(const Node &x); // no copying586 587 void buildChildren();588 589 /* Obscure class data */590 struct Data;591 Data *m;592 };593 594 class VBOXXML_CLASS ElementNode : public Node595 {596 public:597 int getChildElements(ElementNodesList &children,598 const char *pcszMatch = NULL) const;599 600 const ElementNode* findChildElement(const char *pcszMatch) const;601 const ElementNode* findChildElementFromId(const char *pcszId) const;602 603 const AttributeNode* findAttribute(const char *pcszMatch) const;604 bool getAttributeValue(const char *pcszMatch, const char *&ppcsz) const;605 bool getAttributeValue(const char *pcszMatch, int64_t &i) const;606 bool getAttributeValue(const char *pcszMatch, uint64_t &i) const;607 608 ElementNode* createChild(const char *pcszElementName);609 ContentNode* addContent(const char *pcszContent);610 AttributeNode* setAttribute(const char *pcszName, const char *pcszValue);611 612 protected:613 // hide the default constructor so people use only our factory methods614 ElementNode();615 ElementNode(const ElementNode &x); // no copying616 617 friend class Node;618 friend class Document;619 friend class XmlFileParser;620 };621 622 class VBOXXML_CLASS ContentNode : public Node623 {624 public:625 626 protected:627 // hide the default constructor so people use only our factory methods628 ContentNode();629 ContentNode(const ContentNode &x); // no copying630 631 friend class Node;632 friend class ElementNode;633 };634 635 class VBOXXML_CLASS AttributeNode : public Node636 {637 public:638 639 protected:640 // hide the default constructor so people use only our factory methods641 AttributeNode();642 AttributeNode(const AttributeNode &x); // no copying643 644 friend class Node;645 friend class ElementNode;646 };647 648 /*649 * NodesLoop650 *651 */652 653 class VBOXXML_CLASS NodesLoop654 {655 public:656 NodesLoop(const ElementNode &node, const char *pcszMatch = NULL);657 ~NodesLoop();658 const ElementNode* forAllNodes() const;659 660 private:661 /* Obscure class data */662 struct Data;663 Data *m;664 };665 666 /*667 * Document668 *669 */670 671 class VBOXXML_CLASS Document672 {673 public:674 Document();675 ~Document();676 677 Document(const Document &x);678 Document& operator=(const Document &x);679 680 const ElementNode* getRootElement() const;681 682 ElementNode* createRootElement(const char *pcszRootElementName);683 684 private:685 friend class XmlFileParser;686 friend class XmlFileWriter;687 688 void refreshInternals();689 690 /* Obscure class data */691 struct Data;692 Data *m;693 };694 695 /*696 * XmlParserBase697 *698 */699 700 class VBOXXML_CLASS XmlParserBase701 {702 protected:703 XmlParserBase();704 ~XmlParserBase();705 706 xmlParserCtxtPtr m_ctxt;707 };708 709 /*710 * XmlFileParser711 *712 */713 714 class VBOXXML_CLASS XmlFileParser : public XmlParserBase715 {716 public:717 XmlFileParser();718 ~XmlFileParser();719 720 void read(const char *pcszFilename, Document &doc);721 722 private:723 /* Obscure class data */724 struct Data;725 struct Data *m;726 727 static int ReadCallback(void *aCtxt, char *aBuf, int aLen);728 static int CloseCallback (void *aCtxt);729 };730 731 /*732 * XmlFileWriter733 *734 */735 736 class VBOXXML_CLASS XmlFileWriter737 {738 public:739 XmlFileWriter(Document &doc);740 ~XmlFileWriter();741 742 void write(const char *pcszFilename);743 744 static int WriteCallback(void *aCtxt, const char *aBuf, int aLen);745 static int CloseCallback (void *aCtxt);746 747 private:748 /* Obscure class data */749 struct Data;750 Data *m;751 };752 753 #if defined(_MSC_VER)754 #pragma warning (default:4251)755 #endif756 757 #endif /* IN_RING3 */758 759 /** @} */760 761 } // end namespace xml762 763 #endif /* ___VBox_vboxxml_h */ -
trunk/src/VBox/Main/ApplianceImpl.cpp
r21068 r21073 26 26 #include <iprt/file.h> 27 27 #include <iprt/s3.h> 28 #include "iprt/xml_cpp.h" 28 29 29 30 #include <VBox/param.h> … … 39 40 40 41 #include "Logging.h" 41 42 #include "VBox/xml.h"43 42 44 43 using namespace std; … … 234 233 // 235 234 //////////////////////////////////////////////////////////////////////////////// 236 237 static Utf8Str stripFilename(const Utf8Str &strFile)238 {239 Utf8Str str2(strFile);240 RTPathStripFilename(str2.mutableRaw());241 return str2;242 }243 235 244 236 static const struct … … 2246 2238 /* The disk image has to be on the same place as the OVF file. So 2247 2239 * strip the filename out of the full file path. */ 2248 Utf8Str strSrcDir = stripFilename(pAppliance->m->strPath); 2240 Utf8Str strSrcDir(pAppliance->m->strPath); 2241 strSrcDir.stripFilename(); 2249 2242 2250 2243 /* Iterate over all given disk images */ … … 3522 3515 const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf; 3523 3516 // target path needs to be composed from where the output OVF is 3524 Utf8Str strTargetFilePath = stripFilename(m->strPath); 3517 Utf8Str strTargetFilePath(m->strPath); 3518 strTargetFilePath.stripFilename(); 3525 3519 strTargetFilePath.append("/"); 3526 3520 strTargetFilePath.append(strTargetFileNameOnly); … … 3721 3715 const Utf8Str &strTargetFileNameOnly = (*itH)->strOvf; 3722 3716 /* Target path needs to be composed from where the output OVF is */ 3723 Utf8Str strTargetFilePath = stripFilename(m->strPath); 3717 Utf8Str strTargetFilePath(m->strPath); 3718 strTargetFilePath.stripFilename(); 3724 3719 strTargetFilePath.append("/"); 3725 3720 strTargetFilePath.append(strTargetFileNameOnly); … … 4736 4731 4737 4732 Utf8Str strTargetVmdkName(bstrName); 4738 RTPathStripExt(strTargetVmdkName.mutableRaw());4733 strTargetVmdkName.stripExt(); 4739 4734 strTargetVmdkName.append(".vmdk"); 4740 4735 -
trunk/src/VBox/Main/ConsoleImpl.cpp
r20928 r21073 1073 1073 for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i) 1074 1074 { 1075 Utf8Buf. alloc(cchBuf + 1024);1075 Utf8Buf.reserve(cchBuf + 1024); 1076 1076 if (Utf8Buf.isNull()) 1077 1077 return E_OUTOFMEMORY; … … 1081 1081 vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", ENUM_PROPS_HOST, 3, 1082 1082 &parm[0]); 1083 Utf8Buf.jolt(); 1083 1084 if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT) 1084 1085 return setError (E_FAIL, tr ("Internal application error")); … … 1717 1718 { 1718 1719 Utf8Str dir = stateFilePath; 1719 RTPathStripFilename (dir.mutableRaw());1720 if (!RTDirExists 1720 dir.stripFilename(); 1721 if (!RTDirExists(dir)) 1721 1722 { 1722 1723 int vrc = RTDirCreateFullPath (dir, 0777); … … 3865 3866 3866 3867 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 3867 /* To save doing a const cast, we use the mutableRaw() member. */ 3868 parm[0].u.pointer.addr = Utf8Name.mutableRaw(); 3868 parm[0].u.pointer.addr = (void*)Utf8Name.c_str(); 3869 3869 /* The + 1 is the null terminator */ 3870 3870 parm[0].u.pointer.size = (uint32_t)Utf8Name.length() + 1; … … 3882 3882 if (vrc != VERR_NOT_FOUND) 3883 3883 { 3884 size_t iFlags = strlen(pszBuffer) + 1; 3885 Utf8Str(pszBuffer).cloneTo (aValue); 3884 Utf8Str strBuffer(pszBuffer); 3885 strBuffer.cloneTo(aValue); 3886 3886 3887 *aTimestamp = parm[2].u.uint64; 3887 Utf8Str(pszBuffer + iFlags).cloneTo (aFlags); 3888 3889 size_t iFlags = strBuffer.length() + 1; 3890 Utf8Str(pszBuffer + iFlags).cloneTo(aFlags); 3888 3891 } 3889 3892 else … … 3930 3933 3931 3934 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 3932 /* To save doing a const cast, we use the mutableRaw() member. */ 3933 parm[0].u.pointer.addr = Utf8Name.mutableRaw(); 3935 parm[0].u.pointer.addr = (void*)Utf8Name.c_str(); 3934 3936 /* The + 1 is the null terminator */ 3935 3937 parm[0].u.pointer.size = (uint32_t)Utf8Name.length() + 1; … … 3938 3940 { 3939 3941 parm[1].type = VBOX_HGCM_SVC_PARM_PTR; 3940 /* To save doing a const cast, we use the mutableRaw() member. */ 3941 parm[1].u.pointer.addr = Utf8Value.mutableRaw(); 3942 parm[1].u.pointer.addr = (void*)Utf8Value.c_str(); 3942 3943 /* The + 1 is the null terminator */ 3943 3944 parm[1].u.pointer.size = (uint32_t)Utf8Value.length() + 1; … … 3947 3948 { 3948 3949 parm[2].type = VBOX_HGCM_SVC_PARM_PTR; 3949 /* To save doing a const cast, we use the mutableRaw() member. */ 3950 parm[2].u.pointer.addr = Utf8Flags.mutableRaw(); 3950 parm[2].u.pointer.addr = (void*)Utf8Flags.c_str(); 3951 3951 /* The + 1 is the null terminator */ 3952 3952 parm[2].u.pointer.size = (uint32_t)Utf8Flags.length() + 1; -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r20995 r21073 1814 1814 { 1815 1815 /* Pull over the properties from the server. */ 1816 SafeArray 1817 SafeArray 1818 SafeArray 1819 SafeArray 1816 SafeArray<BSTR> namesOut; 1817 SafeArray<BSTR> valuesOut; 1818 SafeArray<ULONG64> timestampsOut; 1819 SafeArray<BSTR> flagsOut; 1820 1820 hrc = pConsole->mControl->PullGuestProperties(ComSafeArrayAsOutParam(namesOut), 1821 1821 ComSafeArrayAsOutParam(valuesOut), … … 1829 1829 rc = VERR_INVALID_PARAMETER; 1830 1830 1831 std::vector 1832 std::vector 1833 std::vector 1831 std::vector<Utf8Str> utf8Names, utf8Values, utf8Flags; 1832 std::vector<char *> names, values, flags; 1833 std::vector<ULONG64> timestamps; 1834 1834 for (unsigned i = 0; i < cProps && RT_SUCCESS(rc); ++i) 1835 1835 if ( !VALID_PTR(namesOut[i]) -
trunk/src/VBox/Main/MachineImpl.cpp
r21002 r21073 3450 3450 AssertReturn (!mData->mConfigFileFull.isNull(), VERR_GENERAL_FAILURE); 3451 3451 3452 Utf8Str s ettingsDir = mData->mConfigFileFull;3453 3454 RTPathStripFilename (settingsDir.mutableRaw());3455 char folder 3456 int vrc = RTPathAbsEx (settingsDir, aPath, folder, sizeof(folder));3457 if (RT_SUCCESS 3452 Utf8Str strSettingsDir = mData->mConfigFileFull; 3453 3454 strSettingsDir.stripFilename(); 3455 char folder[RTPATH_MAX]; 3456 int vrc = RTPathAbsEx(strSettingsDir, aPath, folder, sizeof(folder)); 3457 if (RT_SUCCESS(vrc)) 3458 3458 aResult = folder; 3459 3459 … … 3483 3483 Utf8Str settingsDir = mData->mConfigFileFull; 3484 3484 3485 RTPathStripFilename (settingsDir.mutableRaw());3486 if (RTPathStartsWith 3485 settingsDir.stripFilename(); 3486 if (RTPathStartsWith(aPath, settingsDir)) 3487 3487 { 3488 3488 /* when assigning, we create a separate Utf8Str instance because both … … 3491 3491 * first, and since its the same as aPath, an attempt to copy garbage 3492 3492 * will be made. */ 3493 aResult = Utf8Str 3493 aResult = Utf8Str(aPath + settingsDir.length() + 1); 3494 3494 } 3495 3495 } … … 5949 5949 /* first, rename the directory if it matches the machine name */ 5950 5950 configDir = configFile; 5951 RTPathStripFilename (configDir.mutableRaw());5951 configDir.stripFilename(); 5952 5952 newConfigDir = configDir; 5953 if (RTPathFilename 5953 if (RTPathFilename(configDir) == name) 5954 5954 { 5955 RTPathStripFilename (newConfigDir.mutableRaw());5955 newConfigDir.stripFilename(); 5956 5956 newConfigDir = Utf8StrFmt ("%s%c%s", 5957 5957 newConfigDir.raw(), RTPATH_DELIMITER, newName.raw()); … … 6078 6078 6079 6079 /* ensure the settings directory exists */ 6080 Utf8Str path = mData->mConfigFileFull;6081 RTPathStripFilename (path.mutableRaw());6082 if (!RTDirExists 6083 { 6084 vrc = RTDirCreateFullPath 6085 if (RT_FAILURE 6080 Utf8Str path(mData->mConfigFileFull); 6081 path.stripFilename(); 6082 if (!RTDirExists(path)) 6083 { 6084 vrc = RTDirCreateFullPath(path, 0777); 6085 if (RT_FAILURE(vrc)) 6086 6086 { 6087 6087 return setError (E_FAIL, … … 7655 7655 * @note Not thread safe (must be called from this object's lock). 7656 7656 */ 7657 bool Machine::isInOwnDir 7657 bool Machine::isInOwnDir(Utf8Str *aSettingsDir /* = NULL */) 7658 7658 { 7659 7659 Utf8Str settingsDir = mData->mConfigFileFull; 7660 RTPathStripFilename (settingsDir.mutableRaw());7661 char *dirName = RTPathFilename 7660 settingsDir.stripFilename(); 7661 char *dirName = RTPathFilename(settingsDir); 7662 7662 7663 7663 AssertReturn (dirName, false); -
trunk/src/VBox/Main/Makefile.kmk
r20932 r21073 519 519 include 520 520 VBoxSettings_SOURCES = \ 521 xml/xml.cpp \522 521 xml/Settings.cpp 523 522 VBoxSettings_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/$(notdir $(LIB_SETTINGS)) -Wl,-x # no debug info please. -
trunk/src/VBox/Main/SharedFolderImpl.cpp
r20977 r21073 28 28 29 29 #include <iprt/param.h> 30 #include <iprt/cpputils.h> 30 31 #include <iprt/path.h> 31 #include <iprt/cpputils.h>32 32 33 33 // constructor / destructor … … 199 199 ; 200 200 #else 201 if (hostPathLen == 1 && RTPATH_IS_SEP 201 if (hostPathLen == 1 && RTPATH_IS_SEP(hostPath[0])) 202 202 ; 203 203 #endif 204 204 else 205 RTPathStripTrailingSlash (hostPath.mutableRaw());205 hostPath.stripTrailingSlash(); 206 206 207 207 /* Check whether the path is full (absolute) */ -
trunk/src/VBox/Main/VirtualBoxErrorInfoImpl.cpp
r20267 r21073 156 156 AssertComRC (rc); 157 157 Utf8Str message; 158 rc = aInfo->GetMessage (message.asOutParam()); 158 rc = aInfo->GetMessage(message.asOutParam()); 159 message.jolt(); 159 160 AssertComRC (rc); 160 161 mText = message; -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r20978 r21073 3870 3870 HRESULT VirtualBox::ensureFilePathExists (const char *aFileName) 3871 3871 { 3872 Utf8Str dir = aFileName;3873 RTPathStripFilename (dir.mutableRaw());3874 if (!RTDirExists (dir))3875 { 3876 int vrc = RTDirCreateFullPath (dir, 0777);3872 Utf8Str strDir(aFileName); 3873 strDir.stripFilename(); 3874 if (!RTDirExists(strDir)) 3875 { 3876 int vrc = RTDirCreateFullPath(strDir, 0777); 3877 3877 if (RT_FAILURE (vrc)) 3878 3878 { 3879 3879 return setError (E_FAIL, 3880 3880 tr ("Could not create the directory '%s' (%Rrc)"), 3881 dir.raw(), vrc);3881 strDir.c_str(), vrc); 3882 3882 } 3883 3883 } -
trunk/src/VBox/Main/glue/ErrorInfo.cpp
r20267 r21073 118 118 119 119 Utf8Str message; 120 rc = ex->GetMessage (message.asOutParam()); 120 rc = ex->GetMessage(message.asOutParam()); 121 message.jolt(); 121 122 gotSomething |= NS_SUCCEEDED (rc); 122 123 if (NS_SUCCEEDED (rc)) … … 182 183 LONG lrc; 183 184 184 rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc; 185 rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc; 185 186 gotSomething |= SUCCEEDED (rc); 186 187 gotAll &= SUCCEEDED (rc); -
trunk/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp
r20267 r21073 179 179 AssertComRC (rc); 180 180 Utf8Str message; 181 rc = aInfo->GetMessage (message.asOutParam()); 181 rc = aInfo->GetMessage(message.asOutParam()); 182 message.jolt(); 182 183 AssertComRC (rc); 183 184 mText = message; -
trunk/src/VBox/Main/glue/string.cpp
r17634 r21073 26 26 27 27 #include <iprt/err.h> 28 #include <iprt/path.h> 28 29 29 30 namespace com … … 85 86 86 87 size_t cbCopy = psz - pFirst; 87 ret. alloc(cbCopy + 1);88 memcpy(ret. str, pFirst, cbCopy);89 ret. str[cbCopy] = '\0';88 ret.reserve(cbCopy + 1); 89 memcpy(ret.m_psz, pFirst, cbCopy); 90 ret.m_psz[cbCopy] = '\0'; 90 91 } 91 92 } … … 95 96 } 96 97 98 bool Utf8Str::endsWith(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const 99 { 100 size_t l1 = length(); 101 if (l1 == 0) 102 return false; 103 104 size_t l2 = that.length(); 105 if (l1 < l2) 106 return false; 107 108 size_t l = l1 - l2; 109 if (cs == CaseSensitive) 110 return ::RTStrCmp(&m_psz[l], that.m_psz) == 0; 111 else 112 return ::RTStrICmp(&m_psz[l], that.m_psz) == 0; 113 } 114 115 bool Utf8Str::startsWith(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const 116 { 117 size_t l1 = length(); 118 size_t l2 = that.length(); 119 if (l1 == 0 || l2 == 0) 120 return false; 121 122 if (l1 < l2) 123 return false; 124 125 if (cs == CaseSensitive) 126 return ::RTStrNCmp(m_psz, that.m_psz, l2) == 0; 127 else 128 return ::RTStrNICmp(m_psz, that.m_psz, l2) == 0; 129 } 130 131 bool Utf8Str::contains(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const 132 { 133 if (cs == CaseSensitive) 134 return ::RTStrStr(m_psz, that.m_psz) != NULL; 135 else 136 return ::RTStrIStr(m_psz, that.m_psz) != NULL; 137 } 138 139 Utf8Str& Utf8Str::toLower() 140 { 141 if (!isEmpty()) 142 ::RTStrToLower(m_psz); 143 return *this; 144 } 145 146 Utf8Str& Utf8Str::toUpper() 147 { 148 if (!isEmpty()) 149 ::RTStrToUpper(m_psz); 150 return *this; 151 } 152 153 void Utf8Str::stripTrailingSlash() 154 { 155 RTPathStripTrailingSlash(m_psz); 156 jolt(); 157 } 158 159 void Utf8Str::stripFilename() 160 { 161 RTPathStripFilename(m_psz); 162 jolt(); 163 } 164 165 void Utf8Str::stripExt() 166 { 167 RTPathStripExt(m_psz); 168 jolt(); 169 } 170 97 171 int Utf8Str::toInt(uint64_t &i) const 98 172 { 99 if (! str)173 if (!m_psz) 100 174 return VERR_NO_DIGITS; 101 return RTStrToUInt64Ex( str, NULL, 0, &i);175 return RTStrToUInt64Ex(m_psz, NULL, 0, &i); 102 176 } 103 177 104 178 int Utf8Str::toInt(uint32_t &i) const 105 179 { 106 if (! str)180 if (!m_psz) 107 181 return VERR_NO_DIGITS; 108 return RTStrToUInt32Ex( str, NULL, 0, &i);182 return RTStrToUInt32Ex(m_psz, NULL, 0, &i); 109 183 } 110 184 -
trunk/src/VBox/Main/include/ApplianceImpl.h
r20082 r21073 92 92 const ComObjPtr <VirtualBox, ComWeakRef> mVirtualBox; 93 93 94 struct Data; // o bscure, defined in AppliannceImpl.cpp94 struct Data; // opaque, defined in ApplianceImpl.cpp 95 95 Data *m; 96 96 -
trunk/src/VBox/Main/webservice/vboxweb.cpp
r20928 r21073 603 603 * @return 604 604 */ 605 std::string ConvertComString(const com::Guid &bstr) 606 { 605 std::string ConvertComString(const com::Guid &uuid) 606 { 607 com::Bstr bstr(uuid); 607 608 com::Utf8Str ustr(bstr); 608 609 const char *pcsz; -
trunk/src/VBox/Main/xml/xml.cpp
r19530 r21073 1 /** @file2 * VirtualBox XML Manipulation API.3 */4 5 /*6 * Copyright (C) 2007-2009 Sun Microsystems, Inc.7 *8 * This file is part of VirtualBox Open Source Edition (OSE), as9 * available from http://www.virtualbox.org. This file is free software;10 * you can redistribute it and/or modify it under the terms of the GNU11 * General Public License (GPL) as published by the Free Software12 * Foundation, in version 2 as it comes in the "COPYING" file of the13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.15 *16 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa17 * Clara, CA 95054 USA or visit http://www.sun.com if you need18 * additional information or have any questions.19 */20 21 #include "Logging.h"22 23 #include <iprt/cdefs.h>24 #include <iprt/err.h>25 #include <iprt/file.h>26 #include <iprt/lock.h>27 #include <iprt/string.h>28 29 #include <libxml/tree.h>30 #include <libxml/parser.h>31 #include <libxml/globals.h>32 #include <libxml/xmlIO.h>33 #include <libxml/xmlsave.h>34 #include <libxml/uri.h>35 36 #include <libxml/xmlschemas.h>37 38 #include <list>39 #include <map>40 #include <boost/shared_ptr.hpp>41 42 #include "VBox/xml.h"43 44 ////////////////////////////////////////////////////////////////////////////////45 //46 // globals47 //48 ////////////////////////////////////////////////////////////////////////////////49 50 /**51 * Global module initialization structure. This is to wrap non-reentrant bits52 * of libxml, among other things.53 *54 * The constructor and destructor of this structure are used to perform global55 * module initiaizaton and cleanup. Thee must be only one global variable of56 * this structure.57 */58 static59 class Global60 {61 public:62 63 Global()64 {65 /* Check the parser version. The docs say it will kill the app if66 * there is a serious version mismatch, but I couldn't find it in the67 * source code (it only prints the error/warning message to the console) so68 * let's leave it as is for informational purposes. */69 LIBXML_TEST_VERSION70 71 /* Init libxml */72 xmlInitParser();73 74 /* Save the default entity resolver before someone has replaced it */75 sxml.defaultEntityLoader = xmlGetExternalEntityLoader();76 }77 78 ~Global()79 {80 /* Shutdown libxml */81 xmlCleanupParser();82 }83 84 struct85 {86 xmlExternalEntityLoader defaultEntityLoader;87 88 /** Used to provide some thread safety missing in libxml2 (see e.g.89 * XmlTreeBackend::read()) */90 RTLockMtx lock;91 }92 sxml; /* XXX naming this xml will break with gcc-3.3 */93 }94 gGlobal;95 96 97 98 namespace xml99 {100 101 ////////////////////////////////////////////////////////////////////////////////102 //103 // Exceptions104 //105 ////////////////////////////////////////////////////////////////////////////////106 107 LogicError::LogicError(RT_SRC_POS_DECL)108 : Error(NULL)109 {110 char *msg = NULL;111 RTStrAPrintf(&msg, "In '%s', '%s' at #%d",112 pszFunction, pszFile, iLine);113 setWhat(msg);114 RTStrFree(msg);115 }116 117 XmlError::XmlError(xmlErrorPtr aErr)118 {119 if (!aErr)120 throw EInvalidArg(RT_SRC_POS);121 122 char *msg = Format(aErr);123 setWhat(msg);124 RTStrFree(msg);125 }126 127 /**128 * Composes a single message for the given error. The caller must free the129 * returned string using RTStrFree() when no more necessary.130 */131 // static132 char *XmlError::Format(xmlErrorPtr aErr)133 {134 const char *msg = aErr->message ? aErr->message : "<none>";135 size_t msgLen = strlen(msg);136 /* strip spaces, trailing EOLs and dot-like char */137 while (msgLen && strchr(" \n.?!", msg [msgLen - 1]))138 --msgLen;139 140 char *finalMsg = NULL;141 RTStrAPrintf(&finalMsg, "%.*s.\nLocation: '%s', line %d (%d), column %d",142 msgLen, msg, aErr->file, aErr->line, aErr->int1, aErr->int2);143 144 return finalMsg;145 }146 147 EIPRTFailure::EIPRTFailure(int aRC)148 : RuntimeError(NULL),149 mRC(aRC)150 {151 char *newMsg = NULL;152 RTStrAPrintf(&newMsg, "Runtime error: %d (%s)", aRC, RTErrGetShort(aRC));153 setWhat(newMsg);154 RTStrFree(newMsg);155 }156 157 ////////////////////////////////////////////////////////////////////////////////158 //159 // File Class160 //161 //////////////////////////////////////////////////////////////////////////////162 163 struct File::Data164 {165 Data()166 : fileName (NULL), handle (NIL_RTFILE), opened (false) {}167 168 char *fileName;169 RTFILE handle;170 bool opened : 1;171 };172 173 File::File(Mode aMode, const char *aFileName)174 : m (new Data())175 {176 m->fileName = RTStrDup (aFileName);177 if (m->fileName == NULL)178 throw ENoMemory();179 180 unsigned flags = 0;181 switch (aMode)182 {183 case Mode_Read:184 flags = RTFILE_O_READ;185 break;186 case Mode_WriteCreate: // fail if file exists187 flags = RTFILE_O_WRITE | RTFILE_O_CREATE;188 break;189 case Mode_Overwrite: // overwrite if file exists190 flags = RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE;191 break;192 case Mode_ReadWrite:193 flags = RTFILE_O_READ | RTFILE_O_WRITE;194 }195 196 int vrc = RTFileOpen (&m->handle, aFileName, flags);197 if (RT_FAILURE (vrc))198 throw EIPRTFailure (vrc);199 200 m->opened = true;201 }202 203 File::File (RTFILE aHandle, const char *aFileName /* = NULL */)204 : m (new Data())205 {206 if (aHandle == NIL_RTFILE)207 throw EInvalidArg (RT_SRC_POS);208 209 m->handle = aHandle;210 211 if (aFileName)212 {213 m->fileName = RTStrDup (aFileName);214 if (m->fileName == NULL)215 throw ENoMemory();216 }217 218 setPos (0);219 }220 221 File::~File()222 {223 if (m->opened)224 RTFileClose (m->handle);225 226 RTStrFree (m->fileName);227 }228 229 const char *File::uri() const230 {231 return m->fileName;232 }233 234 uint64_t File::pos() const235 {236 uint64_t p = 0;237 int vrc = RTFileSeek (m->handle, 0, RTFILE_SEEK_CURRENT, &p);238 if (RT_SUCCESS (vrc))239 return p;240 241 throw EIPRTFailure (vrc);242 }243 244 void File::setPos (uint64_t aPos)245 {246 uint64_t p = 0;247 unsigned method = RTFILE_SEEK_BEGIN;248 int vrc = VINF_SUCCESS;249 250 /* check if we overflow int64_t and move to INT64_MAX first */251 if (((int64_t) aPos) < 0)252 {253 vrc = RTFileSeek (m->handle, INT64_MAX, method, &p);254 aPos -= (uint64_t) INT64_MAX;255 method = RTFILE_SEEK_CURRENT;256 }257 /* seek the rest */258 if (RT_SUCCESS (vrc))259 vrc = RTFileSeek (m->handle, (int64_t) aPos, method, &p);260 if (RT_SUCCESS (vrc))261 return;262 263 throw EIPRTFailure (vrc);264 }265 266 int File::read (char *aBuf, int aLen)267 {268 size_t len = aLen;269 int vrc = RTFileRead (m->handle, aBuf, len, &len);270 if (RT_SUCCESS (vrc))271 return (int)len;272 273 throw EIPRTFailure (vrc);274 }275 276 int File::write (const char *aBuf, int aLen)277 {278 size_t len = aLen;279 int vrc = RTFileWrite (m->handle, aBuf, len, &len);280 if (RT_SUCCESS (vrc))281 return (int)len;282 283 throw EIPRTFailure (vrc);284 285 return -1 /* failure */;286 }287 288 void File::truncate()289 {290 int vrc = RTFileSetSize (m->handle, pos());291 if (RT_SUCCESS (vrc))292 return;293 294 throw EIPRTFailure (vrc);295 }296 297 ////////////////////////////////////////////////////////////////////////////////298 //299 // MemoryBuf Class300 //301 //////////////////////////////////////////////////////////////////////////////302 303 struct MemoryBuf::Data304 {305 Data()306 : buf (NULL), len (0), uri (NULL), pos (0) {}307 308 const char *buf;309 size_t len;310 char *uri;311 312 size_t pos;313 };314 315 MemoryBuf::MemoryBuf (const char *aBuf, size_t aLen, const char *aURI /* = NULL */)316 : m (new Data())317 {318 if (aBuf == NULL)319 throw EInvalidArg (RT_SRC_POS);320 321 m->buf = aBuf;322 m->len = aLen;323 m->uri = RTStrDup (aURI);324 }325 326 MemoryBuf::~MemoryBuf()327 {328 RTStrFree (m->uri);329 }330 331 const char *MemoryBuf::uri() const332 {333 return m->uri;334 }335 336 uint64_t MemoryBuf::pos() const337 {338 return m->pos;339 }340 341 void MemoryBuf::setPos (uint64_t aPos)342 {343 size_t pos = (size_t) aPos;344 if ((uint64_t) pos != aPos)345 throw EInvalidArg();346 347 if (pos > m->len)348 throw EInvalidArg();349 350 m->pos = pos;351 }352 353 int MemoryBuf::read (char *aBuf, int aLen)354 {355 if (m->pos >= m->len)356 return 0 /* nothing to read */;357 358 size_t len = m->pos + aLen < m->len ? aLen : m->len - m->pos;359 memcpy (aBuf, m->buf + m->pos, len);360 m->pos += len;361 362 return (int)len;363 }364 365 ////////////////////////////////////////////////////////////////////////////////366 //367 // GlobalLock class368 //369 ////////////////////////////////////////////////////////////////////////////////370 371 struct GlobalLock::Data372 {373 PFNEXTERNALENTITYLOADER pOldLoader;374 RTLock lock;375 376 Data()377 : pOldLoader(NULL),378 lock(gGlobal.sxml.lock)379 {380 }381 };382 383 GlobalLock::GlobalLock()384 : m(new Data())385 {386 }387 388 GlobalLock::~GlobalLock()389 {390 if (m->pOldLoader)391 xmlSetExternalEntityLoader(m->pOldLoader);392 delete m;393 m = NULL;394 }395 396 void GlobalLock::setExternalEntityLoader(PFNEXTERNALENTITYLOADER pLoader)397 {398 m->pOldLoader = xmlGetExternalEntityLoader();399 xmlSetExternalEntityLoader(pLoader);400 }401 402 // static403 xmlParserInput* GlobalLock::callDefaultLoader(const char *aURI,404 const char *aID,405 xmlParserCtxt *aCtxt)406 {407 return gGlobal.sxml.defaultEntityLoader(aURI, aID, aCtxt);408 }409 410 ////////////////////////////////////////////////////////////////////////////////411 //412 // Node class413 //414 ////////////////////////////////////////////////////////////////////////////////415 416 struct Node::Data417 {418 xmlNode *plibNode; // != NULL if this is an element or content node419 xmlAttr *plibAttr; // != NULL if this is an attribute node420 421 Node *pParent; // NULL only for the root element422 const char *pcszName; // element or attribute name, points either into plibNode or plibAttr;423 // NULL if this is a content node424 425 struct compare_const_char426 {427 bool operator()(const char* s1, const char* s2) const428 {429 return strcmp(s1, s2) < 0;430 }431 };432 433 // attributes, if this is an element; can be empty434 typedef std::map<const char*, boost::shared_ptr<AttributeNode>, compare_const_char > AttributesMap;435 AttributesMap attribs;436 437 // child elements, if this is an element; can be empty438 typedef std::list< boost::shared_ptr<Node> > InternalNodesList;439 InternalNodesList children;440 };441 442 Node::Node(EnumType type)443 : mType(type),444 m(new Data)445 {446 m->plibNode = NULL;447 m->plibAttr = NULL;448 m->pParent = NULL;449 }450 451 Node::~Node()452 {453 delete m;454 }455 456 void Node::buildChildren() // private457 {458 // go thru this element's attributes459 xmlAttr *plibAttr = m->plibNode->properties;460 while (plibAttr)461 {462 const char *pcszAttribName = (const char*)plibAttr->name;463 boost::shared_ptr<AttributeNode> pNew(new AttributeNode);464 pNew->m->plibAttr = plibAttr;465 pNew->m->pcszName = (const char*)plibAttr->name;466 pNew->m->pParent = this;467 // store468 m->attribs[pcszAttribName] = pNew;469 470 plibAttr = plibAttr->next;471 }472 473 // go thru this element's child elements474 xmlNodePtr plibNode = m->plibNode->children;475 while (plibNode)476 {477 boost::shared_ptr<Node> pNew;478 479 if (plibNode->name)480 pNew = boost::shared_ptr<Node>(new ElementNode);481 else482 pNew = boost::shared_ptr<Node>(new ContentNode);483 484 pNew->m->plibNode = plibNode;485 pNew->m->pcszName = (const char*)plibNode->name;486 pNew->m->pParent = this;487 // store488 m->children.push_back(pNew);489 490 // recurse for this child element to get its own children491 pNew->buildChildren();492 493 plibNode = plibNode->next;494 }495 }496 497 const char* Node::getName() const498 {499 return m->pcszName;500 }501 502 /**503 * Returns the value of a node. If this node is an attribute, returns504 * the attribute value; if this node is an element, then this returns505 * the element text content.506 * @return507 */508 const char* Node::getValue() const509 {510 if ( (m->plibAttr)511 && (m->plibAttr->children)512 )513 // libxml hides attribute values in another node created as a514 // single child of the attribute node, and it's in the content field515 return (const char*)m->plibAttr->children->content;516 517 if ( (m->plibNode)518 && (m->plibNode->children)519 )520 return (const char*)m->plibNode->children->content;521 522 return NULL;523 }524 525 /**526 * Copies the value of a node into the given integer variable.527 * Returns TRUE only if a value was found and was actually an528 * integer of the given type.529 * @return530 */531 bool Node::copyValue(int32_t &i) const532 {533 const char *pcsz;534 if ( ((pcsz = getValue()))535 && (VINF_SUCCESS == RTStrToInt32Ex(pcsz, NULL, 10, &i))536 )537 return true;538 539 return false;540 }541 542 /**543 * Copies the value of a node into the given integer variable.544 * Returns TRUE only if a value was found and was actually an545 * integer of the given type.546 * @return547 */548 bool Node::copyValue(uint32_t &i) const549 {550 const char *pcsz;551 if ( ((pcsz = getValue()))552 && (VINF_SUCCESS == RTStrToUInt32Ex(pcsz, NULL, 10, &i))553 )554 return true;555 556 return false;557 }558 559 /**560 * Copies the value of a node into the given integer variable.561 * Returns TRUE only if a value was found and was actually an562 * integer of the given type.563 * @return564 */565 bool Node::copyValue(int64_t &i) const566 {567 const char *pcsz;568 if ( ((pcsz = getValue()))569 && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 10, &i))570 )571 return true;572 573 return false;574 }575 576 /**577 * Copies the value of a node into the given integer variable.578 * Returns TRUE only if a value was found and was actually an579 * integer of the given type.580 * @return581 */582 bool Node::copyValue(uint64_t &i) const583 {584 const char *pcsz;585 if ( ((pcsz = getValue()))586 && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 10, &i))587 )588 return true;589 590 return false;591 }592 593 /**594 * Returns the line number of the current node in the source XML file.595 * Useful for error messages.596 * @return597 */598 int Node::getLineNumber() const599 {600 if (m->plibAttr)601 return m->pParent->m->plibNode->line;602 603 return m->plibNode->line;604 }605 606 ElementNode::ElementNode()607 : Node(IsElement)608 {609 }610 611 /**612 * Builds a list of direct child elements of the current element that613 * match the given string; if pcszMatch is NULL, all direct child614 * elements are returned.615 * @param children out: list of nodes to which children will be appended.616 * @param pcszMatch in: match string, or NULL to return all children.617 * @return Number of items appended to the list (0 if none).618 */619 int ElementNode::getChildElements(ElementNodesList &children,620 const char *pcszMatch /*= NULL*/)621 const622 {623 int i = 0;624 Data::InternalNodesList::const_iterator625 it,626 last = m->children.end();627 for (it = m->children.begin();628 it != last;629 ++it)630 {631 // export this child node if ...632 if ( (!pcszMatch) // the caller wants all nodes or633 || (!strcmp(pcszMatch, (**it).getName())) // the element name matches634 )635 {636 Node *pNode = (*it).get();637 if (pNode->isElement())638 children.push_back(static_cast<ElementNode*>(pNode));639 ++i;640 }641 }642 return i;643 }644 645 /**646 * Returns the first child element whose name matches pcszMatch.647 * @param pcszMatch648 * @return649 */650 const ElementNode* ElementNode::findChildElement(const char *pcszMatch)651 const652 {653 Data::InternalNodesList::const_iterator654 it,655 last = m->children.end();656 for (it = m->children.begin();657 it != last;658 ++it)659 {660 if ((**it).isElement())661 {662 ElementNode *pelm = static_cast<ElementNode*>((*it).get());663 if (!strcmp(pcszMatch, pelm->getName())) // the element name matches664 return pelm;665 }666 }667 668 return NULL;669 }670 671 /**672 * Returns the first child element whose "id" attribute matches pcszId.673 * @param pcszId identifier to look for.674 * @return child element or NULL if not found.675 */676 const ElementNode* ElementNode::findChildElementFromId(const char *pcszId) const677 {678 Data::InternalNodesList::const_iterator679 it,680 last = m->children.end();681 for (it = m->children.begin();682 it != last;683 ++it)684 {685 if ((**it).isElement())686 {687 ElementNode *pelm = static_cast<ElementNode*>((*it).get());688 const AttributeNode *pAttr;689 if ( ((pAttr = pelm->findAttribute("id")))690 && (!strcmp(pAttr->getValue(), pcszId))691 )692 return pelm;693 }694 }695 696 return NULL;697 }698 699 /**700 *701 * @param pcszMatch702 * @return703 */704 const AttributeNode* ElementNode::findAttribute(const char *pcszMatch) const705 {706 Data::AttributesMap::const_iterator it;707 708 it = m->attribs.find(pcszMatch);709 if (it != m->attribs.end())710 return it->second.get();711 712 return NULL;713 }714 715 /**716 * Convenience method which attempts to find the attribute with the given717 * name and returns its value as a string.718 *719 * @param pcszMatch name of attribute to find.720 * @param str out: attribute value721 * @return TRUE if attribute was found and str was thus updated.722 */723 bool ElementNode::getAttributeValue(const char *pcszMatch, const char *&ppcsz) const724 {725 const Node* pAttr;726 if ((pAttr = findAttribute(pcszMatch)))727 {728 ppcsz = pAttr->getValue();729 return true;730 }731 732 return false;733 }734 735 /**736 * Convenience method which attempts to find the attribute with the given737 * name and returns its value as a signed long integer. This calls738 * RTStrToInt64Ex internally and will only output the integer if that739 * function returns no error.740 *741 * @param pcszMatch name of attribute to find.742 * @param i out: attribute value743 * @return TRUE if attribute was found and str was thus updated.744 */745 bool ElementNode::getAttributeValue(const char *pcszMatch, int64_t &i) const746 {747 const char *pcsz;748 if ( (getAttributeValue(pcszMatch, pcsz))749 && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 10, &i))750 )751 return true;752 753 return false;754 }755 756 /**757 * Convenience method which attempts to find the attribute with the given758 * name and returns its value as an unsigned long integer.This calls759 * RTStrToUInt64Ex internally and will only output the integer if that760 * function returns no error.761 *762 * @param pcszMatch name of attribute to find.763 * @param i out: attribute value764 * @return TRUE if attribute was found and str was thus updated.765 */766 bool ElementNode::getAttributeValue(const char *pcszMatch, uint64_t &i) const767 {768 const char *pcsz;769 if ( (getAttributeValue(pcszMatch, pcsz))770 && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 10, &i))771 )772 return true;773 774 return false;775 }776 777 /**778 * Creates a new child element node and appends it to the list779 * of children in "this".780 *781 * @param pcszElementName782 * @return783 */784 ElementNode* ElementNode::createChild(const char *pcszElementName)785 {786 // we must be an element, not an attribute787 if (!m->plibNode)788 throw ENodeIsNotElement(RT_SRC_POS);789 790 // libxml side: create new node791 xmlNode *plibNode;792 if (!(plibNode = xmlNewNode(NULL, // namespace793 (const xmlChar*)pcszElementName)))794 throw ENoMemory();795 xmlAddChild(m->plibNode, plibNode);796 797 // now wrap this in C++798 ElementNode *p = new ElementNode;799 boost::shared_ptr<ElementNode> pNew(p);800 pNew->m->plibNode = plibNode;801 pNew->m->pcszName = (const char*)plibNode->name;802 803 m->children.push_back(pNew);804 805 return p;806 }807 808 809 /**810 * Creates a content node and appends it to the list of children811 * in "this".812 *813 * @param pcszElementName814 * @return815 */816 ContentNode* ElementNode::addContent(const char *pcszContent)817 {818 // libxml side: create new node819 xmlNode *plibNode;820 if (!(plibNode = xmlNewText((const xmlChar*)pcszContent)))821 throw ENoMemory();822 xmlAddChild(m->plibNode, plibNode);823 824 // now wrap this in C++825 ContentNode *p = new ContentNode;826 boost::shared_ptr<ContentNode> pNew(p);827 pNew->m->plibNode = plibNode;828 pNew->m->pcszName = NULL;829 830 m->children.push_back(pNew);831 832 return p;833 }834 835 /**836 * Sets the given attribute.837 *838 * If an attribute with the given name exists, it is overwritten,839 * otherwise a new attribute is created. Returns the attribute node840 * that was either created or changed.841 *842 * @param pcszName843 * @param pcszValue844 * @return845 */846 AttributeNode* ElementNode::setAttribute(const char *pcszName, const char *pcszValue)847 {848 Data::AttributesMap::const_iterator it;849 850 it = m->attribs.find(pcszName);851 if (it == m->attribs.end())852 {853 // libxml side: xmlNewProp creates an attribute854 xmlAttr *plibAttr = xmlNewProp(m->plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);855 const char *pcszAttribName = (const char*)plibAttr->name;856 857 // C++ side: create an attribute node around it858 boost::shared_ptr<AttributeNode> pNew(new AttributeNode);859 pNew->m->plibAttr = plibAttr;860 pNew->m->pcszName = (const char*)plibAttr->name;861 pNew->m->pParent = this;862 // store863 m->attribs[pcszAttribName] = pNew;864 }865 else866 {867 // @todo868 throw LogicError("Attribute exists");869 }870 871 return NULL;872 873 }874 875 876 AttributeNode::AttributeNode()877 : Node(IsAttribute)878 {879 }880 881 ContentNode::ContentNode()882 : Node(IsContent)883 {884 }885 886 /*887 * NodesLoop888 *889 */890 891 struct NodesLoop::Data892 {893 ElementNodesList listElements;894 ElementNodesList::const_iterator it;895 };896 897 NodesLoop::NodesLoop(const ElementNode &node, const char *pcszMatch /* = NULL */)898 {899 m = new Data;900 node.getChildElements(m->listElements, pcszMatch);901 m->it = m->listElements.begin();902 }903 904 NodesLoop::~NodesLoop()905 {906 delete m;907 }908 909 910 /**911 * Handy convenience helper for looping over all child elements. Create an912 * instance of NodesLoop on the stack and call this method until it returns913 * NULL, like this:914 * <code>915 * xml::Node node; // should point to an element916 * xml::NodesLoop loop(node, "child"); // find all "child" elements under node917 * const xml::Node *pChild = NULL;918 * while (pChild = loop.forAllNodes())919 * ...;920 * </code>921 * @param node922 * @param pcszMatch923 * @return924 */925 const ElementNode* NodesLoop::forAllNodes() const926 {927 const ElementNode *pNode = NULL;928 929 if (m->it != m->listElements.end())930 {931 pNode = *(m->it);932 ++(m->it);933 }934 935 return pNode;936 }937 938 ////////////////////////////////////////////////////////////////////////////////939 //940 // Document class941 //942 ////////////////////////////////////////////////////////////////////////////////943 944 struct Document::Data945 {946 xmlDocPtr plibDocument;947 ElementNode *pRootElement;948 949 Data()950 {951 plibDocument = NULL;952 pRootElement = NULL;953 }954 955 ~Data()956 {957 reset();958 }959 960 void reset()961 {962 if (plibDocument)963 {964 xmlFreeDoc(plibDocument);965 plibDocument = NULL;966 }967 if (pRootElement)968 {969 delete pRootElement;970 pRootElement = NULL;971 }972 }973 974 void copyFrom(const Document::Data *p)975 {976 if (p->plibDocument)977 {978 plibDocument = xmlCopyDoc(p->plibDocument,979 1); // recursive == copy all980 }981 }982 };983 984 Document::Document()985 : m(new Data)986 {987 }988 989 Document::Document(const Document &x)990 : m(new Data)991 {992 m->copyFrom(x.m);993 };994 995 Document& Document::operator=(const Document &x)996 {997 m->reset();998 m->copyFrom(x.m);999 return *this;1000 };1001 1002 Document::~Document()1003 {1004 delete m;1005 }1006 1007 /**1008 * private method to refresh all internal structures after the internal pDocument1009 * has changed. Called from XmlFileParser::read(). m->reset() must have been1010 * called before to make sure all members except the internal pDocument are clean.1011 */1012 void Document::refreshInternals() // private1013 {1014 m->pRootElement = new ElementNode();1015 m->pRootElement->m->plibNode = xmlDocGetRootElement(m->plibDocument);1016 m->pRootElement->m->pcszName = (const char*)m->pRootElement->m->plibNode->name;1017 1018 m->pRootElement->buildChildren();1019 }1020 1021 /**1022 * Returns the root element of the document, or NULL if the document is empty.1023 * @return1024 */1025 const ElementNode* Document::getRootElement() const1026 {1027 return m->pRootElement;1028 }1029 1030 /**1031 * Creates a new element node and sets it as the root element. This will1032 * only work if the document is empty; otherwise EDocumentNotEmpty is thrown.1033 */1034 ElementNode* Document::createRootElement(const char *pcszRootElementName)1035 {1036 if (m->pRootElement || m->plibDocument)1037 throw EDocumentNotEmpty(RT_SRC_POS);1038 1039 // libxml side: create document, create root node1040 m->plibDocument = xmlNewDoc((const xmlChar*)"1.0");1041 xmlNode *plibRootNode;1042 if (!(plibRootNode = xmlNewNode(NULL, // namespace1043 (const xmlChar*)pcszRootElementName)))1044 throw ENoMemory();1045 xmlDocSetRootElement(m->plibDocument, plibRootNode);1046 1047 // now wrap this in C++1048 m->pRootElement = new ElementNode();1049 m->pRootElement->m->plibNode = plibRootNode;1050 m->pRootElement->m->pcszName = (const char*)plibRootNode->name;1051 1052 return m->pRootElement;1053 }1054 1055 ////////////////////////////////////////////////////////////////////////////////1056 //1057 // XmlParserBase class1058 //1059 ////////////////////////////////////////////////////////////////////////////////1060 1061 XmlParserBase::XmlParserBase()1062 {1063 m_ctxt = xmlNewParserCtxt();1064 if (m_ctxt == NULL)1065 throw ENoMemory();1066 }1067 1068 XmlParserBase::~XmlParserBase()1069 {1070 xmlFreeParserCtxt (m_ctxt);1071 m_ctxt = NULL;1072 }1073 1074 ////////////////////////////////////////////////////////////////////////////////1075 //1076 // XmlFileParser class1077 //1078 ////////////////////////////////////////////////////////////////////////////////1079 1080 struct XmlFileParser::Data1081 {1082 xmlParserCtxtPtr ctxt;1083 ministring strXmlFilename;1084 1085 Data()1086 {1087 if (!(ctxt = xmlNewParserCtxt()))1088 throw xml::ENoMemory();1089 }1090 1091 ~Data()1092 {1093 xmlFreeParserCtxt(ctxt);1094 ctxt = NULL;1095 }1096 };1097 1098 XmlFileParser::XmlFileParser()1099 : XmlParserBase(),1100 m(new Data())1101 {1102 }1103 1104 XmlFileParser::~XmlFileParser()1105 {1106 delete m;1107 m = NULL;1108 }1109 1110 struct IOContext1111 {1112 File file;1113 ministring error;1114 1115 IOContext(const char *pcszFilename, File::Mode mode)1116 : file(mode, pcszFilename)1117 {1118 }1119 1120 void setError(const xml::Error &x)1121 {1122 error = x.what();1123 }1124 1125 void setError(const std::exception &x)1126 {1127 error = x.what();1128 }1129 };1130 1131 struct ReadContext : IOContext1132 {1133 ReadContext(const char *pcszFilename)1134 : IOContext(pcszFilename, File::Mode_Read)1135 {1136 }1137 };1138 1139 struct WriteContext : IOContext1140 {1141 WriteContext(const char *pcszFilename)1142 : IOContext(pcszFilename, File::Mode_Overwrite)1143 {1144 }1145 };1146 1147 /**1148 * Reads the given file and fills the given Document object with its contents.1149 * Throws XmlError on parsing errors.1150 *1151 * The document that is passed in will be reset before being filled if not empty.1152 *1153 * @param pcszFilename in: name fo file to parse.1154 * @param doc out: document to be reset and filled with data according to file contents.1155 */1156 void XmlFileParser::read(const char *pcszFilename,1157 Document &doc)1158 {1159 GlobalLock lock;1160 // global.setExternalEntityLoader(ExternalEntityLoader);1161 1162 m->strXmlFilename = pcszFilename;1163 1164 ReadContext context(pcszFilename);1165 doc.m->reset();1166 if (!(doc.m->plibDocument = xmlCtxtReadIO(m->ctxt,1167 ReadCallback,1168 CloseCallback,1169 &context,1170 pcszFilename,1171 NULL, // encoding = auto1172 XML_PARSE_NOBLANKS)))1173 throw XmlError(xmlCtxtGetLastError(m->ctxt));1174 1175 doc.refreshInternals();1176 }1177 1178 // static1179 int XmlFileParser::ReadCallback(void *aCtxt, char *aBuf, int aLen)1180 {1181 ReadContext *pContext = static_cast<ReadContext*>(aCtxt);1182 1183 /* To prevent throwing exceptions while inside libxml2 code, we catch1184 * them and forward to our level using a couple of variables. */1185 1186 try1187 {1188 return pContext->file.read(aBuf, aLen);1189 }1190 catch (const xml::EIPRTFailure &err) { pContext->setError(err); }1191 catch (const xml::Error &err) { pContext->setError(err); }1192 catch (const std::exception &err) { pContext->setError(err); }1193 catch (...) { pContext->setError(xml::LogicError(RT_SRC_POS)); }1194 1195 return -1 /* failure */;1196 }1197 1198 int XmlFileParser::CloseCallback(void *aCtxt)1199 {1200 /// @todo to be written1201 1202 return -1;1203 }1204 1205 ////////////////////////////////////////////////////////////////////////////////1206 //1207 // XmlFileWriter class1208 //1209 ////////////////////////////////////////////////////////////////////////////////1210 1211 struct XmlFileWriter::Data1212 {1213 Document *pDoc;1214 };1215 1216 XmlFileWriter::XmlFileWriter(Document &doc)1217 {1218 m = new Data();1219 m->pDoc = &doc;1220 }1221 1222 XmlFileWriter::~XmlFileWriter()1223 {1224 delete m;1225 }1226 1227 void XmlFileWriter::write(const char *pcszFilename)1228 {1229 WriteContext context(pcszFilename);1230 1231 GlobalLock lock;1232 1233 /* serialize to the stream */1234 xmlIndentTreeOutput = 1;1235 xmlTreeIndentString = " ";1236 xmlSaveNoEmptyTags = 0;1237 1238 xmlSaveCtxtPtr saveCtxt;1239 if (!(saveCtxt = xmlSaveToIO(WriteCallback,1240 CloseCallback,1241 &context,1242 NULL,1243 XML_SAVE_FORMAT)))1244 throw xml::LogicError(RT_SRC_POS);1245 1246 long rc = xmlSaveDoc(saveCtxt, m->pDoc->m->plibDocument);1247 if (rc == -1)1248 {1249 /* look if there was a forwared exception from the lower level */1250 // if (m->trappedErr.get() != NULL)1251 // m->trappedErr->rethrow();1252 1253 /* there must be an exception from the Output implementation,1254 * otherwise the save operation must always succeed. */1255 throw xml::LogicError(RT_SRC_POS);1256 }1257 1258 xmlSaveClose(saveCtxt);1259 }1260 1261 int XmlFileWriter::WriteCallback(void *aCtxt, const char *aBuf, int aLen)1262 {1263 WriteContext *pContext = static_cast<WriteContext*>(aCtxt);1264 1265 /* To prevent throwing exceptions while inside libxml2 code, we catch1266 * them and forward to our level using a couple of variables. */1267 try1268 {1269 return pContext->file.write(aBuf, aLen);1270 }1271 catch (const xml::EIPRTFailure &err) { pContext->setError(err); }1272 catch (const xml::Error &err) { pContext->setError(err); }1273 catch (const std::exception &err) { pContext->setError(err); }1274 catch (...) { pContext->setError(xml::LogicError(RT_SRC_POS)); }1275 1276 return -1 /* failure */;1277 }1278 1279 int XmlFileWriter::CloseCallback(void *aCtxt)1280 {1281 /// @todo to be written1282 1283 return -1;1284 }1285 1286 1287 } // end namespace xml1288 1289 -
trunk/src/VBox/Runtime/Makefile.kmk
r21046 r21073 51 51 LIBRARIES += RuntimeR3 52 52 DLLS += VBoxRT 53 54 # Temporary(?) hack.55 VBOX_WITH_LIBXML2_IN_VBOXRT=56 53 57 54 else # !VBOX_ONLY_ADDITIONS && !VBOX_ONLY_DOCS … … 165 162 # 166 163 RuntimeR3_TEMPLATE = VBOXR3STATIC 164 RuntimeR3_SDKS = VBOX_LIBXML2 167 165 RuntimeR3_SDKS.win = WINPSDK W2K3DDK 168 166 RuntimeR3_DEFS = IN_RT_R3 IN_SUP_R3 LDR_WITH_NATIVE LDR_WITH_ELF32 LDR_WITH_PE RT_WITH_VBOX RT_NO_GIP … … 306 304 r3/test.cpp \ 307 305 r3/testi.cpp \ 308 r3/tcp.cpp 306 r3/tcp.cpp \ 307 r3/xml.cpp 309 308 310 309 #if1of ($(KBUILD_TARGET_ARCH),amd64 x86) … … 787 786 # 788 787 VBoxRT_TEMPLATE = VBOXR3 789 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT790 788 VBoxRT_SDKS = VBOX_OPENSSL VBOX_LIBXML2 VBOX_LIBCURL 791 endif792 789 VBoxRT_SDKS.win = WINPSDK W2K3DDK VBOX_NTDLL 793 790 ifeq ($(KBUILD_TARGET)$(VBOX_WITH_HARDENING),darwin) … … 799 796 VBox/VBoxRTDeps.cpp \ 800 797 $(RuntimeR3_SOURCES) 801 if defined(VBOX_WITH_LIBXML2_IN_VBOXRT)802 798 VBoxRT_SOURCES += \ 803 799 common/misc/s3.cpp 804 endif805 800 VBoxRT_SOURCES.$(KBUILD_TARGET) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET)) 806 801 VBoxRT_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) … … 818 813 $(PATH_LIB)/VBox-kStuff$(VBOX_SUFF_LIB) 819 814 endif 820 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT821 ifndef SDK_VBOX_LIBXML2_LIBS822 815 VBoxRT_LIBS += \ 823 816 $(PATH_LIB)/VBox-libxml2$(VBOX_SUFF_LIB) 824 endif825 ifndef SDK_VBOX_OPENSSL_LIBS826 817 VBoxRT_LIBS += \ 827 818 $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB) 828 endif829 endif830 819 VBoxRT_LIBS.darwin = \ 831 820 iconv … … 851 840 $(PATH_LIB)/RuntimeR3L4$(VBOX_SUFF_LIB) 852 841 853 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT854 VBox/VBoxRTDeps.cpp_DEFS = VBOX_WITH_LIBXML2_IN_VBOXRT855 endif856 857 842 if1of ($(DLLS), VBoxRT) 858 843 $$(VBoxRT_0_OUTDIR)/VBoxRT.def: \ 859 844 $(PATH_SUB_CURRENT)/r3/win/VBoxRT-$$(if-expr $$(KBUILD_TARGET_ARCH) == amd64,win64,win32).def \ 860 $( if-expr defined(VBOX_WITH_LIBXML2_IN_VBOXRT),$(PATH_SUB_CURRENT)/r3/win/$(if $(VBOX_OSE),VBoxRT-openssl-ose.def,VBoxRT-openssl.def),)845 $(PATH_SUB_CURRENT)/r3/win/$(if $(VBOX_OSE),VBoxRT-openssl-ose.def,VBoxRT-openssl.def) 861 846 $(RM) -f -- $@ 862 847 $(REDIRECT) -wto $@ -- $(CAT_EXT) $^ -
trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp
r20862 r21073 36 36 #include <iprt/assert.h> 37 37 #include <iprt/asm.h> 38 #ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 38 39 39 # include <libxml/xmlmodule.h> 40 40 # include <libxml/globals.h> … … 44 44 # include <openssl/x509.h> 45 45 # include <openssl/rsa.h> 46 #endif47 46 48 47 … … 55 54 (PFNRT)SUPR3PageAllocEx, 56 55 (PFNRT)SUPSemEventCreate, 57 #ifdef VBOX_WITH_LIBXML2_IN_VBOXRT58 56 (PFNRT)xmlModuleOpen, 59 57 (PFNRT)MD5_Init, … … 65 63 (PFNRT)i2d_X509, 66 64 (PFNRT)RSA_generate_key, 67 #endif68 65 (PFNRT)RTAssertShouldPanic, 69 66 (PFNRT)ASMAtomicReadU64, -
trunk/src/VBox/Runtime/testcase/tstUtf8.cpp
r20606 r21073 42 42 #include <iprt/err.h> 43 43 #include <iprt/test.h> 44 #include <iprt/ministring_cpp.h> 44 45 45 46 #include <stdlib.h> /** @todo use our random. */ … … 926 927 927 928 929 void testMinistring(RTTEST hTest) 930 { 931 RTTestSub(hTest, "class ministring"); 932 933 #define CHECK(expr) \ 934 do { \ 935 if (!(expr)) \ 936 RTTestFailed(hTest, "%d: FAILED %s", __LINE__, #expr); \ 937 } while (0) 938 939 #define CHECK_DUMP(expr, value) \ 940 do { \ 941 if (!(expr)) \ 942 RTTestFailed(hTest, "%d: FAILED %s, got \"%s\"", __LINE__, #expr, value); \ 943 } while (0) 944 945 #define CHECK_DUMP_I(expr) \ 946 do { \ 947 if (!(expr)) \ 948 RTTestFailed(hTest, "%d: FAILED %s, got \"%d\"", __LINE__, #expr, expr); \ 949 } while (0) 950 951 ministring empty; 952 CHECK( (empty.length() == 0) ); 953 CHECK( (empty.capacity() == 0) ); 954 955 ministring sixbytes("12345"); 956 CHECK( (sixbytes.length() == 5) ); 957 CHECK( (sixbytes.capacity() == 6) ); 958 959 sixbytes.append("678"); 960 CHECK( (sixbytes.length() == 8) ); 961 CHECK( (sixbytes.capacity() == 9) ); 962 963 char *psz = sixbytes.mutableRaw(); 964 // 12345678 965 // ^ 966 // 0123456 967 psz[6] = '\0'; 968 sixbytes.jolt(); 969 CHECK( (sixbytes.length() == 6) ); 970 CHECK( (sixbytes.capacity() == 7) ); 971 972 ministring morebytes("tobereplaced"); 973 morebytes = "newstring "; 974 morebytes.append(sixbytes); 975 976 CHECK_DUMP( (morebytes == "newstring 123456"), morebytes.c_str() ); 977 978 ministring third(morebytes); 979 third.reserve(100 * 1024); // 100 KB 980 CHECK_DUMP( (third == "newstring 123456"), morebytes.c_str() ); 981 CHECK( (third.capacity() == 100 * 1024) ); 982 CHECK( (third.length() == morebytes.length()) ); // must not have changed 983 984 ministring copy1(morebytes); 985 ministring copy2 = morebytes; 986 CHECK( (copy1 == copy2) ); 987 988 copy1 = NULL; 989 CHECK( (copy1.isNull()) ); 990 991 copy1 = ""; 992 CHECK( (copy1.isEmpty()) ); 993 994 CHECK( (ministring("abc") < ministring("def")) ); 995 CHECK( (ministring("abc") != ministring("def")) ); 996 CHECK_DUMP_I( (ministring("def") > ministring("abc")) ); 997 998 copy2.setNull(); 999 for (int i = 0; 1000 i < 100; 1001 ++i) 1002 { 1003 copy2.reserve(50); // should be ignored after 50 loops 1004 copy2.append("1"); 1005 } 1006 CHECK( (copy2.length() == 100) ); 1007 1008 #undef CHECK 1009 } 1010 928 1011 int main() 929 1012 { … … 946 1029 TstRTStrXCmp(hTest); 947 1030 testStrStr(hTest); 1031 1032 testMinistring(hTest); 1033 948 1034 Benchmarks(hTest); 949 1035
Note:
See TracChangeset
for help on using the changeset viewer.