VirtualBox

Changeset 21073 in vbox


Ignore:
Timestamp:
Jun 30, 2009 3:01:09 PM (15 years ago)
Author:
vboxsync
Message:

Main: move libxml2 to IPRT unconditionally (remove VBOX_WITH_LIBXML2_IN_VBOXRT); move xml classes to IPRT; introduce IPRT ministring class as base for both Utf8Str and xml.cpp, with better performance (remembers string lengths and can thus use memcpy instead of strdup); introduce some Utf8Str helpers to avoid string buffer hacks in Main code

Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r21067 r21073  
    490490## Use the new version of liblzf. Remove with the old liblzf.
    491491#VBOX_WITH_NEW_LIBLZF = 1
    492 ## For experimenting with linking libxml2 into VBoxRT.
    493 VBOX_WITH_LIBXML2_IN_VBOXRT = 1
    494492
    495493## For experimenting with disabling preemption instead of interrupts
     
    17991797#
    18001798SDK_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
     1799SDK_VBOX_LIBXML2_INCS   ?= $(PATH_ROOT)/src/libs/libxml2-2.6.30/include
     1800SDK_VBOX_LIBXML2_DEFS  ?= _REENTRANT
     1801SDK_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
    18201804
    18211805SDK_VBOX_LIBXSLT          = .
     
    18531837SDK_VBOX_OPENSSL_INCS ?= $(SDK_VBOX_OPENSSL_VBOX_DEFAULT_INCS)
    18541838SDK_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
     1839SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB)
    18581840# Build entire openssl library, not just the minimal subset.
    18591841if1of ($(KBUILD_TARGET), linux solaris)
  • trunk/include/VBox/com/string.h

    r18589 r21073  
    4949#include "VBox/com/assert.h"
    5050
    51 #include <iprt/string.h>
    5251#include <iprt/cpputils.h>
    5352#include <iprt/alloc.h>
     53#include <iprt/ministring_cpp.h>
    5454
    5555namespace com
     
    153153    }
    154154
    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); }
    159159
    160160#if defined (VBOX_WITH_XPCOM)
    161     bool operator != (const wchar_t *that) const
     161    bool operator!=(const wchar_t *that) const
    162162    {
    163163        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
    164164        return !!compare ((CBSTR) that);
    165165    }
    166     bool operator == (const wchar_t *that) const
     166    bool operator==(const wchar_t *that) const
    167167    {
    168168        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
     
    171171#endif
    172172
    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; }
    178178#if defined (VBOX_WITH_XPCOM)
    179     bool operator < (const wchar_t *that) const
     179    bool operator<(const wchar_t *that) const
    180180    {
    181181        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
     
    303303
    304304/* 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); }
     305inline bool operator==(CBSTR l, const Bstr &r) { return r.operator== (l); }
     306inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!= (l); }
     307inline bool operator==(BSTR l, const Bstr &r) { return r.operator== (l); }
     308inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!= (l); }
    309309
    310310////////////////////////////////////////////////////////////////////////////////
     
    324324 *    afterwards.
    325325 */
    326 class Utf8Str
     326class Utf8Str : public ministring
    327327{
    328328public:
    329329
    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    }
    560375
    561376    /**
     
    564379     *  caller.
    565380     */
    566     const Utf8Str &cloneTo (char **pstr) const
     381    const Utf8Str& cloneTo(char **pstr) const
    567382    {
    568383        if (pstr)
    569         {
    570             *pstr = NULL;
    571             raw_copy (*pstr, str);
    572         }
     384            *pstr = RTStrDup(m_psz);
    573385        return *this;
    574386    }
     
    582394     *  string.
    583395     */
    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;
    588402        return *this;
    589403    }
     
    594408     *  caller.
    595409     */
    596     const Utf8Str &cloneTo (BSTR *pstr) const
     410    const Utf8Str& cloneTo(BSTR *pstr) const
    597411    {
    598412        if (pstr)
    599413        {
    600414            *pstr = NULL;
    601             Bstr::raw_copy (*pstr, str);
     415            Bstr::raw_copy(*pstr, m_psz);
    602416        }
    603417        return *this;
     
    623437
    624438    /**
    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.
    626492     *
    627493     * @returns 32-bit unsigned number on success.
     
    630496    int toInt32() const
    631497    {
    632         return RTStrToInt32(str);
     498        return RTStrToInt32(m_psz);
    633499    }
    634500
     
    641507    int toUInt32() const
    642508    {
    643         return RTStrToUInt32(str);
     509        return RTStrToUInt32(m_psz);
    644510    }
    645511
     
    652518    int64_t toInt64() const
    653519    {
    654         return RTStrToInt64(str);
     520        return RTStrToInt64(m_psz);
    655521    }
    656522
     
    663529    uint64_t toUInt64() const
    664530    {
    665         return RTStrToUInt64(str);
     531        return RTStrToUInt64(m_psz);
    666532    }
    667533
     
    684550     *  Takes the ownership of the returned data.
    685551     */
    686     char **asOutParam() { setNull(); return &str; }
     552    char **asOutParam()
     553    {
     554        cleanup();
     555        return &m_psz;
     556    }
    687557
    688558    /**
     
    693563protected:
    694564
    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    }
    730592
    731593    friend class Bstr; /* to access our raw_copy() */
    732594};
    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); }
    737595
    738596// work around error C2593 of the stupid MSVC 7.x ambiguity resolver
     
    760618}
    761619
    762 inline const Bstr &Bstr::cloneTo (char **pstr) const
    763 {
    764     if (pstr) {
    765         *pstr = NULL;
    766         Utf8Str::raw_copy (*pstr, bstr);
     620inline const Bstr& Bstr::cloneTo(char **pstr) const
     621{
     622    if (pstr)
     623    {
     624        Utf8Str ustr(*this);
     625        ustr.detachTo(pstr);
    767626    }
    768627    return *this;
  • trunk/include/VBox/settings.h

    r16560 r21073  
    3131#define ___VBox_settings_h
    3232
     33#include <limits>
     34
    3335#include <iprt/cdefs.h>
    3436#include <iprt/cpputils.h>
    35 #include <iprt/string.h>
    36 
    37 #include <list>
    38 #include <memory>
    39 #include <limits>
    40 
    4137#include <iprt/time.h>
     38#include <iprt/xml_cpp.h>
    4239
    4340#include <VBox/com/Guid.h>
    44 
    45 #include <VBox/xml.h>
    46 
    47 // #include <stdarg.h>
    4841
    4942/* these conflict with numeric_digits<>::min and max */
  • trunk/include/VBox/xml.h

    r19530 r21073  
    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

    r21068 r21073  
    2626#include <iprt/file.h>
    2727#include <iprt/s3.h>
     28#include "iprt/xml_cpp.h"
    2829
    2930#include <VBox/param.h>
     
    3940
    4041#include "Logging.h"
    41 
    42 #include "VBox/xml.h"
    4342
    4443using namespace std;
     
    234233//
    235234////////////////////////////////////////////////////////////////////////////////
    236 
    237 static Utf8Str stripFilename(const Utf8Str &strFile)
    238 {
    239     Utf8Str str2(strFile);
    240     RTPathStripFilename(str2.mutableRaw());
    241     return str2;
    242 }
    243235
    244236static const struct
     
    22462238                    /* The disk image has to be on the same place as the OVF file. So
    22472239                     * 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();
    22492242
    22502243                    /* Iterate over all given disk images */
     
    35223515            const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf;
    35233516            // 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();
    35253519            strTargetFilePath.append("/");
    35263520            strTargetFilePath.append(strTargetFileNameOnly);
     
    37213715                const Utf8Str &strTargetFileNameOnly = (*itH)->strOvf;
    37223716                /* 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();
    37243719                strTargetFilePath.append("/");
    37253720                strTargetFilePath.append(strTargetFileNameOnly);
     
    47364731
    47374732            Utf8Str strTargetVmdkName(bstrName);
    4738             RTPathStripExt(strTargetVmdkName.mutableRaw());
     4733            strTargetVmdkName.stripExt();
    47394734            strTargetVmdkName.append(".vmdk");
    47404735
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r20928 r21073  
    10731073    for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i)
    10741074    {
    1075         Utf8Buf.alloc(cchBuf + 1024);
     1075        Utf8Buf.reserve(cchBuf + 1024);
    10761076        if (Utf8Buf.isNull())
    10771077            return E_OUTOFMEMORY;
     
    10811081        vrc = mVMMDev->hgcmHostCall ("VBoxGuestPropSvc", ENUM_PROPS_HOST, 3,
    10821082                                     &parm[0]);
     1083        Utf8Buf.jolt();
    10831084        if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT)
    10841085            return setError (E_FAIL, tr ("Internal application error"));
     
    17171718        {
    17181719            Utf8Str dir = stateFilePath;
    1719             RTPathStripFilename (dir.mutableRaw());
    1720             if (!RTDirExists (dir))
     1720            dir.stripFilename();
     1721            if (!RTDirExists(dir))
    17211722            {
    17221723                int vrc = RTDirCreateFullPath (dir, 0777);
     
    38653866
    38663867    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();
    38693869    /* The + 1 is the null terminator */
    38703870    parm[0].u.pointer.size = (uint32_t)Utf8Name.length() + 1;
     
    38823882        if (vrc != VERR_NOT_FOUND)
    38833883        {
    3884             size_t iFlags = strlen(pszBuffer) + 1;
    3885             Utf8Str(pszBuffer).cloneTo (aValue);
     3884            Utf8Str strBuffer(pszBuffer);
     3885            strBuffer.cloneTo(aValue);
     3886
    38863887            *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);
    38883891        }
    38893892        else
     
    39303933
    39313934    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();
    39343936    /* The + 1 is the null terminator */
    39353937    parm[0].u.pointer.size = (uint32_t)Utf8Name.length() + 1;
     
    39383940    {
    39393941        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();
    39423943        /* The + 1 is the null terminator */
    39433944        parm[1].u.pointer.size = (uint32_t)Utf8Value.length() + 1;
     
    39473948    {
    39483949        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();
    39513951        /* The + 1 is the null terminator */
    39523952        parm[2].u.pointer.size = (uint32_t)Utf8Flags.length() + 1;
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r20995 r21073  
    18141814        {
    18151815            /* 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;
    18201820            hrc = pConsole->mControl->PullGuestProperties(ComSafeArrayAsOutParam(namesOut),
    18211821                                                ComSafeArrayAsOutParam(valuesOut),
     
    18291829                rc = VERR_INVALID_PARAMETER;
    18301830
    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;
    18341834            for (unsigned i = 0; i < cProps && RT_SUCCESS(rc); ++i)
    18351835                if (   !VALID_PTR(namesOut[i])
  • trunk/src/VBox/Main/MachineImpl.cpp

    r21002 r21073  
    34503450    AssertReturn (!mData->mConfigFileFull.isNull(), VERR_GENERAL_FAILURE);
    34513451
    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))
     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))
    34583458        aResult = folder;
    34593459
     
    34833483    Utf8Str settingsDir = mData->mConfigFileFull;
    34843484
    3485     RTPathStripFilename (settingsDir.mutableRaw());
    3486     if (RTPathStartsWith (aPath, settingsDir))
     3485    settingsDir.stripFilename();
     3486    if (RTPathStartsWith(aPath, settingsDir))
    34873487    {
    34883488        /* when assigning, we create a separate Utf8Str instance because both
     
    34913491         * first, and since its the same as aPath, an attempt to copy garbage
    34923492         * will be made. */
    3493         aResult = Utf8Str (aPath + settingsDir.length() + 1);
     3493        aResult = Utf8Str(aPath + settingsDir.length() + 1);
    34943494    }
    34953495}
     
    59495949            /* first, rename the directory if it matches the machine name */
    59505950            configDir = configFile;
    5951             RTPathStripFilename (configDir.mutableRaw());
     5951            configDir.stripFilename();
    59525952            newConfigDir = configDir;
    5953             if (RTPathFilename (configDir) == name)
     5953            if (RTPathFilename(configDir) == name)
    59545954            {
    5955                 RTPathStripFilename (newConfigDir.mutableRaw());
     5955                newConfigDir.stripFilename();
    59565956                newConfigDir = Utf8StrFmt ("%s%c%s",
    59575957                    newConfigDir.raw(), RTPATH_DELIMITER, newName.raw());
     
    60786078
    60796079        /* ensure the settings directory exists */
    6080         Utf8Str path = mData->mConfigFileFull;
    6081         RTPathStripFilename (path.mutableRaw());
    6082         if (!RTDirExists (path))
    6083         {
    6084             vrc = RTDirCreateFullPath (path, 0777);
    6085             if (RT_FAILURE (vrc))
     6080        Utf8Str path(mData->mConfigFileFull);
     6081        path.stripFilename();
     6082        if (!RTDirExists(path))
     6083        {
     6084            vrc = RTDirCreateFullPath(path, 0777);
     6085            if (RT_FAILURE(vrc))
    60866086            {
    60876087                return setError (E_FAIL,
     
    76557655 *  @note Not thread safe (must be called from this object's lock).
    76567656 */
    7657 bool Machine::isInOwnDir (Utf8Str *aSettingsDir /* = NULL */)
     7657bool Machine::isInOwnDir(Utf8Str *aSettingsDir /* = NULL */)
    76587658{
    76597659    Utf8Str settingsDir = mData->mConfigFileFull;
    7660     RTPathStripFilename (settingsDir.mutableRaw());
    7661     char *dirName = RTPathFilename (settingsDir);
     7660    settingsDir.stripFilename();
     7661    char *dirName = RTPathFilename(settingsDir);
    76627662
    76637663    AssertReturn (dirName, false);
  • trunk/src/VBox/Main/Makefile.kmk

    r20932 r21073  
    519519        include
    520520VBoxSettings_SOURCES    = \
    521         xml/xml.cpp \
    522521        xml/Settings.cpp
    523522VBoxSettings_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  
    2828
    2929#include <iprt/param.h>
     30#include <iprt/cpputils.h>
    3031#include <iprt/path.h>
    31 #include <iprt/cpputils.h>
    3232
    3333// constructor / destructor
     
    199199        ;
    200200#else
    201     if (hostPathLen == 1 && RTPATH_IS_SEP (hostPath[0]))
     201    if (hostPathLen == 1 && RTPATH_IS_SEP(hostPath[0]))
    202202        ;
    203203#endif
    204204    else
    205         RTPathStripTrailingSlash (hostPath.mutableRaw());
     205        hostPath.stripTrailingSlash();
    206206
    207207    /* Check whether the path is full (absolute) */
  • trunk/src/VBox/Main/VirtualBoxErrorInfoImpl.cpp

    r20267 r21073  
    156156    AssertComRC (rc);
    157157    Utf8Str message;
    158     rc = aInfo->GetMessage (message.asOutParam());
     158    rc = aInfo->GetMessage(message.asOutParam());
     159    message.jolt();
    159160    AssertComRC (rc);
    160161    mText = message;
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r20978 r21073  
    38703870HRESULT VirtualBox::ensureFilePathExists (const char *aFileName)
    38713871{
    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);
    38773877        if (RT_FAILURE (vrc))
    38783878        {
    38793879            return setError (E_FAIL,
    38803880                tr ("Could not create the directory '%s' (%Rrc)"),
    3881                 dir.raw(), vrc);
     3881                strDir.c_str(), vrc);
    38823882        }
    38833883    }
  • trunk/src/VBox/Main/glue/ErrorInfo.cpp

    r20267 r21073  
    118118
    119119                    Utf8Str message;
    120                     rc = ex->GetMessage (message.asOutParam());
     120                    rc = ex->GetMessage(message.asOutParam());
     121                    message.jolt();
    121122                    gotSomething |= NS_SUCCEEDED (rc);
    122123                    if (NS_SUCCEEDED (rc))
     
    182183    LONG lrc;
    183184
    184     rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc;   
     185    rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc;
    185186    gotSomething |= SUCCEEDED (rc);
    186187    gotAll &= SUCCEEDED (rc);
  • trunk/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp

    r20267 r21073  
    179179    AssertComRC (rc);
    180180    Utf8Str message;
    181     rc = aInfo->GetMessage (message.asOutParam());
     181    rc = aInfo->GetMessage(message.asOutParam());
     182    message.jolt();
    182183    AssertComRC (rc);
    183184    mText = message;
  • trunk/src/VBox/Main/glue/string.cpp

    r17634 r21073  
    2626
    2727#include <iprt/err.h>
     28#include <iprt/path.h>
    2829
    2930namespace com
     
    8586
    8687                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';
    9091            }
    9192        }
     
    9596}
    9697
     98bool 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
     115bool 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
     131bool 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
     139Utf8Str& Utf8Str::toLower()
     140{
     141    if (!isEmpty())
     142        ::RTStrToLower(m_psz);
     143    return *this;
     144}
     145
     146Utf8Str& Utf8Str::toUpper()
     147{
     148    if (!isEmpty())
     149        ::RTStrToUpper(m_psz);
     150    return *this;
     151}
     152
     153void Utf8Str::stripTrailingSlash()
     154{
     155    RTPathStripTrailingSlash(m_psz);
     156    jolt();
     157}
     158
     159void Utf8Str::stripFilename()
     160{
     161    RTPathStripFilename(m_psz);
     162    jolt();
     163}
     164
     165void Utf8Str::stripExt()
     166{
     167    RTPathStripExt(m_psz);
     168    jolt();
     169}
     170
    97171int Utf8Str::toInt(uint64_t &i) const
    98172{
    99     if (!str)
     173    if (!m_psz)
    100174        return VERR_NO_DIGITS;
    101     return RTStrToUInt64Ex(str, NULL, 0, &i);
     175    return RTStrToUInt64Ex(m_psz, NULL, 0, &i);
    102176}
    103177
    104178int Utf8Str::toInt(uint32_t &i) const
    105179{
    106     if (!str)
     180    if (!m_psz)
    107181        return VERR_NO_DIGITS;
    108     return RTStrToUInt32Ex(str, NULL, 0, &i);
     182    return RTStrToUInt32Ex(m_psz, NULL, 0, &i);
    109183}
    110184
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r20082 r21073  
    9292    const ComObjPtr <VirtualBox, ComWeakRef> mVirtualBox;
    9393
    94     struct Data;            // obscure, defined in AppliannceImpl.cpp
     94    struct Data;            // opaque, defined in ApplianceImpl.cpp
    9595    Data *m;
    9696
  • trunk/src/VBox/Main/webservice/vboxweb.cpp

    r20928 r21073  
    603603 * @return
    604604 */
    605 std::string ConvertComString(const com::Guid &bstr)
    606 {
     605std::string ConvertComString(const com::Guid &uuid)
     606{
     607    com::Bstr bstr(uuid);
    607608    com::Utf8Str ustr(bstr);
    608609    const char *pcsz;
  • trunk/src/VBox/Main/xml/xml.cpp

    r19530 r21073  
    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

    r21046 r21073  
    5151 LIBRARIES += RuntimeR3
    5252 DLLS += VBoxRT
    53 
    54  # Temporary(?) hack.
    55  VBOX_WITH_LIBXML2_IN_VBOXRT=
    5653
    5754else # !VBOX_ONLY_ADDITIONS && !VBOX_ONLY_DOCS
     
    165162#
    166163RuntimeR3_TEMPLATE      = VBOXR3STATIC
     164RuntimeR3_SDKS          = VBOX_LIBXML2
    167165RuntimeR3_SDKS.win      = WINPSDK W2K3DDK
    168166RuntimeR3_DEFS          = IN_RT_R3 IN_SUP_R3 LDR_WITH_NATIVE LDR_WITH_ELF32 LDR_WITH_PE RT_WITH_VBOX RT_NO_GIP
     
    306304        r3/test.cpp \
    307305        r3/testi.cpp \
    308         r3/tcp.cpp
     306        r3/tcp.cpp \
     307        r3/xml.cpp
    309308
    310309#if1of ($(KBUILD_TARGET_ARCH),amd64 x86)
     
    787786#
    788787VBoxRT_TEMPLATE                = VBOXR3
    789 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    790788VBoxRT_SDKS                    = VBOX_OPENSSL VBOX_LIBXML2 VBOX_LIBCURL
    791 endif
    792789VBoxRT_SDKS.win                = WINPSDK W2K3DDK VBOX_NTDLL
    793790ifeq ($(KBUILD_TARGET)$(VBOX_WITH_HARDENING),darwin)
     
    799796        VBox/VBoxRTDeps.cpp \
    800797        $(RuntimeR3_SOURCES)
    801 if defined(VBOX_WITH_LIBXML2_IN_VBOXRT)
    802798VBoxRT_SOURCES                += \
    803799        common/misc/s3.cpp
    804 endif
    805800VBoxRT_SOURCES.$(KBUILD_TARGET) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET))
    806801VBoxRT_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))
     
    818813        $(PATH_LIB)/VBox-kStuff$(VBOX_SUFF_LIB)
    819814endif
    820 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    821  ifndef SDK_VBOX_LIBXML2_LIBS
    822815  VBoxRT_LIBS                 += \
    823816        $(PATH_LIB)/VBox-libxml2$(VBOX_SUFF_LIB)
    824  endif
    825  ifndef SDK_VBOX_OPENSSL_LIBS
    826817  VBoxRT_LIBS                 += \
    827818        $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB)
    828  endif
    829 endif
    830819VBoxRT_LIBS.darwin             = \
    831820        iconv
     
    851840        $(PATH_LIB)/RuntimeR3L4$(VBOX_SUFF_LIB)
    852841
    853 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    854 VBox/VBoxRTDeps.cpp_DEFS = VBOX_WITH_LIBXML2_IN_VBOXRT
    855 endif
    856 
    857842if1of ($(DLLS), VBoxRT)
    858843$$(VBoxRT_0_OUTDIR)/VBoxRT.def: \
    859844                $(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)
    861846        $(RM) -f -- $@
    862847        $(REDIRECT) -wto $@ -- $(CAT_EXT) $^
  • trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp

    r20862 r21073  
    3636#include <iprt/assert.h>
    3737#include <iprt/asm.h>
    38 #ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
     38
    3939# include <libxml/xmlmodule.h>
    4040# include <libxml/globals.h>
     
    4444# include <openssl/x509.h>
    4545# include <openssl/rsa.h>
    46 #endif
    4746
    4847
     
    5554    (PFNRT)SUPR3PageAllocEx,
    5655    (PFNRT)SUPSemEventCreate,
    57 #ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    5856    (PFNRT)xmlModuleOpen,
    5957    (PFNRT)MD5_Init,
     
    6563    (PFNRT)i2d_X509,
    6664    (PFNRT)RSA_generate_key,
    67 #endif
    6865    (PFNRT)RTAssertShouldPanic,
    6966    (PFNRT)ASMAtomicReadU64,
  • trunk/src/VBox/Runtime/testcase/tstUtf8.cpp

    r20606 r21073  
    4242#include <iprt/err.h>
    4343#include <iprt/test.h>
     44#include <iprt/ministring_cpp.h>
    4445
    4546#include <stdlib.h> /** @todo use our random. */
     
    926927
    927928
     929void 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
    9281011int main()
    9291012{
     
    9461029    TstRTStrXCmp(hTest);
    9471030    testStrStr(hTest);
     1031
     1032    testMinistring(hTest);
     1033
    9481034    Benchmarks(hTest);
    9491035
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette