Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

string.h

Go to the documentation of this file.
/* $Id: string.h $ */

/** @file
 * MS COM / XPCOM Abstraction Layer:
 * Smart string classes declaration
 */

/*
 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 * additional information or have any questions.
 */

#ifndef ___VBox_com_string_h
#define ___VBox_com_string_h

/* Make sure all the stdint.h macros are included - must come first! */
#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
#endif

#if defined (VBOX_WITH_XPCOM)
# include <nsMemory.h>
#endif

#include "VBox/com/defs.h"
#include "VBox/com/assert.h"

#include <iprt/cpputils.h>
#include <iprt/alloc.h>
#include <iprt/ministring_cpp.h>

namespace com
{

class Utf8Str;

/**
 *  Helper class that represents the |BSTR| type and hides platform-specific
 *  implementation details.
 *
 *  This class uses COM/XPCOM-provided memory management routines to allocate
 *  and free string buffers. This makes it possible to:
 *  - use it as a type of member variables of COM/XPCOM components and pass
 *    their values to callers through component methods' output parameters
 *    using the #cloneTo() operation;
 *  - adopt (take ownership of) string buffers returned in output parameters
 *    of COM methods using the #asOutParam() operation and correctly free them
 *    afterwards.
 */
00073 class Bstr
{
public:

    typedef BSTR String;
    typedef CBSTR ConstString;

    Bstr () : bstr (NULL) {}

    Bstr (const Bstr &that) : bstr (NULL) { raw_copy (bstr, that.bstr); }
    Bstr (CBSTR that) : bstr (NULL) { raw_copy (bstr, that); }

#if defined (VBOX_WITH_XPCOM)
    Bstr (const wchar_t *that) : bstr (NULL)
    {
        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
        raw_copy (bstr, (CBSTR) that);
    }
#endif

    Bstr (const iprt::MiniString &that);
    Bstr (const char *that);

    /** Shortcut that calls #alloc(aSize) right after object creation. */
00097     Bstr (size_t aSize) : bstr (NULL) { alloc (aSize); }

    ~Bstr () { setNull(); }

    Bstr &operator = (const Bstr &that) { safe_assign (that.bstr); return *this; }
    Bstr &operator = (CBSTR that) { safe_assign (that); return *this; }

    Bstr &operator = (const Utf8Str &that);
    Bstr &operator = (const char *that);

    Bstr &setNull()
    {
        if (bstr)
        {
            ::SysFreeString (bstr);
            bstr = NULL;
        }
        return *this;
    }

    Bstr &setNullIfEmpty()
    {
        if (bstr && *bstr == 0)
        {
            ::SysFreeString (bstr);
            bstr = NULL;
        }
        return *this;
    }

    /**
     *  Allocates memory for a string capable to store \a aSize - 1 characters;
     *  in other words, aSize includes the terminating zero character. If \a aSize
     *  is zero, or if a memory allocation error occurs, this object will become null.
     */
00132     Bstr &alloc (size_t aSize)
    {
        setNull();
        if (aSize)
        {
            unsigned int size = (unsigned int) aSize; Assert (size == aSize);
            bstr = ::SysAllocStringLen (NULL, size - 1);
            if (bstr)
                bstr [0] = 0;
        }
        return *this;
    }

    int compare (CBSTR str) const
    {
        return ::RTUtf16Cmp ((PRTUTF16) bstr, (PRTUTF16) str);
    }

    int compare (BSTR str) const
    {
        return ::RTUtf16Cmp ((PRTUTF16) bstr, (PRTUTF16) str);
    }

    bool operator==(const Bstr &that) const { return !compare (that.bstr); }
    bool operator!=(const Bstr &that) const { return !!compare (that.bstr); }
    bool operator==(CBSTR that) const { return !compare (that); }
    bool operator==(BSTR that) const { return !compare (that); }

#if defined (VBOX_WITH_XPCOM)
    bool operator!=(const wchar_t *that) const
    {
        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
        return !!compare ((CBSTR) that);
    }
    bool operator==(const wchar_t *that) const
    {
        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
        return !compare ((CBSTR) that);
    }
#endif

    bool operator!=(CBSTR that) const { return !!compare (that); }
    bool operator!=(BSTR that) const { return !!compare (that); }
    bool operator<(const Bstr &that) const { return compare (that.bstr) < 0; }
    bool operator<(CBSTR that) const { return compare (that) < 0; }
    bool operator<(BSTR that) const { return compare (that) < 0; }
#if defined (VBOX_WITH_XPCOM)
    bool operator<(const wchar_t *that) const
    {
        AssertCompile (sizeof (wchar_t) == sizeof (OLECHAR));
        return compare ((CBSTR) that) < 0;
    }
#endif

    int compareIgnoreCase (CBSTR str) const
    {
        return ::RTUtf16LocaleICmp (bstr, str);
    }

    bool isNull() const { return bstr == NULL; }
    operator bool() const { return !isNull(); }

    bool isEmpty() const { return isNull() || *bstr == 0; }

    size_t length() const { return isNull() ? 0 : ::RTUtf16Len ((PRTUTF16) bstr); }

    /** Intended to to pass instances as |CBSTR| input parameters to methods. */
00199     operator CBSTR () const { return bstr; }

    /**
     * Intended to to pass instances as |BSTR| input parameters to methods.
     * Note that we have to provide this mutable BSTR operator since in MS COM
     * input BSTR parameters of interface methods are not const.
     */
00206     operator BSTR () { return bstr; }

    /**
     *  The same as operator CBSTR(), but for situations where the compiler
     *  cannot typecast implicitly (for example, in printf() argument list).
     */
00212     CBSTR raw() const { return bstr; }

    /**
     *  Returns a non-const raw pointer that allows to modify the string directly.
     *  @warning
     *      Be sure not to modify data beyond the allocated memory! The
     *      guaranteed size of the allocated memory is at least #length()
     *      bytes after creation and after every assignment operation.
     */
00221     BSTR mutableRaw() { return bstr; }

    /**
     *  Intended to assign copies of instances to |BSTR| out parameters from
     *  within the interface method. Transfers the ownership of the duplicated
     *  string to the caller.
     */
00228     const Bstr &cloneTo (BSTR *pstr) const
    {
        if (pstr)
        {
            *pstr = NULL;
            raw_copy (*pstr, bstr);
        }
        return *this;
    }

    /**
     *  Intended to assign instances to |BSTR| out parameters from within the
     *  interface method. Transfers the ownership of the original string to the
     *  caller and resets the instance to null.
     *
     *  As opposed to cloneTo(), this method doesn't create a copy of the
     *  string.
     */
00246     Bstr &detachTo (BSTR *pstr)
    {
        *pstr = bstr;
        bstr = NULL;
        return *this;
    }

    /**
     *  Intended to assign copies of instances to |char *| out parameters from
     *  within the interface method. Transfers the ownership of the duplicated
     *  string to the caller.
     */
    const Bstr &cloneTo (char **pstr) const;

    /**
     *  Intended to pass instances as |BSTR| out parameters to methods.
     *  Takes the ownership of the returned data.
     */
00264     BSTR *asOutParam() { setNull(); return &bstr; }

    /**
     *  Static immutable null object. May be used for comparison purposes.
     */
00269     static const Bstr Null;

protected:

    void safe_assign (CBSTR str)
    {
        if (bstr != str)
        {
            setNull();
            raw_copy (bstr, str);
        }
    }

    inline static void raw_copy(BSTR &ls, CBSTR rs)
    {
        if (rs)
            ls = ::SysAllocString((const OLECHAR *) rs);
    }

    inline static void raw_copy (BSTR &ls, const char *rs)
    {
        if (rs)
        {
            PRTUTF16 s = NULL;
            ::RTStrToUtf16 (rs, &s);
            raw_copy (ls, (BSTR) s);
            ::RTUtf16Free (s);
        }
    }

    BSTR bstr;

    friend class Utf8Str; /* to access our raw_copy() */
};

/* symmetric compare operators */
inline bool operator==(CBSTR l, const Bstr &r) { return r.operator== (l); }
inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!= (l); }
inline bool operator==(BSTR l, const Bstr &r) { return r.operator== (l); }
inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!= (l); }

