Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(865)

Side by Side Diff: core/fxcrt/fx_basic_bstring.cpp

Issue 1810823002: Use CFX_RetainPtr to ref count CFX_ByteString (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@retain_ptr
Patch Set: Rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | core/fxcrt/fx_basic_bstring_unittest.cpp » ('j') | core/fxcrt/include/fx_string.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <cctype> 9 #include <cctype>
10 10
(...skipping 25 matching lines...) Expand all
36 } 36 }
37 if ((flags & FXFORMAT_SIGNED) && i < 0) { 37 if ((flags & FXFORMAT_SIGNED) && i < 0) {
38 buf1[buf_pos--] = '-'; 38 buf1[buf_pos--] = '-';
39 } 39 }
40 int len = 31 - buf_pos; 40 int len = 31 - buf_pos;
41 for (int ii = 0; ii < len; ii++) { 41 for (int ii = 0; ii < len; ii++) {
42 buf[ii] = buf1[ii + buf_pos + 1]; 42 buf[ii] = buf1[ii + buf_pos + 1];
43 } 43 }
44 return len; 44 return len;
45 } 45 }
46
46 CFX_ByteString CFX_ByteString::FormatInteger(int i, uint32_t flags) { 47 CFX_ByteString CFX_ByteString::FormatInteger(int i, uint32_t flags) {
47 char buf[32]; 48 char buf[32];
48 return CFX_ByteStringC(buf, _Buffer_itoa(buf, i, flags)); 49 return CFX_ByteStringC(buf, _Buffer_itoa(buf, i, flags));
49 } 50 }
50 51
51 // static 52 // static
52 CFX_ByteString::StringData* CFX_ByteString::StringData::Create(int nLen) { 53 CFX_ByteString::StringData* CFX_ByteString::StringData::Create(
53 // |nLen| is currently declared as in |int|. TODO(palmer): It should be 54 FX_STRSIZE nLen) {
54 // a |size_t|, or at least unsigned. 55 FXSYS_assert(nLen > 0);
55 if (nLen == 0 || nLen < 0) {
56 return NULL;
57 }
58 56
59 // Fixed portion of header plus a NUL char not included in m_nAllocLength. 57 // Fixed portion of header plus a NUL char not included in m_nAllocLength.
60 // sizeof(FX_CHAR) is always 1, used for consistency with CFX_Widestring. 58 // sizeof(FX_CHAR) is always 1, used for consistency with CFX_Widestring.
61 int overhead = offsetof(StringData, m_String) + sizeof(FX_CHAR); 59 int overhead = offsetof(StringData, m_String) + sizeof(FX_CHAR);
62 pdfium::base::CheckedNumeric<int> nSize = nLen; 60 pdfium::base::CheckedNumeric<int> nSize = nLen;
63 nSize += overhead; 61 nSize += overhead;
64 62
65 // Now round to an 8-byte boundary. We'd expect that this is the minimum 63 // Now round to an 8-byte boundary. We'd expect that this is the minimum
66 // granularity of any of the underlying allocators, so there may be cases 64 // granularity of any of the underlying allocators, so there may be cases
67 // where we can save a re-alloc when adding a few characters to a string 65 // where we can save a re-alloc when adding a few characters to a string
68 // by using this otherwise wasted space. 66 // by using this otherwise wasted space.
69 nSize += 7; 67 nSize += 7;
70 int totalSize = nSize.ValueOrDie() & ~7; 68 int totalSize = nSize.ValueOrDie() & ~7;
71 int usableSize = totalSize - overhead; 69 int usableSize = totalSize - overhead;
72 FXSYS_assert(usableSize >= nLen); 70 FXSYS_assert(usableSize >= nLen);
73 71
74 void* pData = FX_Alloc(uint8_t, totalSize); 72 void* pData = FX_Alloc(uint8_t, totalSize);
75 return new (pData) StringData(nLen, usableSize); 73 return new (pData) StringData(nLen, usableSize);
76 } 74 }
77 CFX_ByteString::~CFX_ByteString() { 75
78 if (m_pData) { 76 CFX_ByteString::StringData* CFX_ByteString::StringData::Create(
79 m_pData->Release(); 77 const StringData& other) {
80 } 78 StringData* result = Create(other.m_nDataLength);
81 } 79 result->CopyContents(other);
82 CFX_ByteString::CFX_ByteString(const FX_CHAR* lpsz, FX_STRSIZE nLen) { 80 return result;
83 if (nLen < 0) { 81 }
84 nLen = lpsz ? FXSYS_strlen(lpsz) : 0; 82
85 } 83 CFX_ByteString::StringData* CFX_ByteString::StringData::Create(
86 if (nLen) { 84 const FX_CHAR* pStr,
87 m_pData = StringData::Create(nLen); 85 FX_STRSIZE nLen) {
88 if (m_pData) { 86 StringData* result = Create(nLen);
89 FXSYS_memcpy(m_pData->m_String, lpsz, nLen); 87 result->CopyContents(pStr, nLen);
90 } 88 return result;
91 } else { 89 }
92 m_pData = NULL; 90
93 } 91 CFX_ByteString::StringData::StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
94 } 92 : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
95 CFX_ByteString::CFX_ByteString(const uint8_t* lpsz, FX_STRSIZE nLen) { 93 FXSYS_assert(dataLen >= 0);
94 FXSYS_assert(allocLen >= 0);
Lei Zhang 2016/03/30 00:15:32 The next assert implies this one.
Tom Sepez 2016/03/30 18:49:18 Done.
95 FXSYS_assert(dataLen <= allocLen);
96 m_String[dataLen] = 0;
97 }
98
99 void CFX_ByteString::StringData::CopyContents(const StringData& other) {
100 FXSYS_memcpy(m_String, other.m_String, other.m_nDataLength + 1);
dsinclair 2016/03/30 13:27:20 Does this need to verify that m_nDataLength >= oth
dsinclair 2016/03/30 13:27:20 m_nDataLength appears to be the length of the stri
Tom Sepez 2016/03/30 18:49:18 No, m_DataLength doesn't include the terminating N
Tom Sepez 2016/03/30 18:49:18 All of these copy* routines expect the caller to h
101 }
102
103 void CFX_ByteString::StringData::CopyContents(const FX_CHAR* pStr,
104 FX_STRSIZE nLen) {
105 FXSYS_memcpy(m_String, pStr, nLen);
dsinclair 2016/03/30 13:27:20 ditto on checking length of m_String?
Tom Sepez 2016/03/30 18:49:18 Asserted
106 m_String[nLen] = 0;
107 }
108
109 void CFX_ByteString::StringData::CopyContentsAt(FX_STRSIZE offset,
110 const FX_CHAR* pStr,
111 FX_STRSIZE nLen) {
112 FXSYS_memcpy(m_String + offset, pStr, nLen);
dsinclair 2016/03/30 13:27:20 ditto on length >= offset+nLen?
Tom Sepez 2016/03/30 18:49:18 Asserted
113 m_String[offset + nLen] = 0;
114 }
115
116 CFX_ByteString::CFX_ByteString(const FX_CHAR* pStr, FX_STRSIZE nLen) {
117 if (nLen < 0)
118 nLen = pStr ? FXSYS_strlen(pStr) : 0;
119
120 if (nLen)
121 m_pData.Reset(StringData::Create(pStr, nLen));
122 }
123
124 CFX_ByteString::CFX_ByteString(const uint8_t* pStr, FX_STRSIZE nLen) {
96 if (nLen > 0) { 125 if (nLen > 0) {
97 m_pData = StringData::Create(nLen); 126 m_pData.Reset(
98 if (m_pData) { 127 StringData::Create(reinterpret_cast<const FX_CHAR*>(pStr), nLen));
99 FXSYS_memcpy(m_pData->m_String, lpsz, nLen); 128 }
100 } 129 }
101 } else { 130
102 m_pData = NULL;
103 }
104 }
105 CFX_ByteString::CFX_ByteString(char ch) { 131 CFX_ByteString::CFX_ByteString(char ch) {
106 m_pData = StringData::Create(1); 132 m_pData.Reset(StringData::Create(1));
107 if (m_pData) { 133 m_pData->m_String[0] = ch;
108 m_pData->m_String[0] = ch; 134 }
109 } 135
110 }
111 CFX_ByteString::CFX_ByteString(const CFX_ByteString& stringSrc) {
112 if (!stringSrc.m_pData) {
113 m_pData = NULL;
114 return;
115 }
116 if (stringSrc.m_pData->m_nRefs >= 0) {
117 m_pData = stringSrc.m_pData;
118 m_pData->Retain();
119 } else {
120 m_pData = NULL;
121 *this = stringSrc;
122 }
123 }
124 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& stringSrc) { 136 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& stringSrc) {
125 if (stringSrc.IsEmpty()) { 137 if (!stringSrc.IsEmpty()) {
126 m_pData = NULL; 138 m_pData.Reset(
127 return; 139 StringData::Create(stringSrc.GetCStr(), stringSrc.GetLength()));
128 } 140 }
129 m_pData = NULL; 141 }
130 *this = stringSrc; 142
131 }
132 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& str1, 143 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& str1,
133 const CFX_ByteStringC& str2) { 144 const CFX_ByteStringC& str2) {
134 m_pData = NULL;
135 int nNewLen = str1.GetLength() + str2.GetLength(); 145 int nNewLen = str1.GetLength() + str2.GetLength();
136 if (nNewLen == 0) { 146 if (nNewLen == 0)
137 return; 147 return;
138 } 148
139 m_pData = StringData::Create(nNewLen); 149 m_pData.Reset(StringData::Create(nNewLen));
140 if (m_pData) { 150 m_pData->CopyContents(str1.GetCStr(), str1.GetLength());
141 FXSYS_memcpy(m_pData->m_String, str1.GetCStr(), str1.GetLength()); 151 m_pData->CopyContentsAt(str1.GetLength(), str2.GetCStr(), str2.GetLength());
142 FXSYS_memcpy(m_pData->m_String + str1.GetLength(), str2.GetCStr(), 152 }
143 str2.GetLength()); 153
144 } 154 CFX_ByteString::~CFX_ByteString() {}
145 } 155
146 const CFX_ByteString& CFX_ByteString::operator=(const FX_CHAR* lpsz) { 156 const CFX_ByteString& CFX_ByteString::operator=(const FX_CHAR* pStr) {
147 if (!lpsz || lpsz[0] == 0) { 157 if (!pStr || pStr[0] == 0)
dsinclair 2016/03/30 13:27:20 nit: '\0' as we're comparing chars
Tom Sepez 2016/03/30 18:49:18 !pStr[0]
148 Empty(); 158 Empty();
149 } else { 159 else
150 AssignCopy(FXSYS_strlen(lpsz), lpsz); 160 AssignCopy(pStr, FXSYS_strlen(pStr));
151 } 161
152 return *this; 162 return *this;
153 } 163 }
164
154 const CFX_ByteString& CFX_ByteString::operator=(const CFX_ByteStringC& str) { 165 const CFX_ByteString& CFX_ByteString::operator=(const CFX_ByteStringC& str) {
155 if (str.IsEmpty()) { 166 if (str.IsEmpty())
156 Empty(); 167 Empty();
157 } else { 168 else
158 AssignCopy(str.GetLength(), str.GetCStr()); 169 AssignCopy(str.GetCStr(), str.GetLength());
159 } 170
160 return *this; 171 return *this;
161 } 172 }
173
162 const CFX_ByteString& CFX_ByteString::operator=( 174 const CFX_ByteString& CFX_ByteString::operator=(
163 const CFX_ByteString& stringSrc) { 175 const CFX_ByteString& stringSrc) {
164 if (m_pData == stringSrc.m_pData) { 176 if (m_pData != stringSrc.m_pData)
165 return *this;
166 }
167 if (stringSrc.IsEmpty()) {
168 Empty();
169 } else if ((m_pData && m_pData->m_nRefs < 0) ||
170 (stringSrc.m_pData && stringSrc.m_pData->m_nRefs < 0)) {
171 AssignCopy(stringSrc.m_pData->m_nDataLength, stringSrc.m_pData->m_String);
172 } else {
173 Empty();
174 m_pData = stringSrc.m_pData; 177 m_pData = stringSrc.m_pData;
175 if (m_pData) { 178
176 m_pData->Retain(); 179 return *this;
177 } 180 }
178 } 181
179 return *this;
180 }
181 const CFX_ByteString& CFX_ByteString::operator=(const CFX_BinaryBuf& buf) { 182 const CFX_ByteString& CFX_ByteString::operator=(const CFX_BinaryBuf& buf) {
182 Load(buf.GetBuffer(), buf.GetSize()); 183 Load(buf.GetBuffer(), buf.GetSize());
183 return *this; 184 return *this;
184 } 185 }
186
185 void CFX_ByteString::Load(const uint8_t* buf, FX_STRSIZE len) { 187 void CFX_ByteString::Load(const uint8_t* buf, FX_STRSIZE len) {
186 Empty(); 188 if (!len) {
187 if (len) { 189 Empty();
188 m_pData = StringData::Create(len); 190 return;
189 if (m_pData) { 191 }
190 FXSYS_memcpy(m_pData->m_String, buf, len); 192
191 } 193 m_pData.Reset(StringData::Create(reinterpret_cast<const FX_CHAR*>(buf), len));
192 } else { 194 }
193 m_pData = NULL; 195
194 } 196 const CFX_ByteString& CFX_ByteString::operator+=(const FX_CHAR* pStr) {
195 } 197 if (pStr)
196 const CFX_ByteString& CFX_ByteString::operator+=(const FX_CHAR* lpsz) { 198 Concat(pStr, FXSYS_strlen(pStr));
197 if (lpsz) { 199
198 ConcatInPlace(FXSYS_strlen(lpsz), lpsz); 200 return *this;
199 } 201 }
200 return *this; 202
201 }
202 const CFX_ByteString& CFX_ByteString::operator+=(char ch) { 203 const CFX_ByteString& CFX_ByteString::operator+=(char ch) {
203 ConcatInPlace(1, &ch); 204 Concat(&ch, 1);
204 return *this; 205 return *this;
205 } 206 }
207
206 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteString& str) { 208 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteString& str) {
207 if (!str.m_pData) { 209 if (str.m_pData)
208 return *this; 210 Concat(str.m_pData->m_String, str.m_pData->m_nDataLength);
209 } 211
210 ConcatInPlace(str.m_pData->m_nDataLength, str.m_pData->m_String); 212 return *this;
211 return *this; 213 }
212 } 214
213 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteStringC& str) { 215 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteStringC& str) {
214 if (str.IsEmpty()) { 216 if (!str.IsEmpty())
215 return *this; 217 Concat(str.GetCStr(), str.GetLength());
216 } 218
217 ConcatInPlace(str.GetLength(), str.GetCStr()); 219 return *this;
218 return *this; 220 }
219 } 221
220 bool CFX_ByteString::Equal(const char* ptr) const { 222 bool CFX_ByteString::Equal(const char* ptr) const {
221 if (!m_pData) { 223 if (!m_pData)
222 return !ptr || ptr[0] == '\0'; 224 return !ptr || ptr[0] == '\0';
223 } 225
224 if (!ptr) { 226 if (!ptr)
225 return m_pData->m_nDataLength == 0; 227 return m_pData->m_nDataLength == 0;
226 } 228
227 return FXSYS_strlen(ptr) == m_pData->m_nDataLength && 229 return FXSYS_strlen(ptr) == m_pData->m_nDataLength &&
228 FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; 230 FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
229 } 231 }
232
230 bool CFX_ByteString::Equal(const CFX_ByteStringC& str) const { 233 bool CFX_ByteString::Equal(const CFX_ByteStringC& str) const {
231 if (!m_pData) { 234 if (!m_pData)
232 return str.IsEmpty(); 235 return str.IsEmpty();
233 } 236
234 return m_pData->m_nDataLength == str.GetLength() && 237 return m_pData->m_nDataLength == str.GetLength() &&
235 FXSYS_memcmp(m_pData->m_String, str.GetCStr(), str.GetLength()) == 0; 238 FXSYS_memcmp(m_pData->m_String, str.GetCStr(), str.GetLength()) == 0;
236 } 239 }
240
237 bool CFX_ByteString::Equal(const CFX_ByteString& other) const { 241 bool CFX_ByteString::Equal(const CFX_ByteString& other) const {
238 if (IsEmpty()) { 242 if (IsEmpty())
239 return other.IsEmpty(); 243 return other.IsEmpty();
240 } 244
241 if (other.IsEmpty()) { 245 if (other.IsEmpty())
242 return false; 246 return false;
243 } 247
244 return other.m_pData->m_nDataLength == m_pData->m_nDataLength && 248 return other.m_pData->m_nDataLength == m_pData->m_nDataLength &&
245 FXSYS_memcmp(other.m_pData->m_String, m_pData->m_String, 249 FXSYS_memcmp(other.m_pData->m_String, m_pData->m_String,
246 m_pData->m_nDataLength) == 0; 250 m_pData->m_nDataLength) == 0;
247 } 251 }
248 void CFX_ByteString::Empty() { 252
249 if (m_pData) {
250 m_pData->Release();
251 m_pData = NULL;
252 }
253 }
254 bool CFX_ByteString::EqualNoCase(const CFX_ByteStringC& str) const { 253 bool CFX_ByteString::EqualNoCase(const CFX_ByteStringC& str) const {
255 if (!m_pData) { 254 if (!m_pData)
256 return str.IsEmpty(); 255 return str.IsEmpty();
257 } 256
258 FX_STRSIZE len = str.GetLength(); 257 FX_STRSIZE len = str.GetLength();
259 if (m_pData->m_nDataLength != len) { 258 if (m_pData->m_nDataLength != len)
260 return false; 259 return false;
261 } 260
262 const uint8_t* pThis = (const uint8_t*)m_pData->m_String; 261 const uint8_t* pThis = (const uint8_t*)m_pData->m_String;
263 const uint8_t* pThat = str.GetPtr(); 262 const uint8_t* pThat = str.GetPtr();
264 for (FX_STRSIZE i = 0; i < len; i++) { 263 for (FX_STRSIZE i = 0; i < len; i++) {
265 if ((*pThis) != (*pThat)) { 264 if ((*pThis) != (*pThat)) {
266 uint8_t bThis = *pThis; 265 uint8_t bThis = *pThis;
267 if (bThis >= 'A' && bThis <= 'Z') { 266 if (bThis >= 'A' && bThis <= 'Z')
268 bThis += 'a' - 'A'; 267 bThis += 'a' - 'A';
269 } 268
270 uint8_t bThat = *pThat; 269 uint8_t bThat = *pThat;
271 if (bThat >= 'A' && bThat <= 'Z') { 270 if (bThat >= 'A' && bThat <= 'Z')
272 bThat += 'a' - 'A'; 271 bThat += 'a' - 'A';
273 } 272
274 if (bThis != bThat) { 273 if (bThis != bThat)
275 return false; 274 return false;
276 }
277 } 275 }
278 pThis++; 276 pThis++;
279 pThat++; 277 pThat++;
280 } 278 }
281 return true; 279 return true;
282 } 280 }
283 void CFX_ByteString::AssignCopy(FX_STRSIZE nSrcLen, 281
284 const FX_CHAR* lpszSrcData) { 282 void CFX_ByteString::AssignCopy(const FX_CHAR* pSrcData, FX_STRSIZE nSrcLen) {
285 AllocBeforeWrite(nSrcLen); 283 AllocBeforeWrite(nSrcLen);
286 FXSYS_memcpy(m_pData->m_String, lpszSrcData, nSrcLen); 284 m_pData->CopyContents(pSrcData, nSrcLen);
287 m_pData->m_nDataLength = nSrcLen; 285 m_pData->m_nDataLength = nSrcLen;
288 m_pData->m_String[nSrcLen] = 0; 286 }
289 } 287
290 void CFX_ByteString::CopyBeforeWrite() { 288 void CFX_ByteString::CopyBeforeWrite() {
291 if (!m_pData || m_pData->m_nRefs <= 1) { 289 if (!m_pData || m_pData->CanOperateInPlace(m_pData->m_nDataLength))
292 return; 290 return;
293 } 291
294 StringData* pData = m_pData; 292 if (!m_pData->m_nDataLength) {
295 m_pData->Release(); 293 Empty();
296 FX_STRSIZE nDataLength = pData->m_nDataLength; 294 return;
297 m_pData = StringData::Create(nDataLength); 295 }
298 if (m_pData) { 296
299 FXSYS_memcpy(m_pData->m_String, pData->m_String, nDataLength + 1); 297 CFX_RetainPtr<StringData> pData(StringData::Create(*m_pData));
300 } 298 m_pData.Swap(pData);
301 } 299 }
300
302 void CFX_ByteString::AllocBeforeWrite(FX_STRSIZE nLen) { 301 void CFX_ByteString::AllocBeforeWrite(FX_STRSIZE nLen) {
303 if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nLen) { 302 if (m_pData && m_pData->CanOperateInPlace(nLen))
304 return; 303 return;
305 } 304
306 Empty(); 305 if (!nLen) {
307 m_pData = StringData::Create(nLen); 306 Empty();
308 } 307 return;
308 }
309
310 m_pData.Reset(StringData::Create(nLen));
311 }
312
309 void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) { 313 void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) {
310 if (!m_pData) { 314 if (!m_pData)
311 return; 315 return;
312 } 316
317 if (nNewLength == -1)
318 nNewLength = FXSYS_strlen(m_pData->m_String);
319
320 if (nNewLength == 0) {
321 Empty();
322 return;
323 }
324
325 FXSYS_assert(nNewLength <= m_pData->m_nAllocLength);
313 CopyBeforeWrite(); 326 CopyBeforeWrite();
314 if (nNewLength == -1) {
315 nNewLength = FXSYS_strlen((const FX_CHAR*)m_pData->m_String);
316 }
317 if (nNewLength == 0) {
318 Empty();
319 return;
320 }
321 FXSYS_assert(nNewLength <= m_pData->m_nAllocLength);
322 m_pData->m_nDataLength = nNewLength; 327 m_pData->m_nDataLength = nNewLength;
323 m_pData->m_String[nNewLength] = 0; 328 m_pData->m_String[nNewLength] = 0;
324 } 329 }
330
325 void CFX_ByteString::Reserve(FX_STRSIZE len) { 331 void CFX_ByteString::Reserve(FX_STRSIZE len) {
326 GetBuffer(len); 332 GetBuffer(len);
327 ReleaseBuffer(GetLength()); 333 ReleaseBuffer(GetLength());
328 } 334 }
335
329 FX_CHAR* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) { 336 FX_CHAR* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) {
330 if (!m_pData && nMinBufLength == 0) {
331 return NULL;
332 }
333 if (m_pData && m_pData->m_nRefs <= 1 &&
334 m_pData->m_nAllocLength >= nMinBufLength) {
335 return m_pData->m_String;
336 }
337 if (!m_pData) { 337 if (!m_pData) {
338 m_pData = StringData::Create(nMinBufLength); 338 if (nMinBufLength == 0)
339 if (!m_pData) { 339 return nullptr;
340 return NULL; 340
341 } 341 m_pData.Reset(StringData::Create(nMinBufLength));
342 m_pData->m_nDataLength = 0; 342 m_pData->m_nDataLength = 0;
343 m_pData->m_String[0] = 0; 343 m_pData->m_String[0] = 0;
344 return m_pData->m_String; 344 return m_pData->m_String;
345 } 345 }
346 StringData* pOldData = m_pData; 346
347 FX_STRSIZE nOldLen = pOldData->m_nDataLength; 347 if (m_pData->CanOperateInPlace(nMinBufLength))
348 if (nMinBufLength < nOldLen) { 348 return m_pData->m_String;
349 nMinBufLength = nOldLen; 349
350 } 350 nMinBufLength = std::max(nMinBufLength, m_pData->m_nDataLength);
351 m_pData = StringData::Create(nMinBufLength); 351 if (nMinBufLength == 0)
352 if (!m_pData) { 352 return nullptr;
353 return NULL; 353
354 } 354 CFX_RetainPtr<StringData> pNewData(StringData::Create(nMinBufLength));
355 FXSYS_memcpy(m_pData->m_String, pOldData->m_String, (nOldLen + 1)); 355 pNewData->CopyContents(*m_pData);
356 m_pData->m_nDataLength = nOldLen; 356 pNewData->m_nDataLength = m_pData->m_nDataLength;
357 pOldData->Release(); 357 m_pData.Swap(pNewData);
358 return m_pData->m_String; 358 return m_pData->m_String;
359 } 359 }
360
360 FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) { 361 FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) {
361 if (!m_pData) { 362 if (!m_pData)
362 return 0; 363 return 0;
363 } 364
364 if (nIndex < 0) { 365 if (nIndex < 0)
365 nIndex = 0; 366 nIndex = 0;
366 } 367
367 FX_STRSIZE nOldLength = m_pData->m_nDataLength; 368 FX_STRSIZE nOldLength = m_pData->m_nDataLength;
368 if (nCount > 0 && nIndex < nOldLength) { 369 if (nCount > 0 && nIndex < nOldLength) {
369 FX_STRSIZE mLength = nIndex + nCount; 370 FX_STRSIZE mLength = nIndex + nCount;
370 if (mLength >= nOldLength) { 371 if (mLength >= nOldLength) {
371 m_pData->m_nDataLength = nIndex; 372 m_pData->m_nDataLength = nIndex;
372 return m_pData->m_nDataLength; 373 return m_pData->m_nDataLength;
373 } 374 }
374 CopyBeforeWrite(); 375 CopyBeforeWrite();
375 int nBytesToCopy = nOldLength - mLength + 1; 376 int nBytesToCopy = nOldLength - mLength + 1;
376 FXSYS_memmove(m_pData->m_String + nIndex, m_pData->m_String + mLength, 377 FXSYS_memmove(m_pData->m_String + nIndex, m_pData->m_String + mLength,
377 nBytesToCopy); 378 nBytesToCopy);
378 m_pData->m_nDataLength = nOldLength - nCount; 379 m_pData->m_nDataLength = nOldLength - nCount;
379 } 380 }
380 return m_pData->m_nDataLength; 381 return m_pData->m_nDataLength;
381 } 382 }
382 void CFX_ByteString::ConcatInPlace(FX_STRSIZE nSrcLen, 383
383 const FX_CHAR* lpszSrcData) { 384 void CFX_ByteString::Concat(const FX_CHAR* pSrcData, FX_STRSIZE nSrcLen) {
384 if (nSrcLen == 0 || !lpszSrcData) { 385 if (!pSrcData || nSrcLen <= 0)
386 return;
387
388 if (!m_pData) {
389 m_pData.Reset(StringData::Create(pSrcData, nSrcLen));
385 return; 390 return;
386 } 391 }
387 if (!m_pData) { 392
388 m_pData = StringData::Create(nSrcLen); 393 if (m_pData->CanOperateInPlace(m_pData->m_nDataLength + nSrcLen)) {
389 if (!m_pData) { 394 m_pData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen);
390 return; 395 m_pData->m_nDataLength += nSrcLen;
391 }
392 FXSYS_memcpy(m_pData->m_String, lpszSrcData, nSrcLen);
393 return; 396 return;
394 } 397 }
395 if (m_pData->m_nRefs > 1 || 398
396 m_pData->m_nDataLength + nSrcLen > m_pData->m_nAllocLength) { 399 CFX_RetainPtr<StringData> pNewData(
397 ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcData); 400 StringData::Create(m_pData->m_nDataLength + nSrcLen));
398 } else { 401 pNewData->CopyContents(*m_pData);
399 FXSYS_memcpy(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, 402 pNewData->CopyContentsAt(m_pData->m_nDataLength, pSrcData, nSrcLen);
400 nSrcLen); 403 m_pData.Swap(pNewData);
401 m_pData->m_nDataLength += nSrcLen;
402 m_pData->m_String[m_pData->m_nDataLength] = 0;
403 }
404 } 404 }
405 void CFX_ByteString::ConcatCopy(FX_STRSIZE nSrc1Len, 405
406 const FX_CHAR* lpszSrc1Data,
407 FX_STRSIZE nSrc2Len,
408 const FX_CHAR* lpszSrc2Data) {
409 int nNewLen = nSrc1Len + nSrc2Len;
410 if (nNewLen <= 0) {
411 return;
412 }
413 // Don't release until done copying, might be one of the arguments.
414 StringData* pOldData = m_pData;
415 m_pData = StringData::Create(nNewLen);
416 if (m_pData) {
417 memcpy(m_pData->m_String, lpszSrc1Data, nSrc1Len);
418 memcpy(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len);
419 }
420 pOldData->Release();
421 }
422 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst) const { 406 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst) const {
423 if (!m_pData) {
424 return CFX_ByteString();
425 }
426 return Mid(nFirst, m_pData->m_nDataLength - nFirst); 407 return Mid(nFirst, m_pData->m_nDataLength - nFirst);
427 } 408 }
409
428 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const { 410 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const {
429 if (nFirst < 0) { 411 if (!m_pData)
430 nFirst = 0; 412 return CFX_ByteString();
431 } 413
432 if (nCount < 0) { 414 nFirst = std::max(nFirst, 0);
415 nCount = std::max(nCount, 0);
416 if (nFirst + nCount > m_pData->m_nDataLength)
Lei Zhang 2016/03/30 00:15:32 Should we worry about integer overflows?
Tom Sepez 2016/03/30 18:49:18 Sure. re-written.
417 nCount = m_pData->m_nDataLength - nFirst;
418
419 if (nFirst > m_pData->m_nDataLength)
Lei Zhang 2016/03/30 00:15:32 Should we check this first before line 416, and ma
Tom Sepez 2016/03/30 18:49:18 Done.
433 nCount = 0; 420 nCount = 0;
434 } 421
435 if (nFirst + nCount > m_pData->m_nDataLength) { 422 if (nFirst == 0 && nFirst + nCount == m_pData->m_nDataLength)
436 nCount = m_pData->m_nDataLength - nFirst;
437 }
438 if (nFirst > m_pData->m_nDataLength) {
439 nCount = 0;
440 }
441 if (nFirst == 0 && nFirst + nCount == m_pData->m_nDataLength) {
442 return *this; 423 return *this;
443 } 424
444 CFX_ByteString dest; 425 CFX_ByteString dest;
445 AllocCopy(dest, nCount, nFirst); 426 AllocCopy(dest, nCount, nFirst);
446 return dest; 427 return dest;
447 } 428 }
429
448 void CFX_ByteString::AllocCopy(CFX_ByteString& dest, 430 void CFX_ByteString::AllocCopy(CFX_ByteString& dest,
449 FX_STRSIZE nCopyLen, 431 FX_STRSIZE nCopyLen,
450 FX_STRSIZE nCopyIndex) const { 432 FX_STRSIZE nCopyIndex) const {
451 // |FX_STRSIZE| is currently typedef'd as in |int|. TODO(palmer): It 433 if (nCopyLen <= 0)
452 // should be a |size_t|, or at least unsigned.
453 if (nCopyLen == 0 || nCopyLen < 0) {
454 return; 434 return;
455 } 435
456 ASSERT(!dest.m_pData); 436 CFX_RetainPtr<StringData> pNewData(
457 dest.m_pData = StringData::Create(nCopyLen); 437 StringData::Create(m_pData->m_String + nCopyIndex, nCopyLen));
458 if (dest.m_pData) { 438 dest.m_pData.Swap(pNewData);
459 FXSYS_memcpy(dest.m_pData->m_String, m_pData->m_String + nCopyIndex,
460 nCopyLen);
461 }
462 } 439 }
440
463 #define FORCE_ANSI 0x10000 441 #define FORCE_ANSI 0x10000
464 #define FORCE_UNICODE 0x20000 442 #define FORCE_UNICODE 0x20000
465 #define FORCE_INT64 0x40000 443 #define FORCE_INT64 0x40000
466 void CFX_ByteString::FormatV(const FX_CHAR* lpszFormat, va_list argList) { 444
445 void CFX_ByteString::FormatV(const FX_CHAR* pFormat, va_list argList) {
467 va_list argListSave; 446 va_list argListSave;
468 #if defined(__ARMCC_VERSION) || \ 447 #if defined(__ARMCC_VERSION) || \
469 (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || \ 448 (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || \
470 _FX_CPU_ == _FX_ARM64_)) || \ 449 _FX_CPU_ == _FX_ARM64_)) || \
471 defined(__native_client__) 450 defined(__native_client__)
472 va_copy(argListSave, argList); 451 va_copy(argListSave, argList);
473 #else 452 #else
474 argListSave = argList; 453 argListSave = argList;
475 #endif 454 #endif
476 int nMaxLen = 0; 455 int nMaxLen = 0;
477 for (const FX_CHAR* lpsz = lpszFormat; *lpsz != 0; lpsz++) { 456 for (const FX_CHAR* pStr = pFormat; *pStr != 0; pStr++) {
478 if (*lpsz != '%' || *(lpsz = lpsz + 1) == '%') { 457 if (*pStr != '%' || *(pStr = pStr + 1) == '%') {
479 nMaxLen += FXSYS_strlen(lpsz); 458 nMaxLen += FXSYS_strlen(pStr);
480 continue; 459 continue;
481 } 460 }
482 int nItemLen = 0; 461 int nItemLen = 0;
483 int nWidth = 0; 462 int nWidth = 0;
484 for (; *lpsz != 0; lpsz++) { 463 for (; *pStr != 0; pStr++) {
485 if (*lpsz == '#') { 464 if (*pStr == '#') {
486 nMaxLen += 2; 465 nMaxLen += 2;
487 } else if (*lpsz == '*') { 466 } else if (*pStr == '*') {
488 nWidth = va_arg(argList, int); 467 nWidth = va_arg(argList, int);
489 } else if (*lpsz != '-' && *lpsz != '+' && *lpsz != '0' && *lpsz != ' ') { 468 } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' && *pStr != ' ') {
490 break; 469 break;
491 } 470 }
492 } 471 }
493 if (nWidth == 0) { 472 if (nWidth == 0) {
494 nWidth = FXSYS_atoi(lpsz); 473 nWidth = FXSYS_atoi(pStr);
495 while (std::isdigit(*lpsz)) 474 while (std::isdigit(*pStr))
496 lpsz++; 475 pStr++;
497 } 476 }
498 if (nWidth < 0 || nWidth > 128 * 1024) { 477 if (nWidth < 0 || nWidth > 128 * 1024) {
499 lpszFormat = "Bad width"; 478 pFormat = "Bad width";
500 nMaxLen = 10; 479 nMaxLen = 10;
501 break; 480 break;
502 } 481 }
503 int nPrecision = 0; 482 int nPrecision = 0;
504 if (*lpsz == '.') { 483 if (*pStr == '.') {
505 lpsz++; 484 pStr++;
506 if (*lpsz == '*') { 485 if (*pStr == '*') {
507 nPrecision = va_arg(argList, int); 486 nPrecision = va_arg(argList, int);
508 lpsz++; 487 pStr++;
509 } else { 488 } else {
510 nPrecision = FXSYS_atoi(lpsz); 489 nPrecision = FXSYS_atoi(pStr);
511 while (std::isdigit(*lpsz)) 490 while (std::isdigit(*pStr))
512 lpsz++; 491 pStr++;
513 } 492 }
514 } 493 }
515 if (nPrecision < 0 || nPrecision > 128 * 1024) { 494 if (nPrecision < 0 || nPrecision > 128 * 1024) {
516 lpszFormat = "Bad precision"; 495 pFormat = "Bad precision";
517 nMaxLen = 14; 496 nMaxLen = 14;
518 break; 497 break;
519 } 498 }
520 int nModifier = 0; 499 int nModifier = 0;
521 if (FXSYS_strncmp(lpsz, "I64", 3) == 0) { 500 if (FXSYS_strncmp(pStr, "I64", 3) == 0) {
522 lpsz += 3; 501 pStr += 3;
523 nModifier = FORCE_INT64; 502 nModifier = FORCE_INT64;
524 } else { 503 } else {
525 switch (*lpsz) { 504 switch (*pStr) {
526 case 'h': 505 case 'h':
527 nModifier = FORCE_ANSI; 506 nModifier = FORCE_ANSI;
528 lpsz++; 507 pStr++;
529 break; 508 break;
530 case 'l': 509 case 'l':
531 nModifier = FORCE_UNICODE; 510 nModifier = FORCE_UNICODE;
532 lpsz++; 511 pStr++;
533 break; 512 break;
534 case 'F': 513 case 'F':
535 case 'N': 514 case 'N':
536 case 'L': 515 case 'L':
537 lpsz++; 516 pStr++;
538 break; 517 break;
539 } 518 }
540 } 519 }
541 switch (*lpsz | nModifier) { 520 switch (*pStr | nModifier) {
542 case 'c': 521 case 'c':
543 case 'C': 522 case 'C':
544 nItemLen = 2; 523 nItemLen = 2;
545 va_arg(argList, int); 524 va_arg(argList, int);
546 break; 525 break;
547 case 'c' | FORCE_ANSI: 526 case 'c' | FORCE_ANSI:
548 case 'C' | FORCE_ANSI: 527 case 'C' | FORCE_ANSI:
549 nItemLen = 2; 528 nItemLen = 2;
550 va_arg(argList, int); 529 va_arg(argList, int);
551 break; 530 break;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 } break; 581 } break;
603 } 582 }
604 if (nItemLen != 0) { 583 if (nItemLen != 0) {
605 if (nPrecision != 0 && nItemLen > nPrecision) { 584 if (nPrecision != 0 && nItemLen > nPrecision) {
606 nItemLen = nPrecision; 585 nItemLen = nPrecision;
607 } 586 }
608 if (nItemLen < nWidth) { 587 if (nItemLen < nWidth) {
609 nItemLen = nWidth; 588 nItemLen = nWidth;
610 } 589 }
611 } else { 590 } else {
612 switch (*lpsz) { 591 switch (*pStr) {
613 case 'd': 592 case 'd':
614 case 'i': 593 case 'i':
615 case 'u': 594 case 'u':
616 case 'x': 595 case 'x':
617 case 'X': 596 case 'X':
618 case 'o': 597 case 'o':
619 if (nModifier & FORCE_INT64) { 598 if (nModifier & FORCE_INT64) {
620 va_arg(argList, int64_t); 599 va_arg(argList, int64_t);
621 } else { 600 } else {
622 va_arg(argList, int); 601 va_arg(argList, int);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 va_arg(argList, int*); 640 va_arg(argList, int*);
662 break; 641 break;
663 } 642 }
664 } 643 }
665 nMaxLen += nItemLen; 644 nMaxLen += nItemLen;
666 } 645 }
667 nMaxLen += 32; // Fudge factor. 646 nMaxLen += 32; // Fudge factor.
668 GetBuffer(nMaxLen); 647 GetBuffer(nMaxLen);
669 if (m_pData) { 648 if (m_pData) {
670 memset(m_pData->m_String, 0, nMaxLen); 649 memset(m_pData->m_String, 0, nMaxLen);
671 FXSYS_vsnprintf(m_pData->m_String, nMaxLen - 1, lpszFormat, argListSave); 650 FXSYS_vsnprintf(m_pData->m_String, nMaxLen - 1, pFormat, argListSave);
672 ReleaseBuffer(); 651 ReleaseBuffer();
673 } 652 }
674 va_end(argListSave); 653 va_end(argListSave);
675 } 654 }
676 void CFX_ByteString::Format(const FX_CHAR* lpszFormat, ...) { 655
656 void CFX_ByteString::Format(const FX_CHAR* pFormat, ...) {
677 va_list argList; 657 va_list argList;
678 va_start(argList, lpszFormat); 658 va_start(argList, pFormat);
679 FormatV(lpszFormat, argList); 659 FormatV(pFormat, argList);
680 va_end(argList); 660 va_end(argList);
681 } 661 }
662
682 FX_STRSIZE CFX_ByteString::Insert(FX_STRSIZE nIndex, FX_CHAR ch) { 663 FX_STRSIZE CFX_ByteString::Insert(FX_STRSIZE nIndex, FX_CHAR ch) {
664 FX_STRSIZE nNewLength = m_pData ? m_pData->m_nDataLength : 0;
665 nIndex = std::max(nIndex, 0);
666 nIndex = std::min(nIndex, nNewLength);
667 nNewLength++;
668
683 CopyBeforeWrite(); 669 CopyBeforeWrite();
684 if (nIndex < 0) { 670 if (!m_pData || m_pData->m_nAllocLength < nNewLength) {
685 nIndex = 0; 671 CFX_RetainPtr<StringData> pNewData(StringData::Create(nNewLength));
672 pNewData->CopyContents(*m_pData);
673 m_pData.Swap(pNewData);
686 } 674 }
687 FX_STRSIZE nNewLength = m_pData ? m_pData->m_nDataLength : 0; 675
688 if (nIndex > nNewLength) {
689 nIndex = nNewLength;
690 }
691 nNewLength++;
692 if (!m_pData || m_pData->m_nAllocLength < nNewLength) {
693 StringData* pOldData = m_pData;
694 const FX_CHAR* pstr = m_pData->m_String;
695 m_pData = StringData::Create(nNewLength);
696 if (!m_pData) {
697 return 0;
698 }
699 if (pOldData) {
700 FXSYS_memmove(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1));
701 pOldData->Release();
702 } else {
703 m_pData->m_String[0] = 0;
704 }
705 }
706 FXSYS_memmove(m_pData->m_String + nIndex + 1, m_pData->m_String + nIndex, 676 FXSYS_memmove(m_pData->m_String + nIndex + 1, m_pData->m_String + nIndex,
707 (nNewLength - nIndex)); 677 nNewLength - nIndex);
708 m_pData->m_String[nIndex] = ch; 678 m_pData->m_String[nIndex] = ch;
709 m_pData->m_nDataLength = nNewLength; 679 m_pData->m_nDataLength = nNewLength;
710 return nNewLength; 680 return nNewLength;
711 } 681 }
682
712 CFX_ByteString CFX_ByteString::Right(FX_STRSIZE nCount) const { 683 CFX_ByteString CFX_ByteString::Right(FX_STRSIZE nCount) const {
713 if (!m_pData) { 684 if (!m_pData)
714 return CFX_ByteString(); 685 return CFX_ByteString();
715 } 686
716 if (nCount < 0) { 687 if (nCount < 0)
Lei Zhang 2016/03/30 00:15:32 Use std::max() here too?
Tom Sepez 2016/03/30 18:49:18 Done.
717 nCount = 0; 688 nCount = 0;
718 } 689
719 if (nCount >= m_pData->m_nDataLength) { 690 if (nCount >= m_pData->m_nDataLength)
720 return *this; 691 return *this;
721 } 692
722 CFX_ByteString dest; 693 CFX_ByteString dest;
723 AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount); 694 AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount);
724 return dest; 695 return dest;
725 } 696 }
697
726 CFX_ByteString CFX_ByteString::Left(FX_STRSIZE nCount) const { 698 CFX_ByteString CFX_ByteString::Left(FX_STRSIZE nCount) const {
727 if (!m_pData) { 699 if (!m_pData)
728 return CFX_ByteString(); 700 return CFX_ByteString();
729 } 701
730 if (nCount < 0) { 702 if (nCount < 0)
Lei Zhang 2016/03/30 00:15:32 std::max()
Tom Sepez 2016/03/30 18:49:18 Done.
731 nCount = 0; 703 nCount = 0;
732 } 704
733 if (nCount >= m_pData->m_nDataLength) { 705 if (nCount >= m_pData->m_nDataLength)
734 return *this; 706 return *this;
735 } 707
736 CFX_ByteString dest; 708 CFX_ByteString dest;
737 AllocCopy(dest, nCount, 0); 709 AllocCopy(dest, nCount, 0);
738 return dest; 710 return dest;
739 } 711 }
712
740 FX_STRSIZE CFX_ByteString::Find(FX_CHAR ch, FX_STRSIZE nStart) const { 713 FX_STRSIZE CFX_ByteString::Find(FX_CHAR ch, FX_STRSIZE nStart) const {
741 if (!m_pData) { 714 if (!m_pData)
742 return -1; 715 return -1;
743 } 716
717 if (nStart >= m_pData->m_nDataLength)
718 return -1;
719
720 const FX_CHAR* pStr = FXSYS_strchr(m_pData->m_String + nStart, ch);
721 return pStr ? (int)(pStr - m_pData->m_String) : -1;
722 }
723
724 FX_STRSIZE CFX_ByteString::ReverseFind(FX_CHAR ch) const {
725 if (!m_pData)
726 return -1;
727
744 FX_STRSIZE nLength = m_pData->m_nDataLength; 728 FX_STRSIZE nLength = m_pData->m_nDataLength;
745 if (nStart >= nLength) { 729 while (nLength--) {
746 return -1; 730 if (m_pData->m_String[nLength] == ch)
747 } 731 return nLength;
748 const FX_CHAR* lpsz = FXSYS_strchr(m_pData->m_String + nStart, ch);
749 return lpsz ? (int)(lpsz - m_pData->m_String) : -1;
750 }
751 FX_STRSIZE CFX_ByteString::ReverseFind(FX_CHAR ch) const {
752 if (!m_pData) {
753 return -1;
754 }
755 FX_STRSIZE nLength = m_pData->m_nDataLength;
756 while (nLength) {
757 if (m_pData->m_String[nLength - 1] == ch) {
758 return nLength - 1;
759 }
760 nLength--;
761 } 732 }
762 return -1; 733 return -1;
763 } 734 }
735
764 const FX_CHAR* FX_strstr(const FX_CHAR* str1, 736 const FX_CHAR* FX_strstr(const FX_CHAR* str1,
765 int len1, 737 int len1,
766 const FX_CHAR* str2, 738 const FX_CHAR* str2,
767 int len2) { 739 int len2) {
768 if (len2 > len1 || len2 == 0) { 740 if (len2 > len1 || len2 == 0) {
769 return NULL; 741 return nullptr;
770 } 742 }
771 const FX_CHAR* end_ptr = str1 + len1 - len2; 743 const FX_CHAR* end_ptr = str1 + len1 - len2;
772 while (str1 <= end_ptr) { 744 while (str1 <= end_ptr) {
773 int i = 0; 745 int i = 0;
774 while (1) { 746 while (1) {
775 if (str1[i] != str2[i]) { 747 if (str1[i] != str2[i]) {
776 break; 748 break;
777 } 749 }
778 i++; 750 i++;
779 if (i == len2) { 751 if (i == len2) {
780 return str1; 752 return str1;
781 } 753 }
782 } 754 }
783 str1++; 755 str1++;
784 } 756 }
785 return NULL; 757 return nullptr;
786 } 758 }
787 FX_STRSIZE CFX_ByteString::Find(const CFX_ByteStringC& lpszSub, 759
760 FX_STRSIZE CFX_ByteString::Find(const CFX_ByteStringC& pSub,
788 FX_STRSIZE nStart) const { 761 FX_STRSIZE nStart) const {
789 if (!m_pData) { 762 if (!m_pData)
790 return -1; 763 return -1;
791 } 764
792 FX_STRSIZE nLength = m_pData->m_nDataLength; 765 FX_STRSIZE nLength = m_pData->m_nDataLength;
793 if (nStart > nLength) { 766 if (nStart > nLength)
794 return -1; 767 return -1;
795 } 768
796 const FX_CHAR* lpsz = 769 const FX_CHAR* pStr =
797 FX_strstr(m_pData->m_String + nStart, m_pData->m_nDataLength - nStart, 770 FX_strstr(m_pData->m_String + nStart, m_pData->m_nDataLength - nStart,
798 lpszSub.GetCStr(), lpszSub.GetLength()); 771 pSub.GetCStr(), pSub.GetLength());
799 return lpsz ? (int)(lpsz - m_pData->m_String) : -1; 772 return pStr ? (int)(pStr - m_pData->m_String) : -1;
800 } 773 }
774
801 void CFX_ByteString::MakeLower() { 775 void CFX_ByteString::MakeLower() {
802 if (!m_pData) { 776 if (!m_pData)
803 return; 777 return;
804 } 778
805 CopyBeforeWrite(); 779 CopyBeforeWrite();
806 if (GetLength() < 1) { 780 if (GetLength() < 1)
807 return; 781 return;
808 } 782
809 FXSYS_strlwr(m_pData->m_String); 783 FXSYS_strlwr(m_pData->m_String);
810 } 784 }
785
811 void CFX_ByteString::MakeUpper() { 786 void CFX_ByteString::MakeUpper() {
812 if (!m_pData) { 787 if (!m_pData)
813 return; 788 return;
814 } 789
815 CopyBeforeWrite(); 790 CopyBeforeWrite();
816 if (GetLength() < 1) { 791 if (GetLength() < 1)
817 return; 792 return;
818 } 793
819 FXSYS_strupr(m_pData->m_String); 794 FXSYS_strupr(m_pData->m_String);
820 } 795 }
796
821 FX_STRSIZE CFX_ByteString::Remove(FX_CHAR chRemove) { 797 FX_STRSIZE CFX_ByteString::Remove(FX_CHAR chRemove) {
822 if (!m_pData) { 798 if (!m_pData) {
823 return 0; 799 return 0;
824 } 800 }
825 CopyBeforeWrite(); 801 CopyBeforeWrite();
826 if (GetLength() < 1) { 802 if (GetLength() < 1) {
827 return 0; 803 return 0;
828 } 804 }
829 FX_CHAR* pstrSource = m_pData->m_String; 805 FX_CHAR* pstrSource = m_pData->m_String;
830 FX_CHAR* pstrDest = m_pData->m_String; 806 FX_CHAR* pstrDest = m_pData->m_String;
831 FX_CHAR* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; 807 FX_CHAR* pstrEnd = m_pData->m_String + m_pData->m_nDataLength;
832 while (pstrSource < pstrEnd) { 808 while (pstrSource < pstrEnd) {
833 if (*pstrSource != chRemove) { 809 if (*pstrSource != chRemove) {
834 *pstrDest = *pstrSource; 810 *pstrDest = *pstrSource;
835 pstrDest++; 811 pstrDest++;
836 } 812 }
837 pstrSource++; 813 pstrSource++;
838 } 814 }
839 *pstrDest = 0; 815 *pstrDest = 0;
840 FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest); 816 FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest);
841 m_pData->m_nDataLength -= nCount; 817 m_pData->m_nDataLength -= nCount;
842 return nCount; 818 return nCount;
843 } 819 }
844 FX_STRSIZE CFX_ByteString::Replace(const CFX_ByteStringC& lpszOld, 820
845 const CFX_ByteStringC& lpszNew) { 821 FX_STRSIZE CFX_ByteString::Replace(const CFX_ByteStringC& pOld,
846 if (!m_pData) { 822 const CFX_ByteStringC& pNew) {
823 if (!m_pData || pOld.IsEmpty())
847 return 0; 824 return 0;
848 } 825
849 if (lpszOld.IsEmpty()) { 826 FX_STRSIZE nSourceLen = pOld.GetLength();
850 return 0; 827 FX_STRSIZE nReplacementLen = pNew.GetLength();
851 }
852 FX_STRSIZE nSourceLen = lpszOld.GetLength();
853 FX_STRSIZE nReplacementLen = lpszNew.GetLength();
854 FX_STRSIZE nCount = 0; 828 FX_STRSIZE nCount = 0;
855 const FX_CHAR* pStart = m_pData->m_String; 829 const FX_CHAR* pStart = m_pData->m_String;
856 FX_CHAR* pEnd = m_pData->m_String + m_pData->m_nDataLength; 830 FX_CHAR* pEnd = m_pData->m_String + m_pData->m_nDataLength;
857 while (1) { 831 while (1) {
858 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart), 832 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart),
859 lpszOld.GetCStr(), nSourceLen); 833 pOld.GetCStr(), nSourceLen);
860 if (!pTarget) { 834 if (!pTarget)
861 break; 835 break;
862 } 836
863 nCount++; 837 nCount++;
864 pStart = pTarget + nSourceLen; 838 pStart = pTarget + nSourceLen;
865 } 839 }
866 if (nCount == 0) { 840 if (nCount == 0)
867 return 0; 841 return 0;
868 } 842
869 FX_STRSIZE nNewLength = 843 FX_STRSIZE nNewLength =
870 m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; 844 m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount;
845
871 if (nNewLength == 0) { 846 if (nNewLength == 0) {
872 Empty(); 847 Empty();
873 return nCount; 848 return nCount;
874 } 849 }
875 StringData* pNewData = StringData::Create(nNewLength); 850
876 if (!pNewData) { 851 CFX_RetainPtr<StringData> pNewData(StringData::Create(nNewLength));
877 return 0;
878 }
879 pStart = m_pData->m_String; 852 pStart = m_pData->m_String;
880 FX_CHAR* pDest = pNewData->m_String; 853 FX_CHAR* pDest = pNewData->m_String;
881 for (FX_STRSIZE i = 0; i < nCount; i++) { 854 for (FX_STRSIZE i = 0; i < nCount; i++) {
882 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart), 855 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart),
883 lpszOld.GetCStr(), nSourceLen); 856 pOld.GetCStr(), nSourceLen);
884 FXSYS_memcpy(pDest, pStart, pTarget - pStart); 857 FXSYS_memcpy(pDest, pStart, pTarget - pStart);
885 pDest += pTarget - pStart; 858 pDest += pTarget - pStart;
886 FXSYS_memcpy(pDest, lpszNew.GetCStr(), lpszNew.GetLength()); 859 FXSYS_memcpy(pDest, pNew.GetCStr(), pNew.GetLength());
887 pDest += lpszNew.GetLength(); 860 pDest += pNew.GetLength();
888 pStart = pTarget + nSourceLen; 861 pStart = pTarget + nSourceLen;
889 } 862 }
890 FXSYS_memcpy(pDest, pStart, pEnd - pStart); 863 FXSYS_memcpy(pDest, pStart, pEnd - pStart);
891 m_pData->Release(); 864 m_pData.Swap(pNewData);
892 m_pData = pNewData;
893 return nCount; 865 return nCount;
894 } 866 }
867
895 void CFX_ByteString::SetAt(FX_STRSIZE nIndex, FX_CHAR ch) { 868 void CFX_ByteString::SetAt(FX_STRSIZE nIndex, FX_CHAR ch) {
896 if (!m_pData) { 869 if (!m_pData) {
897 return; 870 return;
898 } 871 }
899 FXSYS_assert(nIndex >= 0); 872 FXSYS_assert(nIndex >= 0);
900 FXSYS_assert(nIndex < m_pData->m_nDataLength); 873 FXSYS_assert(nIndex < m_pData->m_nDataLength);
901 CopyBeforeWrite(); 874 CopyBeforeWrite();
902 m_pData->m_String[nIndex] = ch; 875 m_pData->m_String[nIndex] = ch;
903 } 876 }
877
904 CFX_WideString CFX_ByteString::UTF8Decode() const { 878 CFX_WideString CFX_ByteString::UTF8Decode() const {
905 CFX_UTF8Decoder decoder; 879 CFX_UTF8Decoder decoder;
906 for (FX_STRSIZE i = 0; i < GetLength(); i++) { 880 for (FX_STRSIZE i = 0; i < GetLength(); i++) {
907 decoder.Input((uint8_t)m_pData->m_String[i]); 881 decoder.Input((uint8_t)m_pData->m_String[i]);
908 } 882 }
909 return decoder.GetResult(); 883 return decoder.GetResult();
910 } 884 }
911 885
912 // static 886 // static
913 CFX_ByteString CFX_ByteString::FromUnicode(const FX_WCHAR* str, 887 CFX_ByteString CFX_ByteString::FromUnicode(const FX_WCHAR* str,
(...skipping 23 matching lines...) Expand all
937 } 911 }
938 } 912 }
939 if (this_len < that_len) { 913 if (this_len < that_len) {
940 return -1; 914 return -1;
941 } 915 }
942 if (this_len > that_len) { 916 if (this_len > that_len) {
943 return 1; 917 return 1;
944 } 918 }
945 return 0; 919 return 0;
946 } 920 }
947 void CFX_ByteString::TrimRight(const CFX_ByteStringC& lpszTargets) { 921 void CFX_ByteString::TrimRight(const CFX_ByteStringC& pTargets) {
948 if (!m_pData || lpszTargets.IsEmpty()) { 922 if (!m_pData || pTargets.IsEmpty()) {
949 return; 923 return;
950 } 924 }
951 CopyBeforeWrite(); 925 CopyBeforeWrite();
952 FX_STRSIZE pos = GetLength(); 926 FX_STRSIZE pos = GetLength();
953 if (pos < 1) { 927 if (pos < 1) {
954 return; 928 return;
955 } 929 }
956 while (pos) { 930 while (pos) {
957 FX_STRSIZE i = 0; 931 FX_STRSIZE i = 0;
958 while (i < lpszTargets.GetLength() && 932 while (i < pTargets.GetLength() &&
959 lpszTargets[i] != m_pData->m_String[pos - 1]) { 933 pTargets[i] != m_pData->m_String[pos - 1]) {
960 i++; 934 i++;
961 } 935 }
962 if (i == lpszTargets.GetLength()) { 936 if (i == pTargets.GetLength()) {
963 break; 937 break;
964 } 938 }
965 pos--; 939 pos--;
966 } 940 }
967 if (pos < m_pData->m_nDataLength) { 941 if (pos < m_pData->m_nDataLength) {
968 m_pData->m_String[pos] = 0; 942 m_pData->m_String[pos] = 0;
969 m_pData->m_nDataLength = pos; 943 m_pData->m_nDataLength = pos;
970 } 944 }
971 } 945 }
972 void CFX_ByteString::TrimRight(FX_CHAR chTarget) { 946 void CFX_ByteString::TrimRight(FX_CHAR chTarget) {
973 TrimRight(CFX_ByteStringC(chTarget)); 947 TrimRight(CFX_ByteStringC(chTarget));
974 } 948 }
975 void CFX_ByteString::TrimRight() { 949 void CFX_ByteString::TrimRight() {
976 TrimRight("\x09\x0a\x0b\x0c\x0d\x20"); 950 TrimRight("\x09\x0a\x0b\x0c\x0d\x20");
977 } 951 }
978 void CFX_ByteString::TrimLeft(const CFX_ByteStringC& lpszTargets) { 952 void CFX_ByteString::TrimLeft(const CFX_ByteStringC& pTargets) {
979 if (!m_pData) { 953 if (!m_pData) {
980 return; 954 return;
981 } 955 }
982 if (lpszTargets.IsEmpty()) { 956 if (pTargets.IsEmpty()) {
983 return; 957 return;
984 } 958 }
985 CopyBeforeWrite(); 959 CopyBeforeWrite();
986 FX_STRSIZE len = GetLength(); 960 FX_STRSIZE len = GetLength();
987 if (len < 1) { 961 if (len < 1) {
988 return; 962 return;
989 } 963 }
990 FX_STRSIZE pos = 0; 964 FX_STRSIZE pos = 0;
991 while (pos < len) { 965 while (pos < len) {
992 FX_STRSIZE i = 0; 966 FX_STRSIZE i = 0;
993 while (i < lpszTargets.GetLength() && 967 while (i < pTargets.GetLength() && pTargets[i] != m_pData->m_String[pos]) {
994 lpszTargets[i] != m_pData->m_String[pos]) {
995 i++; 968 i++;
996 } 969 }
997 if (i == lpszTargets.GetLength()) { 970 if (i == pTargets.GetLength()) {
998 break; 971 break;
999 } 972 }
1000 pos++; 973 pos++;
1001 } 974 }
1002 if (pos) { 975 if (pos) {
1003 FX_STRSIZE nDataLength = len - pos; 976 FX_STRSIZE nDataLength = len - pos;
1004 FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos, 977 FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos,
1005 (nDataLength + 1) * sizeof(FX_CHAR)); 978 (nDataLength + 1) * sizeof(FX_CHAR));
1006 m_pData->m_nDataLength = nDataLength; 979 m_pData->m_nDataLength = nDataLength;
1007 } 980 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 fraction %= scale; 1052 fraction %= scale;
1080 scale /= 10; 1053 scale /= 10;
1081 } 1054 }
1082 return buf_size; 1055 return buf_size;
1083 } 1056 }
1084 CFX_ByteString CFX_ByteString::FormatFloat(FX_FLOAT d, int precision) { 1057 CFX_ByteString CFX_ByteString::FormatFloat(FX_FLOAT d, int precision) {
1085 FX_CHAR buf[32]; 1058 FX_CHAR buf[32];
1086 FX_STRSIZE len = FX_ftoa(d, buf); 1059 FX_STRSIZE len = FX_ftoa(d, buf);
1087 return CFX_ByteString(buf, len); 1060 return CFX_ByteString(buf, len);
1088 } 1061 }
OLDNEW
« no previous file with comments | « no previous file | core/fxcrt/fx_basic_bstring_unittest.cpp » ('j') | core/fxcrt/include/fx_string.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698