summaryrefslogtreecommitdiffstats
path: root/include/VBox/com/string.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /include/VBox/com/string.h
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/VBox/com/string.h')
-rw-r--r--include/VBox/com/string.h1494
1 files changed, 1494 insertions, 0 deletions
diff --git a/include/VBox/com/string.h b/include/VBox/com/string.h
new file mode 100644
index 00000000..6bf19ae6
--- /dev/null
+++ b/include/VBox/com/string.h
@@ -0,0 +1,1494 @@
+/* $Id: string.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Smart string classes declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_string_h
+#define VBOX_INCLUDED_com_string_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* 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/mem.h>
+#include <iprt/utf16.h>
+#include <iprt/cpp/ministring.h>
+
+
+/** @defgroup grp_com_str Smart String Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+class Utf8Str;
+
+// global constant in glue/string.cpp that represents an empty BSTR
+extern const BSTR g_bstrEmpty;
+
+/**
+ * String class used universally in Main for COM-style Utf-16 strings.
+ *
+ * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions
+ * back and forth since most of VirtualBox and our libraries use UTF-8.
+ *
+ * To make things more obscure, on Windows, a COM-style BSTR is not just a
+ * pointer to a null-terminated wide character array, but the four bytes (32
+ * bits) BEFORE the memory that the pointer points to are a length DWORD. One
+ * must therefore avoid pointer arithmetic and always use SysAllocString and
+ * the like to deal with BSTR pointers, which manage that DWORD correctly.
+ *
+ * For platforms other than Windows, we provide our own versions of the Sys*
+ * functions in Main/xpcom/helpers.cpp which do NOT use length prefixes though
+ * to be compatible with how XPCOM allocates string parameters to public
+ * functions.
+ *
+ * The Bstr class hides all this handling behind a std::string-like interface
+ * and also provides automatic conversions to RTCString and Utf8Str instances.
+ *
+ * The one advantage of using the SysString* routines is that 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. Also, the class can adopt (take ownership
+ * of) string buffers returned in output parameters of COM methods using the
+ * #asOutParam() operation and correctly free them afterwards.
+ *
+ * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates
+ * between NULL strings and empty strings. In other words, Bstr("") and
+ * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory,
+ * reports a zero length and zero allocated bytes for both, and returns an
+ * empty C wide string from raw().
+ *
+ * @note All Bstr methods ASSUMES valid UTF-16 or UTF-8 input strings.
+ * The VirtualBox policy in this regard is to validate strings coming
+ * from external sources before passing them to Bstr or Utf8Str.
+ */
+class Bstr
+{
+public:
+
+ Bstr()
+ : m_bstr(NULL)
+ { }
+
+ Bstr(const Bstr &that)
+ {
+ copyFrom((const OLECHAR *)that.m_bstr);
+ }
+
+ Bstr(CBSTR that)
+ {
+ copyFrom((const OLECHAR *)that);
+ }
+
+#if defined(VBOX_WITH_XPCOM)
+ Bstr(const wchar_t *that)
+ {
+ AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR));
+ copyFrom((const OLECHAR *)that);
+ }
+#endif
+
+ Bstr(const RTCString &that)
+ {
+ copyFrom(that.c_str());
+ }
+
+ Bstr(const char *that)
+ {
+ copyFrom(that);
+ }
+
+ Bstr(const char *a_pThat, size_t a_cchMax)
+ {
+ copyFromN(a_pThat, a_cchMax);
+ }
+
+ ~Bstr()
+ {
+ setNull();
+ }
+
+ Bstr &operator=(const Bstr &that)
+ {
+ cleanupAndCopyFrom((const OLECHAR *)that.m_bstr);
+ return *this;
+ }
+
+ Bstr &operator=(CBSTR that)
+ {
+ cleanupAndCopyFrom((const OLECHAR *)that);
+ return *this;
+ }
+
+#if defined(VBOX_WITH_XPCOM)
+ Bstr &operator=(const wchar_t *that)
+ {
+ cleanupAndCopyFrom((const OLECHAR *)that);
+ return *this;
+ }
+#endif
+
+ Bstr &setNull()
+ {
+ cleanup();
+ return *this;
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(const Bstr &a_rSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromEx((const OLECHAR *)a_rSrcStr.m_bstr);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pSrcStr The source string
+ */
+ HRESULT assignEx(CBSTR a_pSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromEx((const OLECHAR *)a_pSrcStr);
+ }
+
+ /**
+ * Assign the value of a RTCString/Utf8Str string, no exceptions.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(RTCString const &a_rSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromNoThrow(a_rSrcStr.c_str(), a_rSrcStr.length());
+ }
+
+ /**
+ * Assign the value of a RTCString/Utf8Str substring, no exceptions.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVALIDARG.
+ * @param a_rSrcStr The source string
+ * @param a_offSrc The character (byte) offset of the substring.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(RTCString const &a_rSrcStr, size_t a_offSrc, size_t a_cchSrc) RT_NOEXCEPT
+ {
+ size_t const cchTmp = a_rSrcStr.length();
+ if ( a_offSrc + a_cchSrc < cchTmp
+ && a_offSrc < cchTmp)
+ return cleanupAndCopyFromNoThrow(a_rSrcStr.c_str() + a_offSrc, a_cchSrc);
+ return E_INVALIDARG;
+ }
+
+ /**
+ * Assign the value of a zero terminated UTF-8 string, no exceptions.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pszSrcStr The source string.
+ */
+ HRESULT assignEx(const char *a_pszSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromNoThrow(a_pszSrcStr, RTSTR_MAX);
+ }
+
+ /**
+ * Assign the value of a UTF-8 substring, no exceptions.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pszSrcStr The source string.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(const char *a_pszSrcStr, size_t a_cchSrc) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromNoThrow(a_pszSrcStr, a_cchSrc);
+ }
+
+#ifdef _MSC_VER
+# if _MSC_VER >= 1400
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+# endif
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+
+ /** Case sensitivity selector. */
+ enum CaseSensitivity
+ {
+ CaseSensitive,
+ CaseInsensitive
+ };
+
+ /**
+ * Compares the member string to str.
+ * @param str
+ * @param cs Whether comparison should be case-sensitive.
+ * @return
+ */
+ int compare(CBSTR str, CaseSensitivity cs = CaseSensitive) const
+ {
+ if (cs == CaseSensitive)
+ return ::RTUtf16Cmp((PRTUTF16)m_bstr, (PRTUTF16)str);
+ return ::RTUtf16LocaleICmp((PRTUTF16)m_bstr, (PRTUTF16)str);
+ }
+
+ int compare(BSTR str, CaseSensitivity cs = CaseSensitive) const
+ {
+ return compare((CBSTR)str, cs);
+ }
+
+ int compare(const Bstr &that, CaseSensitivity cs = CaseSensitive) const
+ {
+ return compare(that.m_bstr, cs);
+ }
+
+ bool operator==(const Bstr &that) const { return !compare(that.m_bstr); }
+ 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.m_bstr); }
+ 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.m_bstr) < 0; }
+ bool operator<(CBSTR that) const { return compare(that) < 0; }
+ bool operator<(BSTR that) const { return compare(that) < 0; }
+ bool operator<=(const Bstr &that) const { return compare(that.m_bstr) <= 0; }
+ bool operator<=(CBSTR that) const { return compare(that) <= 0; }
+ bool operator<=(BSTR that) const { return compare(that) <= 0; }
+ bool operator>(const Bstr &that) const { return compare(that.m_bstr) > 0; }
+ bool operator>(CBSTR that) const { return compare(that) > 0; }
+ bool operator>(BSTR that) const { return compare(that) > 0; }
+ bool operator>=(const Bstr &that) const { return compare(that.m_bstr) >= 0; }
+ bool operator>=(CBSTR that) const { return compare(that) >= 0; }
+ bool operator>=(BSTR that) const { return compare(that) >= 0; }
+
+ /**
+ * Compares this string to an UTF-8 C style string.
+ *
+ * @retval 0 if equal
+ * @retval -1 if this string is smaller than the UTF-8 one.
+ * @retval 1 if the UTF-8 string is smaller than this.
+ *
+ * @param a_pszRight The string to compare with.
+ * @param a_enmCase Whether comparison should be case-sensitive.
+ */
+ int compareUtf8(const char *a_pszRight, CaseSensitivity a_enmCase = CaseSensitive) const;
+
+ /** Java style compare method.
+ * @returns true if @a a_pszRight equals this string.
+ * @param a_pszRight The (UTF-8) string to compare with. */
+ bool equals(const char *a_pszRight) const { return compareUtf8(a_pszRight, CaseSensitive) == 0; }
+
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_pszRight equals this string.
+ * @param a_pszRight The (UTF-8) string to compare with. */
+ bool equalsIgnoreCase(const char *a_pszRight) const { return compareUtf8(a_pszRight, CaseInsensitive) == 0; }
+
+ /** Java style compare method.
+ * @returns true if @a a_rThat equals this string.
+ * @param a_rThat The other Bstr instance to compare with. */
+ bool equals(const Bstr &a_rThat) const { return compare(a_rThat.m_bstr, CaseSensitive) == 0; }
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_rThat equals this string.
+ * @param a_rThat The other Bstr instance to compare with. */
+ bool equalsIgnoreCase(const Bstr &a_rThat) const { return compare(a_rThat.m_bstr, CaseInsensitive) == 0; }
+
+ /** Java style compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native const BSTR to compare with. */
+ bool equals(CBSTR a_pThat) const { return compare(a_pThat, CaseSensitive) == 0; }
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native const BSTR to compare with. */
+ bool equalsIgnoreCase(CBSTR a_pThat) const { return compare(a_pThat, CaseInsensitive) == 0; }
+
+ /** Java style compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native BSTR to compare with. */
+ bool equals(BSTR a_pThat) const { return compare(a_pThat, CaseSensitive) == 0; }
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native BSTR to compare with. */
+ bool equalsIgnoreCase(BSTR a_pThat) const { return compare(a_pThat, CaseInsensitive) == 0; }
+
+ /**
+ * Checks if the string starts with @a a_rStart.
+ */
+ bool startsWith(Bstr const &a_rStart) const;
+ /**
+ * Checks if the string starts with @a a_rStart.
+ */
+ bool startsWith(RTCString const &a_rStart) const;
+ /**
+ * Checks if the string starts with @a a_pszStart.
+ */
+ bool startsWith(const char *a_pszStart) const;
+
+ /**
+ * Returns true if the member string has no length.
+ * This is true for instances created from both NULL and "" input strings.
+ *
+ * @note Always use this method to check if an instance is empty. Do not
+ * use length() because that may need to run through the entire string
+ * (Bstr does not cache string lengths).
+ */
+ bool isEmpty() const { return m_bstr == NULL || *m_bstr == 0; }
+
+ /**
+ * Returns true if the member string has a length of one or more.
+ *
+ * @returns true if not empty, false if empty (NULL or "").
+ */
+ bool isNotEmpty() const { return m_bstr != NULL && *m_bstr != 0; }
+
+ size_t length() const { return isEmpty() ? 0 : ::RTUtf16Len((PRTUTF16)m_bstr); }
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &printfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /** @name Append methods and operators
+ * @{ */
+
+ /**
+ * Appends the string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const Bstr &rThat);
+
+ /**
+ * Appends the string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const Bstr &rThat) RT_NOEXCEPT;
+
+ /**
+ * Appends the UTF-8 string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const RTCString &rThat);
+
+ /**
+ * Appends the UTF-8 string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const RTCString &rThat) RT_NOEXCEPT;
+
+ /**
+ * Appends the UTF-16 string @a pszSrc to @a this.
+ *
+ * @param pwszSrc The C-style UTF-16 string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(CBSTR pwszSrc);
+
+ /**
+ * Appends the UTF-16 string @a pszSrc to @a this.
+ *
+ * @param pwszSrc The C-style UTF-16 string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(CBSTR pwszSrc) RT_NOEXCEPT;
+
+ /**
+ * Appends the UTF-8 string @a pszSrc to @a this.
+ *
+ * @param pszSrc The C-style string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const char *pszSrc);
+
+ /**
+ * Appends the UTF-8 string @a pszSrc to @a this.
+ *
+ * @param pszSrc The C-style string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const char *pszSrc) RT_NOEXCEPT;
+
+ /**
+ * Appends the a substring from @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (UTF-16
+ * offset, not codepoint).
+ * @param cwcMax The maximum number of UTF-16 units to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const Bstr &rThat, size_t offStart, size_t cwcMax = RTSTR_MAX);
+
+ /**
+ * Appends the a substring from @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (UTF-16
+ * offset, not codepoint).
+ * @param cwcMax The maximum number of UTF-16 units to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const Bstr &rThat, size_t offStart, size_t cwcMax = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Appends the a substring from UTF-8 @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (byte offset,
+ * not codepoint).
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const RTCString &rThat, size_t offStart, size_t cchMax = RTSTR_MAX);
+
+ /**
+ * Appends the a substring from UTF-8 @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (byte offset,
+ * not codepoint).
+ * @param cchMax The maximum number of bytes to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const RTCString &rThat, size_t offStart, size_t cchMax = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Appends the first @a cchMax chars from UTF-16 string @a pszThat to @a this.
+ *
+ * @param pwszThat The C-style UTF-16 string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(CBSTR pwszThat, size_t cchMax);
+
+ /**
+ * Appends the first @a cchMax chars from UTF-16 string @a pszThat to @a this.
+ *
+ * @param pwszThat The C-style UTF-16 string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(CBSTR pwszThat, size_t cchMax) RT_NOEXCEPT;
+
+ /**
+ * Appends the first @a cchMax chars from string @a pszThat to @a this.
+ *
+ * @param pszThat The C-style string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const char *pszThat, size_t cchMax);
+
+ /**
+ * Appends the first @a cchMax chars from string @a pszThat to @a this.
+ *
+ * @param pszThat The C-style string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const char *pszThat, size_t cchMax) RT_NOEXCEPT;
+
+ /**
+ * Appends the given character to @a this.
+ *
+ * @param ch The character to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(char ch);
+
+ /**
+ * Appends the given character to @a this.
+ *
+ * @param ch The character to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(char ch) RT_NOEXCEPT;
+
+ /**
+ * Appends the given unicode code point to @a this.
+ *
+ * @param uc The unicode code point to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &appendCodePoint(RTUNICP uc);
+
+ /**
+ * Appends the given unicode code point to @a this.
+ *
+ * @param uc The unicode code point to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendCodePointNoThrow(RTUNICP uc) RT_NOEXCEPT;
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &appendPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendPrintfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &appendPrintfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendPrintfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Shortcut to append(), Bstr variant.
+ *
+ * @param rThat The string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(const Bstr &rThat)
+ {
+ return append(rThat);
+ }
+
+ /**
+ * Shortcut to append(), RTCString variant.
+ *
+ * @param rThat The string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(const RTCString &rThat)
+ {
+ return append(rThat);
+ }
+
+ /**
+ * Shortcut to append(), CBSTR variant.
+ *
+ * @param pwszThat The C-style string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(CBSTR pwszThat)
+ {
+ return append(pwszThat);
+ }
+
+ /**
+ * Shortcut to append(), const char * variant.
+ *
+ * @param pszThat The C-style string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(const char *pszThat)
+ {
+ return append(pszThat);
+ }
+
+ /**
+ * Shortcut to append(), char variant.
+ *
+ * @param ch The character to append.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(char ch)
+ {
+ return append(ch);
+ }
+
+ /** @} */
+
+ /**
+ * Erases a sequence from the string.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start erasing (UTF-16
+ * units, not codepoints).
+ * @param cwcLength How much following @a offStart to erase (UTF-16
+ * units, not codepoints).
+ */
+ Bstr &erase(size_t offStart = 0, size_t cwcLength = RTSTR_MAX) RT_NOEXCEPT;
+
+
+ /** @name BASE64 related methods
+ * @{ */
+ /**
+ * Encodes the given data as BASE64.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param pvData Pointer to the data to encode.
+ * @param cbData Number of bytes to encode.
+ * @param fLineBreaks Whether to add line breaks (true) or just encode it
+ * as a continuous string.
+ * @sa RTBase64EncodeUtf16
+ */
+ HRESULT base64Encode(const void *pvData, size_t cbData, bool fLineBreaks = false);
+
+ /**
+ * Decodes the string as BASE64.
+ *
+ * @returns IPRT status code, see RTBase64DecodeUtf16Ex.
+ * @param pvData Where to return the decoded bytes.
+ * @param cbData Size of the @a pvData return buffer.
+ * @param pcbActual Where to return number of bytes actually decoded.
+ * This is optional and if not specified, the request
+ * will fail unless @a cbData matches the data size
+ * exactly.
+ * @param ppwszEnd Where to return pointer to the first non-base64
+ * character following the encoded data. This is
+ * optional and if NULL, the request will fail if there
+ * are anything trailing the encoded bytes in the
+ * string.
+ * @sa base64DecodedSize, RTBase64DecodeUtf16
+ */
+ int base64Decode(void *pvData, size_t cbData, size_t *pcbActual = NULL, PRTUTF16 *ppwszEnd = NULL);
+
+ /**
+ * Determins the size of the BASE64 encoded data in the string.
+ *
+ * @returns The length in bytes. -1 if the encoding is bad.
+ *
+ * @param ppwszEnd If not NULL, this will point to the first char
+ * following the Base64 encoded text block. If
+ * NULL the entire string is assumed to be Base64.
+ * @sa base64Decode, RTBase64DecodedUtf16Size
+ */
+ ssize_t base64DecodedSize(PRTUTF16 *ppwszEnd = NULL);
+ /** @} */
+
+#if defined(VBOX_WITH_XPCOM)
+ /**
+ * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
+ * returns a pointer to a global variable containing an empty BSTR with a proper zero
+ * length prefix so that Windows is happy.
+ */
+ CBSTR raw() const
+ {
+ if (m_bstr)
+ return m_bstr;
+
+ return g_bstrEmpty;
+ }
+#else
+ /**
+ * Windows-only hack, as the automatically generated headers use BSTR.
+ * So if we don't want to cast like crazy we have to be more loose than
+ * on XPCOM.
+ *
+ * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
+ * returns a pointer to a global variable containing an empty BSTR with a proper zero
+ * length prefix so that Windows is happy.
+ */
+ BSTR raw() const
+ {
+ if (m_bstr)
+ return m_bstr;
+
+ return g_bstrEmpty;
+ }
+#endif
+
+ /**
+ * Returns a non-const raw pointer that allows modifying the string directly.
+ *
+ * @note As opposed to raw(), this DOES return NULL if the member string is
+ * empty because we cannot return a mutable pointer to the global variable
+ * with the empty string.
+ *
+ * @note If modifying the string size (only shrinking it is allows), #jolt() or
+ * #joltNoThrow() must be called!
+ *
+ * @note Do not modify memory beyond the #length() of the string!
+ *
+ * @sa joltNoThrow(), mutalbleRaw(), reserve(), reserveNoThrow()
+ */
+ BSTR mutableRaw() { return m_bstr; }
+
+ /**
+ * Correct the embedded length after using mutableRaw().
+ *
+ * This is needed on COM (Windows) to update the embedded string length. It is
+ * a stub on hosts using XPCOM.
+ *
+ * @param cwcNew The new string length, if handy, otherwise a negative
+ * number.
+ * @sa joltNoThrow(), mutalbleRaw(), reserve(), reserveNoThrow()
+ */
+#ifndef VBOX_WITH_XPCOM
+ void jolt(ssize_t cwcNew = -1);
+#else
+ void jolt(ssize_t cwcNew = -1)
+ {
+ Assert(cwcNew < 0 || (cwcNew == 0 && !m_bstr) || m_bstr[cwcNew] == '\0'); RT_NOREF(cwcNew);
+ }
+#endif
+
+ /**
+ * Correct the embedded length after using mutableRaw().
+ *
+ * This is needed on COM (Windows) to update the embedded string length. It is
+ * a stub on hosts using XPCOM.
+ *
+ * @returns S_OK on success, E_OUTOFMEMORY if shrinking the string failed.
+ * @param cwcNew The new string length, if handy, otherwise a negative
+ * number.
+ * @sa jolt(), mutalbleRaw(), reserve(), reserveNoThrow()
+ */
+#ifndef VBOX_WITH_XPCOM
+ HRESULT joltNoThrow(ssize_t cwcNew = -1) RT_NOEXCEPT;
+#else
+ HRESULT joltNoThrow(ssize_t cwcNew = -1) RT_NOEXCEPT
+ {
+ Assert(cwcNew < 0 || (cwcNew == 0 && !m_bstr) || m_bstr[cwcNew] == '\0'); RT_NOREF(cwcNew);
+ return S_OK;
+ }
+#endif
+
+ /**
+ * Make sure at that least @a cwc of buffer space is reserved.
+ *
+ * Requests that the contained memory buffer have at least cb bytes allocated.
+ * This may expand or shrink the string's storage, but will never truncate the
+ * contained string. In other words, cb will be ignored if it's smaller than
+ * length() + 1.
+ *
+ * @param cwcMin The new minimum string length that the can be stored. This
+ * does not include the terminator.
+ * @param fForce Force this size.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ void reserve(size_t cwcMin, bool fForce = false);
+
+ /**
+ * A C like version of the #reserve() method, i.e. return code instead of throw.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param cwcMin The new minimum string length that the can be stored. This
+ * does not include the terminator.
+ * @param fForce Force this size.
+ */
+ HRESULT reserveNoThrow(size_t cwcMin, bool fForce = false) RT_NOEXCEPT;
+
+ /**
+ * 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.
+ *
+ * If the member string is empty, this allocates an empty BSTR in *pstr
+ * (i.e. makes it point to a new buffer with a null byte).
+ *
+ * @deprecated Use cloneToEx instead to avoid throwing exceptions.
+ */
+ void cloneTo(BSTR *pstr) const
+ {
+ if (pstr)
+ {
+ *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!*pstr)
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A version of cloneTo that does not throw any out of memory exceptions, but
+ * returns E_OUTOFMEMORY intead.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+ HRESULT cloneToEx(BSTR *pstr) const
+ {
+ if (!pstr)
+ return S_OK;
+ *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
+ return pstr ? S_OK : E_OUTOFMEMORY;
+ }
+
+ /**
+ * 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.
+ *
+ * If the member string is empty, this allocates an empty BSTR in *pstr
+ * (i.e. makes it point to a new buffer with a null byte).
+ *
+ * @param pbstrDst The BSTR variable to detach the string to.
+ *
+ * @throws std::bad_alloc if we failed to allocate a new empty string.
+ */
+ void detachTo(BSTR *pbstrDst)
+ {
+ if (m_bstr)
+ {
+ *pbstrDst = m_bstr;
+ m_bstr = NULL;
+ }
+ else
+ {
+ // allocate null BSTR
+ *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!*pbstrDst)
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A version of detachTo that does not throw exceptions on out-of-memory
+ * conditions, but instead returns E_OUTOFMEMORY.
+ *
+ * @param pbstrDst The BSTR variable to detach the string to.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+ HRESULT detachToEx(BSTR *pbstrDst)
+ {
+ if (m_bstr)
+ {
+ *pbstrDst = m_bstr;
+ m_bstr = NULL;
+ }
+ else
+ {
+ // allocate null BSTR
+ *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
+ if (!*pbstrDst)
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+
+ /**
+ * Intended to pass instances as |BSTR| out parameters to methods.
+ * Takes the ownership of the returned data.
+ */
+ BSTR *asOutParam()
+ {
+ cleanup();
+ return &m_bstr;
+ }
+
+ /**
+ * Static immutable empty-string object. May be used for comparison purposes.
+ */
+ static const Bstr Empty;
+
+protected:
+
+ void cleanup();
+
+ /**
+ * Protected internal helper to copy a string. This ignores the previous object
+ * state, so either call this from a constructor or call cleanup() first.
+ *
+ * This variant copies from a zero-terminated UTF-16 string (which need not
+ * be a BSTR, i.e. need not have a length prefix).
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_bstrSrc The source string. The caller guarantees
+ * that this is valid UTF-16.
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFrom(const OLECHAR *a_bstrSrc);
+
+ /** cleanup() + copyFrom() - for assignment operators. */
+ void cleanupAndCopyFrom(const OLECHAR *a_bstrSrc);
+
+ /**
+ * Protected internal helper to copy a string, implying cleanup().
+ *
+ * This variant copies from a zero-terminated UTF-16 string (which need not be a
+ * BSTR, i.e. need not have a length prefix).
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_bstrSrc The source string. The caller guarantees
+ * that this is valid UTF-16.
+ * @returns S_OK or E_OUTOFMEMORY
+ */
+ HRESULT cleanupAndCopyFromEx(const OLECHAR *a_bstrSrc) RT_NOEXCEPT;
+
+ /**
+ * Protected internal helper to copy a string. This ignores the previous object
+ * state, so either call this from a constructor or call cleanup() first.
+ *
+ * This variant copies and converts from a zero-terminated UTF-8 string.
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_pszSrc The source string. The caller guarantees
+ * that this is valid UTF-8.
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFrom(const char *a_pszSrc)
+ {
+ copyFromN(a_pszSrc, RTSTR_MAX);
+ }
+
+ /**
+ * Variant of copyFrom for sub-string constructors.
+ *
+ * @param a_pszSrc The source string. The caller guarantees
+ * that this is valid UTF-8.
+ * @param a_cchSrc The maximum number of chars (not codepoints) to
+ * copy. If you pass RTSTR_MAX it'll be exactly
+ * like copyFrom().
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFromN(const char *a_pszSrc, size_t a_cchSrc);
+
+ /** cleanup() + non-throwing copyFromN(). */
+ HRESULT cleanupAndCopyFromNoThrow(const char *a_pszSrc, size_t a_cchMax) RT_NOEXCEPT;
+
+ Bstr &appendWorkerUtf16(PCRTUTF16 pwszSrc, size_t cwcSrc);
+ Bstr &appendWorkerUtf8(const char *pszSrc, size_t cchSrc);
+ HRESULT appendWorkerUtf16NoThrow(PCRTUTF16 pwszSrc, size_t cwcSrc) RT_NOEXCEPT;
+ HRESULT appendWorkerUtf8NoThrow(const char *pszSrc, size_t cchSrc) RT_NOEXCEPT;
+
+ static DECLCALLBACK(size_t) printfOutputCallbackNoThrow(void *pvArg, const char *pachChars, size_t cbChars) RT_NOEXCEPT;
+
+ BSTR m_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); }
+
+
+
+
+/**
+ * String class used universally in Main for UTF-8 strings.
+ *
+ * This is based on RTCString, to which some functionality has been
+ * moved. Here we keep things that are specific to Main, such as conversions
+ * with UTF-16 strings (Bstr).
+ *
+ * Like RTCString, Utf8Str does not differentiate between NULL strings
+ * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) behave the
+ * same. In both cases, RTCString allocates no memory, reports
+ * a zero length and zero allocated bytes for both, and returns an empty
+ * C string from c_str().
+ *
+ * @note All Utf8Str methods ASSUMES valid UTF-8 or UTF-16 input strings.
+ * The VirtualBox policy in this regard is to validate strings coming
+ * from external sources before passing them to Utf8Str or Bstr.
+ */
+class Utf8Str : public RTCString
+{
+public:
+
+ Utf8Str() {}
+
+ Utf8Str(const RTCString &that)
+ : RTCString(that)
+ {}
+
+ Utf8Str(const char *that)
+ : RTCString(that)
+ {}
+
+ Utf8Str(const Bstr &that)
+ {
+ copyFrom(that.raw());
+ }
+
+ Utf8Str(CBSTR that, size_t a_cwcSize = RTSTR_MAX)
+ {
+ copyFrom(that, a_cwcSize);
+ }
+
+ Utf8Str(const char *a_pszSrc, size_t a_cchSrc)
+ : RTCString(a_pszSrc, a_cchSrc)
+ {
+ }
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param a_va Argument vector containing the arguments
+ * specified by the format string.
+ * @sa RTCString::printfV
+ */
+ Utf8Str(const char *a_pszFormat, va_list a_va) RT_IPRT_FORMAT_ATTR(1, 0)
+ : RTCString(a_pszFormat, a_va)
+ {
+ }
+
+ Utf8Str& operator=(const RTCString &that)
+ {
+ RTCString::operator=(that);
+ return *this;
+ }
+
+ Utf8Str& operator=(const char *that)
+ {
+ RTCString::operator=(that);
+ return *this;
+ }
+
+ Utf8Str& operator=(const Bstr &that)
+ {
+ cleanup();
+ copyFrom(that.raw());
+ return *this;
+ }
+
+ Utf8Str& operator=(CBSTR that)
+ {
+ cleanup();
+ copyFrom(that);
+ return *this;
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(Utf8Str const &a_rSrcStr)
+ {
+ return copyFromExNComRC(a_rSrcStr.m_psz, 0, a_rSrcStr.m_cch);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVALIDARG.
+ * @param a_rSrcStr The source string
+ * @param a_offSrc The character (byte) offset of the substring.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(Utf8Str const &a_rSrcStr, size_t a_offSrc, size_t a_cchSrc)
+ {
+ if ( a_offSrc + a_cchSrc > a_rSrcStr.m_cch
+ || a_offSrc > a_rSrcStr.m_cch)
+ return E_INVALIDARG;
+ return copyFromExNComRC(a_rSrcStr.m_psz, a_offSrc, a_cchSrc);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pcszSrc The source string
+ */
+ HRESULT assignEx(const char *a_pcszSrc)
+ {
+ return copyFromExNComRC(a_pcszSrc, 0, a_pcszSrc ? strlen(a_pcszSrc) : 0);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pcszSrc The source string
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(const char *a_pcszSrc, size_t a_cchSrc)
+ {
+ return copyFromExNComRC(a_pcszSrc, 0, a_cchSrc);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+#if defined(VBOX_WITH_XPCOM)
+ /**
+ * Intended to assign instances to |char *| out parameters from within the
+ * interface method. Transfers the ownership of the duplicated string to the
+ * caller.
+ *
+ * This allocates a single 0 byte in the target if the member string is empty.
+ *
+ * This uses XPCOM memory allocation and thus only works on XPCOM. MSCOM doesn't
+ * like char* strings anyway.
+ */
+ void cloneTo(char **pstr) const;
+
+ /**
+ * A version of cloneTo that does not throw allocation errors but returns
+ * E_OUTOFMEMORY instead.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneToEx(char **pstr) const;
+#endif
+
+ /**
+ * Intended to assign instances to |BSTR| out parameters from within the
+ * interface method. Transfers the ownership of the duplicated string to the
+ * caller.
+ */
+ void cloneTo(BSTR *pstr) const
+ {
+ if (pstr)
+ {
+ Bstr bstr(*this);
+ bstr.cloneTo(pstr);
+ }
+ }
+
+ /**
+ * A version of cloneTo that does not throw allocation errors but returns
+ * E_OUTOFMEMORY instead.
+ *
+ * @param pbstr Where to store a clone of the string.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneToEx(BSTR *pbstr) const RT_NOEXCEPT;
+
+ /**
+ * Safe assignment from BSTR.
+ *
+ * @param pbstrSrc The source string.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneEx(CBSTR pbstrSrc)
+ {
+ cleanup();
+ return copyFromEx(pbstrSrc);
+ }
+
+ /**
+ * Removes a trailing slash from the member string, if present.
+ * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripTrailingSlash();
+
+ /**
+ * Removes a trailing filename from the member string, if present.
+ * Calls RTPathStripFilename() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripFilename();
+
+ /**
+ * Removes the path component from the member string, if present.
+ * Calls RTPathFilename() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripPath();
+
+ /**
+ * Removes a trailing file name suffix from the member string, if present.
+ * Calls RTPathStripSuffix() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripSuffix();
+
+ /**
+ * Parses key=value pairs.
+ *
+ * @returns offset of the @a a_rPairSeparator following the returned value.
+ * @retval npos is returned if there are no more key/value pairs.
+ *
+ * @param a_rKey Reference to variable that should receive
+ * the key substring. This is set to null if
+ * no key/value found. (It's also possible the
+ * key is an empty string, so be careful.)
+ * @param a_rValue Reference to variable that should receive
+ * the value substring. This is set to null if
+ * no key/value found. (It's also possible the
+ * value is an empty string, so be careful.)
+ * @param a_offStart The offset to start searching from. This is
+ * typically 0 for the first call, and the
+ * return value of the previous call for the
+ * subsequent ones.
+ * @param a_rPairSeparator The pair separator string. If this is an
+ * empty string, the whole string will be
+ * considered as a single key/value pair.
+ * @param a_rKeyValueSeparator The key/value separator string.
+ */
+ size_t parseKeyValue(Utf8Str &a_rKey, Utf8Str &a_rValue, size_t a_offStart = 0,
+ const Utf8Str &a_rPairSeparator = ",", const Utf8Str &a_rKeyValueSeparator = "=") const;
+
+ /**
+ * Static immutable empty-string object. May be used for comparison purposes.
+ */
+ static const Utf8Str Empty;
+protected:
+
+ void copyFrom(CBSTR a_pbstr, size_t a_cwcMax = RTSTR_MAX);
+ HRESULT copyFromEx(CBSTR a_pbstr);
+ HRESULT copyFromExNComRC(const char *a_pcszSrc, size_t a_offSrc, size_t a_cchSrc);
+
+ friend class Bstr; /* to access our raw_copy() */
+};
+
+/**
+ * Class with RTCString::printf as constructor for your convenience.
+ *
+ * Constructing a Utf8Str string object from a format string and a variable
+ * number of arguments can easily be confused with the other Utf8Str
+ * constructures, thus this child class.
+ *
+ * The usage of this class is like the following:
+ * @code
+ Utf8StrFmt strName("program name = %s", argv[0]);
+ @endcode
+ *
+ * @note Do not use in assignments to Utf8Str variables. Instead use
+ * RTCString::printf directly on the variable! This avoid an extra
+ * temporary Utf8Str instance and assignment operation.
+ */
+class Utf8StrFmt : public Utf8Str
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ */
+ explicit Utf8StrFmt(const char *a_pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2)
+ {
+ va_list va;
+ va_start(va, a_pszFormat);
+ printfV(a_pszFormat, va);
+ va_end(va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ Utf8StrFmt()
+ { }
+
+private:
+};
+
+/**
+ * Class with Bstr::printf as constructor for your convenience.
+ */
+class BstrFmt : public Bstr
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat printf-like format string (in UTF-8 encoding), see
+ * iprt/string.h for details.
+ * @param ... List of the arguments for the format string.
+ */
+ explicit BstrFmt(const char *a_pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2)
+ {
+ va_list va;
+ va_start(va, a_pszFormat);
+ printfV(a_pszFormat, va);
+ va_end(va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ BstrFmt()
+ { }
+};
+
+/**
+ * Class with Bstr::printfV as constructor for your convenience.
+ */
+class BstrFmtVA : public Bstr
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat printf-like format string (in UTF-8 encoding), see
+ * iprt/string.h for details.
+ * @param a_va List of arguments for the format string
+ */
+ BstrFmtVA(const char *a_pszFormat, va_list a_va) RT_IPRT_FORMAT_ATTR(1, 0)
+ {
+ printfV(a_pszFormat, a_va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ BstrFmtVA()
+ { }
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_string_h */
+