////////////////////////////////////////////////////////////////////////////////

/**
 *  Helper class that represents UTF8 (|char *|) strings. Useful in
 *  conjunction with Bstr to simplify conversions between UTF16 (|BSTR|)
 *  and UTF8.
 *
 *  This class uses COM/XPCOM-provided memory management routines to allocate
 *  and free string buffers. This makes it possible to:
 *  - use it as a type of member variables of COM/XPCOM components and pass
 *    their values to callers through component methods' output parameters
 *    using the #cloneTo() operation;
 *  - adopt (take ownership of) string buffers returned in output parameters
 *    of COM methods using the #asOutParam() operation and correctly free them
 *    afterwards.
 */
00326 class Utf8Str : public iprt::MiniString
{
public:

    Utf8Str() {}

    Utf8Str(const MiniString &that)
        : MiniString(that)
    {}

    Utf8Str(const char *that)
        : MiniString(that)
    {}

    Utf8Str(const Bstr &that)
    {
        copyFrom(that);
    }

    Utf8Str(CBSTR that)
    {
        copyFrom(that);
    }

    Utf8Str& operator=(const MiniString &that)
    {
        MiniString::operator=(that);
        return *this;
    }

00356     Utf8Str& operator=(const char *that)
    {
        MiniString::operator=(that);
        return *this;
    }

    Utf8Str& operator=(const Bstr &that)
    {
        cleanup();
        copyFrom(that);
        return *this;
    }

    Utf8Str& operator=(CBSTR that)
    {
        cleanup();
        copyFrom(that);
        return *this;
    }

    /**
     * Intended to assign instances to |char *| out parameters from within the
     * interface method. Transfers the ownership of the duplicated string to the
     * caller.
     *
     * @remarks The returned string must be freed by RTStrFree, not RTMemFree.
     */
00383     const Utf8Str& cloneTo(char **pstr) const
    {
        if (pstr) /** @todo r=bird: This needs to if m_psz is NULL. Shouldn't it also throw std::bad_alloc? */
            *pstr = RTStrDup(m_psz);
        return *this;
    }

    /**
     *  Intended to assign instances to |char *| out parameters from within the
     *  interface method. Transfers the ownership of the original string to the
     *  caller and resets the instance to null.
     *
     *  As opposed to cloneTo(), this method doesn't create a copy of the
     *  string.
     */
00398     Utf8Str& detachTo(char **pstr)
    {
        *pstr = m_psz;
        m_psz = NULL;
        m_cbAllocated = 0;
        m_cbLength = 0;
        return *this;
    }

    /**
     *  Intended to assign instances to |BSTR| out parameters from within the
     *  interface method. Transfers the ownership of the duplicated string to the
     *  caller.
     */
00412     const Utf8Str& cloneTo(BSTR *pstr) const
    {
        if (pstr)
        {
            *pstr = NULL;
            Bstr::raw_copy(*pstr, m_psz);
        }
        return *this;
    }

    /**
     * Converts "this" to lower case by calling RTStrToLower().
     * @return
     */
    Utf8Str& toLower();

    /**
     * Converts "this" to upper case by calling RTStrToUpper().
     * @return
     */
    Utf8Str& toUpper();

    /**
     * Removes a trailing slash from the member string, if present.
     * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
     */
    void stripTrailingSlash();

    /**
     * Removes a trailing filename from the member string, if present.
     * Calls RTPathStripFilename() without having to mess with mutableRaw().
     */
    void stripFilename();

    /**
     * Removes a trailing file name extension from the member string, if present.
     * Calls RTPathStripExt() without having to mess with mutableRaw().
     */
    void stripExt();

    /**
     * Attempts to convert the member string into a 32-bit integer.
     *
     * @returns 32-bit unsigned number on success.
     * @returns 0 on failure.
     */
00458     int toInt32() const
    {
        return RTStrToInt32(m_psz);
    }

    /**
     * Attempts to convert the member string into an unsigned 32-bit integer.
     *
     * @returns 32-bit unsigned number on success.
     * @returns 0 on failure.
     */
00469     int toUInt32() const
    {
        return RTStrToUInt32(m_psz);
    }

    /**
     * Intended to pass instances as out (|char **|) parameters to methods. Takes
     * the ownership of the returned data.
     *
     * @remarks    See ministring::jolt().
     */
00480     char **asOutParam()
    {
        cleanup();
        return &m_psz;
    }

    /**
     *  Static immutable null object. May be used for comparison purposes.
     */
00489     static const Utf8Str Null;

protected:

    /**
     * As with the ministring::copyFrom() variants, this unconditionally
     * sets the members to a copy of the given other strings and makes
     * no assumptions about previous contents. This can therefore be used
     * both in copy constructors, when member variables have no defined
     * value, and in assignments after having called cleanup().
     *
     * This variant converts from a UTF-16 string, most probably from
     * a Bstr assignment.
     *
     * @param rs
     */
00505     void copyFrom(CBSTR s)
    {
        if (s)
        {
            RTUtf16ToUtf8((PRTUTF16)s, &m_psz); /** @todo r=bird: This isn't throwing std::bad_alloc / handling return codes.
                                                 * Also, this technically requires using RTStrFree, ministring::cleanup() uses RTMemFree. */
            m_cbLength = strlen(m_psz);         /** @todo optimize by using a different RTUtf* function */
            m_cbAllocated = m_cbLength + 1;
        }
        else
        {
            m_cbLength = 0;
            m_cbAllocated = 0;
            m_psz = NULL;
        }
    }

    friend class Bstr; /* to access our raw_copy() */
};

