VirtualBox

source: vbox/trunk/src/VBox/Main/glue/string.cpp@ 54796

Last change on this file since 54796 was 52554, checked in by vboxsync, 10 years ago

VBox/Main: #1909: Bug & coding style fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: string.cpp 52554 2014-09-01 16:00:05Z vboxsync $ */
2/** @file
3 * MS COM / XPCOM Abstraction Layer - UTF-8 and UTF-16 string classes.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VBox/com/string.h"
19
20#include <iprt/err.h>
21#include <iprt/path.h>
22#include <iprt/log.h>
23
24namespace com
25{
26
27// BSTR representing a null wide char with 32 bits of length prefix (0);
28// this will work on Windows as well as other platforms where BSTR does
29// not use length prefixes
30const OLECHAR g_achEmptyBstr[3] = { 0, 0, 0 };
31const BSTR g_bstrEmpty = (BSTR)&g_achEmptyBstr[2];
32
33/* static */
34const Bstr Bstr::Empty; /* default ctor is OK */
35
36void Bstr::copyFromN(const char *a_pszSrc, size_t a_cchMax)
37{
38 /*
39 * Initialie m_bstr first in case of throws further down in the code, then
40 * check for empty input (m_bstr == NULL means empty, there are no NULL
41 * strings).
42 */
43 m_bstr = NULL;
44 if (!a_cchMax || !a_pszSrc || !*a_pszSrc)
45 return;
46
47 /*
48 * Calculate the length and allocate a BSTR string buffer of the right
49 * size, i.e. optimize heap usage.
50 */
51 size_t cwc;
52 int vrc = ::RTStrCalcUtf16LenEx(a_pszSrc, a_cchMax, &cwc);
53 if (RT_FAILURE(vrc))
54 {
55 /* ASSUME: input is valid Utf-8. Fake out of memory error. */
56 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTStrNLen(a_pszSrc, a_cchMax), a_pszSrc));
57 throw std::bad_alloc();
58 }
59
60 m_bstr = ::SysAllocStringByteLen(NULL, (unsigned)(cwc * sizeof(OLECHAR)));
61 if (RT_UNLIKELY(!m_bstr))
62 throw std::bad_alloc();
63
64 PRTUTF16 pwsz = (PRTUTF16)m_bstr;
65 vrc = ::RTStrToUtf16Ex(a_pszSrc, a_cchMax, &pwsz, cwc + 1, NULL);
66 if (RT_FAILURE(vrc))
67 {
68 /* This should not happen! */
69 AssertRC(vrc);
70 cleanup();
71 throw std::bad_alloc();
72 }
73}
74
75
76/* static */
77const Utf8Str Utf8Str::Empty; /* default ctor is OK */
78
79#if defined(VBOX_WITH_XPCOM)
80void Utf8Str::cloneTo(char **pstr) const
81{
82 size_t cb = length() + 1;
83 *pstr = (char*)nsMemory::Alloc(cb);
84 if (RT_UNLIKELY(!*pstr))
85 throw std::bad_alloc();
86 memcpy(*pstr, c_str(), cb);
87}
88
89HRESULT Utf8Str::cloneToEx(char **pstr) const
90{
91 size_t cb = length() + 1;
92 *pstr = (char*)nsMemory::Alloc(cb);
93 if (RT_UNLIKELY(!*pstr))
94 return E_OUTOFMEMORY;
95 memcpy(*pstr, c_str(), cb);
96 return S_OK;
97}
98#endif
99
100Utf8Str& Utf8Str::stripTrailingSlash()
101{
102 if (length())
103 {
104 ::RTPathStripTrailingSlash(m_psz);
105 jolt();
106 }
107 return *this;
108}
109
110Utf8Str& Utf8Str::stripFilename()
111{
112 if (length())
113 {
114 RTPathStripFilename(m_psz);
115 jolt();
116 }
117 return *this;
118}
119
120Utf8Str& Utf8Str::stripPath()
121{
122 if (length())
123 {
124 char *pszName = ::RTPathFilename(m_psz);
125 if (pszName)
126 {
127 size_t cchName = length() - (pszName - m_psz);
128 memmove(m_psz, pszName, cchName + 1);
129 jolt();
130 }
131 else
132 cleanup();
133 }
134 return *this;
135}
136
137Utf8Str& Utf8Str::stripSuffix()
138{
139 if (length())
140 {
141 RTPathStripSuffix(m_psz);
142 jolt();
143 }
144 return *this;
145}
146
147size_t Utf8Str::parseKeyValue(Utf8Str &key, Utf8Str &value, size_t pos, const Utf8Str &pairSeparator, const Utf8Str &keyValueSeparator) const
148{
149 size_t start = pos;
150 while(start == (pos = find(pairSeparator.c_str(), pos)))
151 start = ++pos;
152
153 size_t kvSepPos = find(keyValueSeparator.c_str(), start);
154 if (kvSepPos < pos)
155 {
156 key = substr(start, kvSepPos - start);
157 value = substr(kvSepPos + 1, pos - kvSepPos - 1);
158 }
159 else
160 {
161 key = value = "";
162 }
163 return pos;
164}
165
166/**
167 * Internal function used in Utf8Str copy constructors and assignment when
168 * copying from a UTF-16 string.
169 *
170 * As with the RTCString::copyFrom() variants, this unconditionally sets the
171 * members to a copy of the given other strings and makes no assumptions about
172 * previous contents. This can therefore be used both in copy constructors,
173 * when member variables have no defined value, and in assignments after having
174 * called cleanup().
175 *
176 * This variant converts from a UTF-16 string, most probably from
177 * a Bstr assignment.
178 *
179 * @param a_pbstr The source string. The caller guarantees that this
180 * is valid UTF-16.
181 * @param a_cwcMax The number of characters to be copied. If set to RTSTR_MAX,
182 * the entire string will be copied.
183 *
184 * @sa RTCString::copyFromN
185 */
186void Utf8Str::copyFrom(CBSTR a_pbstr, size_t a_cwcMax)
187{
188 if (a_pbstr && *a_pbstr)
189 {
190 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
191 a_cwcMax, // size_t cwcString: translate entire string
192 &m_psz, // char **ppsz: output buffer
193 0, // size_t cch: if 0, func allocates buffer in *ppsz
194 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator.
195 if (RT_SUCCESS(vrc))
196 m_cbAllocated = m_cch + 1;
197 else
198 {
199 if ( vrc != VERR_NO_STR_MEMORY
200 && vrc != VERR_NO_MEMORY)
201 {
202 /* ASSUME: input is valid Utf-16. Fake out of memory error. */
203 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr));
204 }
205
206 m_cch = 0;
207 m_cbAllocated = 0;
208 m_psz = NULL;
209
210 throw std::bad_alloc();
211 }
212 }
213 else
214 {
215 m_cch = 0;
216 m_cbAllocated = 0;
217 m_psz = NULL;
218 }
219}
220
221/**
222 * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns
223 * E_OUTOFMEMORY instead.
224 *
225 * @param a_pbstr The source string.
226 * @returns S_OK or E_OUTOFMEMORY.
227 */
228HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr)
229{
230 if (a_pbstr && *a_pbstr)
231 {
232 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
233 RTSTR_MAX, // size_t cwcString: translate entire string
234 &m_psz, // char **ppsz: output buffer
235 0, // size_t cch: if 0, func allocates buffer in *ppsz
236 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator.
237 if (RT_SUCCESS(vrc))
238 m_cbAllocated = m_cch + 1;
239 else
240 {
241 if ( vrc != VERR_NO_STR_MEMORY
242 && vrc != VERR_NO_MEMORY)
243 {
244 /* ASSUME: input is valid Utf-16. Fake out of memory error. */
245 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr));
246 }
247
248 m_cch = 0;
249 m_cbAllocated = 0;
250 m_psz = NULL;
251
252 return E_OUTOFMEMORY;
253 }
254 }
255 else
256 {
257 m_cch = 0;
258 m_cbAllocated = 0;
259 m_psz = NULL;
260 }
261 return S_OK;
262}
263
264
265/**
266 * A variant of Utf8Str::copyFromN that does not throw any exceptions but
267 * returns E_OUTOFMEMORY instead.
268 *
269 * @param a_pcszSrc The source string.
270 * @param a_offSrc Start offset to copy from.
271 * @param a_cchSrc The source string.
272 * @returns S_OK or E_OUTOFMEMORY.
273 *
274 * @remarks This calls cleanup() first, so the caller doesn't have to. (Saves
275 * code space.)
276 */
277HRESULT Utf8Str::copyFromExNComRC(const char *a_pcszSrc, size_t a_offSrc, size_t a_cchSrc)
278{
279 cleanup();
280 if (a_cchSrc)
281 {
282 m_psz = RTStrAlloc(a_cchSrc + 1);
283 if (RT_LIKELY(m_psz))
284 {
285 m_cch = a_cchSrc;
286 m_cbAllocated = a_cchSrc + 1;
287 memcpy(m_psz, a_pcszSrc + a_offSrc, a_cchSrc);
288 m_psz[a_cchSrc] = '\0';
289 }
290 else
291 {
292 m_cch = 0;
293 m_cbAllocated = 0;
294 return E_OUTOFMEMORY;
295 }
296 }
297 else
298 {
299 m_cch = 0;
300 m_cbAllocated = 0;
301 m_psz = NULL;
302 }
303 return S_OK;
304}
305
306} /* namespace com */
Note: See TracBrowser for help on using the repository browser.

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