VirtualBox

Changeset 21077 in vbox


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

back out r49329, r49331, will start over

Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r21073 r21077  
    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.
     493VBOX_WITH_LIBXML2_IN_VBOXRT = 1
    492494
    493495## For experimenting with disabling preemption instead of interrupts
     
    17971799#
    17981800SDK_VBOX_LIBXML2          = .
    1799 SDK_VBOX_LIBXML2_INCS   ?= $(PATH_ROOT)/src/libs/libxml2-2.6.30/include
    1800 SDK_VBOX_LIBXML2_DEFS  ?= _REENTRANT
    1801 SDK_VBOX_LIBXML2_DEFS.win += WIN32 _WINDOWS _MBCS
    1802 # note: no linking to LIB here, we do that explicitly in src/VBox/Runtime/Makefile.kmk to link
    1803 # libxml against VBoxRT
     1801#if1of ($(KBUILD_TARGET),win os2 solaris)
     1802 SDK_VBOX_LIBXML2_INCS   ?= $(PATH_ROOT)/src/libs/libxml2-2.6.30/include
     1803 ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
     1804  SDK_VBOX_LIBXML2_DEFS  ?= _REENTRANT
     1805 else
     1806  SDK_VBOX_LIBXML2_DEFS  ?= LIBXML_STATIC _REENTRANT
     1807  SDK_VBOX_LIBXML2_LIBS  ?= $(PATH_LIB)/VBox-libxml2$(VBOX_SUFF_LIB)
     1808 endif
     1809 SDK_VBOX_LIBXML2_DEFS.win += WIN32 _WINDOWS _MBCS
     1810#else if1of ($(KBUILD_TARGET),linux)
     1811# SDK_VBOX_LIBXML2_INCS      ?=
     1812# SDK_VBOX_LIBXML2_LIBS      ?=
     1813# SDK_VBOX_LIBXML2_CFLAGS    ?= $(shell pkg-config libxml-2.0 --cflags)
     1814# SDK_VBOX_LIBXML2_CXXFLAGS  ?= $(SDK_VBOX_LIBXML2_CFLAGS)
     1815# SDK_VBOX_LIBXML2_LDFLAGS   ?= $(shell pkg-config libxml-2.0 --libs)
     1816#else
     1817# SDK_VBOX_LIBXML2_INCS   ?=
     1818# SDK_VBOX_LIBXML2_LIBS   ?= xml2
     1819#endif
    18041820
    18051821SDK_VBOX_LIBXSLT          = .
     
    18371853SDK_VBOX_OPENSSL_INCS ?= $(SDK_VBOX_OPENSSL_VBOX_DEFAULT_INCS)
    18381854SDK_VBOX_OPENSSL_ORDERDEPS ?= $(crypto-headers_1_TARGET)
    1839 SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB)
     1855ifndef VBOX_WITH_LIBXML2_IN_VBOXRT
     1856 SDK_VBOX_OPENSSL_LIBS ?= $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB)
     1857endif
    18401858# Build entire openssl library, not just the minimal subset.
    18411859if1of ($(KBUILD_TARGET), linux solaris)
  • trunk/include/VBox/com/string.h

    r21073 r21077  
    4949#include "VBox/com/assert.h"
    5050
     51#include <iprt/string.h>
    5152#include <iprt/cpputils.h>
    5253#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 : public ministring
     326class Utf8Str
    327327{
    328328public:
    329329
    330     Utf8Str() {}
    331 
    332     Utf8Str(const Utf8Str &that)
    333         : ministring(that)
    334     {}
    335 
    336     Utf8Str(const char *that)
    337         : ministring(that)
    338     {}
    339 
    340     Utf8Str(const Bstr &that)
    341     {
    342         copyFrom(that);
    343     }
    344 
    345     Utf8Str(CBSTR that)
    346     {
    347         copyFrom(that);
    348     }
    349 
    350     Utf8Str& operator=(const Utf8Str &that)
    351     {
    352         ministring::operator=(that);
    353         return *this;
    354     }
    355 
    356     Utf8Str& operator=(const char *that)
    357     {
    358         ministring::operator=(that);
    359         return *this;
    360     }
    361 
    362     Utf8Str& operator=(const Bstr &that)
    363     {
    364         cleanup();
    365         copyFrom(that);
    366         return *this;
    367     }
    368 
    369     Utf8Str& operator=(CBSTR that)
    370     {
    371         cleanup();
    372         copyFrom(that);
    373         return *this;
    374     }
     330    enum CaseSensitivity
     331    {
     332        CaseSensitive,
     333        CaseInsensitive
     334    };
     335
     336    typedef char *String;
     337    typedef const char *ConstString;
     338
     339    Utf8Str () : str (NULL) {}
     340
     341    Utf8Str (const Utf8Str &that) : str (NULL) { raw_copy (str, that.str); }
     342    Utf8Str (const char *that) : str (NULL) { raw_copy (str, that); }
     343
     344    Utf8Str (const Bstr &that) : str (NULL) { raw_copy (str, that); }
     345    Utf8Str (CBSTR that) : str (NULL) { raw_copy (str, that); }
     346
     347    /** Shortcut that calls #alloc(aSize) right after object creation. */
     348    Utf8Str (size_t aSize) : str (NULL) { alloc(aSize); }
     349
     350    virtual ~Utf8Str () { setNull(); }
     351
     352    Utf8Str &operator = (const Utf8Str &that) { safe_assign (that.str); return *this; }
     353    Utf8Str &operator = (const char *that) { safe_assign (that); return *this; }
     354
     355    Utf8Str &operator = (const Bstr &that)
     356    {
     357        setNull();
     358        raw_copy (str, that);
     359        return *this;
     360    }
     361    Utf8Str &operator = (CBSTR that)
     362    {
     363        setNull();
     364        raw_copy (str, that);
     365        return *this;
     366    }
     367
     368    Utf8Str &setNull()
     369    {
     370        if (str)
     371        {
     372#if !defined (VBOX_WITH_XPCOM)
     373            ::RTStrFree (str);
     374#else
     375            nsMemory::Free (str);
     376#endif
     377            str = NULL;
     378        }
     379        return *this;
     380    }
     381
     382    Utf8Str &setNullIfEmpty()
     383    {
     384        if (str && *str == 0)
     385        {
     386#if !defined (VBOX_WITH_XPCOM)
     387            ::RTStrFree (str);
     388#else
     389            nsMemory::Free (str);
     390#endif
     391            str = NULL;
     392        }
     393        return *this;
     394    }
     395
     396    /**
     397     *  Allocates memory for a string capable to store \a aSize - 1 bytes (not characters!);
     398     *  in other words, aSize includes the terminating zero character. If \a aSize
     399     *  is zero, or if a memory allocation error occurs, this object will become null.
     400     */
     401    Utf8Str &alloc (size_t aSize)
     402    {
     403        setNull();
     404        if (aSize)
     405        {
     406#if !defined (VBOX_WITH_XPCOM)
     407            str = (char *) ::RTMemTmpAlloc (aSize);
     408#else
     409            str = (char *) nsMemory::Alloc (aSize);
     410#endif
     411            if (str)
     412                str [0] = 0;
     413        }
     414        return *this;
     415    }
     416
     417    void append(const Utf8Str &that)
     418    {
     419        size_t cbThis = length();
     420        size_t cbThat = that.length();
     421
     422        if (cbThat)
     423        {
     424            size_t cbBoth = cbThis + cbThat + 1;
     425
     426            // @todo optimize with realloc() once the memory management is fixed
     427            char *pszTemp;
     428#if !defined (VBOX_WITH_XPCOM)
     429            pszTemp = (char*)::RTMemTmpAlloc(cbBoth);
     430#else
     431            pszTemp = (char*)nsMemory::Alloc(cbBoth);
     432#endif
     433            if (str)
     434            {
     435                memcpy(pszTemp, str, cbThis);
     436                setNull();
     437            }
     438            if (that.str)
     439                memcpy(pszTemp + cbThis, that.str, cbThat);
     440            pszTemp[cbThis + cbThat] = '\0';
     441
     442            str = pszTemp;
     443        }
     444    }
     445
     446    int compare (const char *pcsz, CaseSensitivity cs = CaseSensitive) const
     447    {
     448        if (str == pcsz)
     449            return 0;
     450        if (str == NULL)
     451            return -1;
     452        if (pcsz == NULL)
     453            return 1;
     454
     455        if (cs == CaseSensitive)
     456            return ::RTStrCmp(str, pcsz);
     457        else
     458            return ::RTStrICmp(str, pcsz);
     459    }
     460
     461    int compare (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const
     462    {
     463        return compare (that.str, cs);
     464    }
     465
     466    bool operator == (const Utf8Str &that) const { return !compare (that); }
     467    bool operator != (const Utf8Str &that) const { return !!compare (that); }
     468    bool operator == (const char *that) const { return !compare (that); }
     469    bool operator != (const char *that) const { return !!compare (that); }
     470    bool operator < (const Utf8Str &that) const { return compare (that) < 0; }
     471    bool operator < (const char *that) const { return compare (that) < 0; }
     472
     473    bool endsWith (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const
     474    {
     475        if (isNull() || that.isNull())
     476            return false;
     477
     478        size_t l1 = length();
     479        size_t l2 = that.length();
     480        if (l1 < l2)
     481            return false;
     482
     483        size_t l = l1 - l2;
     484        if (cs == CaseSensitive)
     485            return ::RTStrCmp(&str[l], that.str) == 0;
     486        else
     487            return ::RTStrICmp(&str[l], that.str) == 0;
     488    }
     489
     490    bool startsWith (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const
     491    {
     492        if (isNull() || that.isNull())
     493            return false;
     494
     495        size_t l1 = length();
     496        size_t l2 = that.length();
     497        if (l1 < l2)
     498            return false;
     499
     500        if (cs == CaseSensitive)
     501            return ::RTStrNCmp(str, that.str, l2) == 0;
     502        else
     503            return ::RTStrNICmp(str, that.str, l2) == 0;
     504    }
     505
     506    bool contains (const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const
     507    {
     508        if (cs == CaseSensitive)
     509            return ::RTStrStr (str, that.str) != NULL;
     510        else
     511            return ::RTStrIStr (str, that.str) != NULL;
     512    }
     513
     514    Utf8Str& toLower()
     515    {
     516        if (isEmpty())
     517            return *this;
     518
     519        ::RTStrToLower(str);
     520
     521        return *this;
     522    }
     523
     524    Utf8Str& toUpper()
     525    {
     526        if (isEmpty())
     527            return *this;
     528
     529        ::RTStrToUpper(str);
     530
     531        return *this;
     532    }
     533
     534    bool isNull() const { return str == NULL; }
     535    operator bool() const { return !isNull(); }
     536
     537    bool isEmpty() const { return isNull() || *str == 0; }
     538
     539    size_t length() const { return isNull() ? 0 : ::strlen (str); }
     540
     541    /** Intended to to pass instances as input (|char *|) parameters to methods. */
     542    operator const char *() const { return str; }
     543
     544    /** The same as operator const char *(), but for situations where the compiler
     545        cannot typecast implicitly (for example, in printf() argument list). */
     546    const char *raw() const { return str; }
     547
     548    /** The same as operator const char *(), but for situations where the compiler
     549        cannot typecast implicitly (for example, in printf() argument list). */
     550    const char *c_str() const { return str; }
     551
     552    /**
     553     *  Returns a non-const raw pointer that allows to modify the string directly.
     554     *  @warning
     555     *      Be sure not to modify data beyond the allocated memory! The
     556     *      guaranteed size of the allocated memory is at least #length()
     557     *      bytes after creation and after every assignment operation.
     558     */
     559    char *mutableRaw() { return str; }
    375560
    376561    /**
     
    379564     *  caller.
    380565     */
    381     const Utf8Str& cloneTo(char **pstr) const
     566    const Utf8Str &cloneTo (char **pstr) const
    382567    {
    383568        if (pstr)
    384             *pstr = RTStrDup(m_psz);
     569        {
     570            *pstr = NULL;
     571            raw_copy (*pstr, str);
     572        }
    385573        return *this;
    386574    }
     
    394582     *  string.
    395583     */
    396     Utf8Str& detachTo(char **pstr)
    397     {
    398         *pstr = m_psz;
    399         m_psz = NULL;
    400         m_cbAllocated = 0;
    401         m_cbLength = 0;
     584    Utf8Str &detachTo (char **pstr)
     585    {
     586        *pstr = str;
     587        str = NULL;
    402588        return *this;
    403589    }
     
    408594     *  caller.
    409595     */
    410     const Utf8Str& cloneTo(BSTR *pstr) const
     596    const Utf8Str &cloneTo (BSTR *pstr) const
    411597    {
    412598        if (pstr)
    413599        {
    414600            *pstr = NULL;
    415             Bstr::raw_copy(*pstr, m_psz);
     601            Bstr::raw_copy (*pstr, str);
    416602        }
    417603        return *this;
     
    437623
    438624    /**
    439      * Returns true if "this" ends with "that".
    440      * @param that
    441      * @param cs
    442      * @return
    443      */
    444     bool endsWith(const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const;
    445 
    446     /**
    447      * Returns true if "this" begins with "that".
    448      * @return
    449      */
    450     bool startsWith(const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const;
    451 
    452     /**
    453      * Returns true if "this" contains "that" (strstr).
    454      * @param that
    455      * @param cs
    456      * @return
    457      */
    458     bool contains(const Utf8Str &that, CaseSensitivity cs = CaseSensitive) const;
    459 
    460     /**
    461      * Converts "this" to lower case by calling RTStrToLower().
    462      * @return
    463      */
    464     Utf8Str& toLower();
    465 
    466     /**
    467      * Converts "this" to upper case by calling RTStrToUpper().
    468      * @return
    469      */
    470     Utf8Str& toUpper();
    471 
    472     /**
    473      * Removes a trailing slash from the member string, if present.
    474      * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
    475      */
    476     void stripTrailingSlash();
    477 
    478     /**
    479      * Removes a trailing filename from the member string, if present.
    480      * Calls RTPathStripFilename() without having to mess with mutableRaw().
    481      */
    482     void stripFilename();
    483 
    484     /**
    485      * Removes a trailing file name extension from the member string, if present.
    486      * Calls RTPathStripExt() without having to mess with mutableRaw().
    487      */
    488     void stripExt();
    489 
    490     /**
    491      * Attempts to convert the member string into a 32-bit integer.
     625     * Attempts to convert the member string into an 32-bit integer.
    492626     *
    493627     * @returns 32-bit unsigned number on success.
     
    496630    int toInt32() const
    497631    {
    498         return RTStrToInt32(m_psz);
     632        return RTStrToInt32(str);
    499633    }
    500634
     
    507641    int toUInt32() const
    508642    {
    509         return RTStrToUInt32(m_psz);
     643        return RTStrToUInt32(str);
    510644    }
    511645
     
    518652    int64_t toInt64() const
    519653    {
    520         return RTStrToInt64(m_psz);
     654        return RTStrToInt64(str);
    521655    }
    522656
     
    529663    uint64_t toUInt64() const
    530664    {
    531         return RTStrToUInt64(m_psz);
     665        return RTStrToUInt64(str);
    532666    }
    533667
     
    550684     *  Takes the ownership of the returned data.
    551685     */
    552     char **asOutParam()
    553     {
    554         cleanup();
    555         return &m_psz;
    556     }
     686    char **asOutParam() { setNull(); return &str; }
    557687
    558688    /**
     
    563693protected:
    564694
    565     /**
    566      * As with the ministring::copyFrom() variants, this unconditionally
    567      * sets the members to a copy of the given other strings and makes
    568      * no assumptions about previous contents. This can therefore be used
    569      * both in copy constructors, when member variables have no defined
    570      * value, and in assignments after having called cleanup().
    571      *
    572      * This variant converts from a UTF-16 string, most probably from
    573      * a Bstr assignment.
    574      *
    575      * @param rs
    576      */
    577     void copyFrom(CBSTR s)
    578     {
    579         if (s)
    580         {
    581             RTUtf16ToUtf8((PRTUTF16)s, &m_psz);
    582             m_cbLength = strlen(m_psz);             // TODO optimize by using a different RTUtf* function
    583             m_cbAllocated = m_cbLength + 1;
    584         }
    585         else
    586         {
    587             m_cbLength = 0;
    588             m_cbAllocated = 0;
    589             m_psz = NULL;
    590         }
    591     }
     695    void safe_assign (const char *s)
     696    {
     697        if (str != s)
     698        {
     699            setNull();
     700            raw_copy (str, s);
     701        }
     702    }
     703
     704    inline static void raw_copy (char *&ls, const char *rs)
     705    {
     706        if (rs)
     707#if !defined (VBOX_WITH_XPCOM)
     708            ::RTStrDupEx (&ls, rs);
     709#else
     710            ls = (char *) nsMemory::Clone (rs, strlen (rs) + 1);
     711#endif
     712    }
     713
     714    inline static void raw_copy (char *&ls, CBSTR rs)
     715    {
     716        if (rs)
     717        {
     718#if !defined (VBOX_WITH_XPCOM)
     719            ::RTUtf16ToUtf8 ((PRTUTF16) rs, &ls);
     720#else
     721            char *s = NULL;
     722            ::RTUtf16ToUtf8 ((PRTUTF16) rs, &s);
     723            raw_copy (ls, s);
     724            ::RTStrFree (s);
     725#endif
     726        }
     727    }
     728
     729    char *str;
    592730
    593731    friend class Bstr; /* to access our raw_copy() */
    594732};
     733
     734// symmetric compare operators
     735inline bool operator== (const char *l, const Utf8Str &r) { return r.operator== (l); }
     736inline bool operator!= (const char *l, const Utf8Str &r) { return r.operator!= (l); }
    595737
    596738// work around error C2593 of the stupid MSVC 7.x ambiguity resolver
     
    618760}
    619761
    620 inline const Bstr& Bstr::cloneTo(char **pstr) const
    621 {
    622     if (pstr)
    623     {
    624         Utf8Str ustr(*this);
    625         ustr.detachTo(pstr);
     762inline const Bstr &Bstr::cloneTo (char **pstr) const
     763{
     764    if (pstr) {
     765        *pstr = NULL;
     766        Utf8Str::raw_copy (*pstr, bstr);
    626767    }
    627768    return *this;
  • trunk/include/VBox/settings.h

    r21073 r21077  
    3131#define ___VBox_settings_h
    3232
    33 #include <limits>
    34 
    3533#include <iprt/cdefs.h>
    3634#include <iprt/cpputils.h>
     35#include <iprt/string.h>
     36
     37#include <list>
     38#include <memory>
     39#include <limits>
     40
    3741#include <iprt/time.h>
    38 #include <iprt/xml_cpp.h>
    3942
    4043#include <VBox/com/Guid.h>
     44
     45#include <VBox/xml.h>
     46
     47// #include <stdarg.h>
    4148
    4249/* these conflict with numeric_digits<>::min and max */
  • trunk/include/VBox/xml.h

    r21073 r21077  
     1/** @file
     2 * VirtualBox XML helper APIs.
     3 */
     4
     5/*
     6 * Copyright (C) 2007-2008 Sun Microsystems, Inc.
     7 *
     8 * This file is part of VirtualBox Open Source Edition (OSE), as
     9 * available from http://www.virtualbox.org. This file is free software;
     10 * you can redistribute it and/or modify it under the terms of the GNU
     11 * General Public License (GPL) as published by the Free Software
     12 * Foundation, in version 2 as it comes in the "COPYING" file of the
     13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
     14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     15 *
     16 * The contents of this file may alternatively be used under the terms
     17 * of the Common Development and Distribution License Version 1.0
     18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
     19 * VirtualBox OSE distribution, in which case the provisions of the
     20 * CDDL are applicable instead of those of the GPL.
     21 *
     22 * You may elect to license modified versions of this file under the
     23 * terms and conditions of either the GPL or the CDDL or both.
     24 *
     25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
     26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
     27 * additional information or have any questions.
     28 */
     29
     30#ifndef ___VBox_vboxxml_h
     31#define ___VBox_vboxxml_h
     32
     33#ifndef IN_RING3
     34# error "There are no XML APIs available in Ring-0 Context!"
     35#else /* IN_RING3 */
     36
     37/** @def IN_VBOXXML_R3
     38 * Used to indicate whether we're inside the same link module as the
     39 * XML Settings File Manipulation API.
     40 *
     41 * @todo should go to a separate common include together with VBOXXML2_CLASS
     42 * once there becomes more than one header in the VBoxXML2 library.
     43 */
     44#ifdef DOXYGEN_RUNNING
     45# define IN_VBOXXML_R3
     46#endif
     47
     48/** @def VBOXXML_CLASS
     49 * Class export/import wrapper. */
     50#ifdef IN_VBOXXML_R3
     51# define VBOXXML_CLASS DECLEXPORT_CLASS
     52#else
     53# define VBOXXML_CLASS DECLIMPORT_CLASS
     54#endif
     55
     56/*
     57 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a
     58 * result of private data member declarations of some classes below) need to
     59 * be exported too to in order to be accessible by clients.
     60 *
     61 * The alternative is to instantiate a template before the data member
     62 * declaration with the VBOXXML_CLASS prefix, but the standard disables
     63 * explicit instantiations in a foreign namespace. In other words, a declaration
     64 * like:
     65 *
     66 *   template class VBOXXML_CLASS std::auto_ptr <Data>;
     67 *
     68 * right before the member declaration makes MSVC happy too, but this is not a
     69 * valid C++ construct (and G++ spits it out). So, for now we just disable the
     70 * warning and will come back to this problem one day later.
     71 *
     72 * We also disable another warning (4275) saying that a DLL-exported class
     73 * inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->
     74 * std::bad_alloc). I can't get how it can harm yet.
     75 */
     76#if defined(_MSC_VER)
     77#pragma warning (disable:4251)
     78#pragma warning (disable:4275)
     79#endif
     80
     81/* Forwards */
     82typedef struct _xmlParserInput xmlParserInput;
     83typedef xmlParserInput *xmlParserInputPtr;
     84typedef struct _xmlParserCtxt xmlParserCtxt;
     85typedef xmlParserCtxt *xmlParserCtxtPtr;
     86typedef struct _xmlError xmlError;
     87typedef xmlError *xmlErrorPtr;
     88
     89namespace xml
     90{
     91
     92// Little string class for XML only
     93//////////////////////////////////////////////////////////////////////////////
     94
     95class ministring
     96{
     97public:
     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
     137private:
     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 */
     163class VBOXXML_CLASS Error : public std::exception
     164{
     165public:
     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
     201private:
     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
     222class VBOXXML_CLASS LogicError : public Error
     223{
     224public:
     225
     226    LogicError(const char *aMsg = NULL)
     227        : xml::Error(aMsg)
     228    {}
     229
     230    LogicError(RT_SRC_POS_DECL);
     231};
     232
     233class VBOXXML_CLASS RuntimeError : public Error
     234{
     235public:
     236
     237    RuntimeError(const char *aMsg = NULL)
     238        : xml::Error(aMsg)
     239    {}
     240};
     241
     242class VBOXXML_CLASS XmlError : public RuntimeError
     243{
     244public:
     245    XmlError(xmlErrorPtr aErr);
     246
     247    static char *Format(xmlErrorPtr aErr);
     248};
     249
     250// Logical errors
     251//////////////////////////////////////////////////////////////////////////////
     252
     253class VBOXXML_CLASS ENotImplemented : public LogicError
     254{
     255public:
     256    ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {}
     257    ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     258};
     259
     260class VBOXXML_CLASS EInvalidArg : public LogicError
     261{
     262public:
     263    EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {}
     264    EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     265};
     266
     267class VBOXXML_CLASS EDocumentNotEmpty : public LogicError
     268{
     269public:
     270    EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}
     271    EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     272};
     273
     274class VBOXXML_CLASS ENodeIsNotElement : public LogicError
     275{
     276public:
     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
     284class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc
     285{
     286public:
     287    ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {}
     288    virtual ~ENoMemory() throw() {}
     289};
     290
     291class VBOXXML_CLASS EIPRTFailure : public RuntimeError
     292{
     293public:
     294
     295    EIPRTFailure (int aRC);
     296
     297    int rc() const { return mRC; }
     298
     299private:
     300    int mRC;
     301};
     302
     303
     304/**
     305 * The Stream class is a base class for I/O streams.
     306 */
     307class VBOXXML_CLASS Stream
     308{
     309public:
     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 */
     342class VBOXXML_CLASS Input : virtual public Stream
     343{
     344public:
     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 */
     360class VBOXXML_CLASS Output : virtual public Stream
     361{
     362public:
     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 */
     397class VBOXXML_CLASS File : public Input, public Output
     398{
     399public:
     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
     466private:
     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 */
     480class VBOXXML_CLASS MemoryBuf : public Input
     481{
     482public:
     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
     494private:
     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
     510typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,
     511                                               const char *aID,
     512                                               xmlParserCtxt *aCtxt);
     513typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;
     514
     515class VBOXXML_CLASS GlobalLock
     516{
     517public:
     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
     527private:
     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
     553class ElementNode;
     554typedef std::list<const ElementNode*> ElementNodesList;
     555
     556class AttributeNode;
     557
     558class ContentNode;
     559
     560class VBOXXML_CLASS Node
     561{
     562public:
     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
     579protected:
     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
     594class VBOXXML_CLASS ElementNode : public Node
     595{
     596public:
     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
     612protected:
     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
     622class VBOXXML_CLASS ContentNode : public Node
     623{
     624public:
     625
     626protected:
     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
     635class VBOXXML_CLASS AttributeNode : public Node
     636{
     637public:
     638
     639protected:
     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
     653class VBOXXML_CLASS NodesLoop
     654{
     655public:
     656    NodesLoop(const ElementNode &node, const char *pcszMatch = NULL);
     657    ~NodesLoop();
     658    const ElementNode* forAllNodes() const;
     659
     660private:
     661    /* Obscure class data */
     662    struct Data;
     663    Data *m;
     664};
     665
     666/*
     667 * Document
     668 *
     669 */
     670
     671class VBOXXML_CLASS Document
     672{
     673public:
     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
     684private:
     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
     700class VBOXXML_CLASS XmlParserBase
     701{
     702protected:
     703    XmlParserBase();
     704    ~XmlParserBase();
     705
     706    xmlParserCtxtPtr m_ctxt;
     707};
     708
     709/*
     710 * XmlFileParser
     711 *
     712 */
     713
     714class VBOXXML_CLASS XmlFileParser : public XmlParserBase
     715{
     716public:
     717    XmlFileParser();
     718    ~XmlFileParser();
     719
     720    void read(const char *pcszFilename, Document &doc);
     721
     722private:
     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
     736class VBOXXML_CLASS XmlFileWriter
     737{
     738public:
     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
     747private:
     748    /* Obscure class data */
     749    struct Data;
     750    Data *m;
     751};
     752
     753#if defined(_MSC_VER)
     754#pragma warning (default:4251)
     755#endif
     756
     757#endif /* IN_RING3 */
     758
     759/** @} */
     760
     761} // end namespace xml
     762
     763#endif /* ___VBox_vboxxml_h */
  • trunk/src/VBox/Main/ApplianceImpl.cpp

    r21073 r21077  
    2626#include <iprt/file.h>
    2727#include <iprt/s3.h>
    28 #include "iprt/xml_cpp.h"
    2928
    3029#include <VBox/param.h>
     
    4039
    4140#include "Logging.h"
     41
     42#include "VBox/xml.h"
    4243
    4344using namespace std;
     
    233234//
    234235////////////////////////////////////////////////////////////////////////////////
     236
     237static Utf8Str stripFilename(const Utf8Str &strFile)
     238{
     239    Utf8Str str2(strFile);
     240    RTPathStripFilename(str2.mutableRaw());
     241    return str2;
     242}
    235243
    236244static const struct
     
    22382246                    /* The disk image has to be on the same place as the OVF file. So
    22392247                     * strip the filename out of the full file path. */
    2240                     Utf8Str strSrcDir(pAppliance->m->strPath);
    2241                     strSrcDir.stripFilename();
     2248                    Utf8Str strSrcDir = stripFilename(pAppliance->m->strPath);
    22422249
    22432250                    /* Iterate over all given disk images */
     
    35153522            const Utf8Str &strTargetFileNameOnly = pDiskEntry->strOvf;
    35163523            // target path needs to be composed from where the output OVF is
    3517             Utf8Str strTargetFilePath(m->strPath);
    3518             strTargetFilePath.stripFilename();
     3524            Utf8Str strTargetFilePath = stripFilename(m->strPath);
    35193525            strTargetFilePath.append("/");
    35203526            strTargetFilePath.append(strTargetFileNameOnly);
     
    37153721                const Utf8Str &strTargetFileNameOnly = (*itH)->strOvf;
    37163722                /* Target path needs to be composed from where the output OVF is */
    3717                 Utf8Str strTargetFilePath(m->strPath);
    3718                 strTargetFilePath.stripFilename();
     3723                Utf8Str strTargetFilePath = stripFilename(m->strPath);
    37193724                strTargetFilePath.append("/");
    37203725                strTargetFilePath.append(strTargetFileNameOnly);
     
    47314736
    47324737            Utf8Str strTargetVmdkName(bstrName);
    4733             strTargetVmdkName.stripExt();
     4738            RTPathStripExt(strTargetVmdkName.mutableRaw());
    47344739            strTargetVmdkName.append(".vmdk");
    47354740
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r21073 r21077  
    10731073    for (unsigned i = 0; i < 10 && (VERR_BUFFER_OVERFLOW == vrc); ++i)
    10741074    {
    1075         Utf8Buf.reserve(cchBuf + 1024);
     1075        Utf8Buf.alloc(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();
    10841083        if (parm[2].type != VBOX_HGCM_SVC_PARM_32BIT)
    10851084            return setError (E_FAIL, tr ("Internal application error"));
     
    17181717        {
    17191718            Utf8Str dir = stateFilePath;
    1720             dir.stripFilename();
    1721             if (!RTDirExists(dir))
     1719            RTPathStripFilename (dir.mutableRaw());
     1720            if (!RTDirExists (dir))
    17221721            {
    17231722                int vrc = RTDirCreateFullPath (dir, 0777);
     
    38663865
    38673866    parm[0].type = VBOX_HGCM_SVC_PARM_PTR;
    3868     parm[0].u.pointer.addr = (void*)Utf8Name.c_str();
     3867    /* To save doing a const cast, we use the mutableRaw() member. */
     3868    parm[0].u.pointer.addr = Utf8Name.mutableRaw();
    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             Utf8Str strBuffer(pszBuffer);
    3885             strBuffer.cloneTo(aValue);
    3886 
     3884            size_t iFlags = strlen(pszBuffer) + 1;
     3885            Utf8Str(pszBuffer).cloneTo (aValue);
    38873886            *aTimestamp = parm[2].u.uint64;
    3888 
    3889             size_t iFlags = strBuffer.length() + 1;
    3890             Utf8Str(pszBuffer + iFlags).cloneTo(aFlags);
     3887            Utf8Str(pszBuffer + iFlags).cloneTo (aFlags);
    38913888        }
    38923889        else
     
    39333930
    39343931    parm[0].type = VBOX_HGCM_SVC_PARM_PTR;
    3935     parm[0].u.pointer.addr = (void*)Utf8Name.c_str();
     3932    /* To save doing a const cast, we use the mutableRaw() member. */
     3933    parm[0].u.pointer.addr = Utf8Name.mutableRaw();
    39363934    /* The + 1 is the null terminator */
    39373935    parm[0].u.pointer.size = (uint32_t)Utf8Name.length() + 1;
     
    39403938    {
    39413939        parm[1].type = VBOX_HGCM_SVC_PARM_PTR;
    3942         parm[1].u.pointer.addr = (void*)Utf8Value.c_str();
     3940        /* To save doing a const cast, we use the mutableRaw() member. */
     3941        parm[1].u.pointer.addr = Utf8Value.mutableRaw();
    39433942        /* The + 1 is the null terminator */
    39443943        parm[1].u.pointer.size = (uint32_t)Utf8Value.length() + 1;
     
    39483947    {
    39493948        parm[2].type = VBOX_HGCM_SVC_PARM_PTR;
    3950         parm[2].u.pointer.addr = (void*)Utf8Flags.c_str();
     3949        /* To save doing a const cast, we use the mutableRaw() member. */
     3950        parm[2].u.pointer.addr = Utf8Flags.mutableRaw();
    39513951        /* The + 1 is the null terminator */
    39523952        parm[2].u.pointer.size = (uint32_t)Utf8Flags.length() + 1;
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

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

    r21073 r21077  
    34503450    AssertReturn (!mData->mConfigFileFull.isNull(), VERR_GENERAL_FAILURE);
    34513451
    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))
     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))
    34583458        aResult = folder;
    34593459
     
    34833483    Utf8Str settingsDir = mData->mConfigFileFull;
    34843484
    3485     settingsDir.stripFilename();
    3486     if (RTPathStartsWith(aPath, settingsDir))
     3485    RTPathStripFilename (settingsDir.mutableRaw());
     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             configDir.stripFilename();
     5951            RTPathStripFilename (configDir.mutableRaw());
    59525952            newConfigDir = configDir;
    5953             if (RTPathFilename(configDir) == name)
     5953            if (RTPathFilename (configDir) == name)
    59545954            {
    5955                 newConfigDir.stripFilename();
     5955                RTPathStripFilename (newConfigDir.mutableRaw());
    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         path.stripFilename();
    6082         if (!RTDirExists(path))
    6083         {
    6084             vrc = RTDirCreateFullPath(path, 0777);
    6085             if (RT_FAILURE(vrc))
     6080        Utf8Str path = mData->mConfigFileFull;
     6081        RTPathStripFilename (path.mutableRaw());
     6082        if (!RTDirExists (path))
     6083        {
     6084            vrc = RTDirCreateFullPath (path, 0777);
     6085            if (RT_FAILURE (vrc))
    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     settingsDir.stripFilename();
    7661     char *dirName = RTPathFilename(settingsDir);
     7660    RTPathStripFilename (settingsDir.mutableRaw());
     7661    char *dirName = RTPathFilename (settingsDir);
    76627662
    76637663    AssertReturn (dirName, false);
  • trunk/src/VBox/Main/Makefile.kmk

    r21073 r21077  
    519519        include
    520520VBoxSettings_SOURCES    = \
     521        xml/xml.cpp \
    521522        xml/Settings.cpp
    522523VBoxSettings_LDFLAGS.darwin = -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/$(notdir $(LIB_SETTINGS)) -Wl,-x # no debug info please.
  • trunk/src/VBox/Main/SharedFolderImpl.cpp

    r21073 r21077  
    2828
    2929#include <iprt/param.h>
     30#include <iprt/path.h>
    3031#include <iprt/cpputils.h>
    31 #include <iprt/path.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         hostPath.stripTrailingSlash();
     205        RTPathStripTrailingSlash (hostPath.mutableRaw());
    206206
    207207    /* Check whether the path is full (absolute) */
  • trunk/src/VBox/Main/VirtualBoxErrorInfoImpl.cpp

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

    r21073 r21077  
    38703870HRESULT VirtualBox::ensureFilePathExists (const char *aFileName)
    38713871{
    3872     Utf8Str strDir(aFileName);
    3873     strDir.stripFilename();
    3874     if (!RTDirExists(strDir))
    3875     {
    3876         int vrc = RTDirCreateFullPath(strDir, 0777);
     3872    Utf8Str dir = aFileName;
     3873    RTPathStripFilename (dir.mutableRaw());
     3874    if (!RTDirExists (dir))
     3875    {
     3876        int vrc = RTDirCreateFullPath (dir, 0777);
    38773877        if (RT_FAILURE (vrc))
    38783878        {
    38793879            return setError (E_FAIL,
    38803880                tr ("Could not create the directory '%s' (%Rrc)"),
    3881                 strDir.c_str(), vrc);
     3881                dir.raw(), vrc);
    38823882        }
    38833883    }
  • trunk/src/VBox/Main/glue/ErrorInfo.cpp

    r21073 r21077  
    118118
    119119                    Utf8Str message;
    120                     rc = ex->GetMessage(message.asOutParam());
    121                     message.jolt();
     120                    rc = ex->GetMessage (message.asOutParam());
    122121                    gotSomething |= NS_SUCCEEDED (rc);
    123122                    if (NS_SUCCEEDED (rc))
     
    183182    LONG lrc;
    184183
    185     rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc;
     184    rc = info->COMGETTER(ResultCode) (&lrc); mResultCode = lrc;   
    186185    gotSomething |= SUCCEEDED (rc);
    187186    gotAll &= SUCCEEDED (rc);
  • trunk/src/VBox/Main/glue/VirtualBoxErrorInfo.cpp

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

    r21073 r21077  
    2626
    2727#include <iprt/err.h>
    28 #include <iprt/path.h>
    2928
    3029namespace com
     
    8685
    8786                size_t cbCopy = psz - pFirst;
    88                 ret.reserve(cbCopy + 1);
    89                 memcpy(ret.m_psz, pFirst, cbCopy);
    90                 ret.m_psz[cbCopy] = '\0';
     87                ret.alloc(cbCopy + 1);
     88                memcpy(ret.str, pFirst, cbCopy);
     89                ret.str[cbCopy] = '\0';
    9190            }
    9291        }
     
    9695}
    9796
    98 bool Utf8Str::endsWith(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const
    99 {
    100     size_t l1 = length();
    101     if (l1 == 0)
    102         return false;
    103 
    104     size_t l2 = that.length();
    105     if (l1 < l2)
    106         return false;
    107 
    108     size_t l = l1 - l2;
    109     if (cs == CaseSensitive)
    110         return ::RTStrCmp(&m_psz[l], that.m_psz) == 0;
    111     else
    112         return ::RTStrICmp(&m_psz[l], that.m_psz) == 0;
    113 }
    114 
    115 bool Utf8Str::startsWith(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const
    116 {
    117     size_t l1 = length();
    118     size_t l2 = that.length();
    119     if (l1 == 0 || l2 == 0)
    120         return false;
    121 
    122     if (l1 < l2)
    123         return false;
    124 
    125     if (cs == CaseSensitive)
    126         return ::RTStrNCmp(m_psz, that.m_psz, l2) == 0;
    127     else
    128         return ::RTStrNICmp(m_psz, that.m_psz, l2) == 0;
    129 }
    130 
    131 bool Utf8Str::contains(const Utf8Str &that, CaseSensitivity cs /*= CaseSensitive*/) const
    132 {
    133     if (cs == CaseSensitive)
    134         return ::RTStrStr(m_psz, that.m_psz) != NULL;
    135     else
    136         return ::RTStrIStr(m_psz, that.m_psz) != NULL;
    137 }
    138 
    139 Utf8Str& Utf8Str::toLower()
    140 {
    141     if (!isEmpty())
    142         ::RTStrToLower(m_psz);
    143     return *this;
    144 }
    145 
    146 Utf8Str& Utf8Str::toUpper()
    147 {
    148     if (!isEmpty())
    149         ::RTStrToUpper(m_psz);
    150     return *this;
    151 }
    152 
    153 void Utf8Str::stripTrailingSlash()
    154 {
    155     RTPathStripTrailingSlash(m_psz);
    156     jolt();
    157 }
    158 
    159 void Utf8Str::stripFilename()
    160 {
    161     RTPathStripFilename(m_psz);
    162     jolt();
    163 }
    164 
    165 void Utf8Str::stripExt()
    166 {
    167     RTPathStripExt(m_psz);
    168     jolt();
    169 }
    170 
    17197int Utf8Str::toInt(uint64_t &i) const
    17298{
    173     if (!m_psz)
     99    if (!str)
    174100        return VERR_NO_DIGITS;
    175     return RTStrToUInt64Ex(m_psz, NULL, 0, &i);
     101    return RTStrToUInt64Ex(str, NULL, 0, &i);
    176102}
    177103
    178104int Utf8Str::toInt(uint32_t &i) const
    179105{
    180     if (!m_psz)
     106    if (!str)
    181107        return VERR_NO_DIGITS;
    182     return RTStrToUInt32Ex(m_psz, NULL, 0, &i);
     108    return RTStrToUInt32Ex(str, NULL, 0, &i);
    183109}
    184110
  • trunk/src/VBox/Main/include/ApplianceImpl.h

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

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

    r21073 r21077  
     1/** @file
     2 * VirtualBox XML Manipulation API.
     3 */
     4
     5/*
     6 * Copyright (C) 2007-2009 Sun Microsystems, Inc.
     7 *
     8 * This file is part of VirtualBox Open Source Edition (OSE), as
     9 * available from http://www.virtualbox.org. This file is free software;
     10 * you can redistribute it and/or modify it under the terms of the GNU
     11 * General Public License (GPL) as published by the Free Software
     12 * Foundation, in version 2 as it comes in the "COPYING" file of the
     13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
     14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     15 *
     16 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
     17 * Clara, CA 95054 USA or visit http://www.sun.com if you need
     18 * additional information or have any questions.
     19 */
     20
     21#include "Logging.h"
     22
     23#include <iprt/cdefs.h>
     24#include <iprt/err.h>
     25#include <iprt/file.h>
     26#include <iprt/lock.h>
     27#include <iprt/string.h>
     28
     29#include <libxml/tree.h>
     30#include <libxml/parser.h>
     31#include <libxml/globals.h>
     32#include <libxml/xmlIO.h>
     33#include <libxml/xmlsave.h>
     34#include <libxml/uri.h>
     35
     36#include <libxml/xmlschemas.h>
     37
     38#include <list>
     39#include <map>
     40#include <boost/shared_ptr.hpp>
     41
     42#include "VBox/xml.h"
     43
     44////////////////////////////////////////////////////////////////////////////////
     45//
     46// globals
     47//
     48////////////////////////////////////////////////////////////////////////////////
     49
     50/**
     51 * Global module initialization structure. This is to wrap non-reentrant bits
     52 * of libxml, among other things.
     53 *
     54 * The constructor and destructor of this structure are used to perform global
     55 * module initiaizaton and cleanup. Thee must be only one global variable of
     56 * this structure.
     57 */
     58static
     59class Global
     60{
     61public:
     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}
     94gGlobal;
     95
     96
     97
     98namespace xml
     99{
     100
     101////////////////////////////////////////////////////////////////////////////////
     102//
     103// Exceptions
     104//
     105////////////////////////////////////////////////////////////////////////////////
     106
     107LogicError::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
     117XmlError::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
     132char *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
     147EIPRTFailure::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
     163struct 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
     173File::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
     203File::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
     221File::~File()
     222{
     223    if (m->opened)
     224        RTFileClose (m->handle);
     225
     226    RTStrFree (m->fileName);
     227}
     228
     229const char *File::uri() const
     230{
     231    return m->fileName;
     232}
     233
     234uint64_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
     244void 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
     266int 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
     276int 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
     288void 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
     303struct 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
     315MemoryBuf::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
     326MemoryBuf::~MemoryBuf()
     327{
     328    RTStrFree (m->uri);
     329}
     330
     331const char *MemoryBuf::uri() const
     332{
     333    return m->uri;
     334}
     335
     336uint64_t MemoryBuf::pos() const
     337{
     338    return m->pos;
     339}
     340
     341void 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
     353int 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
     371struct GlobalLock::Data
     372{
     373    PFNEXTERNALENTITYLOADER pOldLoader;
     374    RTLock lock;
     375
     376    Data()
     377        : pOldLoader(NULL),
     378          lock(gGlobal.sxml.lock)
     379    {
     380    }
     381};
     382
     383GlobalLock::GlobalLock()
     384    : m(new Data())
     385{
     386}
     387
     388GlobalLock::~GlobalLock()
     389{
     390    if (m->pOldLoader)
     391        xmlSetExternalEntityLoader(m->pOldLoader);
     392    delete m;
     393    m = NULL;
     394}
     395
     396void GlobalLock::setExternalEntityLoader(PFNEXTERNALENTITYLOADER pLoader)
     397{
     398    m->pOldLoader = xmlGetExternalEntityLoader();
     399    xmlSetExternalEntityLoader(pLoader);
     400}
     401
     402// static
     403xmlParserInput* 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
     416struct 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
     442Node::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
     451Node::~Node()
     452{
     453    delete m;
     454}
     455
     456void 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
     497const 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 */
     508const 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 */
     531bool 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 */
     548bool 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 */
     565bool 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 */
     582bool 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 */
     598int Node::getLineNumber() const
     599{
     600    if (m->plibAttr)
     601        return m->pParent->m->plibNode->line;
     602
     603    return m->plibNode->line;
     604}
     605
     606ElementNode::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 */
     619int 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 */
     650const 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 */
     676const 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 */
     704const 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 */
     723bool 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 */
     745bool 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 */
     766bool 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 */
     784ElementNode* 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 */
     816ContentNode* 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 */
     846AttributeNode* 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
     876AttributeNode::AttributeNode()
     877    : Node(IsAttribute)
     878{
     879}
     880
     881ContentNode::ContentNode()
     882    : Node(IsContent)
     883{
     884}
     885
     886/*
     887 * NodesLoop
     888 *
     889 */
     890
     891struct NodesLoop::Data
     892{
     893    ElementNodesList listElements;
     894    ElementNodesList::const_iterator it;
     895};
     896
     897NodesLoop::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
     904NodesLoop::~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 */
     925const 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
     944struct 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
     984Document::Document()
     985    : m(new Data)
     986{
     987}
     988
     989Document::Document(const Document &x)
     990    : m(new Data)
     991{
     992    m->copyFrom(x.m);
     993};
     994
     995Document& Document::operator=(const Document &x)
     996{
     997    m->reset();
     998    m->copyFrom(x.m);
     999    return *this;
     1000};
     1001
     1002Document::~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 */
     1012void 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 */
     1025const 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 */
     1034ElementNode* 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
     1061XmlParserBase::XmlParserBase()
     1062{
     1063    m_ctxt = xmlNewParserCtxt();
     1064    if (m_ctxt == NULL)
     1065        throw ENoMemory();
     1066}
     1067
     1068XmlParserBase::~XmlParserBase()
     1069{
     1070    xmlFreeParserCtxt (m_ctxt);
     1071    m_ctxt = NULL;
     1072}
     1073
     1074////////////////////////////////////////////////////////////////////////////////
     1075//
     1076// XmlFileParser class
     1077//
     1078////////////////////////////////////////////////////////////////////////////////
     1079
     1080struct 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
     1098XmlFileParser::XmlFileParser()
     1099    : XmlParserBase(),
     1100      m(new Data())
     1101{
     1102}
     1103
     1104XmlFileParser::~XmlFileParser()
     1105{
     1106    delete m;
     1107    m = NULL;
     1108}
     1109
     1110struct 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
     1131struct ReadContext : IOContext
     1132{
     1133    ReadContext(const char *pcszFilename)
     1134        : IOContext(pcszFilename, File::Mode_Read)
     1135    {
     1136    }
     1137};
     1138
     1139struct 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 */
     1156void 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
     1179int 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
     1198int XmlFileParser::CloseCallback(void *aCtxt)
     1199{
     1200    /// @todo to be written
     1201
     1202    return -1;
     1203}
     1204
     1205////////////////////////////////////////////////////////////////////////////////
     1206//
     1207// XmlFileWriter class
     1208//
     1209////////////////////////////////////////////////////////////////////////////////
     1210
     1211struct XmlFileWriter::Data
     1212{
     1213    Document *pDoc;
     1214};
     1215
     1216XmlFileWriter::XmlFileWriter(Document &doc)
     1217{
     1218    m = new Data();
     1219    m->pDoc = &doc;
     1220}
     1221
     1222XmlFileWriter::~XmlFileWriter()
     1223{
     1224    delete m;
     1225}
     1226
     1227void 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
     1261int 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
     1279int XmlFileWriter::CloseCallback(void *aCtxt)
     1280{
     1281    /// @todo to be written
     1282
     1283    return -1;
     1284}
     1285
     1286
     1287} // end namespace xml
     1288
     1289
  • trunk/src/VBox/Runtime/Makefile.kmk

    r21073 r21077  
    5151 LIBRARIES += RuntimeR3
    5252 DLLS += VBoxRT
     53
     54 # Temporary(?) hack.
     55 VBOX_WITH_LIBXML2_IN_VBOXRT=
    5356
    5457else # !VBOX_ONLY_ADDITIONS && !VBOX_ONLY_DOCS
     
    162165#
    163166RuntimeR3_TEMPLATE      = VBOXR3STATIC
    164 RuntimeR3_SDKS          = VBOX_LIBXML2
    165167RuntimeR3_SDKS.win      = WINPSDK W2K3DDK
    166168RuntimeR3_DEFS          = IN_RT_R3 IN_SUP_R3 LDR_WITH_NATIVE LDR_WITH_ELF32 LDR_WITH_PE RT_WITH_VBOX RT_NO_GIP
     
    304306        r3/test.cpp \
    305307        r3/testi.cpp \
    306         r3/tcp.cpp \
    307         r3/xml.cpp
     308        r3/tcp.cpp
    308309
    309310#if1of ($(KBUILD_TARGET_ARCH),amd64 x86)
     
    786787#
    787788VBoxRT_TEMPLATE                = VBOXR3
     789ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    788790VBoxRT_SDKS                    = VBOX_OPENSSL VBOX_LIBXML2 VBOX_LIBCURL
     791endif
    789792VBoxRT_SDKS.win                = WINPSDK W2K3DDK VBOX_NTDLL
    790793ifeq ($(KBUILD_TARGET)$(VBOX_WITH_HARDENING),darwin)
     
    796799        VBox/VBoxRTDeps.cpp \
    797800        $(RuntimeR3_SOURCES)
     801if defined(VBOX_WITH_LIBXML2_IN_VBOXRT)
    798802VBoxRT_SOURCES                += \
    799803        common/misc/s3.cpp
     804endif
    800805VBoxRT_SOURCES.$(KBUILD_TARGET) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET))
    801806VBoxRT_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH) = $(RuntimeR3_SOURCES.$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH))
     
    813818        $(PATH_LIB)/VBox-kStuff$(VBOX_SUFF_LIB)
    814819endif
     820ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
     821 ifndef SDK_VBOX_LIBXML2_LIBS
    815822  VBoxRT_LIBS                 += \
    816823        $(PATH_LIB)/VBox-libxml2$(VBOX_SUFF_LIB)
     824 endif
     825 ifndef SDK_VBOX_OPENSSL_LIBS
    817826  VBoxRT_LIBS                 += \
    818827        $(PATH_LIB)/VBox-libcrypto$(VBOX_SUFF_LIB)
     828 endif
     829endif
    819830VBoxRT_LIBS.darwin             = \
    820831        iconv
     
    840851        $(PATH_LIB)/RuntimeR3L4$(VBOX_SUFF_LIB)
    841852
     853ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
     854VBox/VBoxRTDeps.cpp_DEFS = VBOX_WITH_LIBXML2_IN_VBOXRT
     855endif
     856
    842857if1of ($(DLLS), VBoxRT)
    843858$$(VBoxRT_0_OUTDIR)/VBoxRT.def: \
    844859                $(PATH_SUB_CURRENT)/r3/win/VBoxRT-$$(if-expr $$(KBUILD_TARGET_ARCH) == amd64,win64,win32).def \
    845                 $(PATH_SUB_CURRENT)/r3/win/$(if $(VBOX_OSE),VBoxRT-openssl-ose.def,VBoxRT-openssl.def)
     860                $(if-expr defined(VBOX_WITH_LIBXML2_IN_VBOXRT),$(PATH_SUB_CURRENT)/r3/win/$(if $(VBOX_OSE),VBoxRT-openssl-ose.def,VBoxRT-openssl.def),)
    846861        $(RM) -f -- $@
    847862        $(REDIRECT) -wto $@ -- $(CAT_EXT) $^
  • trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp

    r21073 r21077  
    3636#include <iprt/assert.h>
    3737#include <iprt/asm.h>
    38 
     38#ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    3939# include <libxml/xmlmodule.h>
    4040# include <libxml/globals.h>
     
    4444# include <openssl/x509.h>
    4545# include <openssl/rsa.h>
     46#endif
    4647
    4748
     
    5455    (PFNRT)SUPR3PageAllocEx,
    5556    (PFNRT)SUPSemEventCreate,
     57#ifdef VBOX_WITH_LIBXML2_IN_VBOXRT
    5658    (PFNRT)xmlModuleOpen,
    5759    (PFNRT)MD5_Init,
     
    6365    (PFNRT)i2d_X509,
    6466    (PFNRT)RSA_generate_key,
     67#endif
    6568    (PFNRT)RTAssertShouldPanic,
    6669    (PFNRT)ASMAtomicReadU64,
  • trunk/src/VBox/Runtime/testcase/tstUtf8.cpp

    r21073 r21077  
    4242#include <iprt/err.h>
    4343#include <iprt/test.h>
    44 #include <iprt/ministring_cpp.h>
    4544
    4645#include <stdlib.h> /** @todo use our random. */
     
    927926
    928927
    929 void testMinistring(RTTEST hTest)
    930 {
    931     RTTestSub(hTest, "class ministring");
    932 
    933 #define CHECK(expr) \
    934     do { \
    935         if (!(expr)) \
    936             RTTestFailed(hTest, "%d: FAILED %s", __LINE__, #expr); \
    937     } while (0)
    938 
    939 #define CHECK_DUMP(expr, value) \
    940     do { \
    941         if (!(expr)) \
    942             RTTestFailed(hTest, "%d: FAILED %s, got \"%s\"", __LINE__, #expr, value); \
    943     } while (0)
    944 
    945 #define CHECK_DUMP_I(expr) \
    946     do { \
    947         if (!(expr)) \
    948             RTTestFailed(hTest, "%d: FAILED %s, got \"%d\"", __LINE__, #expr, expr); \
    949     } while (0)
    950 
    951     ministring empty;
    952     CHECK( (empty.length() == 0) );
    953     CHECK( (empty.capacity() == 0) );
    954 
    955     ministring sixbytes("12345");
    956     CHECK( (sixbytes.length() == 5) );
    957     CHECK( (sixbytes.capacity() == 6) );
    958 
    959     sixbytes.append("678");
    960     CHECK( (sixbytes.length() == 8) );
    961     CHECK( (sixbytes.capacity() == 9) );
    962 
    963     char *psz = sixbytes.mutableRaw();
    964         // 12345678
    965         //       ^
    966         // 0123456
    967     psz[6] = '\0';
    968     sixbytes.jolt();
    969     CHECK( (sixbytes.length() == 6) );
    970     CHECK( (sixbytes.capacity() == 7) );
    971 
    972     ministring morebytes("tobereplaced");
    973     morebytes = "newstring ";
    974     morebytes.append(sixbytes);
    975 
    976     CHECK_DUMP( (morebytes == "newstring 123456"), morebytes.c_str() );
    977 
    978     ministring third(morebytes);
    979     third.reserve(100 * 1024);      // 100 KB
    980     CHECK_DUMP( (third == "newstring 123456"), morebytes.c_str() );
    981     CHECK( (third.capacity() == 100 * 1024) );
    982     CHECK( (third.length() == morebytes.length()) );        // must not have changed
    983 
    984     ministring copy1(morebytes);
    985     ministring copy2 = morebytes;
    986     CHECK( (copy1 == copy2) );
    987 
    988     copy1 = NULL;
    989     CHECK( (copy1.isNull()) );
    990 
    991     copy1 = "";
    992     CHECK( (copy1.isEmpty()) );
    993 
    994     CHECK( (ministring("abc") < ministring("def")) );
    995     CHECK( (ministring("abc") != ministring("def")) );
    996     CHECK_DUMP_I( (ministring("def") > ministring("abc")) );
    997 
    998     copy2.setNull();
    999     for (int i = 0;
    1000          i < 100;
    1001          ++i)
    1002     {
    1003         copy2.reserve(50);      // should be ignored after 50 loops
    1004         copy2.append("1");
    1005     }
    1006     CHECK( (copy2.length() == 100) );
    1007 
    1008 #undef CHECK
    1009 }
    1010 
    1011928int main()
    1012929{
     
    1029946    TstRTStrXCmp(hTest);
    1030947    testStrStr(hTest);
    1031 
    1032     testMinistring(hTest);
    1033 
    1034948    Benchmarks(hTest);
    1035949
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