// work around error C2593 of the stupid MSVC 7.x ambiguity resolver
WORKAROUND_MSVC7_ERROR_C2593_FOR_BOOL_OP (Bstr)

////////////////////////////////////////////////////////////////////////////////

// inlined Bstr members that depend on Utf8Str

inline Bstr::Bstr(const iprt::MiniString &that)
    : bstr(NULL)
{
    raw_copy(bstr, that.c_str());
}

inline Bstr::Bstr(const char *that)
    : bstr(NULL)
{
    raw_copy(bstr, that);
}

inline Bstr &Bstr::operator=(const Utf8Str &that)
{
    setNull();
    raw_copy(bstr, that.c_str());
    return *this;
}
inline Bstr &Bstr::operator=(const char *that)
{
    setNull();
    raw_copy(bstr, that);
    return *this;
}

00557 inline const Bstr& Bstr::cloneTo(char **pstr) const
{
    if (pstr)
    {
        Utf8Str ustr(*this);
        ustr.detachTo(pstr);
    }
    return *this;
}

////////////////////////////////////////////////////////////////////////////////

/**
 *  This class is a printf-like formatter for Utf8Str strings. Its purpose is
 *  to construct Utf8Str objects from a format string and a list of arguments
 *  for the format string.
 *
 *  The usage of this class is like the following:
 *  <code>
 *      Utf8StrFmt string ("program name = %s", argv[0]);
 *  </code>
 */
