VirtualBox

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

Last change on this file since 56290 was 55942, checked in by vboxsync, 9 years ago

Bstr: Replaced RT_UNLIKELY with RT_LIKELY to improve our karma wrt MSC.

  • 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 55942 2015-05-19 23:00:07Z 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_SUCCESS(vrc))
54 {
55 m_bstr = ::SysAllocStringByteLen(NULL, (unsigned)(cwc * sizeof(OLECHAR)));
56 if (RT_LIKELY(m_bstr))
57 {
58 PRTUTF16 pwsz = (PRTUTF16)m_bstr;
59 vrc = ::RTStrToUtf16Ex(a_pszSrc, a_cchMax, &pwsz, cwc + 1, NULL);
60 if (RT_SUCCESS(vrc))
61 return;
62
63 /* This should not happen! */
64 AssertRC(vrc);
65 cleanup();
66 }
67 }
68 else /* ASSUME: input is valid Utf-8. Fake out of memory error. */
69 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTStrNLen(a_pszSrc, a_cchMax), a_pszSrc));
70 throw std::bad_alloc();
71}
72
73
74/* static */
75const Utf8Str Utf8Str::Empty; /* default ctor is OK */
76
77#if defined(VBOX_WITH_XPCOM)
78void Utf8Str::cloneTo(char **pstr) const
79{
80 size_t cb = length() + 1;
81 *pstr = (char *)nsMemory::Alloc(cb);
82 if (RT_LIKELY(*pstr))
83 memcpy(*pstr, c_str(), cb);
84 else
85 throw std::bad_alloc();
86}
87
88HRESULT Utf8Str::cloneToEx(char **pstr) const
89{
90 size_t cb = length() + 1;
91 *pstr = (char *)nsMemory::Alloc(cb);
92 if (RT_LIKELY(*pstr))
93 {
94 memcpy(*pstr, c_str(), cb);
95 return S_OK;
96 }
97 return E_OUTOFMEMORY;
98}
99#endif
100
101Utf8Str& Utf8Str::stripTrailingSlash()
102{
103 if (length())
104 {
105 ::RTPathStripTrailingSlash(m_psz);
106 jolt();
107 }
108 return *this;
109}
110
111Utf8Str& Utf8Str::stripFilename()
112{
113 if (length())
114 {
115 RTPathStripFilename(m_psz);
116 jolt();
117 }
118 return *this;
119}
120
121Utf8Str& Utf8Str::stripPath()
122{
123 if (length())
124 {
125 char *pszName = ::RTPathFilename(m_psz);
126 if (pszName)
127 {
128 size_t cchName = length() - (pszName - m_psz);
129 memmove(m_psz, pszName, cchName + 1);
130 jolt();
131 }
132 else
133 cleanup();
134 }
135 return *this;
136}
137
138Utf8Str& Utf8Str::stripSuffix()
139{
140 if (length())
141 {
142 RTPathStripSuffix(m_psz);
143 jolt();
144 }
145 return *this;
146}
147
148size_t Utf8Str::parseKeyValue(Utf8Str &key, Utf8Str &value, size_t pos, const Utf8Str &pairSeparator, const Utf8Str &keyValueSeparator) const
149{
150 size_t start = pos;
151 while(start == (pos = find(pairSeparator.c_str(), pos)))
152 start = ++pos;
153
154 size_t kvSepPos = find(keyValueSeparator.c_str(), start);
155 if (kvSepPos < pos)
156 {
157 key = substr(start, kvSepPos - start);
158 value = substr(kvSepPos + 1, pos - kvSepPos - 1);
159 }
160 else
161 {
162 key = value = "";
163 }
164 return pos;
165}
166
167/**
168 * Internal function used in Utf8Str copy constructors and assignment when
169 * copying from a UTF-16 string.
170 *
171 * As with the RTCString::copyFrom() variants, this unconditionally sets the
172 * members to a copy of the given other strings and makes no assumptions about
173 * previous contents. This can therefore be used both in copy constructors,
174 * when member variables have no defined value, and in assignments after having
175 * called cleanup().
176 *
177 * This variant converts from a UTF-16 string, most probably from
178 * a Bstr assignment.
179 *
180 * @param a_pbstr The source string. The caller guarantees that this
181 * is valid UTF-16.
182 * @param a_cwcMax The number of characters to be copied. If set to RTSTR_MAX,
183 * the entire string will be copied.
184 *
185 * @sa RTCString::copyFromN
186 */
187void Utf8Str::copyFrom(CBSTR a_pbstr, size_t a_cwcMax)
188{
189 if (a_pbstr && *a_pbstr)
190 {
191 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
192 a_cwcMax, // size_t cwcString: translate entire string
193 &m_psz, // char **ppsz: output buffer
194 0, // size_t cch: if 0, func allocates buffer in *ppsz
195 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator.
196 if (RT_SUCCESS(vrc))
197 m_cbAllocated = m_cch + 1;
198 else
199 {
200 if ( vrc != VERR_NO_STR_MEMORY
201 && vrc != VERR_NO_MEMORY)
202 {
203 /* ASSUME: input is valid Utf-16. Fake out of memory error. */
204 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr));
205 }
206
207 m_cch = 0;
208 m_cbAllocated = 0;
209 m_psz = NULL;
210
211 throw std::bad_alloc();
212 }
213 }
214 else
215 {
216 m_cch = 0;
217 m_cbAllocated = 0;
218 m_psz = NULL;
219 }
220}
221
222/**
223 * A variant of Utf8Str::copyFrom that does not throw any exceptions but returns
224 * E_OUTOFMEMORY instead.
225 *
226 * @param a_pbstr The source string.
227 * @returns S_OK or E_OUTOFMEMORY.
228 */
229HRESULT Utf8Str::copyFromEx(CBSTR a_pbstr)
230{
231 if (a_pbstr && *a_pbstr)
232 {
233 int vrc = RTUtf16ToUtf8Ex((PCRTUTF16)a_pbstr,
234 RTSTR_MAX, // size_t cwcString: translate entire string
235 &m_psz, // char **ppsz: output buffer
236 0, // size_t cch: if 0, func allocates buffer in *ppsz
237 &m_cch); // size_t *pcch: receives the size of the output string, excluding the terminator.
238 if (RT_SUCCESS(vrc))
239 m_cbAllocated = m_cch + 1;
240 else
241 {
242 if ( vrc != VERR_NO_STR_MEMORY
243 && vrc != VERR_NO_MEMORY)
244 {
245 /* ASSUME: input is valid Utf-16. Fake out of memory error. */
246 AssertLogRelMsgFailed(("%Rrc %.*Rhxs\n", vrc, RTUtf16Len(a_pbstr) * sizeof(RTUTF16), a_pbstr));
247 }
248
249 m_cch = 0;
250 m_cbAllocated = 0;
251 m_psz = NULL;
252
253 return E_OUTOFMEMORY;
254 }
255 }
256 else
257 {
258 m_cch = 0;
259 m_cbAllocated = 0;
260 m_psz = NULL;
261 }
262 return S_OK;
263}
264
265
266/**
267 * A variant of Utf8Str::copyFromN that does not throw any exceptions but
268 * returns E_OUTOFMEMORY instead.
269 *
270 * @param a_pcszSrc The source string.
271 * @param a_offSrc Start offset to copy from.
272 * @param a_cchSrc The source string.
273 * @returns S_OK or E_OUTOFMEMORY.
274 *
275 * @remarks This calls cleanup() first, so the caller doesn't have to. (Saves
276 * code space.)
277 */
278HRESULT Utf8Str::copyFromExNComRC(const char *a_pcszSrc, size_t a_offSrc, size_t a_cchSrc)
279{
280 cleanup();
281 if (a_cchSrc)
282 {
283 m_psz = RTStrAlloc(a_cchSrc + 1);
284 if (RT_LIKELY(m_psz))
285 {
286 m_cch = a_cchSrc;
287 m_cbAllocated = a_cchSrc + 1;
288 memcpy(m_psz, a_pcszSrc + a_offSrc, a_cchSrc);
289 m_psz[a_cchSrc] = '\0';
290 }
291 else
292 {
293 m_cch = 0;
294 m_cbAllocated = 0;
295 return E_OUTOFMEMORY;
296 }
297 }
298 else
299 {
300 m_cch = 0;
301 m_cbAllocated = 0;
302 m_psz = NULL;
303 }
304 return S_OK;
305}
306
307} /* 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