OLD | NEW |
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> // For offsetof(). | 7 #include <stddef.h> // For offsetof(). |
8 | 8 |
9 #include "../../include/fxcrt/fx_basic.h" | 9 #include "../../include/fxcrt/fx_basic.h" |
10 #include "../../../third_party/base/numerics/safe_math.h" | 10 #include "../../../third_party/base/numerics/safe_math.h" |
11 | 11 |
12 static int _Buffer_itoa(char* buf, int i, FX_DWORD flags) | 12 static int _Buffer_itoa(char* buf, int i, FX_DWORD flags) { |
13 { | 13 if (i == 0) { |
14 if (i == 0) { | 14 buf[0] = '0'; |
15 buf[0] = '0'; | 15 return 1; |
16 return 1; | 16 } |
17 } | 17 char buf1[32]; |
18 char buf1[32]; | 18 int buf_pos = 31; |
19 int buf_pos = 31; | 19 FX_DWORD u = i; |
20 FX_DWORD u = i; | 20 if ((flags & FXFORMAT_SIGNED) && i < 0) { |
21 if ((flags & FXFORMAT_SIGNED) && i < 0) { | 21 u = -i; |
22 u = -i; | 22 } |
23 } | 23 int base = 10; |
24 int base = 10; | 24 const FX_CHAR* string = "0123456789abcdef"; |
25 const FX_CHAR* string = "0123456789abcdef"; | 25 if (flags & FXFORMAT_HEX) { |
26 if (flags & FXFORMAT_HEX) { | 26 base = 16; |
27 base = 16; | 27 if (flags & FXFORMAT_CAPITAL) { |
28 if (flags & FXFORMAT_CAPITAL) { | 28 string = "0123456789ABCDEF"; |
29 string = "0123456789ABCDEF"; | 29 } |
30 } | 30 } |
31 } | 31 while (u != 0) { |
32 while (u != 0) { | 32 buf1[buf_pos--] = string[u % base]; |
33 buf1[buf_pos--] = string[u % base]; | 33 u = u / base; |
34 u = u / base; | 34 } |
35 } | 35 if ((flags & FXFORMAT_SIGNED) && i < 0) { |
36 if ((flags & FXFORMAT_SIGNED) && i < 0) { | 36 buf1[buf_pos--] = '-'; |
37 buf1[buf_pos--] = '-'; | 37 } |
38 } | 38 int len = 31 - buf_pos; |
39 int len = 31 - buf_pos; | 39 for (int ii = 0; ii < len; ii++) { |
40 for (int ii = 0; ii < len; ii ++) { | 40 buf[ii] = buf1[ii + buf_pos + 1]; |
41 buf[ii] = buf1[ii + buf_pos + 1]; | 41 } |
42 } | 42 return len; |
43 return len; | 43 } |
44 } | 44 CFX_ByteString CFX_ByteString::FormatInteger(int i, FX_DWORD flags) { |
45 CFX_ByteString CFX_ByteString::FormatInteger(int i, FX_DWORD flags) | 45 char buf[32]; |
46 { | 46 return CFX_ByteStringC(buf, _Buffer_itoa(buf, i, flags)); |
47 char buf[32]; | |
48 return CFX_ByteStringC(buf, _Buffer_itoa(buf, i, flags)); | |
49 } | 47 } |
50 | 48 |
51 // static | 49 // static |
52 CFX_ByteString::StringData* CFX_ByteString::StringData::Create(int nLen) | 50 CFX_ByteString::StringData* CFX_ByteString::StringData::Create(int nLen) { |
53 { | 51 // |nLen| is currently declared as in |int|. TODO(palmer): It should be |
54 // |nLen| is currently declared as in |int|. TODO(palmer): It should be | 52 // a |size_t|, or at least unsigned. |
55 // a |size_t|, or at least unsigned. | 53 if (nLen == 0 || nLen < 0) { |
56 if (nLen == 0 || nLen < 0) { | 54 return NULL; |
57 return NULL; | 55 } |
58 } | |
59 | 56 |
60 // 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. |
61 // 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. |
62 int overhead = offsetof(StringData, m_String) + sizeof(FX_CHAR); | 59 int overhead = offsetof(StringData, m_String) + sizeof(FX_CHAR); |
63 pdfium::base::CheckedNumeric<int> nSize = nLen; | 60 pdfium::base::CheckedNumeric<int> nSize = nLen; |
64 nSize += overhead; | 61 nSize += overhead; |
65 | 62 |
66 // 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 |
67 // 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 |
68 // 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 |
69 // by using this otherwise wasted space. | 66 // by using this otherwise wasted space. |
70 nSize += 7; | 67 nSize += 7; |
71 int totalSize = nSize.ValueOrDie() & ~7; | 68 int totalSize = nSize.ValueOrDie() & ~7; |
72 int usableSize = totalSize - overhead; | 69 int usableSize = totalSize - overhead; |
73 FXSYS_assert(usableSize >= nLen); | 70 FXSYS_assert(usableSize >= nLen); |
74 | 71 |
75 void* pData = FX_Alloc(uint8_t, totalSize); | 72 void* pData = FX_Alloc(uint8_t, totalSize); |
76 return new (pData) StringData(nLen, usableSize); | 73 return new (pData) StringData(nLen, usableSize); |
77 } | 74 } |
78 CFX_ByteString::~CFX_ByteString() | 75 CFX_ByteString::~CFX_ByteString() { |
79 { | 76 if (m_pData) { |
| 77 m_pData->Release(); |
| 78 } |
| 79 } |
| 80 CFX_ByteString::CFX_ByteString(const FX_CHAR* lpsz, FX_STRSIZE nLen) { |
| 81 if (nLen < 0) { |
| 82 nLen = lpsz ? FXSYS_strlen(lpsz) : 0; |
| 83 } |
| 84 if (nLen) { |
| 85 m_pData = StringData::Create(nLen); |
80 if (m_pData) { | 86 if (m_pData) { |
81 m_pData->Release(); | 87 FXSYS_memcpy(m_pData->m_String, lpsz, nLen); |
82 } | 88 } |
83 } | 89 } else { |
84 CFX_ByteString::CFX_ByteString(const FX_CHAR* lpsz, FX_STRSIZE nLen) | 90 m_pData = NULL; |
85 { | 91 } |
86 if (nLen < 0) { | 92 } |
87 nLen = lpsz ? FXSYS_strlen(lpsz) : 0; | 93 CFX_ByteString::CFX_ByteString(const uint8_t* lpsz, FX_STRSIZE nLen) { |
88 } | 94 if (nLen > 0) { |
89 if (nLen) { | 95 m_pData = StringData::Create(nLen); |
90 m_pData = StringData::Create(nLen); | |
91 if (m_pData) { | |
92 FXSYS_memcpy(m_pData->m_String, lpsz, nLen); | |
93 } | |
94 } else { | |
95 m_pData = NULL; | |
96 } | |
97 } | |
98 CFX_ByteString::CFX_ByteString(const uint8_t* lpsz, FX_STRSIZE nLen) | |
99 { | |
100 if (nLen > 0) { | |
101 m_pData = StringData::Create(nLen); | |
102 if (m_pData) { | |
103 FXSYS_memcpy(m_pData->m_String, lpsz, nLen); | |
104 } | |
105 } else { | |
106 m_pData = NULL; | |
107 } | |
108 } | |
109 CFX_ByteString::CFX_ByteString(char ch) | |
110 { | |
111 m_pData = StringData::Create(1); | |
112 if (m_pData) { | 96 if (m_pData) { |
113 m_pData->m_String[0] = ch; | 97 FXSYS_memcpy(m_pData->m_String, lpsz, nLen); |
114 } | 98 } |
115 } | 99 } else { |
116 CFX_ByteString::CFX_ByteString(const CFX_ByteString& stringSrc) | 100 m_pData = NULL; |
117 { | 101 } |
118 if (stringSrc.m_pData == NULL) { | 102 } |
119 m_pData = NULL; | 103 CFX_ByteString::CFX_ByteString(char ch) { |
120 return; | 104 m_pData = StringData::Create(1); |
121 } | 105 if (m_pData) { |
122 if (stringSrc.m_pData->m_nRefs >= 0) { | 106 m_pData->m_String[0] = ch; |
123 m_pData = stringSrc.m_pData; | 107 } |
124 m_pData->Retain(); | 108 } |
125 } else { | 109 CFX_ByteString::CFX_ByteString(const CFX_ByteString& stringSrc) { |
126 m_pData = NULL; | 110 if (stringSrc.m_pData == NULL) { |
127 *this = stringSrc; | 111 m_pData = NULL; |
128 } | 112 return; |
129 } | 113 } |
130 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& stringSrc) | 114 if (stringSrc.m_pData->m_nRefs >= 0) { |
131 { | 115 m_pData = stringSrc.m_pData; |
132 if (stringSrc.IsEmpty()) { | 116 m_pData->Retain(); |
133 m_pData = NULL; | 117 } else { |
134 return; | |
135 } | |
136 m_pData = NULL; | 118 m_pData = NULL; |
137 *this = stringSrc; | 119 *this = stringSrc; |
138 } | 120 } |
139 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& str1, const CFX_ByteString
C& str2) | 121 } |
140 { | 122 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& stringSrc) { |
| 123 if (stringSrc.IsEmpty()) { |
141 m_pData = NULL; | 124 m_pData = NULL; |
142 int nNewLen = str1.GetLength() + str2.GetLength(); | 125 return; |
143 if (nNewLen == 0) { | 126 } |
144 return; | 127 m_pData = NULL; |
145 } | 128 *this = stringSrc; |
146 m_pData = StringData::Create(nNewLen); | 129 } |
| 130 CFX_ByteString::CFX_ByteString(const CFX_ByteStringC& str1, |
| 131 const CFX_ByteStringC& str2) { |
| 132 m_pData = NULL; |
| 133 int nNewLen = str1.GetLength() + str2.GetLength(); |
| 134 if (nNewLen == 0) { |
| 135 return; |
| 136 } |
| 137 m_pData = StringData::Create(nNewLen); |
| 138 if (m_pData) { |
| 139 FXSYS_memcpy(m_pData->m_String, str1.GetCStr(), str1.GetLength()); |
| 140 FXSYS_memcpy(m_pData->m_String + str1.GetLength(), str2.GetCStr(), |
| 141 str2.GetLength()); |
| 142 } |
| 143 } |
| 144 const CFX_ByteString& CFX_ByteString::operator=(const FX_CHAR* lpsz) { |
| 145 if (lpsz == NULL || lpsz[0] == 0) { |
| 146 Empty(); |
| 147 } else { |
| 148 AssignCopy(FXSYS_strlen(lpsz), lpsz); |
| 149 } |
| 150 return *this; |
| 151 } |
| 152 const CFX_ByteString& CFX_ByteString::operator=(const CFX_ByteStringC& str) { |
| 153 if (str.IsEmpty()) { |
| 154 Empty(); |
| 155 } else { |
| 156 AssignCopy(str.GetLength(), str.GetCStr()); |
| 157 } |
| 158 return *this; |
| 159 } |
| 160 const CFX_ByteString& CFX_ByteString::operator=( |
| 161 const CFX_ByteString& stringSrc) { |
| 162 if (m_pData == stringSrc.m_pData) { |
| 163 return *this; |
| 164 } |
| 165 if (stringSrc.IsEmpty()) { |
| 166 Empty(); |
| 167 } else if ((m_pData && m_pData->m_nRefs < 0) || |
| 168 (stringSrc.m_pData && stringSrc.m_pData->m_nRefs < 0)) { |
| 169 AssignCopy(stringSrc.m_pData->m_nDataLength, stringSrc.m_pData->m_String); |
| 170 } else { |
| 171 Empty(); |
| 172 m_pData = stringSrc.m_pData; |
147 if (m_pData) { | 173 if (m_pData) { |
148 FXSYS_memcpy(m_pData->m_String, str1.GetCStr(), str1.GetLength()); | 174 m_pData->Retain(); |
149 FXSYS_memcpy(m_pData->m_String + str1.GetLength(), str2.GetCStr(), str2.
GetLength()); | 175 } |
150 } | 176 } |
151 } | 177 return *this; |
152 const CFX_ByteString& CFX_ByteString::operator=(const FX_CHAR* lpsz) | 178 } |
153 { | 179 const CFX_ByteString& CFX_ByteString::operator=(const CFX_BinaryBuf& buf) { |
154 if (lpsz == NULL || lpsz[0] == 0) { | 180 Load(buf.GetBuffer(), buf.GetSize()); |
155 Empty(); | 181 return *this; |
156 } else { | 182 } |
157 AssignCopy(FXSYS_strlen(lpsz), lpsz); | 183 void CFX_ByteString::Load(const uint8_t* buf, FX_STRSIZE len) { |
158 } | 184 Empty(); |
| 185 if (len) { |
| 186 m_pData = StringData::Create(len); |
| 187 if (m_pData) { |
| 188 FXSYS_memcpy(m_pData->m_String, buf, len); |
| 189 } |
| 190 } else { |
| 191 m_pData = NULL; |
| 192 } |
| 193 } |
| 194 const CFX_ByteString& CFX_ByteString::operator+=(const FX_CHAR* lpsz) { |
| 195 if (lpsz) { |
| 196 ConcatInPlace(FXSYS_strlen(lpsz), lpsz); |
| 197 } |
| 198 return *this; |
| 199 } |
| 200 const CFX_ByteString& CFX_ByteString::operator+=(char ch) { |
| 201 ConcatInPlace(1, &ch); |
| 202 return *this; |
| 203 } |
| 204 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteString& string) { |
| 205 if (string.m_pData == NULL) { |
159 return *this; | 206 return *this; |
160 } | 207 } |
161 const CFX_ByteString& CFX_ByteString::operator=(const CFX_ByteStringC& str) | 208 ConcatInPlace(string.m_pData->m_nDataLength, string.m_pData->m_String); |
162 { | 209 return *this; |
163 if (str.IsEmpty()) { | 210 } |
164 Empty(); | 211 const CFX_ByteString& CFX_ByteString::operator+=( |
165 } else { | 212 const CFX_ByteStringC& string) { |
166 AssignCopy(str.GetLength(), str.GetCStr()); | 213 if (string.IsEmpty()) { |
167 } | |
168 return *this; | 214 return *this; |
169 } | 215 } |
170 const CFX_ByteString& CFX_ByteString::operator=(const CFX_ByteString& stringSrc) | 216 ConcatInPlace(string.GetLength(), string.GetCStr()); |
171 { | 217 return *this; |
172 if (m_pData == stringSrc.m_pData) { | 218 } |
173 return *this; | 219 bool CFX_ByteString::Equal(const char* ptr) const { |
174 } | 220 if (!m_pData) { |
175 if (stringSrc.IsEmpty()) { | 221 return !ptr || ptr[0] == '\0'; |
176 Empty(); | 222 } |
177 } else if ((m_pData && m_pData->m_nRefs < 0) || | 223 if (!ptr) { |
178 (stringSrc.m_pData && stringSrc.m_pData->m_nRefs < 0)) { | 224 return m_pData->m_nDataLength == 0; |
179 AssignCopy(stringSrc.m_pData->m_nDataLength, stringSrc.m_pData->m_String
); | 225 } |
180 } else { | 226 return FXSYS_strlen(ptr) == m_pData->m_nDataLength && |
181 Empty(); | 227 FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; |
182 m_pData = stringSrc.m_pData; | 228 } |
183 if (m_pData) { | 229 bool CFX_ByteString::Equal(const CFX_ByteStringC& str) const { |
184 m_pData->Retain(); | 230 if (m_pData == NULL) { |
185 } | 231 return str.IsEmpty(); |
186 } | 232 } |
187 return *this; | 233 return m_pData->m_nDataLength == str.GetLength() && |
188 } | 234 FXSYS_memcmp(m_pData->m_String, str.GetCStr(), str.GetLength()) == 0; |
189 const CFX_ByteString& CFX_ByteString::operator=(const CFX_BinaryBuf& buf) | 235 } |
190 { | 236 bool CFX_ByteString::Equal(const CFX_ByteString& other) const { |
191 Load(buf.GetBuffer(), buf.GetSize()); | 237 if (IsEmpty()) { |
192 return *this; | 238 return other.IsEmpty(); |
193 } | 239 } |
194 void CFX_ByteString::Load(const uint8_t* buf, FX_STRSIZE len) | 240 if (other.IsEmpty()) { |
195 { | 241 return false; |
| 242 } |
| 243 return other.m_pData->m_nDataLength == m_pData->m_nDataLength && |
| 244 FXSYS_memcmp(other.m_pData->m_String, m_pData->m_String, |
| 245 m_pData->m_nDataLength) == 0; |
| 246 } |
| 247 void CFX_ByteString::Empty() { |
| 248 if (m_pData) { |
| 249 m_pData->Release(); |
| 250 m_pData = NULL; |
| 251 } |
| 252 } |
| 253 bool CFX_ByteString::EqualNoCase(const CFX_ByteStringC& str) const { |
| 254 if (m_pData == NULL) { |
| 255 return str.IsEmpty(); |
| 256 } |
| 257 FX_STRSIZE len = str.GetLength(); |
| 258 if (m_pData->m_nDataLength != len) { |
| 259 return false; |
| 260 } |
| 261 const uint8_t* pThis = (const uint8_t*)m_pData->m_String; |
| 262 const uint8_t* pThat = str.GetPtr(); |
| 263 for (FX_STRSIZE i = 0; i < len; i++) { |
| 264 if ((*pThis) != (*pThat)) { |
| 265 uint8_t bThis = *pThis; |
| 266 if (bThis >= 'A' && bThis <= 'Z') { |
| 267 bThis += 'a' - 'A'; |
| 268 } |
| 269 uint8_t bThat = *pThat; |
| 270 if (bThat >= 'A' && bThat <= 'Z') { |
| 271 bThat += 'a' - 'A'; |
| 272 } |
| 273 if (bThis != bThat) { |
| 274 return false; |
| 275 } |
| 276 } |
| 277 pThis++; |
| 278 pThat++; |
| 279 } |
| 280 return true; |
| 281 } |
| 282 void CFX_ByteString::AssignCopy(FX_STRSIZE nSrcLen, |
| 283 const FX_CHAR* lpszSrcData) { |
| 284 AllocBeforeWrite(nSrcLen); |
| 285 FXSYS_memcpy(m_pData->m_String, lpszSrcData, nSrcLen); |
| 286 m_pData->m_nDataLength = nSrcLen; |
| 287 m_pData->m_String[nSrcLen] = 0; |
| 288 } |
| 289 void CFX_ByteString::CopyBeforeWrite() { |
| 290 if (m_pData == NULL || m_pData->m_nRefs <= 1) { |
| 291 return; |
| 292 } |
| 293 StringData* pData = m_pData; |
| 294 m_pData->Release(); |
| 295 FX_STRSIZE nDataLength = pData->m_nDataLength; |
| 296 m_pData = StringData::Create(nDataLength); |
| 297 if (m_pData != NULL) { |
| 298 FXSYS_memcpy(m_pData->m_String, pData->m_String, nDataLength + 1); |
| 299 } |
| 300 } |
| 301 void CFX_ByteString::AllocBeforeWrite(FX_STRSIZE nLen) { |
| 302 if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nLen) { |
| 303 return; |
| 304 } |
| 305 Empty(); |
| 306 m_pData = StringData::Create(nLen); |
| 307 } |
| 308 void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) { |
| 309 if (m_pData == NULL) { |
| 310 return; |
| 311 } |
| 312 CopyBeforeWrite(); |
| 313 if (nNewLength == -1) { |
| 314 nNewLength = FXSYS_strlen((const FX_CHAR*)m_pData->m_String); |
| 315 } |
| 316 if (nNewLength == 0) { |
196 Empty(); | 317 Empty(); |
197 if (len) { | 318 return; |
198 m_pData = StringData::Create(len); | 319 } |
199 if (m_pData) { | 320 FXSYS_assert(nNewLength <= m_pData->m_nAllocLength); |
200 FXSYS_memcpy(m_pData->m_String, buf, len); | 321 m_pData->m_nDataLength = nNewLength; |
201 } | 322 m_pData->m_String[nNewLength] = 0; |
202 } else { | 323 } |
203 m_pData = NULL; | 324 void CFX_ByteString::Reserve(FX_STRSIZE len) { |
204 } | 325 GetBuffer(len); |
205 } | 326 ReleaseBuffer(GetLength()); |
206 const CFX_ByteString& CFX_ByteString::operator+=(const FX_CHAR* lpsz) | 327 } |
207 { | 328 FX_CHAR* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) { |
208 if (lpsz) { | 329 if (m_pData == NULL && nMinBufLength == 0) { |
209 ConcatInPlace(FXSYS_strlen(lpsz), lpsz); | 330 return NULL; |
210 } | 331 } |
211 return *this; | 332 if (m_pData && m_pData->m_nRefs <= 1 && |
212 } | 333 m_pData->m_nAllocLength >= nMinBufLength) { |
213 const CFX_ByteString& CFX_ByteString::operator+=(char ch) | 334 return m_pData->m_String; |
214 { | 335 } |
215 ConcatInPlace(1, &ch); | 336 if (m_pData == NULL) { |
216 return *this; | |
217 } | |
218 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteString& string) | |
219 { | |
220 if (string.m_pData == NULL) { | |
221 return *this; | |
222 } | |
223 ConcatInPlace(string.m_pData->m_nDataLength, string.m_pData->m_String); | |
224 return *this; | |
225 } | |
226 const CFX_ByteString& CFX_ByteString::operator+=(const CFX_ByteStringC& string) | |
227 { | |
228 if (string.IsEmpty()) { | |
229 return *this; | |
230 } | |
231 ConcatInPlace(string.GetLength(), string.GetCStr()); | |
232 return *this; | |
233 } | |
234 bool CFX_ByteString::Equal(const char* ptr) const | |
235 { | |
236 if (!m_pData) { | |
237 return !ptr || ptr[0] == '\0'; | |
238 } | |
239 if (!ptr) { | |
240 return m_pData->m_nDataLength == 0; | |
241 } | |
242 return FXSYS_strlen(ptr) == m_pData->m_nDataLength && | |
243 FXSYS_memcmp(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0; | |
244 } | |
245 bool CFX_ByteString::Equal(const CFX_ByteStringC& str) const | |
246 { | |
247 if (m_pData == NULL) { | |
248 return str.IsEmpty(); | |
249 } | |
250 return m_pData->m_nDataLength == str.GetLength() && | |
251 FXSYS_memcmp(m_pData->m_String, str.GetCStr(), str.GetLength()) == 0; | |
252 } | |
253 bool CFX_ByteString::Equal(const CFX_ByteString& other) const | |
254 { | |
255 if (IsEmpty()) { | |
256 return other.IsEmpty(); | |
257 } | |
258 if (other.IsEmpty()) { | |
259 return false; | |
260 } | |
261 return other.m_pData->m_nDataLength == m_pData->m_nDataLength && | |
262 FXSYS_memcmp(other.m_pData->m_String, | |
263 m_pData->m_String, | |
264 m_pData->m_nDataLength) == 0; | |
265 } | |
266 void CFX_ByteString::Empty() | |
267 { | |
268 if (m_pData) { | |
269 m_pData->Release(); | |
270 m_pData = NULL; | |
271 } | |
272 } | |
273 bool CFX_ByteString::EqualNoCase(const CFX_ByteStringC& str) const | |
274 { | |
275 if (m_pData == NULL) { | |
276 return str.IsEmpty(); | |
277 } | |
278 FX_STRSIZE len = str.GetLength(); | |
279 if (m_pData->m_nDataLength != len) { | |
280 return false; | |
281 } | |
282 const uint8_t* pThis = (const uint8_t*)m_pData->m_String; | |
283 const uint8_t* pThat = str.GetPtr(); | |
284 for (FX_STRSIZE i = 0; i < len; i ++) { | |
285 if ((*pThis) != (*pThat)) { | |
286 uint8_t bThis = *pThis; | |
287 if (bThis >= 'A' && bThis <= 'Z') { | |
288 bThis += 'a' - 'A'; | |
289 } | |
290 uint8_t bThat = *pThat; | |
291 if (bThat >= 'A' && bThat <= 'Z') { | |
292 bThat += 'a' - 'A'; | |
293 } | |
294 if (bThis != bThat) { | |
295 return false; | |
296 } | |
297 } | |
298 pThis ++; | |
299 pThat ++; | |
300 } | |
301 return true; | |
302 } | |
303 void CFX_ByteString::AssignCopy(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData) | |
304 { | |
305 AllocBeforeWrite(nSrcLen); | |
306 FXSYS_memcpy(m_pData->m_String, lpszSrcData, nSrcLen); | |
307 m_pData->m_nDataLength = nSrcLen; | |
308 m_pData->m_String[nSrcLen] = 0; | |
309 } | |
310 void CFX_ByteString::CopyBeforeWrite() | |
311 { | |
312 if (m_pData == NULL || m_pData->m_nRefs <= 1) { | |
313 return; | |
314 } | |
315 StringData* pData = m_pData; | |
316 m_pData->Release(); | |
317 FX_STRSIZE nDataLength = pData->m_nDataLength; | |
318 m_pData = StringData::Create(nDataLength); | |
319 if (m_pData != NULL) { | |
320 FXSYS_memcpy(m_pData->m_String, pData->m_String, nDataLength + 1); | |
321 } | |
322 } | |
323 void CFX_ByteString::AllocBeforeWrite(FX_STRSIZE nLen) | |
324 { | |
325 if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nLen) { | |
326 return; | |
327 } | |
328 Empty(); | |
329 m_pData = StringData::Create(nLen); | |
330 } | |
331 void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength) | |
332 { | |
333 if (m_pData == NULL) { | |
334 return; | |
335 } | |
336 CopyBeforeWrite(); | |
337 if (nNewLength == -1) { | |
338 nNewLength = FXSYS_strlen((const FX_CHAR*)m_pData->m_String); | |
339 } | |
340 if (nNewLength == 0) { | |
341 Empty(); | |
342 return; | |
343 } | |
344 FXSYS_assert(nNewLength <= m_pData->m_nAllocLength); | |
345 m_pData->m_nDataLength = nNewLength; | |
346 m_pData->m_String[nNewLength] = 0; | |
347 } | |
348 void CFX_ByteString::Reserve(FX_STRSIZE len) | |
349 { | |
350 GetBuffer(len); | |
351 ReleaseBuffer(GetLength()); | |
352 } | |
353 FX_CHAR* CFX_ByteString::GetBuffer(FX_STRSIZE nMinBufLength) | |
354 { | |
355 if (m_pData == NULL && nMinBufLength == 0) { | |
356 return NULL; | |
357 } | |
358 if (m_pData && m_pData->m_nRefs <= 1 && m_pData->m_nAllocLength >= nMinBufLe
ngth) { | |
359 return m_pData->m_String; | |
360 } | |
361 if (m_pData == NULL) { | |
362 m_pData = StringData::Create(nMinBufLength); | |
363 if (!m_pData) { | |
364 return NULL; | |
365 } | |
366 m_pData->m_nDataLength = 0; | |
367 m_pData->m_String[0] = 0; | |
368 return m_pData->m_String; | |
369 } | |
370 StringData* pOldData = m_pData; | |
371 FX_STRSIZE nOldLen = pOldData->m_nDataLength; | |
372 if (nMinBufLength < nOldLen) { | |
373 nMinBufLength = nOldLen; | |
374 } | |
375 m_pData = StringData::Create(nMinBufLength); | 337 m_pData = StringData::Create(nMinBufLength); |
376 if (!m_pData) { | 338 if (!m_pData) { |
377 return NULL; | 339 return NULL; |
378 } | 340 } |
379 FXSYS_memcpy(m_pData->m_String, pOldData->m_String, (nOldLen + 1)); | 341 m_pData->m_nDataLength = 0; |
380 m_pData->m_nDataLength = nOldLen; | 342 m_pData->m_String[0] = 0; |
381 pOldData->Release(); | |
382 return m_pData->m_String; | 343 return m_pData->m_String; |
383 } | 344 } |
384 FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) | 345 StringData* pOldData = m_pData; |
385 { | 346 FX_STRSIZE nOldLen = pOldData->m_nDataLength; |
386 if (m_pData == NULL) { | 347 if (nMinBufLength < nOldLen) { |
387 return 0; | 348 nMinBufLength = nOldLen; |
388 } | 349 } |
389 if (nIndex < 0) { | 350 m_pData = StringData::Create(nMinBufLength); |
390 nIndex = 0; | 351 if (!m_pData) { |
391 } | 352 return NULL; |
392 FX_STRSIZE nOldLength = m_pData->m_nDataLength; | 353 } |
393 if (nCount > 0 && nIndex < nOldLength) { | 354 FXSYS_memcpy(m_pData->m_String, pOldData->m_String, (nOldLen + 1)); |
394 FX_STRSIZE mLength = nIndex + nCount; | 355 m_pData->m_nDataLength = nOldLen; |
395 if (mLength >= nOldLength) { | 356 pOldData->Release(); |
396 m_pData->m_nDataLength = nIndex; | 357 return m_pData->m_String; |
397 return m_pData->m_nDataLength; | 358 } |
| 359 FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount) { |
| 360 if (m_pData == NULL) { |
| 361 return 0; |
| 362 } |
| 363 if (nIndex < 0) { |
| 364 nIndex = 0; |
| 365 } |
| 366 FX_STRSIZE nOldLength = m_pData->m_nDataLength; |
| 367 if (nCount > 0 && nIndex < nOldLength) { |
| 368 FX_STRSIZE mLength = nIndex + nCount; |
| 369 if (mLength >= nOldLength) { |
| 370 m_pData->m_nDataLength = nIndex; |
| 371 return m_pData->m_nDataLength; |
| 372 } |
| 373 CopyBeforeWrite(); |
| 374 int nBytesToCopy = nOldLength - mLength + 1; |
| 375 FXSYS_memmove(m_pData->m_String + nIndex, m_pData->m_String + mLength, |
| 376 nBytesToCopy); |
| 377 m_pData->m_nDataLength = nOldLength - nCount; |
| 378 } |
| 379 return m_pData->m_nDataLength; |
| 380 } |
| 381 void CFX_ByteString::ConcatInPlace(FX_STRSIZE nSrcLen, |
| 382 const FX_CHAR* lpszSrcData) { |
| 383 if (nSrcLen == 0 || lpszSrcData == NULL) { |
| 384 return; |
| 385 } |
| 386 if (m_pData == NULL) { |
| 387 m_pData = StringData::Create(nSrcLen); |
| 388 if (!m_pData) { |
| 389 return; |
| 390 } |
| 391 FXSYS_memcpy(m_pData->m_String, lpszSrcData, nSrcLen); |
| 392 return; |
| 393 } |
| 394 if (m_pData->m_nRefs > 1 || |
| 395 m_pData->m_nDataLength + nSrcLen > m_pData->m_nAllocLength) { |
| 396 ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcData); |
| 397 } else { |
| 398 FXSYS_memcpy(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, |
| 399 nSrcLen); |
| 400 m_pData->m_nDataLength += nSrcLen; |
| 401 m_pData->m_String[m_pData->m_nDataLength] = 0; |
| 402 } |
| 403 } |
| 404 void CFX_ByteString::ConcatCopy(FX_STRSIZE nSrc1Len, |
| 405 const FX_CHAR* lpszSrc1Data, |
| 406 FX_STRSIZE nSrc2Len, |
| 407 const FX_CHAR* lpszSrc2Data) { |
| 408 int nNewLen = nSrc1Len + nSrc2Len; |
| 409 if (nNewLen <= 0) { |
| 410 return; |
| 411 } |
| 412 // Don't release until done copying, might be one of the arguments. |
| 413 StringData* pOldData = m_pData; |
| 414 m_pData = StringData::Create(nNewLen); |
| 415 if (m_pData) { |
| 416 memcpy(m_pData->m_String, lpszSrc1Data, nSrc1Len); |
| 417 memcpy(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len); |
| 418 } |
| 419 pOldData->Release(); |
| 420 } |
| 421 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst) const { |
| 422 if (m_pData == NULL) { |
| 423 return CFX_ByteString(); |
| 424 } |
| 425 return Mid(nFirst, m_pData->m_nDataLength - nFirst); |
| 426 } |
| 427 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const { |
| 428 if (nFirst < 0) { |
| 429 nFirst = 0; |
| 430 } |
| 431 if (nCount < 0) { |
| 432 nCount = 0; |
| 433 } |
| 434 if (nFirst + nCount > m_pData->m_nDataLength) { |
| 435 nCount = m_pData->m_nDataLength - nFirst; |
| 436 } |
| 437 if (nFirst > m_pData->m_nDataLength) { |
| 438 nCount = 0; |
| 439 } |
| 440 if (nFirst == 0 && nFirst + nCount == m_pData->m_nDataLength) { |
| 441 return *this; |
| 442 } |
| 443 CFX_ByteString dest; |
| 444 AllocCopy(dest, nCount, nFirst); |
| 445 return dest; |
| 446 } |
| 447 void CFX_ByteString::AllocCopy(CFX_ByteString& dest, |
| 448 FX_STRSIZE nCopyLen, |
| 449 FX_STRSIZE nCopyIndex) const { |
| 450 // |FX_STRSIZE| is currently typedef'd as in |int|. TODO(palmer): It |
| 451 // should be a |size_t|, or at least unsigned. |
| 452 if (nCopyLen == 0 || nCopyLen < 0) { |
| 453 return; |
| 454 } |
| 455 ASSERT(dest.m_pData == NULL); |
| 456 dest.m_pData = StringData::Create(nCopyLen); |
| 457 if (dest.m_pData) { |
| 458 FXSYS_memcpy(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, |
| 459 nCopyLen); |
| 460 } |
| 461 } |
| 462 #define FORCE_ANSI 0x10000 |
| 463 #define FORCE_UNICODE 0x20000 |
| 464 #define FORCE_INT64 0x40000 |
| 465 void CFX_ByteString::FormatV(const FX_CHAR* lpszFormat, va_list argList) { |
| 466 va_list argListSave; |
| 467 #if defined(__ARMCC_VERSION) || \ |
| 468 (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ || _FX_CPU_ == _FX_IA64_ || \ |
| 469 _FX_CPU_ == _FX_ARM64_)) || \ |
| 470 defined(__native_client__) |
| 471 va_copy(argListSave, argList); |
| 472 #else |
| 473 argListSave = argList; |
| 474 #endif |
| 475 int nMaxLen = 0; |
| 476 for (const FX_CHAR* lpsz = lpszFormat; *lpsz != 0; lpsz++) { |
| 477 if (*lpsz != '%' || *(lpsz = lpsz + 1) == '%') { |
| 478 nMaxLen += FXSYS_strlen(lpsz); |
| 479 continue; |
| 480 } |
| 481 int nItemLen = 0; |
| 482 int nWidth = 0; |
| 483 for (; *lpsz != 0; lpsz++) { |
| 484 if (*lpsz == '#') { |
| 485 nMaxLen += 2; |
| 486 } else if (*lpsz == '*') { |
| 487 nWidth = va_arg(argList, int); |
| 488 } else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' || *lpsz == ' ') |
| 489 ; |
| 490 else { |
| 491 break; |
| 492 } |
| 493 } |
| 494 if (nWidth == 0) { |
| 495 nWidth = FXSYS_atoi(lpsz); |
| 496 for (; (*lpsz) >= '0' && (*lpsz) <= '9'; lpsz++) |
| 497 ; |
| 498 } |
| 499 if (nWidth < 0 || nWidth > 128 * 1024) { |
| 500 lpszFormat = "Bad width"; |
| 501 nMaxLen = 10; |
| 502 break; |
| 503 } |
| 504 int nPrecision = 0; |
| 505 if (*lpsz == '.') { |
| 506 lpsz++; |
| 507 if (*lpsz == '*') { |
| 508 nPrecision = va_arg(argList, int); |
| 509 lpsz++; |
| 510 } else { |
| 511 nPrecision = FXSYS_atoi(lpsz); |
| 512 for (; (*lpsz) >= '0' && (*lpsz) <= '9'; lpsz++) |
| 513 ; |
| 514 } |
| 515 } |
| 516 if (nPrecision < 0 || nPrecision > 128 * 1024) { |
| 517 lpszFormat = "Bad precision"; |
| 518 nMaxLen = 14; |
| 519 break; |
| 520 } |
| 521 int nModifier = 0; |
| 522 if (FXSYS_strncmp(lpsz, "I64", 3) == 0) { |
| 523 lpsz += 3; |
| 524 nModifier = FORCE_INT64; |
| 525 } else { |
| 526 switch (*lpsz) { |
| 527 case 'h': |
| 528 nModifier = FORCE_ANSI; |
| 529 lpsz++; |
| 530 break; |
| 531 case 'l': |
| 532 nModifier = FORCE_UNICODE; |
| 533 lpsz++; |
| 534 break; |
| 535 case 'F': |
| 536 case 'N': |
| 537 case 'L': |
| 538 lpsz++; |
| 539 break; |
| 540 } |
| 541 } |
| 542 switch (*lpsz | nModifier) { |
| 543 case 'c': |
| 544 case 'C': |
| 545 nItemLen = 2; |
| 546 va_arg(argList, int); |
| 547 break; |
| 548 case 'c' | FORCE_ANSI: |
| 549 case 'C' | FORCE_ANSI: |
| 550 nItemLen = 2; |
| 551 va_arg(argList, int); |
| 552 break; |
| 553 case 'c' | FORCE_UNICODE: |
| 554 case 'C' | FORCE_UNICODE: |
| 555 nItemLen = 2; |
| 556 va_arg(argList, int); |
| 557 break; |
| 558 case 's': { |
| 559 const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*); |
| 560 if (pstrNextArg == NULL) { |
| 561 nItemLen = 6; |
| 562 } else { |
| 563 nItemLen = FXSYS_strlen(pstrNextArg); |
| 564 if (nItemLen < 1) { |
| 565 nItemLen = 1; |
| 566 } |
398 } | 567 } |
399 CopyBeforeWrite(); | 568 } break; |
400 int nBytesToCopy = nOldLength - mLength + 1; | 569 case 'S': { |
401 FXSYS_memmove(m_pData->m_String + nIndex, | 570 FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); |
402 m_pData->m_String + mLength, nBytesToCopy); | 571 if (pstrNextArg == NULL) { |
403 m_pData->m_nDataLength = nOldLength - nCount; | 572 nItemLen = 6; |
404 } | 573 } else { |
405 return m_pData->m_nDataLength; | 574 nItemLen = FXSYS_wcslen(pstrNextArg); |
406 } | 575 if (nItemLen < 1) { |
407 void CFX_ByteString::ConcatInPlace(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcDat
a) | 576 nItemLen = 1; |
408 { | 577 } |
409 if (nSrcLen == 0 || lpszSrcData == NULL) { | |
410 return; | |
411 } | |
412 if (m_pData == NULL) { | |
413 m_pData = StringData::Create(nSrcLen); | |
414 if (!m_pData) { | |
415 return; | |
416 } | 578 } |
417 FXSYS_memcpy(m_pData->m_String, lpszSrcData, nSrcLen); | 579 } break; |
418 return; | 580 case 's' | FORCE_ANSI: |
419 } | 581 case 'S' | FORCE_ANSI: { |
420 if (m_pData->m_nRefs > 1 || m_pData->m_nDataLength + nSrcLen > m_pData->m_nA
llocLength) { | 582 const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*); |
421 ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcDa
ta); | 583 if (pstrNextArg == NULL) { |
| 584 nItemLen = 6; |
| 585 } else { |
| 586 nItemLen = FXSYS_strlen(pstrNextArg); |
| 587 if (nItemLen < 1) { |
| 588 nItemLen = 1; |
| 589 } |
| 590 } |
| 591 } break; |
| 592 case 's' | FORCE_UNICODE: |
| 593 case 'S' | FORCE_UNICODE: { |
| 594 FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); |
| 595 if (pstrNextArg == NULL) { |
| 596 nItemLen = 6; |
| 597 } else { |
| 598 nItemLen = FXSYS_wcslen(pstrNextArg); |
| 599 if (nItemLen < 1) { |
| 600 nItemLen = 1; |
| 601 } |
| 602 } |
| 603 } break; |
| 604 } |
| 605 if (nItemLen != 0) { |
| 606 if (nPrecision != 0 && nItemLen > nPrecision) { |
| 607 nItemLen = nPrecision; |
| 608 } |
| 609 if (nItemLen < nWidth) { |
| 610 nItemLen = nWidth; |
| 611 } |
422 } else { | 612 } else { |
423 FXSYS_memcpy(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, nS
rcLen); | 613 switch (*lpsz) { |
424 m_pData->m_nDataLength += nSrcLen; | 614 case 'd': |
425 m_pData->m_String[m_pData->m_nDataLength] = 0; | 615 case 'i': |
426 } | 616 case 'u': |
427 } | 617 case 'x': |
428 void CFX_ByteString::ConcatCopy(FX_STRSIZE nSrc1Len, const FX_CHAR* lpszSrc1Data
, | 618 case 'X': |
429 FX_STRSIZE nSrc2Len, const FX_CHAR* lpszSrc2Data
) | 619 case 'o': |
430 { | 620 if (nModifier & FORCE_INT64) { |
431 int nNewLen = nSrc1Len + nSrc2Len; | 621 va_arg(argList, int64_t); |
432 if (nNewLen <= 0) { | 622 } else { |
433 return; | 623 va_arg(argList, int); |
434 } | 624 } |
435 // Don't release until done copying, might be one of the arguments. | 625 nItemLen = 32; |
| 626 if (nItemLen < nWidth + nPrecision) { |
| 627 nItemLen = nWidth + nPrecision; |
| 628 } |
| 629 break; |
| 630 case 'a': |
| 631 case 'A': |
| 632 case 'e': |
| 633 case 'E': |
| 634 case 'g': |
| 635 case 'G': |
| 636 va_arg(argList, double); |
| 637 nItemLen = 128; |
| 638 if (nItemLen < nWidth + nPrecision) { |
| 639 nItemLen = nWidth + nPrecision; |
| 640 } |
| 641 break; |
| 642 case 'f': |
| 643 if (nWidth + nPrecision > 100) { |
| 644 nItemLen = nPrecision + nWidth + 128; |
| 645 } else { |
| 646 char pszTemp[256]; |
| 647 double f = va_arg(argList, double); |
| 648 memset(pszTemp, 0, sizeof(pszTemp)); |
| 649 FXSYS_snprintf(pszTemp, sizeof(pszTemp) - 1, "%*.*f", nWidth, |
| 650 nPrecision + 6, f); |
| 651 nItemLen = FXSYS_strlen(pszTemp); |
| 652 } |
| 653 break; |
| 654 case 'p': |
| 655 va_arg(argList, void*); |
| 656 nItemLen = 32; |
| 657 if (nItemLen < nWidth + nPrecision) { |
| 658 nItemLen = nWidth + nPrecision; |
| 659 } |
| 660 break; |
| 661 case 'n': |
| 662 va_arg(argList, int*); |
| 663 break; |
| 664 } |
| 665 } |
| 666 nMaxLen += nItemLen; |
| 667 } |
| 668 nMaxLen += 32; // Fudge factor. |
| 669 GetBuffer(nMaxLen); |
| 670 if (m_pData) { |
| 671 memset(m_pData->m_String, 0, nMaxLen); |
| 672 FXSYS_vsnprintf(m_pData->m_String, nMaxLen - 1, lpszFormat, argListSave); |
| 673 ReleaseBuffer(); |
| 674 } |
| 675 va_end(argListSave); |
| 676 } |
| 677 void CFX_ByteString::Format(const FX_CHAR* lpszFormat, ...) { |
| 678 va_list argList; |
| 679 va_start(argList, lpszFormat); |
| 680 FormatV(lpszFormat, argList); |
| 681 va_end(argList); |
| 682 } |
| 683 FX_STRSIZE CFX_ByteString::Insert(FX_STRSIZE nIndex, FX_CHAR ch) { |
| 684 CopyBeforeWrite(); |
| 685 if (nIndex < 0) { |
| 686 nIndex = 0; |
| 687 } |
| 688 FX_STRSIZE nNewLength = m_pData ? m_pData->m_nDataLength : 0; |
| 689 if (nIndex > nNewLength) { |
| 690 nIndex = nNewLength; |
| 691 } |
| 692 nNewLength++; |
| 693 if (m_pData == NULL || m_pData->m_nAllocLength < nNewLength) { |
436 StringData* pOldData = m_pData; | 694 StringData* pOldData = m_pData; |
437 m_pData = StringData::Create(nNewLen); | 695 const FX_CHAR* pstr = m_pData->m_String; |
438 if (m_pData) { | 696 m_pData = StringData::Create(nNewLength); |
439 memcpy(m_pData->m_String, lpszSrc1Data, nSrc1Len); | 697 if (!m_pData) { |
440 memcpy(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len); | 698 return 0; |
441 } | 699 } |
442 pOldData->Release(); | 700 if (pOldData != NULL) { |
443 } | 701 FXSYS_memmove(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1)); |
444 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst) const | 702 pOldData->Release(); |
445 { | 703 } else { |
446 if (m_pData == NULL) { | 704 m_pData->m_String[0] = 0; |
447 return CFX_ByteString(); | 705 } |
448 } | 706 } |
449 return Mid(nFirst, m_pData->m_nDataLength - nFirst); | 707 FXSYS_memmove(m_pData->m_String + nIndex + 1, m_pData->m_String + nIndex, |
450 } | 708 (nNewLength - nIndex)); |
451 CFX_ByteString CFX_ByteString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const | 709 m_pData->m_String[nIndex] = ch; |
452 { | 710 m_pData->m_nDataLength = nNewLength; |
453 if (nFirst < 0) { | 711 return nNewLength; |
454 nFirst = 0; | 712 } |
455 } | 713 CFX_ByteString CFX_ByteString::Right(FX_STRSIZE nCount) const { |
456 if (nCount < 0) { | 714 if (m_pData == NULL) { |
457 nCount = 0; | 715 return CFX_ByteString(); |
458 } | 716 } |
459 if (nFirst + nCount > m_pData->m_nDataLength) { | 717 if (nCount < 0) { |
460 nCount = m_pData->m_nDataLength - nFirst; | 718 nCount = 0; |
461 } | 719 } |
462 if (nFirst > m_pData->m_nDataLength) { | 720 if (nCount >= m_pData->m_nDataLength) { |
463 nCount = 0; | 721 return *this; |
464 } | 722 } |
465 if (nFirst == 0 && nFirst + nCount == m_pData->m_nDataLength) { | 723 CFX_ByteString dest; |
466 return *this; | 724 AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount); |
467 } | 725 return dest; |
468 CFX_ByteString dest; | 726 } |
469 AllocCopy(dest, nCount, nFirst); | 727 CFX_ByteString CFX_ByteString::Left(FX_STRSIZE nCount) const { |
470 return dest; | 728 if (m_pData == NULL) { |
471 } | 729 return CFX_ByteString(); |
472 void CFX_ByteString::AllocCopy(CFX_ByteString& dest, FX_STRSIZE nCopyLen, FX_STR
SIZE nCopyIndex) const | 730 } |
473 { | 731 if (nCount < 0) { |
474 // |FX_STRSIZE| is currently typedef'd as in |int|. TODO(palmer): It | 732 nCount = 0; |
475 // should be a |size_t|, or at least unsigned. | 733 } |
476 if (nCopyLen == 0 || nCopyLen < 0) { | 734 if (nCount >= m_pData->m_nDataLength) { |
477 return; | 735 return *this; |
478 } | 736 } |
479 ASSERT(dest.m_pData == NULL); | 737 CFX_ByteString dest; |
480 dest.m_pData = StringData::Create(nCopyLen); | 738 AllocCopy(dest, nCount, 0); |
481 if (dest.m_pData) { | 739 return dest; |
482 FXSYS_memcpy(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, nCo
pyLen); | 740 } |
483 } | 741 FX_STRSIZE CFX_ByteString::Find(FX_CHAR ch, FX_STRSIZE nStart) const { |
484 } | 742 if (m_pData == NULL) { |
485 #define FORCE_ANSI 0x10000 | |
486 #define FORCE_UNICODE 0x20000 | |
487 #define FORCE_INT64 0x40000 | |
488 void CFX_ByteString::FormatV(const FX_CHAR* lpszFormat, va_list argList) | |
489 { | |
490 va_list argListSave; | |
491 #if defined(__ARMCC_VERSION) || (!defined(_MSC_VER) && (_FX_CPU_ == _FX_X64_ ||
_FX_CPU_ == _FX_IA64_ || _FX_CPU_ == _FX_ARM64_)) || defined(__native_client__) | |
492 va_copy(argListSave, argList); | |
493 #else | |
494 argListSave = argList; | |
495 #endif | |
496 int nMaxLen = 0; | |
497 for (const FX_CHAR* lpsz = lpszFormat; *lpsz != 0; lpsz ++) { | |
498 if (*lpsz != '%' || *(lpsz = lpsz + 1) == '%') { | |
499 nMaxLen += FXSYS_strlen(lpsz); | |
500 continue; | |
501 } | |
502 int nItemLen = 0; | |
503 int nWidth = 0; | |
504 for (; *lpsz != 0; lpsz ++) { | |
505 if (*lpsz == '#') { | |
506 nMaxLen += 2; | |
507 } else if (*lpsz == '*') { | |
508 nWidth = va_arg(argList, int); | |
509 } else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' || | |
510 *lpsz == ' ') | |
511 ; | |
512 else { | |
513 break; | |
514 } | |
515 } | |
516 if (nWidth == 0) { | |
517 nWidth = FXSYS_atoi(lpsz); | |
518 for (; (*lpsz) >= '0' && (*lpsz) <= '9'; lpsz ++) | |
519 ; | |
520 } | |
521 if (nWidth < 0 || nWidth > 128 * 1024) { | |
522 lpszFormat = "Bad width"; | |
523 nMaxLen = 10; | |
524 break; | |
525 } | |
526 int nPrecision = 0; | |
527 if (*lpsz == '.') { | |
528 lpsz ++; | |
529 if (*lpsz == '*') { | |
530 nPrecision = va_arg(argList, int); | |
531 lpsz ++; | |
532 } else { | |
533 nPrecision = FXSYS_atoi(lpsz); | |
534 for (; (*lpsz) >= '0' && (*lpsz) <= '9'; lpsz ++) | |
535 ; | |
536 } | |
537 } | |
538 if (nPrecision < 0 || nPrecision > 128 * 1024) { | |
539 lpszFormat = "Bad precision"; | |
540 nMaxLen = 14; | |
541 break; | |
542 } | |
543 int nModifier = 0; | |
544 if (FXSYS_strncmp(lpsz, "I64", 3) == 0) { | |
545 lpsz += 3; | |
546 nModifier = FORCE_INT64; | |
547 } else { | |
548 switch (*lpsz) { | |
549 case 'h': | |
550 nModifier = FORCE_ANSI; | |
551 lpsz ++; | |
552 break; | |
553 case 'l': | |
554 nModifier = FORCE_UNICODE; | |
555 lpsz ++; | |
556 break; | |
557 case 'F': | |
558 case 'N': | |
559 case 'L': | |
560 lpsz ++; | |
561 break; | |
562 } | |
563 } | |
564 switch (*lpsz | nModifier) { | |
565 case 'c': | |
566 case 'C': | |
567 nItemLen = 2; | |
568 va_arg(argList, int); | |
569 break; | |
570 case 'c'|FORCE_ANSI: | |
571 case 'C'|FORCE_ANSI: | |
572 nItemLen = 2; | |
573 va_arg(argList, int); | |
574 break; | |
575 case 'c'|FORCE_UNICODE: | |
576 case 'C'|FORCE_UNICODE: | |
577 nItemLen = 2; | |
578 va_arg(argList, int); | |
579 break; | |
580 case 's': { | |
581 const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*)
; | |
582 if (pstrNextArg == NULL) { | |
583 nItemLen = 6; | |
584 } else { | |
585 nItemLen = FXSYS_strlen(pstrNextArg); | |
586 if (nItemLen < 1) { | |
587 nItemLen = 1; | |
588 } | |
589 } | |
590 } | |
591 break; | |
592 case 'S': { | |
593 FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); | |
594 if (pstrNextArg == NULL) { | |
595 nItemLen = 6; | |
596 } else { | |
597 nItemLen = FXSYS_wcslen(pstrNextArg); | |
598 if (nItemLen < 1) { | |
599 nItemLen = 1; | |
600 } | |
601 } | |
602 } | |
603 break; | |
604 case 's'|FORCE_ANSI: | |
605 case 'S'|FORCE_ANSI: { | |
606 const FX_CHAR* pstrNextArg = va_arg(argList, const FX_CHAR*)
; | |
607 if (pstrNextArg == NULL) { | |
608 nItemLen = 6; | |
609 } else { | |
610 nItemLen = FXSYS_strlen(pstrNextArg); | |
611 if (nItemLen < 1) { | |
612 nItemLen = 1; | |
613 } | |
614 } | |
615 } | |
616 break; | |
617 case 's'|FORCE_UNICODE: | |
618 case 'S'|FORCE_UNICODE: { | |
619 FX_WCHAR* pstrNextArg = va_arg(argList, FX_WCHAR*); | |
620 if (pstrNextArg == NULL) { | |
621 nItemLen = 6; | |
622 } else { | |
623 nItemLen = FXSYS_wcslen(pstrNextArg); | |
624 if (nItemLen < 1) { | |
625 nItemLen = 1; | |
626 } | |
627 } | |
628 } | |
629 break; | |
630 } | |
631 if (nItemLen != 0) { | |
632 if (nPrecision != 0 && nItemLen > nPrecision) { | |
633 nItemLen = nPrecision; | |
634 } | |
635 if (nItemLen < nWidth) { | |
636 nItemLen = nWidth; | |
637 } | |
638 } else { | |
639 switch (*lpsz) { | |
640 case 'd': | |
641 case 'i': | |
642 case 'u': | |
643 case 'x': | |
644 case 'X': | |
645 case 'o': | |
646 if (nModifier & FORCE_INT64) { | |
647 va_arg(argList, int64_t); | |
648 } else { | |
649 va_arg(argList, int); | |
650 } | |
651 nItemLen = 32; | |
652 if (nItemLen < nWidth + nPrecision) { | |
653 nItemLen = nWidth + nPrecision; | |
654 } | |
655 break; | |
656 case 'a': | |
657 case 'A': | |
658 case 'e': | |
659 case 'E': | |
660 case 'g': | |
661 case 'G': | |
662 va_arg(argList, double); | |
663 nItemLen = 128; | |
664 if (nItemLen < nWidth + nPrecision) { | |
665 nItemLen = nWidth + nPrecision; | |
666 } | |
667 break; | |
668 case 'f': | |
669 if (nWidth + nPrecision > 100) { | |
670 nItemLen = nPrecision + nWidth + 128; | |
671 } else { | |
672 char pszTemp[256]; | |
673 double f = va_arg(argList, double); | |
674 memset(pszTemp, 0, sizeof(pszTemp)); | |
675 FXSYS_snprintf(pszTemp, sizeof(pszTemp) - 1, "%*.*f", nW
idth, nPrecision + 6, f); | |
676 nItemLen = FXSYS_strlen(pszTemp); | |
677 } | |
678 break; | |
679 case 'p': | |
680 va_arg(argList, void*); | |
681 nItemLen = 32; | |
682 if (nItemLen < nWidth + nPrecision) { | |
683 nItemLen = nWidth + nPrecision; | |
684 } | |
685 break; | |
686 case 'n': | |
687 va_arg(argList, int*); | |
688 break; | |
689 } | |
690 } | |
691 nMaxLen += nItemLen; | |
692 } | |
693 nMaxLen += 32; // Fudge factor. | |
694 GetBuffer(nMaxLen); | |
695 if (m_pData) { | |
696 memset(m_pData->m_String, 0, nMaxLen); | |
697 FXSYS_vsnprintf(m_pData->m_String, nMaxLen - 1, lpszFormat, argListSave)
; | |
698 ReleaseBuffer(); | |
699 } | |
700 va_end(argListSave); | |
701 } | |
702 void CFX_ByteString::Format(const FX_CHAR* lpszFormat, ...) | |
703 { | |
704 va_list argList; | |
705 va_start(argList, lpszFormat); | |
706 FormatV(lpszFormat, argList); | |
707 va_end(argList); | |
708 } | |
709 FX_STRSIZE CFX_ByteString::Insert(FX_STRSIZE nIndex, FX_CHAR ch) | |
710 { | |
711 CopyBeforeWrite(); | |
712 if (nIndex < 0) { | |
713 nIndex = 0; | |
714 } | |
715 FX_STRSIZE nNewLength = m_pData ? m_pData->m_nDataLength : 0; | |
716 if (nIndex > nNewLength) { | |
717 nIndex = nNewLength; | |
718 } | |
719 nNewLength++; | |
720 if (m_pData == NULL || m_pData->m_nAllocLength < nNewLength) { | |
721 StringData* pOldData = m_pData; | |
722 const FX_CHAR* pstr = m_pData->m_String; | |
723 m_pData = StringData::Create(nNewLength); | |
724 if (!m_pData) { | |
725 return 0; | |
726 } | |
727 if(pOldData != NULL) { | |
728 FXSYS_memmove(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1)
); | |
729 pOldData->Release(); | |
730 } else { | |
731 m_pData->m_String[0] = 0; | |
732 } | |
733 } | |
734 FXSYS_memmove(m_pData->m_String + nIndex + 1, | |
735 m_pData->m_String + nIndex, (nNewLength - nIndex)); | |
736 m_pData->m_String[nIndex] = ch; | |
737 m_pData->m_nDataLength = nNewLength; | |
738 return nNewLength; | |
739 } | |
740 CFX_ByteString CFX_ByteString::Right(FX_STRSIZE nCount) const | |
741 { | |
742 if (m_pData == NULL) { | |
743 return CFX_ByteString(); | |
744 } | |
745 if (nCount < 0) { | |
746 nCount = 0; | |
747 } | |
748 if (nCount >= m_pData->m_nDataLength) { | |
749 return *this; | |
750 } | |
751 CFX_ByteString dest; | |
752 AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount); | |
753 return dest; | |
754 } | |
755 CFX_ByteString CFX_ByteString::Left(FX_STRSIZE nCount) const | |
756 { | |
757 if (m_pData == NULL) { | |
758 return CFX_ByteString(); | |
759 } | |
760 if (nCount < 0) { | |
761 nCount = 0; | |
762 } | |
763 if (nCount >= m_pData->m_nDataLength) { | |
764 return *this; | |
765 } | |
766 CFX_ByteString dest; | |
767 AllocCopy(dest, nCount, 0); | |
768 return dest; | |
769 } | |
770 FX_STRSIZE CFX_ByteString::Find(FX_CHAR ch, FX_STRSIZE nStart) const | |
771 { | |
772 if (m_pData == NULL) { | |
773 return -1; | |
774 } | |
775 FX_STRSIZE nLength = m_pData->m_nDataLength; | |
776 if (nStart >= nLength) { | |
777 return -1; | |
778 } | |
779 const FX_CHAR* lpsz = FXSYS_strchr(m_pData->m_String + nStart, ch); | |
780 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String); | |
781 } | |
782 FX_STRSIZE CFX_ByteString::ReverseFind(FX_CHAR ch) const | |
783 { | |
784 if (m_pData == NULL) { | |
785 return -1; | |
786 } | |
787 FX_STRSIZE nLength = m_pData->m_nDataLength; | |
788 while (nLength) { | |
789 if (m_pData->m_String[nLength - 1] == ch) { | |
790 return nLength - 1; | |
791 } | |
792 nLength --; | |
793 } | |
794 return -1; | 743 return -1; |
795 } | 744 } |
796 const FX_CHAR* FX_strstr(const FX_CHAR* str1, int len1, const FX_CHAR* str2, int
len2) | 745 FX_STRSIZE nLength = m_pData->m_nDataLength; |
797 { | 746 if (nStart >= nLength) { |
798 if (len2 > len1 || len2 == 0) { | 747 return -1; |
799 return NULL; | 748 } |
800 } | 749 const FX_CHAR* lpsz = FXSYS_strchr(m_pData->m_String + nStart, ch); |
801 const FX_CHAR* end_ptr = str1 + len1 - len2; | 750 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String); |
802 while (str1 <= end_ptr) { | 751 } |
803 int i = 0; | 752 FX_STRSIZE CFX_ByteString::ReverseFind(FX_CHAR ch) const { |
804 while (1) { | 753 if (m_pData == NULL) { |
805 if (str1[i] != str2[i]) { | 754 return -1; |
806 break; | 755 } |
807 } | 756 FX_STRSIZE nLength = m_pData->m_nDataLength; |
808 i ++; | 757 while (nLength) { |
809 if (i == len2) { | 758 if (m_pData->m_String[nLength - 1] == ch) { |
810 return str1; | 759 return nLength - 1; |
811 } | 760 } |
812 } | 761 nLength--; |
813 str1 ++; | 762 } |
814 } | 763 return -1; |
| 764 } |
| 765 const FX_CHAR* FX_strstr(const FX_CHAR* str1, |
| 766 int len1, |
| 767 const FX_CHAR* str2, |
| 768 int len2) { |
| 769 if (len2 > len1 || len2 == 0) { |
815 return NULL; | 770 return NULL; |
816 } | 771 } |
817 FX_STRSIZE CFX_ByteString::Find(const CFX_ByteStringC& lpszSub, FX_STRSIZE nStar
t) const | 772 const FX_CHAR* end_ptr = str1 + len1 - len2; |
818 { | 773 while (str1 <= end_ptr) { |
819 if (m_pData == NULL) { | 774 int i = 0; |
820 return -1; | 775 while (1) { |
821 } | 776 if (str1[i] != str2[i]) { |
822 FX_STRSIZE nLength = m_pData->m_nDataLength; | 777 break; |
823 if (nStart > nLength) { | 778 } |
824 return -1; | 779 i++; |
825 } | 780 if (i == len2) { |
826 const FX_CHAR* lpsz = FX_strstr(m_pData->m_String + nStart, m_pData->m_nData
Length - nStart, | 781 return str1; |
827 lpszSub.GetCStr(), lpszSub.GetLength()); | 782 } |
828 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String); | 783 } |
829 } | 784 str1++; |
830 void CFX_ByteString::MakeLower() | 785 } |
831 { | 786 return NULL; |
832 if (m_pData == NULL) { | 787 } |
833 return; | 788 FX_STRSIZE CFX_ByteString::Find(const CFX_ByteStringC& lpszSub, |
834 } | 789 FX_STRSIZE nStart) const { |
835 CopyBeforeWrite(); | 790 if (m_pData == NULL) { |
836 if (GetLength() < 1) { | 791 return -1; |
837 return; | 792 } |
838 } | 793 FX_STRSIZE nLength = m_pData->m_nDataLength; |
839 FXSYS_strlwr(m_pData->m_String); | 794 if (nStart > nLength) { |
840 } | 795 return -1; |
841 void CFX_ByteString::MakeUpper() | 796 } |
842 { | 797 const FX_CHAR* lpsz = |
843 if (m_pData == NULL) { | 798 FX_strstr(m_pData->m_String + nStart, m_pData->m_nDataLength - nStart, |
844 return; | 799 lpszSub.GetCStr(), lpszSub.GetLength()); |
845 } | 800 return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String); |
846 CopyBeforeWrite(); | 801 } |
847 if (GetLength() < 1) { | 802 void CFX_ByteString::MakeLower() { |
848 return; | 803 if (m_pData == NULL) { |
849 } | 804 return; |
850 FXSYS_strupr(m_pData->m_String); | 805 } |
851 } | 806 CopyBeforeWrite(); |
852 FX_STRSIZE CFX_ByteString::Remove(FX_CHAR chRemove) | 807 if (GetLength() < 1) { |
853 { | 808 return; |
854 if (m_pData == NULL) { | 809 } |
855 return 0; | 810 FXSYS_strlwr(m_pData->m_String); |
856 } | 811 } |
857 CopyBeforeWrite(); | 812 void CFX_ByteString::MakeUpper() { |
858 if (GetLength() < 1) { | 813 if (m_pData == NULL) { |
859 return 0; | 814 return; |
860 } | 815 } |
861 FX_CHAR* pstrSource = m_pData->m_String; | 816 CopyBeforeWrite(); |
862 FX_CHAR* pstrDest = m_pData->m_String; | 817 if (GetLength() < 1) { |
863 FX_CHAR* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; | 818 return; |
864 while (pstrSource < pstrEnd) { | 819 } |
865 if (*pstrSource != chRemove) { | 820 FXSYS_strupr(m_pData->m_String); |
866 *pstrDest = *pstrSource; | 821 } |
867 pstrDest ++; | 822 FX_STRSIZE CFX_ByteString::Remove(FX_CHAR chRemove) { |
868 } | 823 if (m_pData == NULL) { |
869 pstrSource ++; | 824 return 0; |
870 } | 825 } |
871 *pstrDest = 0; | 826 CopyBeforeWrite(); |
872 FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest); | 827 if (GetLength() < 1) { |
873 m_pData->m_nDataLength -= nCount; | 828 return 0; |
| 829 } |
| 830 FX_CHAR* pstrSource = m_pData->m_String; |
| 831 FX_CHAR* pstrDest = m_pData->m_String; |
| 832 FX_CHAR* pstrEnd = m_pData->m_String + m_pData->m_nDataLength; |
| 833 while (pstrSource < pstrEnd) { |
| 834 if (*pstrSource != chRemove) { |
| 835 *pstrDest = *pstrSource; |
| 836 pstrDest++; |
| 837 } |
| 838 pstrSource++; |
| 839 } |
| 840 *pstrDest = 0; |
| 841 FX_STRSIZE nCount = (FX_STRSIZE)(pstrSource - pstrDest); |
| 842 m_pData->m_nDataLength -= nCount; |
| 843 return nCount; |
| 844 } |
| 845 FX_STRSIZE CFX_ByteString::Replace(const CFX_ByteStringC& lpszOld, |
| 846 const CFX_ByteStringC& lpszNew) { |
| 847 if (m_pData == NULL) { |
| 848 return 0; |
| 849 } |
| 850 if (lpszOld.IsEmpty()) { |
| 851 return 0; |
| 852 } |
| 853 FX_STRSIZE nSourceLen = lpszOld.GetLength(); |
| 854 FX_STRSIZE nReplacementLen = lpszNew.GetLength(); |
| 855 FX_STRSIZE nCount = 0; |
| 856 const FX_CHAR* pStart = m_pData->m_String; |
| 857 FX_CHAR* pEnd = m_pData->m_String + m_pData->m_nDataLength; |
| 858 while (1) { |
| 859 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart), |
| 860 lpszOld.GetCStr(), nSourceLen); |
| 861 if (pTarget == NULL) { |
| 862 break; |
| 863 } |
| 864 nCount++; |
| 865 pStart = pTarget + nSourceLen; |
| 866 } |
| 867 if (nCount == 0) { |
| 868 return 0; |
| 869 } |
| 870 FX_STRSIZE nNewLength = |
| 871 m_pData->m_nDataLength + (nReplacementLen - nSourceLen) * nCount; |
| 872 if (nNewLength == 0) { |
| 873 Empty(); |
874 return nCount; | 874 return nCount; |
875 } | 875 } |
876 FX_STRSIZE CFX_ByteString::Replace(const CFX_ByteStringC& lpszOld, const CFX_Byt
eStringC& lpszNew) | 876 StringData* pNewData = StringData::Create(nNewLength); |
877 { | 877 if (!pNewData) { |
878 if (m_pData == NULL) { | |
879 return 0; | |
880 } | |
881 if (lpszOld.IsEmpty()) { | |
882 return 0; | |
883 } | |
884 FX_STRSIZE nSourceLen = lpszOld.GetLength(); | |
885 FX_STRSIZE nReplacementLen = lpszNew.GetLength(); | |
886 FX_STRSIZE nCount = 0; | |
887 const FX_CHAR* pStart = m_pData->m_String; | |
888 FX_CHAR* pEnd = m_pData->m_String + m_pData->m_nDataLength; | |
889 while (1) { | |
890 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart),
lpszOld.GetCStr(), nSourceLen); | |
891 if (pTarget == NULL) { | |
892 break; | |
893 } | |
894 nCount++; | |
895 pStart = pTarget + nSourceLen; | |
896 } | |
897 if (nCount == 0) { | |
898 return 0; | |
899 } | |
900 FX_STRSIZE nNewLength = m_pData->m_nDataLength + (nReplacementLen - nSource
Len) * nCount; | |
901 if (nNewLength == 0) { | |
902 Empty(); | |
903 return nCount; | |
904 } | |
905 StringData* pNewData = StringData::Create(nNewLength); | |
906 if (!pNewData) { | |
907 return 0; | |
908 } | |
909 pStart = m_pData->m_String; | |
910 FX_CHAR* pDest = pNewData->m_String; | |
911 for (FX_STRSIZE i = 0; i < nCount; i ++) { | |
912 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart),
lpszOld.GetCStr(), nSourceLen); | |
913 FXSYS_memcpy(pDest, pStart, pTarget - pStart); | |
914 pDest += pTarget - pStart; | |
915 FXSYS_memcpy(pDest, lpszNew.GetCStr(), lpszNew.GetLength()); | |
916 pDest += lpszNew.GetLength(); | |
917 pStart = pTarget + nSourceLen; | |
918 } | |
919 FXSYS_memcpy(pDest, pStart, pEnd - pStart); | |
920 m_pData->Release(); | |
921 m_pData = pNewData; | |
922 return nCount; | |
923 } | |
924 void CFX_ByteString::SetAt(FX_STRSIZE nIndex, FX_CHAR ch) | |
925 { | |
926 if (m_pData == NULL) { | |
927 return; | |
928 } | |
929 FXSYS_assert(nIndex >= 0); | |
930 FXSYS_assert(nIndex < m_pData->m_nDataLength); | |
931 CopyBeforeWrite(); | |
932 m_pData->m_String[nIndex] = ch; | |
933 } | |
934 CFX_WideString CFX_ByteString::UTF8Decode() const | |
935 { | |
936 CFX_UTF8Decoder decoder; | |
937 for (FX_STRSIZE i = 0; i < GetLength(); i ++) { | |
938 decoder.Input((uint8_t)m_pData->m_String[i]); | |
939 } | |
940 return decoder.GetResult(); | |
941 } | |
942 CFX_ByteString CFX_ByteString::FromUnicode(const FX_WCHAR* str, FX_STRSIZE len) | |
943 { | |
944 if (len < 0) { | |
945 len = FXSYS_wcslen(str); | |
946 } | |
947 CFX_ByteString bstr; | |
948 bstr.ConvertFrom(CFX_WideString(str, len)); | |
949 return bstr; | |
950 } | |
951 CFX_ByteString CFX_ByteString::FromUnicode(const CFX_WideString& str) | |
952 { | |
953 return FromUnicode(str.c_str(), str.GetLength()); | |
954 } | |
955 void CFX_ByteString::ConvertFrom(const CFX_WideString& str, CFX_CharMap* pCharMa
p) | |
956 { | |
957 if (pCharMap == NULL) { | |
958 pCharMap = CFX_CharMap::GetDefaultMapper(); | |
959 } | |
960 *this = (*pCharMap->m_GetByteString)(pCharMap, str); | |
961 } | |
962 int CFX_ByteString::Compare(const CFX_ByteStringC& str) const | |
963 { | |
964 if (m_pData == NULL) { | |
965 return str.IsEmpty() ? 0 : -1; | |
966 } | |
967 int this_len = m_pData->m_nDataLength; | |
968 int that_len = str.GetLength(); | |
969 int min_len = this_len < that_len ? this_len : that_len; | |
970 for (int i = 0; i < min_len; i ++) { | |
971 if ((uint8_t)m_pData->m_String[i] < str.GetAt(i)) { | |
972 return -1; | |
973 } | |
974 if ((uint8_t)m_pData->m_String[i] > str.GetAt(i)) { | |
975 return 1; | |
976 } | |
977 } | |
978 if (this_len < that_len) { | |
979 return -1; | |
980 } | |
981 if (this_len > that_len) { | |
982 return 1; | |
983 } | |
984 return 0; | 878 return 0; |
985 } | 879 } |
986 void CFX_ByteString::TrimRight(const CFX_ByteStringC& lpszTargets) | 880 pStart = m_pData->m_String; |
987 { | 881 FX_CHAR* pDest = pNewData->m_String; |
988 if (m_pData == NULL || lpszTargets.IsEmpty()) { | 882 for (FX_STRSIZE i = 0; i < nCount; i++) { |
989 return; | 883 const FX_CHAR* pTarget = FX_strstr(pStart, (FX_STRSIZE)(pEnd - pStart), |
990 } | 884 lpszOld.GetCStr(), nSourceLen); |
991 CopyBeforeWrite(); | 885 FXSYS_memcpy(pDest, pStart, pTarget - pStart); |
992 FX_STRSIZE pos = GetLength(); | 886 pDest += pTarget - pStart; |
993 if (pos < 1) { | 887 FXSYS_memcpy(pDest, lpszNew.GetCStr(), lpszNew.GetLength()); |
994 return; | 888 pDest += lpszNew.GetLength(); |
995 } | 889 pStart = pTarget + nSourceLen; |
996 while (pos) { | 890 } |
997 FX_STRSIZE i = 0; | 891 FXSYS_memcpy(pDest, pStart, pEnd - pStart); |
998 while (i < lpszTargets.GetLength() && lpszTargets[i] != m_pData->m_Strin
g[pos - 1]) { | 892 m_pData->Release(); |
999 i ++; | 893 m_pData = pNewData; |
1000 } | 894 return nCount; |
1001 if (i == lpszTargets.GetLength()) { | 895 } |
1002 break; | 896 void CFX_ByteString::SetAt(FX_STRSIZE nIndex, FX_CHAR ch) { |
1003 } | 897 if (m_pData == NULL) { |
1004 pos --; | 898 return; |
1005 } | 899 } |
1006 if (pos < m_pData->m_nDataLength) { | 900 FXSYS_assert(nIndex >= 0); |
1007 m_pData->m_String[pos] = 0; | 901 FXSYS_assert(nIndex < m_pData->m_nDataLength); |
1008 m_pData->m_nDataLength = pos; | 902 CopyBeforeWrite(); |
1009 } | 903 m_pData->m_String[nIndex] = ch; |
1010 } | 904 } |
1011 void CFX_ByteString::TrimRight(FX_CHAR chTarget) | 905 CFX_WideString CFX_ByteString::UTF8Decode() const { |
1012 { | 906 CFX_UTF8Decoder decoder; |
1013 TrimRight(CFX_ByteStringC(chTarget)); | 907 for (FX_STRSIZE i = 0; i < GetLength(); i++) { |
1014 } | 908 decoder.Input((uint8_t)m_pData->m_String[i]); |
1015 void CFX_ByteString::TrimRight() | 909 } |
1016 { | 910 return decoder.GetResult(); |
1017 TrimRight(FX_BSTRC("\x09\x0a\x0b\x0c\x0d\x20")); | 911 } |
1018 } | 912 CFX_ByteString CFX_ByteString::FromUnicode(const FX_WCHAR* str, |
1019 void CFX_ByteString::TrimLeft(const CFX_ByteStringC& lpszTargets) | 913 FX_STRSIZE len) { |
1020 { | 914 if (len < 0) { |
1021 if (m_pData == NULL) { | 915 len = FXSYS_wcslen(str); |
1022 return; | 916 } |
1023 } | 917 CFX_ByteString bstr; |
1024 if (lpszTargets.IsEmpty()) { | 918 bstr.ConvertFrom(CFX_WideString(str, len)); |
1025 return; | 919 return bstr; |
1026 } | 920 } |
1027 CopyBeforeWrite(); | 921 CFX_ByteString CFX_ByteString::FromUnicode(const CFX_WideString& str) { |
1028 FX_STRSIZE len = GetLength(); | 922 return FromUnicode(str.c_str(), str.GetLength()); |
1029 if (len < 1) { | 923 } |
1030 return; | 924 void CFX_ByteString::ConvertFrom(const CFX_WideString& str, |
1031 } | 925 CFX_CharMap* pCharMap) { |
1032 FX_STRSIZE pos = 0; | 926 if (pCharMap == NULL) { |
1033 while (pos < len) { | 927 pCharMap = CFX_CharMap::GetDefaultMapper(); |
1034 FX_STRSIZE i = 0; | 928 } |
1035 while (i < lpszTargets.GetLength() && lpszTargets[i] != m_pData->m_Strin
g[pos]) { | 929 *this = (*pCharMap->m_GetByteString)(pCharMap, str); |
1036 i ++; | 930 } |
1037 } | 931 int CFX_ByteString::Compare(const CFX_ByteStringC& str) const { |
1038 if (i == lpszTargets.GetLength()) { | 932 if (m_pData == NULL) { |
1039 break; | 933 return str.IsEmpty() ? 0 : -1; |
1040 } | 934 } |
1041 pos ++; | 935 int this_len = m_pData->m_nDataLength; |
1042 } | 936 int that_len = str.GetLength(); |
1043 if (pos) { | 937 int min_len = this_len < that_len ? this_len : that_len; |
1044 FX_STRSIZE nDataLength = len - pos; | 938 for (int i = 0; i < min_len; i++) { |
1045 FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos, (nDataLength +
1)*sizeof(FX_CHAR)); | 939 if ((uint8_t)m_pData->m_String[i] < str.GetAt(i)) { |
1046 m_pData->m_nDataLength = nDataLength; | 940 return -1; |
1047 } | 941 } |
1048 } | 942 if ((uint8_t)m_pData->m_String[i] > str.GetAt(i)) { |
1049 void CFX_ByteString::TrimLeft(FX_CHAR chTarget) | 943 return 1; |
1050 { | 944 } |
1051 TrimLeft(CFX_ByteStringC(chTarget)); | 945 } |
1052 } | 946 if (this_len < that_len) { |
1053 void CFX_ByteString::TrimLeft() | 947 return -1; |
1054 { | 948 } |
1055 TrimLeft(FX_BSTRC("\x09\x0a\x0b\x0c\x0d\x20")); | 949 if (this_len > that_len) { |
1056 } | 950 return 1; |
1057 FX_DWORD CFX_ByteString::GetID(FX_STRSIZE start_pos) const | 951 } |
1058 { | 952 return 0; |
1059 return CFX_ByteStringC(*this).GetID(start_pos); | 953 } |
1060 } | 954 void CFX_ByteString::TrimRight(const CFX_ByteStringC& lpszTargets) { |
1061 FX_DWORD CFX_ByteStringC::GetID(FX_STRSIZE start_pos) const | 955 if (m_pData == NULL || lpszTargets.IsEmpty()) { |
1062 { | 956 return; |
1063 if (m_Length == 0) { | 957 } |
1064 return 0; | 958 CopyBeforeWrite(); |
1065 } | 959 FX_STRSIZE pos = GetLength(); |
1066 if (start_pos < 0 || start_pos >= m_Length) { | 960 if (pos < 1) { |
1067 return 0; | 961 return; |
1068 } | 962 } |
1069 FX_DWORD strid = 0; | 963 while (pos) { |
1070 if (start_pos + 4 > m_Length) { | 964 FX_STRSIZE i = 0; |
1071 for (FX_STRSIZE i = 0; i < m_Length - start_pos; i ++) { | 965 while (i < lpszTargets.GetLength() && |
1072 strid = strid * 256 + m_Ptr[start_pos + i]; | 966 lpszTargets[i] != m_pData->m_String[pos - 1]) { |
1073 } | 967 i++; |
1074 strid = strid << ((4 - m_Length + start_pos) * 8); | 968 } |
1075 } else { | 969 if (i == lpszTargets.GetLength()) { |
1076 for (int i = 0; i < 4; i ++) { | 970 break; |
1077 strid = strid * 256 + m_Ptr[start_pos + i]; | 971 } |
1078 } | 972 pos--; |
1079 } | 973 } |
1080 return strid; | 974 if (pos < m_pData->m_nDataLength) { |
1081 } | 975 m_pData->m_String[pos] = 0; |
1082 FX_STRSIZE FX_ftoa(FX_FLOAT d, FX_CHAR* buf) | 976 m_pData->m_nDataLength = pos; |
1083 { | 977 } |
1084 buf[0] = '0'; | 978 } |
1085 buf[1] = '\0'; | 979 void CFX_ByteString::TrimRight(FX_CHAR chTarget) { |
1086 if (d == 0.0f) { | 980 TrimRight(CFX_ByteStringC(chTarget)); |
1087 return 1; | 981 } |
1088 } | 982 void CFX_ByteString::TrimRight() { |
1089 FX_BOOL bNegative = FALSE; | 983 TrimRight(FX_BSTRC("\x09\x0a\x0b\x0c\x0d\x20")); |
1090 if (d < 0) { | 984 } |
1091 bNegative = TRUE; | 985 void CFX_ByteString::TrimLeft(const CFX_ByteStringC& lpszTargets) { |
1092 d = -d; | 986 if (m_pData == NULL) { |
1093 } | 987 return; |
1094 int scale = 1; | 988 } |
1095 int scaled = FXSYS_round(d); | 989 if (lpszTargets.IsEmpty()) { |
1096 while (scaled < 100000) { | 990 return; |
1097 if (scale == 1000000) { | 991 } |
1098 break; | 992 CopyBeforeWrite(); |
1099 } | 993 FX_STRSIZE len = GetLength(); |
1100 scale *= 10; | 994 if (len < 1) { |
1101 scaled = FXSYS_round(d * scale); | 995 return; |
1102 } | 996 } |
1103 if (scaled == 0) { | 997 FX_STRSIZE pos = 0; |
1104 return 1; | 998 while (pos < len) { |
1105 } | 999 FX_STRSIZE i = 0; |
1106 char buf2[32]; | 1000 while (i < lpszTargets.GetLength() && |
1107 int buf_size = 0; | 1001 lpszTargets[i] != m_pData->m_String[pos]) { |
1108 if (bNegative) { | 1002 i++; |
1109 buf[buf_size++] = '-'; | 1003 } |
1110 } | 1004 if (i == lpszTargets.GetLength()) { |
1111 int i = scaled / scale; | 1005 break; |
1112 FXSYS_itoa(i, buf2, 10); | 1006 } |
1113 FX_STRSIZE len = FXSYS_strlen(buf2); | 1007 pos++; |
1114 FXSYS_memcpy(buf + buf_size, buf2, len); | 1008 } |
1115 buf_size += len; | 1009 if (pos) { |
1116 int fraction = scaled % scale; | 1010 FX_STRSIZE nDataLength = len - pos; |
1117 if (fraction == 0) { | 1011 FXSYS_memmove(m_pData->m_String, m_pData->m_String + pos, |
1118 return buf_size; | 1012 (nDataLength + 1) * sizeof(FX_CHAR)); |
1119 } | 1013 m_pData->m_nDataLength = nDataLength; |
1120 buf[buf_size++] = '.'; | 1014 } |
| 1015 } |
| 1016 void CFX_ByteString::TrimLeft(FX_CHAR chTarget) { |
| 1017 TrimLeft(CFX_ByteStringC(chTarget)); |
| 1018 } |
| 1019 void CFX_ByteString::TrimLeft() { |
| 1020 TrimLeft(FX_BSTRC("\x09\x0a\x0b\x0c\x0d\x20")); |
| 1021 } |
| 1022 FX_DWORD CFX_ByteString::GetID(FX_STRSIZE start_pos) const { |
| 1023 return CFX_ByteStringC(*this).GetID(start_pos); |
| 1024 } |
| 1025 FX_DWORD CFX_ByteStringC::GetID(FX_STRSIZE start_pos) const { |
| 1026 if (m_Length == 0) { |
| 1027 return 0; |
| 1028 } |
| 1029 if (start_pos < 0 || start_pos >= m_Length) { |
| 1030 return 0; |
| 1031 } |
| 1032 FX_DWORD strid = 0; |
| 1033 if (start_pos + 4 > m_Length) { |
| 1034 for (FX_STRSIZE i = 0; i < m_Length - start_pos; i++) { |
| 1035 strid = strid * 256 + m_Ptr[start_pos + i]; |
| 1036 } |
| 1037 strid = strid << ((4 - m_Length + start_pos) * 8); |
| 1038 } else { |
| 1039 for (int i = 0; i < 4; i++) { |
| 1040 strid = strid * 256 + m_Ptr[start_pos + i]; |
| 1041 } |
| 1042 } |
| 1043 return strid; |
| 1044 } |
| 1045 FX_STRSIZE FX_ftoa(FX_FLOAT d, FX_CHAR* buf) { |
| 1046 buf[0] = '0'; |
| 1047 buf[1] = '\0'; |
| 1048 if (d == 0.0f) { |
| 1049 return 1; |
| 1050 } |
| 1051 FX_BOOL bNegative = FALSE; |
| 1052 if (d < 0) { |
| 1053 bNegative = TRUE; |
| 1054 d = -d; |
| 1055 } |
| 1056 int scale = 1; |
| 1057 int scaled = FXSYS_round(d); |
| 1058 while (scaled < 100000) { |
| 1059 if (scale == 1000000) { |
| 1060 break; |
| 1061 } |
| 1062 scale *= 10; |
| 1063 scaled = FXSYS_round(d * scale); |
| 1064 } |
| 1065 if (scaled == 0) { |
| 1066 return 1; |
| 1067 } |
| 1068 char buf2[32]; |
| 1069 int buf_size = 0; |
| 1070 if (bNegative) { |
| 1071 buf[buf_size++] = '-'; |
| 1072 } |
| 1073 int i = scaled / scale; |
| 1074 FXSYS_itoa(i, buf2, 10); |
| 1075 FX_STRSIZE len = FXSYS_strlen(buf2); |
| 1076 FXSYS_memcpy(buf + buf_size, buf2, len); |
| 1077 buf_size += len; |
| 1078 int fraction = scaled % scale; |
| 1079 if (fraction == 0) { |
| 1080 return buf_size; |
| 1081 } |
| 1082 buf[buf_size++] = '.'; |
| 1083 scale /= 10; |
| 1084 while (fraction) { |
| 1085 buf[buf_size++] = '0' + fraction / scale; |
| 1086 fraction %= scale; |
1121 scale /= 10; | 1087 scale /= 10; |
1122 while (fraction) { | 1088 } |
1123 buf[buf_size++] = '0' + fraction / scale; | 1089 return buf_size; |
1124 fraction %= scale; | 1090 } |
1125 scale /= 10; | 1091 CFX_ByteString CFX_ByteString::FormatFloat(FX_FLOAT d, int precision) { |
1126 } | 1092 FX_CHAR buf[32]; |
1127 return buf_size; | 1093 FX_STRSIZE len = FX_ftoa(d, buf); |
1128 } | 1094 return CFX_ByteString(buf, len); |
1129 CFX_ByteString CFX_ByteString::FormatFloat(FX_FLOAT d, int precision) | 1095 } |
1130 { | |
1131 FX_CHAR buf[32]; | |
1132 FX_STRSIZE len = FX_ftoa(d, buf); | |
1133 return CFX_ByteString(buf, len); | |
1134 } | |
OLD | NEW |