Changeset 21077 in vbox
- Timestamp:
- Jun 30, 2009 3:19:12 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 21 edited
-
Config.kmk (modified) (3 diffs)
-
include/VBox/com/string.h (modified) (16 diffs)
-
include/VBox/settings.h (modified) (1 diff)
-
include/VBox/xml.h (modified) (1 diff)
-
src/VBox/Main/ApplianceImpl.cpp (modified) (7 diffs)
-
src/VBox/Main/ConsoleImpl.cpp (modified) (8 diffs)
-
src/VBox/Main/ConsoleImpl2.cpp (modified) (2 diffs)
-
src/VBox/Main/MachineImpl.cpp (modified) (6 diffs)
-
src/VBox/Main/Makefile.kmk (modified) (1 diff)
-
src/VBox/Main/SharedFolderImpl.cpp (modified) (2 diffs)
-
src/VBox/Main/VirtualBoxErrorInfoImpl.cpp (modified) (1 diff)
-
src/VBox/Main/VirtualBoxImpl.cpp (modified) (1 diff)
-
src/VBox/Main/glue/ErrorInfo.cpp (modified) (2 diffs)
-
src/VBox/Main/glue/VirtualBoxErrorInfo.cpp (modified) (1 diff)
-
src/VBox/Main/glue/string.cpp (modified) (3 diffs)
-
src/VBox/Main/include/ApplianceImpl.h (modified) (1 diff)
-
src/VBox/Main/webservice/vboxweb.cpp (modified) (1 diff)
-
src/VBox/Main/xml/xml.cpp (modified) (1 diff)
-
src/VBox/Runtime/Makefile.kmk (modified) (7 diffs)
-
src/VBox/Runtime/VBox/VBoxRTDeps.cpp (modified) (4 diffs)
-
src/VBox/Runtime/testcase/tstUtf8.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Config.kmk
r21073 r21077 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 = 1 492 494 493 495 ## For experimenting with disabling preemption instead of interrupts … … 1797 1799 # 1798 1800 SDK_VBOX_LIBXML2 = . 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 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 1804 1820 1805 1821 SDK_VBOX_LIBXSLT = . … … 1837 1853 SDK_VBOX_OPENSSL_INCS ?= $(SDK_VBOX_OPENSSL_VBOX_DEFAULT_INCS) 1838 1854 SDK_VBOX_OPENSSL_ORDERDEPS ?= $(crypto-headers_1_TARGET) 1839 SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB) 1855 ifndef VBOX_WITH_LIBXML2_IN_VBOXRT 1856 SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB) 1857 endif 1840 1858 # Build entire openssl library, not just the minimal subset. 1841 1859 if1of ($(KBUILD_TARGET), linux solaris) -
trunk/include/VBox/com/string.h
r21073 r21077 49 49 #include "VBox/com/assert.h" 50 50 51 #include <iprt/string.h> 51 52 #include <iprt/cpputils.h> 52 53 #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== (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); }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 : public ministring326 class Utf8Str 327 327 { 328 328 public: 329 329 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 } 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; } 375 560 376 561 /** … … 379 564 * caller. 380 565 */ 381 const Utf8Str & cloneTo(char **pstr) const566 const Utf8Str &cloneTo (char **pstr) const 382 567 { 383 568 if (pstr) 384 *pstr = RTStrDup(m_psz); 569 { 570 *pstr = NULL; 571 raw_copy (*pstr, str); 572 } 385 573 return *this; 386 574 } … … 394 582 * string. 395 583 */ 396 Utf8Str& detachTo(char **pstr) 397 { 398 *pstr = m_psz; 399 m_psz = NULL; 400 m_cbAllocated = 0; 401 m_cbLength = 0; 584 Utf8Str &detachTo (char **pstr) 585 { 586 *pstr = str; 587 str = NULL; 402 588 return *this; 403 589 } … … 408 594 * caller. 409 595 */ 410 const Utf8Str & cloneTo(BSTR *pstr) const596 const Utf8Str &cloneTo (BSTR *pstr) const 411 597 { 412 598 if (pstr) 413 599 { 414 600 *pstr = NULL; 415 Bstr::raw_copy (*pstr, m_psz);601 Bstr::raw_copy (*pstr, str); 416 602 } 417 603 return *this; … … 437 623 438 624 /** 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. 625 * Attempts to convert the member string into an 32-bit integer. 492 626 * 493 627 * @returns 32-bit unsigned number on success. … … 496 630 int toInt32() const 497 631 { 498 return RTStrToInt32( m_psz);632 return RTStrToInt32(str); 499 633 } 500 634 … … 507 641 int toUInt32() const 508 642 { 509 return RTStrToUInt32( m_psz);643 return RTStrToUInt32(str); 510 644 } 511 645 … … 518 652 int64_t toInt64() const 519 653 { 520 return RTStrToInt64( m_psz);654 return RTStrToInt64(str); 521 655 } 522 656 … … 529 663 uint64_t toUInt64() const 530 664 { 531 return RTStrToUInt64( m_psz);665 return RTStrToUInt64(str); 532 666 } 533 667 … … 550 684 * Takes the ownership of the returned data. 551 685 */ 552 char **asOutParam() 553 { 554 cleanup(); 555 return &m_psz; 556 } 686 char **asOutParam() { setNull(); return &str; } 557 687 558 688 /** … … 563 693 protected: 564 694 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 } 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; 592 730 593 731 friend class Bstr; /* to access our raw_copy() */ 594 732 }; 733 734 // symmetric compare operators 735 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); } 595 737 596 738 // work around error C2593 of the stupid MSVC 7.x ambiguity resolver … … 618 760 } 619 761 620 inline const Bstr& Bstr::cloneTo(char **pstr) const 621 { 622 if (pstr) 623 { 624 Utf8Str ustr(*this); 625 ustr.detachTo(pstr); 762 inline const Bstr &Bstr::cloneTo (char **pstr) const 763 { 764 if (pstr) { 765 *pstr = NULL; 766 Utf8Str::raw_copy (*pstr, bstr); 626 767 } 627 768 return *this; -
trunk/include/VBox/settings.h
r21073 r21077 31 31 #define ___VBox_settings_h 32 32 33 #include <limits>34 35 33 #include <iprt/cdefs.h> 36 34 #include <iprt/cpputils.h> 35 #include <iprt/string.h> 36 37 #include <list> 38 #include <memory> 39 #include <limits> 40 37 41 #include <iprt/time.h> 38 #include <iprt/xml_cpp.h>39 42 40 43 #include <VBox/com/Guid.h> 44 45 #include <VBox/xml.h> 46 47 // #include <stdarg.h> 41 48 42 49 /* these conflict with numeric_digits<>::min and max */ -
trunk/include/VBox/xml.h
r21073 r21077 1 /** @file 2 * 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), as 9 * 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 GNU 11 * General Public License (GPL) as published by the Free Software 12 * Foundation, in version 2 as it comes in the "COPYING" file of the 13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 14 * 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 terms 17 * of the Common Development and Distribution License Version 1.0 18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 19 * VirtualBox OSE distribution, in which case the provisions of the 20 * CDDL are applicable instead of those of the GPL. 21 * 22 * You may elect to license modified versions of this file under the 23 * terms and conditions of either the GPL or the CDDL or both. 24 * 25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 26 * Clara, CA 95054 USA or visit http://www.sun.com if you need 27 * additional information or have any questions. 28 */ 29 30 #ifndef ___VBox_vboxxml_h 31 #define ___VBox_vboxxml_h 32 33 #ifndef IN_RING3 34 # error "There are no XML APIs available in Ring-0 Context!" 35 #else /* IN_RING3 */ 36 37 /** @def IN_VBOXXML_R3 38 * Used to indicate whether we're inside the same link module as the 39 * XML Settings File Manipulation API. 40 * 41 * @todo should go to a separate common include together with VBOXXML2_CLASS 42 * once there becomes more than one header in the VBoxXML2 library. 43 */ 44 #ifdef DOXYGEN_RUNNING 45 # define IN_VBOXXML_R3 46 #endif 47 48 /** @def VBOXXML_CLASS 49 * Class export/import wrapper. */ 50 #ifdef IN_VBOXXML_R3 51 # define VBOXXML_CLASS DECLEXPORT_CLASS 52 #else 53 # define VBOXXML_CLASS DECLIMPORT_CLASS 54 #endif 55 56 /* 57 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a 58 * result of private data member declarations of some classes below) need to 59 * be exported too to in order to be accessible by clients. 60 * 61 * The alternative is to instantiate a template before the data member 62 * declaration with the VBOXXML_CLASS prefix, but the standard disables 63 * explicit instantiations in a foreign namespace. In other words, a declaration 64 * 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 a 69 * valid C++ construct (and G++ spits it out). So, for now we just disable the 70 * warning and will come back to this problem one day later. 71 * 72 * We also disable another warning (4275) saying that a DLL-exported class 73 * 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 #endif 80 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 xml 90 { 91 92 // Little string class for XML only 93 ////////////////////////////////////////////////////////////////////////////// 94 95 class ministring 96 { 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() const 133 { 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 // Exceptions 158 ////////////////////////////////////////////////////////////////////////////// 159 160 /** 161 * Base exception class. 162 */ 163 class VBOXXML_CLASS Error : public std::exception 164 { 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 used 203 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 Error 223 { 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 Error 234 { 235 public: 236 237 RuntimeError(const char *aMsg = NULL) 238 : xml::Error(aMsg) 239 {} 240 }; 241 242 class VBOXXML_CLASS XmlError : public RuntimeError 243 { 244 public: 245 XmlError(xmlErrorPtr aErr); 246 247 static char *Format(xmlErrorPtr aErr); 248 }; 249 250 // Logical errors 251 ////////////////////////////////////////////////////////////////////////////// 252 253 class VBOXXML_CLASS ENotImplemented : public LogicError 254 { 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 LogicError 261 { 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 LogicError 268 { 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 LogicError 275 { 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 errors 282 ////////////////////////////////////////////////////////////////////////////// 283 284 class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc 285 { 286 public: 287 ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {} 288 virtual ~ENoMemory() throw() {} 289 }; 290 291 class VBOXXML_CLASS EIPRTFailure : public RuntimeError 292 { 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 Stream 308 { 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 returned 317 * position is a zero-based byte offset from the beginning of the file. 318 * 319 * Throws ENotImplemented if this operation is not implemented for the 320 * 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 the 330 * 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 with 340 * useful functionality. 341 */ 342 class VBOXXML_CLASS Input : virtual public Stream 343 { 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 Stream 361 { 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 the 379 * 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 to 389 * regular files. 390 * 391 * The File class uses IPRT File API for file operations. Note that IPRT File 392 * API is not thread-safe. This means that if you pass the same RTFILE handle to 393 * different File instances that may be simultaneously used on different 394 * threads, you should care about serialization; otherwise you will get garbage 395 * when reading from or writing to such File instances. 396 */ 397 class VBOXXML_CLASS File : public Input, public Output 398 { 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 Read 408 * or ReadWrite, the file must exist. If @a aMode is Write, the file must 409 * 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 file 418 * 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 the 421 * beginning of the file on success. 422 * 423 * Note that the given file handle will not be automatically closed upon 424 * 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 these 428 * 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 name 438 * the corresponding file will be automatically closed. If the object was 439 * 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 the 478 * memory buffer. 479 */ 480 class VBOXXML_CLASS MemoryBuf : public Input 481 { 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 * GlobalLock 506 * 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 GlobalLock 516 { 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 content 536 * 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 nodes 545 * 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 Node 561 { 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 methods 584 Node(EnumType type); 585 Node(const Node &x); // no copying 586 587 void buildChildren(); 588 589 /* Obscure class data */ 590 struct Data; 591 Data *m; 592 }; 593 594 class VBOXXML_CLASS ElementNode : public Node 595 { 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 methods 614 ElementNode(); 615 ElementNode(const ElementNode &x); // no copying 616 617 friend class Node; 618 friend class Document; 619 friend class XmlFileParser; 620 }; 621 622 class VBOXXML_CLASS ContentNode : public Node 623 { 624 public: 625 626 protected: 627 // hide the default constructor so people use only our factory methods 628 ContentNode(); 629 ContentNode(const ContentNode &x); // no copying 630 631 friend class Node; 632 friend class ElementNode; 633 }; 634 635 class VBOXXML_CLASS AttributeNode : public Node 636 { 637 public: 638 639 protected: 640 // hide the default constructor so people use only our factory methods 641 AttributeNode(); 642 AttributeNode(const AttributeNode &x); // no copying 643 644 friend class Node; 645 friend class ElementNode; 646 }; 647 648 /* 649 * NodesLoop 650 * 651 */ 652 653 class VBOXXML_CLASS NodesLoop 654 { 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 * Document 668 * 669 */ 670 671 class VBOXXML_CLASS Document 672 { 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 * XmlParserBase 697 * 698 */ 699 700 class VBOXXML_CLASS XmlParserBase 701 { 702 protected: 703 XmlParserBase(); 704 ~XmlParserBase(); 705 706 xmlParserCtxtPtr m_ctxt; 707 }; 708 709 /* 710 * XmlFileParser 711 * 712 */ 713 714 class VBOXXML_CLASS XmlFileParser : public XmlParserBase 715 { 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 * XmlFileWriter 733 * 734 */ 735 736 class VBOXXML_CLASS XmlFileWriter 737 { 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 #endif 756 757 #endif /* IN_RING3 */ 758 759 /** @} */ 760 761 } // end namespace xml 762 763 #endif /* ___VBox_vboxxml_h */ -
trunk/src/VBox/Main/ApplianceImpl.cpp
r21073 r21077 26 26 #include <iprt/file.h> 27 27 #include <iprt/s3.h> 28 #include "iprt/xml_cpp.h"29 28 30 29 #include <VBox/param.h> … … 40 39 41 40 #include "Logging.h" 41 42 #include "VBox/xml.h" 42 43 43 44 using namespace std; … … 233 234 // 234 235 //////////////////////////////////////////////////////////////////////////////// 236 237 static Utf8Str stripFilename(const Utf8Str &strFile) 238 { 239 Utf8Str str2(strFile); 240 RTPathStripFilename(str2.mutableRaw()); 241 return str2; 242 } 235 243 236 244 static const struct … … 2238 2246 /* The disk image has to be on the same place as the OVF file. So 2239 2247 * strip the filename out of the full file path. */ 2240 Utf8Str strSrcDir(pAppliance->m->strPath); 2241 strSrcDir.stripFilename(); 2248 Utf8Str strSrcDir = stripFilename(pAppliance->m->strPath); 2242 2249 2243 2250 /* Iterate over all given disk images */ … … 3515 3522 const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf; 3516 3523 // target path needs to be composed from where the output OVF is 3517 Utf8Str strTargetFilePath(m->strPath); 3518 strTargetFilePath.stripFilename(); 3524 Utf8Str strTargetFilePath = stripFilename(m->strPath); 3519 3525 strTargetFilePath.append("/"); 3520 3526 strTargetFilePath.append(strTargetFileNameOnly); … … 3715 3721 const Utf8Str &strTargetFileNameOnly = (*itH)->strOvf; 3716 3722 /* Target path needs to be composed from where the output OVF is */ 3717 Utf8Str strTargetFilePath(m->strPath); 3718 strTargetFilePath.stripFilename(); 3723 Utf8Str strTargetFilePath = stripFilename(m->strPath); 3719 3724 strTargetFilePath.append("/"); 3720 3725 strTargetFilePath.append(strTargetFileNameOnly); … … 4731 4736 4732 4737 Utf8Str strTargetVmdkName(bstrName); 4733 strTargetVmdkName.stripExt();4738 RTPathStripExt(strTargetVmdkName.mutableRaw()); 4734 4739 strTargetVmdkName.append(".vmdk"); 4735 4740 -
trunk/src/VBox/Main/ConsoleImpl.cpp
r21073 r21077 1073 1073 for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i) 1074 1074 { 1075 Utf8Buf. reserve(cchBuf + 1024);1075 Utf8Buf.alloc(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();1084 1083 if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT) 1085 1084 return setError (E_FAIL, tr ("Internal application error")); … … 1718 1717 { 1719 1718 Utf8Str dir = stateFilePath; 1720 dir.stripFilename();1721 if (!RTDirExists (dir))1719 RTPathStripFilename (dir.mutableRaw()); 1720 if (!RTDirExists (dir)) 1722 1721 { 1723 1722 int vrc = RTDirCreateFullPath (dir, 0777); … … 3866 3865 3867 3866 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 3868 parm[0].u.pointer.addr = (void*)Utf8Name.c_str(); 3867 /* To save doing a const cast, we use the mutableRaw() member. */ 3868 parm[0].u.pointer.addr = Utf8Name.mutableRaw(); 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 Utf8Str strBuffer(pszBuffer); 3885 strBuffer.cloneTo(aValue); 3886 3884 size_t iFlags = strlen(pszBuffer) + 1; 3885 Utf8Str(pszBuffer).cloneTo (aValue); 3887 3886 *aTimestamp = parm[2].u.uint64; 3888 3889 size_t iFlags = strBuffer.length() + 1; 3890 Utf8Str(pszBuffer + iFlags).cloneTo(aFlags); 3887 Utf8Str(pszBuffer + iFlags).cloneTo (aFlags); 3891 3888 } 3892 3889 else … … 3933 3930 3934 3931 parm[0].type = VBOX_HGCM_SVC_PARM_PTR; 3935 parm[0].u.pointer.addr = (void*)Utf8Name.c_str(); 3932 /* To save doing a const cast, we use the mutableRaw() member. */ 3933 parm[0].u.pointer.addr = Utf8Name.mutableRaw(); 3936 3934 /* The + 1 is the null terminator */ 3937 3935 parm[0].u.pointer.size = (uint32_t)Utf8Name.length() + 1; … … 3940 3938 { 3941 3939 parm[1].type = VBOX_HGCM_SVC_PARM_PTR; 3942 parm[1].u.pointer.addr = (void*)Utf8Value.c_str(); 3940 /* To save doing a const cast, we use the mutableRaw() member. */ 3941 parm[1].u.pointer.addr = Utf8Value.mutableRaw(); 3943 3942 /* The + 1 is the null terminator */ 3944 3943 parm[1].u.pointer.size = (uint32_t)Utf8Value.length() + 1; … … 3948 3947 { 3949 3948 parm[2].type = VBOX_HGCM_SVC_PARM_PTR; 3950 parm[2].u.pointer.addr = (void*)Utf8Flags.c_str(); 3949 /* To save doing a const cast, we use the mutableRaw() member. */ 3950 parm[2].u.pointer.addr = Utf8Flags.mutableRaw(); 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
r21073 r21077 1814 1814 { 1815 1815 /* Pull over the properties from the server. */ 1816 SafeArray <BSTR> namesOut;1817 SafeArray <BSTR> valuesOut;1818 SafeArray <ULONG64> timestampsOut;1819 SafeArray <BSTR> flagsOut;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 <Utf8Str> utf8Names, utf8Values, utf8Flags;1832 std::vector <char *> names, values, flags;1833 std::vector <ULONG64> timestamps;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
r21073 r21077 3450 3450 AssertReturn (!mData->mConfigFileFull.isNull(), VERR_GENERAL_FAILURE); 3451 3451 3452 Utf8Str s trSettingsDir = 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))3452 Utf8Str settingsDir = mData->mConfigFileFull; 3453 3454 RTPathStripFilename (settingsDir.mutableRaw()); 3455 char folder [RTPATH_MAX]; 3456 int vrc = RTPathAbsEx (settingsDir, aPath, folder, sizeof (folder)); 3457 if (RT_SUCCESS (vrc)) 3458 3458 aResult = folder; 3459 3459 … … 3483 3483 Utf8Str settingsDir = mData->mConfigFileFull; 3484 3484 3485 settingsDir.stripFilename();3486 if (RTPathStartsWith (aPath, settingsDir))3485 RTPathStripFilename (settingsDir.mutableRaw()); 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 (aPath + settingsDir.length() + 1);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 configDir.stripFilename();5951 RTPathStripFilename (configDir.mutableRaw()); 5952 5952 newConfigDir = configDir; 5953 if (RTPathFilename (configDir) == name)5953 if (RTPathFilename (configDir) == name) 5954 5954 { 5955 newConfigDir.stripFilename();5955 RTPathStripFilename (newConfigDir.mutableRaw()); 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 path.stripFilename();6082 if (!RTDirExists (path))6083 { 6084 vrc = RTDirCreateFullPath (path, 0777);6085 if (RT_FAILURE (vrc))6080 Utf8Str path = mData->mConfigFileFull; 6081 RTPathStripFilename (path.mutableRaw()); 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 (Utf8Str *aSettingsDir /* = NULL */)7657 bool Machine::isInOwnDir (Utf8Str *aSettingsDir /* = NULL */) 7658 7658 { 7659 7659 Utf8Str settingsDir = mData->mConfigFileFull; 7660 settingsDir.stripFilename();7661 char *dirName = RTPathFilename (settingsDir);7660 RTPathStripFilename (settingsDir.mutableRaw()); 7661 char *dirName = RTPathFilename (settingsDir); 7662 7662 7663 7663 AssertReturn (dirName, false); -
trunk/src/VBox/Main/Makefile.kmk
r21073 r21077 519 519 include 520 520 VBoxSettings_SOURCES = \ 521 xml/xml.cpp \ 521 522 xml/Settings.cpp 522 523 VBoxSettings_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/$(notdir $(LIB_SETTINGS)) -Wl,-x # no debug info please. -
trunk/src/VBox/Main/SharedFolderImpl.cpp
r21073 r21077 28 28 29 29 #include <iprt/param.h> 30 #include <iprt/path.h> 30 31 #include <iprt/cpputils.h> 31 #include <iprt/path.h>32 32 33 33 // constructor / destructor … … 199 199 ; 200 200 #else 201 if (hostPathLen == 1 && RTPATH_IS_SEP (hostPath[0]))201 if (hostPathLen == 1 && RTPATH_IS_SEP (hostPath[0])) 202 202 ; 203 203 #endif 204 204 else 205 hostPath.stripTrailingSlash();205 RTPathStripTrailingSlash (hostPath.mutableRaw()); 206 206 207 207 /* Check whether the path is full (absolute) */ -
trunk/src/VBox/Main/VirtualBoxErrorInfoImpl.cpp
r21073 r21077 156 156 AssertComRC (rc); 157 157 Utf8Str message; 158 rc = aInfo->GetMessage(message.asOutParam()); 159 message.jolt(); 158 rc = aInfo->GetMessage (message.asOutParam()); 160 159 AssertComRC (rc); 161 160 mText = message; -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r21073 r21077 3870 3870 HRESULT VirtualBox::ensureFilePathExists (const char *aFileName) 3871 3871 { 3872 Utf8Str strDir(aFileName);3873 strDir.stripFilename();3874 if (!RTDirExists (strDir))3875 { 3876 int vrc = RTDirCreateFullPath (strDir, 0777);3872 Utf8Str dir = aFileName; 3873 RTPathStripFilename (dir.mutableRaw()); 3874 if (!RTDirExists (dir)) 3875 { 3876 int vrc = RTDirCreateFullPath (dir, 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 strDir.c_str(), vrc);3881 dir.raw(), vrc); 3882 3882 } 3883 3883 } -
trunk/src/VBox/Main/glue/ErrorInfo.cpp
r21073 r21077 118 118 119 119 Utf8Str message; 120 rc = ex->GetMessage(message.asOutParam()); 121 message.jolt(); 120 rc = ex->GetMessage (message.asOutParam()); 122 121 gotSomething |= NS_SUCCEEDED (rc); 123 122 if (NS_SUCCEEDED (rc)) … … 183 182 LONG lrc; 184 183 185 rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc; 184 rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc; 186 185 gotSomething |= SUCCEEDED (rc); 187 186 gotAll &= SUCCEEDED (rc); -
trunk/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp
r21073 r21077 179 179 AssertComRC (rc); 180 180 Utf8Str message; 181 rc = aInfo->GetMessage(message.asOutParam()); 182 message.jolt(); 181 rc = aInfo->GetMessage (message.asOutParam()); 183 182 AssertComRC (rc); 184 183 mText = message; -
trunk/src/VBox/Main/glue/string.cpp
r21073 r21077 26 26 27 27 #include <iprt/err.h> 28 #include <iprt/path.h>29 28 30 29 namespace com … … 86 85 87 86 size_t cbCopy = psz - pFirst; 88 ret. reserve(cbCopy + 1);89 memcpy(ret. m_psz, pFirst, cbCopy);90 ret. m_psz[cbCopy] = '\0';87 ret.alloc(cbCopy + 1); 88 memcpy(ret.str, pFirst, cbCopy); 89 ret.str[cbCopy] = '\0'; 91 90 } 92 91 } … … 96 95 } 97 96 98 bool Utf8Str::endsWith(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const99 {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 else112 return ::RTStrICmp(&m_psz[l], that.m_psz) == 0;113 }114 115 bool Utf8Str::startsWith(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const116 {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 else128 return ::RTStrNICmp(m_psz, that.m_psz, l2) == 0;129 }130 131 bool Utf8Str::contains(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const132 {133 if (cs == CaseSensitive)134 return ::RTStrStr(m_psz, that.m_psz) != NULL;135 else136 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 171 97 int Utf8Str::toInt(uint64_t &i) const 172 98 { 173 if (! m_psz)99 if (!str) 174 100 return VERR_NO_DIGITS; 175 return RTStrToUInt64Ex( m_psz, NULL, 0, &i);101 return RTStrToUInt64Ex(str, NULL, 0, &i); 176 102 } 177 103 178 104 int Utf8Str::toInt(uint32_t &i) const 179 105 { 180 if (! m_psz)106 if (!str) 181 107 return VERR_NO_DIGITS; 182 return RTStrToUInt32Ex( m_psz, NULL, 0, &i);108 return RTStrToUInt32Ex(str, NULL, 0, &i); 183 109 } 184 110 -
trunk/src/VBox/Main/include/ApplianceImpl.h
r21073 r21077 92 92 const ComObjPtr <VirtualBox, ComWeakRef> mVirtualBox; 93 93 94 struct Data; // o paque, defined in ApplianceImpl.cpp94 struct Data; // obscure, defined in AppliannceImpl.cpp 95 95 Data *m; 96 96 -
trunk/src/VBox/Main/webservice/vboxweb.cpp
r21073 r21077 603 603 * @return 604 604 */ 605 std::string ConvertComString(const com::Guid &uuid) 606 { 607 com::Bstr bstr(uuid); 605 std::string ConvertComString(const com::Guid &bstr) 606 { 608 607 com::Utf8Str ustr(bstr); 609 608 const char *pcsz; -
trunk/src/VBox/Main/xml/xml.cpp
r21073 r21077 1 /** @file 2 * 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), as 9 * 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 GNU 11 * General Public License (GPL) as published by the Free Software 12 * Foundation, in version 2 as it comes in the "COPYING" file of the 13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 * 16 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 17 * Clara, CA 95054 USA or visit http://www.sun.com if you need 18 * 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 // globals 47 // 48 //////////////////////////////////////////////////////////////////////////////// 49 50 /** 51 * Global module initialization structure. This is to wrap non-reentrant bits 52 * of libxml, among other things. 53 * 54 * The constructor and destructor of this structure are used to perform global 55 * module initiaizaton and cleanup. Thee must be only one global variable of 56 * this structure. 57 */ 58 static 59 class Global 60 { 61 public: 62 63 Global() 64 { 65 /* Check the parser version. The docs say it will kill the app if 66 * there is a serious version mismatch, but I couldn't find it in the 67 * source code (it only prints the error/warning message to the console) so 68 * let's leave it as is for informational purposes. */ 69 LIBXML_TEST_VERSION 70 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 struct 85 { 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 xml 99 { 100 101 //////////////////////////////////////////////////////////////////////////////// 102 // 103 // Exceptions 104 // 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 the 129 * returned string using RTStrFree() when no more necessary. 130 */ 131 // static 132 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 Class 160 // 161 ////////////////////////////////////////////////////////////////////////////// 162 163 struct File::Data 164 { 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 exists 187 flags = RTFILE_O_WRITE | RTFILE_O_CREATE; 188 break; 189 case Mode_Overwrite: // overwrite if file exists 190 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() const 230 { 231 return m->fileName; 232 } 233 234 uint64_t File::pos() const 235 { 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 Class 300 // 301 ////////////////////////////////////////////////////////////////////////////// 302 303 struct MemoryBuf::Data 304 { 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() const 332 { 333 return m->uri; 334 } 335 336 uint64_t MemoryBuf::pos() const 337 { 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 class 368 // 369 //////////////////////////////////////////////////////////////////////////////// 370 371 struct GlobalLock::Data 372 { 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 // static 403 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 class 413 // 414 //////////////////////////////////////////////////////////////////////////////// 415 416 struct Node::Data 417 { 418 xmlNode *plibNode; // != NULL if this is an element or content node 419 xmlAttr *plibAttr; // != NULL if this is an attribute node 420 421 Node *pParent; // NULL only for the root element 422 const char *pcszName; // element or attribute name, points either into plibNode or plibAttr; 423 // NULL if this is a content node 424 425 struct compare_const_char 426 { 427 bool operator()(const char* s1, const char* s2) const 428 { 429 return strcmp(s1, s2) < 0; 430 } 431 }; 432 433 // attributes, if this is an element; can be empty 434 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 empty 438 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() // private 457 { 458 // go thru this element's attributes 459 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 // store 468 m->attribs[pcszAttribName] = pNew; 469 470 plibAttr = plibAttr->next; 471 } 472 473 // go thru this element's child elements 474 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 else 482 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 // store 488 m->children.push_back(pNew); 489 490 // recurse for this child element to get its own children 491 pNew->buildChildren(); 492 493 plibNode = plibNode->next; 494 } 495 } 496 497 const char* Node::getName() const 498 { 499 return m->pcszName; 500 } 501 502 /** 503 * Returns the value of a node. If this node is an attribute, returns 504 * the attribute value; if this node is an element, then this returns 505 * the element text content. 506 * @return 507 */ 508 const char* Node::getValue() const 509 { 510 if ( (m->plibAttr) 511 && (m->plibAttr->children) 512 ) 513 // libxml hides attribute values in another node created as a 514 // single child of the attribute node, and it's in the content field 515 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 an 528 * integer of the given type. 529 * @return 530 */ 531 bool Node::copyValue(int32_t &i) const 532 { 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 an 545 * integer of the given type. 546 * @return 547 */ 548 bool Node::copyValue(uint32_t &i) const 549 { 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 an 562 * integer of the given type. 563 * @return 564 */ 565 bool Node::copyValue(int64_t &i) const 566 { 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 an 579 * integer of the given type. 580 * @return 581 */ 582 bool Node::copyValue(uint64_t &i) const 583 { 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 * @return 597 */ 598 int Node::getLineNumber() const 599 { 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 that 613 * match the given string; if pcszMatch is NULL, all direct child 614 * 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 const 622 { 623 int i = 0; 624 Data::InternalNodesList::const_iterator 625 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 or 633 || (!strcmp(pcszMatch, (**it).getName())) // the element name matches 634 ) 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 pcszMatch 648 * @return 649 */ 650 const ElementNode* ElementNode::findChildElement(const char *pcszMatch) 651 const 652 { 653 Data::InternalNodesList::const_iterator 654 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 matches 664 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) const 677 { 678 Data::InternalNodesList::const_iterator 679 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 pcszMatch 702 * @return 703 */ 704 const AttributeNode* ElementNode::findAttribute(const char *pcszMatch) const 705 { 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 given 717 * name and returns its value as a string. 718 * 719 * @param pcszMatch name of attribute to find. 720 * @param str out: attribute value 721 * @return TRUE if attribute was found and str was thus updated. 722 */ 723 bool ElementNode::getAttributeValue(const char *pcszMatch, const char *&ppcsz) const 724 { 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 given 737 * name and returns its value as a signed long integer. This calls 738 * RTStrToInt64Ex internally and will only output the integer if that 739 * function returns no error. 740 * 741 * @param pcszMatch name of attribute to find. 742 * @param i out: attribute value 743 * @return TRUE if attribute was found and str was thus updated. 744 */ 745 bool ElementNode::getAttributeValue(const char *pcszMatch, int64_t &i) const 746 { 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 given 758 * name and returns its value as an unsigned long integer.This calls 759 * RTStrToUInt64Ex internally and will only output the integer if that 760 * function returns no error. 761 * 762 * @param pcszMatch name of attribute to find. 763 * @param i out: attribute value 764 * @return TRUE if attribute was found and str was thus updated. 765 */ 766 bool ElementNode::getAttributeValue(const char *pcszMatch, uint64_t &i) const 767 { 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 list 779 * of children in "this". 780 * 781 * @param pcszElementName 782 * @return 783 */ 784 ElementNode* ElementNode::createChild(const char *pcszElementName) 785 { 786 // we must be an element, not an attribute 787 if (!m->plibNode) 788 throw ENodeIsNotElement(RT_SRC_POS); 789 790 // libxml side: create new node 791 xmlNode *plibNode; 792 if (!(plibNode = xmlNewNode(NULL, // namespace 793 (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 children 811 * in "this". 812 * 813 * @param pcszElementName 814 * @return 815 */ 816 ContentNode* ElementNode::addContent(const char *pcszContent) 817 { 818 // libxml side: create new node 819 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 node 840 * that was either created or changed. 841 * 842 * @param pcszName 843 * @param pcszValue 844 * @return 845 */ 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 attribute 854 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 it 858 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 // store 863 m->attribs[pcszAttribName] = pNew; 864 } 865 else 866 { 867 // @todo 868 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 * NodesLoop 888 * 889 */ 890 891 struct NodesLoop::Data 892 { 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 an 912 * instance of NodesLoop on the stack and call this method until it returns 913 * NULL, like this: 914 * <code> 915 * xml::Node node; // should point to an element 916 * xml::NodesLoop loop(node, "child"); // find all "child" elements under node 917 * const xml::Node *pChild = NULL; 918 * while (pChild = loop.forAllNodes()) 919 * ...; 920 * </code> 921 * @param node 922 * @param pcszMatch 923 * @return 924 */ 925 const ElementNode* NodesLoop::forAllNodes() const 926 { 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 class 941 // 942 //////////////////////////////////////////////////////////////////////////////// 943 944 struct Document::Data 945 { 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 all 980 } 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 pDocument 1009 * has changed. Called from XmlFileParser::read(). m->reset() must have been 1010 * called before to make sure all members except the internal pDocument are clean. 1011 */ 1012 void Document::refreshInternals() // private 1013 { 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 * @return 1024 */ 1025 const ElementNode* Document::getRootElement() const 1026 { 1027 return m->pRootElement; 1028 } 1029 1030 /** 1031 * Creates a new element node and sets it as the root element. This will 1032 * 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 node 1040 m->plibDocument = xmlNewDoc((const xmlChar*)"1.0"); 1041 xmlNode *plibRootNode; 1042 if (!(plibRootNode = xmlNewNode(NULL, // namespace 1043 (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 class 1058 // 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 class 1077 // 1078 //////////////////////////////////////////////////////////////////////////////// 1079 1080 struct XmlFileParser::Data 1081 { 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 IOContext 1111 { 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 : IOContext 1132 { 1133 ReadContext(const char *pcszFilename) 1134 : IOContext(pcszFilename, File::Mode_Read) 1135 { 1136 } 1137 }; 1138 1139 struct WriteContext : IOContext 1140 { 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 = auto 1172 XML_PARSE_NOBLANKS))) 1173 throw XmlError(xmlCtxtGetLastError(m->ctxt)); 1174 1175 doc.refreshInternals(); 1176 } 1177 1178 // static 1179 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 catch 1184 * them and forward to our level using a couple of variables. */ 1185 1186 try 1187 { 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 written 1201 1202 return -1; 1203 } 1204 1205 //////////////////////////////////////////////////////////////////////////////// 1206 // 1207 // XmlFileWriter class 1208 // 1209 //////////////////////////////////////////////////////////////////////////////// 1210 1211 struct XmlFileWriter::Data 1212 { 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 catch 1266 * them and forward to our level using a couple of variables. */ 1267 try 1268 { 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 written 1282 1283 return -1; 1284 } 1285 1286 1287 } // end namespace xml 1288 1289 -
trunk/src/VBox/Runtime/Makefile.kmk
r21073 r21077 51 51 LIBRARIES += RuntimeR3 52 52 DLLS += VBoxRT 53 54 # Temporary(?) hack. 55 VBOX_WITH_LIBXML2_IN_VBOXRT= 53 56 54 57 else # !VBOX_ONLY_ADDITIONS && !VBOX_ONLY_DOCS … … 162 165 # 163 166 RuntimeR3_TEMPLATE = VBOXR3STATIC 164 RuntimeR3_SDKS = VBOX_LIBXML2165 167 RuntimeR3_SDKS.win = WINPSDK W2K3DDK 166 168 RuntimeR3_DEFS = IN_RT_R3 IN_SUP_R3 LDR_WITH_NATIVE LDR_WITH_ELF32 LDR_WITH_PE RT_WITH_VBOX RT_NO_GIP … … 304 306 r3/test.cpp \ 305 307 r3/testi.cpp \ 306 r3/tcp.cpp \ 307 r3/xml.cpp 308 r3/tcp.cpp 308 309 309 310 #if1of ($(KBUILD_TARGET_ARCH),amd64 x86) … … 786 787 # 787 788 VBoxRT_TEMPLATE = VBOXR3 789 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 788 790 VBoxRT_SDKS = VBOX_OPENSSL VBOX_LIBXML2 VBOX_LIBCURL 791 endif 789 792 VBoxRT_SDKS.win = WINPSDK W2K3DDK VBOX_NTDLL 790 793 ifeq ($(KBUILD_TARGET)$(VBOX_WITH_HARDENING),darwin) … … 796 799 VBox/VBoxRTDeps.cpp \ 797 800 $(RuntimeR3_SOURCES) 801 if defined(VBOX_WITH_LIBXML2_IN_VBOXRT) 798 802 VBoxRT_SOURCES += \ 799 803 common/misc/s3.cpp 804 endif 800 805 VBoxRT_SOURCES.$(KBUILD_TARGET) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET)) 801 806 VBoxRT_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)) … … 813 818 $(PATH_LIB)/VBox-kStuff$(VBOX_SUFF_LIB) 814 819 endif 820 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 821 ifndef SDK_VBOX_LIBXML2_LIBS 815 822 VBoxRT_LIBS += \ 816 823 $(PATH_LIB)/VBox-libxml2$(VBOX_SUFF_LIB) 824 endif 825 ifndef SDK_VBOX_OPENSSL_LIBS 817 826 VBoxRT_LIBS += \ 818 827 $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB) 828 endif 829 endif 819 830 VBoxRT_LIBS.darwin = \ 820 831 iconv … … 840 851 $(PATH_LIB)/RuntimeR3L4$(VBOX_SUFF_LIB) 841 852 853 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 854 VBox/VBoxRTDeps.cpp_DEFS = VBOX_WITH_LIBXML2_IN_VBOXRT 855 endif 856 842 857 if1of ($(DLLS), VBoxRT) 843 858 $$(VBoxRT_0_OUTDIR)/VBoxRT.def: \ 844 859 $(PATH_SUB_CURRENT)/r3/win/VBoxRT-$$(if-expr $$(KBUILD_TARGET_ARCH) == amd64,win64,win32).def \ 845 $( PATH_SUB_CURRENT)/r3/win/$(if $(VBOX_OSE),VBoxRT-openssl-ose.def,VBoxRT-openssl.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),) 846 861 $(RM) -f -- $@ 847 862 $(REDIRECT) -wto $@ -- $(CAT_EXT) $^ -
trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp
r21073 r21077 36 36 #include <iprt/assert.h> 37 37 #include <iprt/asm.h> 38 38 #ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 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 #endif 46 47 47 48 … … 54 55 (PFNRT)SUPR3PageAllocEx, 55 56 (PFNRT)SUPSemEventCreate, 57 #ifdef VBOX_WITH_LIBXML2_IN_VBOXRT 56 58 (PFNRT)xmlModuleOpen, 57 59 (PFNRT)MD5_Init, … … 63 65 (PFNRT)i2d_X509, 64 66 (PFNRT)RSA_generate_key, 67 #endif 65 68 (PFNRT)RTAssertShouldPanic, 66 69 (PFNRT)ASMAtomicReadU64, -
trunk/src/VBox/Runtime/testcase/tstUtf8.cpp
r21073 r21077 42 42 #include <iprt/err.h> 43 43 #include <iprt/test.h> 44 #include <iprt/ministring_cpp.h>45 44 46 45 #include <stdlib.h> /** @todo use our random. */ … … 927 926 928 927 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 // 12345678965 // ^966 // 0123456967 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 KB980 CHECK_DUMP( (third == "newstring 123456"), morebytes.c_str() );981 CHECK( (third.capacity() == 100 * 1024) );982 CHECK( (third.length() == morebytes.length()) ); // must not have changed983 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 loops1004 copy2.append("1");1005 }1006 CHECK( (copy2.length() == 100) );1007 1008 #undef CHECK1009 }1010 1011 928 int main() 1012 929 { … … 1029 946 TstRTStrXCmp(hTest); 1030 947 testStrStr(hTest); 1031 1032 testMinistring(hTest);1033 1034 948 Benchmarks(hTest); 1035 949
Note:
See TracChangeset
for help on using the changeset viewer.