00579 class Utf8StrFmt : public Utf8Str
{
public:

    /**
     *  Constructs a new string given the format string and the list
     *  of the arguments for the format string.
     *
     *  @param format   printf-like format string (in UTF-8 encoding)
     *  @param ...      list of the arguments for the format string
     */
00590     explicit Utf8StrFmt (const char *format, ...)
    {
        va_list args;
        va_start (args, format);
        init (format, args);
        va_end (args);
    }

protected:

    Utf8StrFmt() {}

    void init (const char *format, va_list args);

private:

    static DECLCALLBACK(size_t) strOutput (void *pvArg, const char *pachChars,
                                           size_t cbChars);
};

/**
 *  This class is a vprintf-like formatter for Utf8Str strings. It is
 *  identical to Utf8StrFmt except that its constructor takes a va_list
 *  argument instead of ellipsis.
 *
 *  Note that a separate class is necessary because va_list is defined as
 *  |char *| on most platforms. For this reason, if we had two overloaded
 *  constructors in Utf8StrFmt (one taking ellipsis and another one taking
 *  va_list) then composing a constructor call using exactly two |char *|
 *  arguments would cause the compiler to use the va_list overload instead of
 *  the ellipsis one which is obviously wrong. The compiler would choose
 *  va_list because ellipsis has the lowest rank when it comes to resolving
 *  overloads, as opposed to va_list which is an exact match for |char *|.
 */
00624 class Utf8StrFmtVA : public Utf8StrFmt
{
public:

    /**
     *  Constructs a new string given the format string and the list
     *  of the arguments for the format string.
     *
     *  @param format   printf-like format string (in UTF-8 encoding)
     *  @param args     list of arguments for the format string
     */
00635     Utf8StrFmtVA (const char *format, va_list args) { init (format, args); }
};

/**
 * The BstrFmt class is a shortcut to <tt>Bstr (Utf8StrFmt (...))</tt>.
 */
00641 class BstrFmt : public Bstr
{
public:

    /**
     * Constructs a new string given the format string and the list of the
     * arguments for the format string.
     *
     * @param aFormat   printf-like format string (in UTF-8 encoding).
     * @param ...       List of the arguments for the format string.
     */
00652     explicit BstrFmt (const char *aFormat, ...)
    {
        va_list args;
        va_start(args, aFormat);
        raw_copy(bstr, Utf8StrFmtVA(aFormat, args).c_str());
        va_end (args);
    }
};

/**
 * The BstrFmtVA class is a shortcut to <tt>Bstr (Utf8StrFmtVA (...))</tt>.
 */
00664 class BstrFmtVA : public Bstr
{
public:

    /**
     * Constructs a new string given the format string and the list of the
     * arguments for the format string.
     *
     * @param aFormat   printf-like format string (in UTF-8 encoding).
     * @param aArgs     List of arguments for the format string
     */
00675     BstrFmtVA (const char *aFormat, va_list aArgs)
    {
        raw_copy(bstr, Utf8StrFmtVA(aFormat, aArgs).c_str());
    }
};

} /* namespace com */

#endif /* !___VBox_com_string_h */


Generated by  Doxygen 1.6.0   Back to index