| 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 |