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 #ifndef CORE_INCLUDE_FXCRT_FX_STRING_H_ | 7 #ifndef CORE_INCLUDE_FXCRT_FX_STRING_H_ |
8 #define CORE_INCLUDE_FXCRT_FX_STRING_H_ | 8 #define CORE_INCLUDE_FXCRT_FX_STRING_H_ |
9 | 9 |
10 #include <stdint.h> // For intptr_t. | 10 #include <stdint.h> // For intptr_t. |
11 #include <algorithm> | 11 #include <algorithm> |
12 | 12 |
13 #include "fx_memory.h" | 13 #include "fx_memory.h" |
14 #include "fx_system.h" | 14 #include "fx_system.h" |
15 | 15 |
16 class CFX_BinaryBuf; | 16 class CFX_BinaryBuf; |
17 class CFX_ByteString; | 17 class CFX_ByteString; |
18 class CFX_WideString; | 18 class CFX_WideString; |
19 struct CFX_CharMap; | 19 struct CFX_CharMap; |
20 | 20 |
21 // An immutable string with caller-provided storage which must outlive the | 21 // An immutable string with caller-provided storage which must outlive the |
22 // string itself. | 22 // string itself. |
23 class CFX_ByteStringC | 23 class CFX_ByteStringC { |
24 { | 24 public: |
25 public: | 25 typedef FX_CHAR value_type; |
26 typedef FX_CHAR value_type; | 26 |
27 | 27 CFX_ByteStringC() { |
28 CFX_ByteStringC() | 28 m_Ptr = NULL; |
29 { | 29 m_Length = 0; |
30 m_Ptr = NULL; | 30 } |
31 m_Length = 0; | 31 |
32 } | 32 CFX_ByteStringC(const uint8_t* ptr, FX_STRSIZE size) { |
33 | 33 m_Ptr = ptr; |
34 CFX_ByteStringC(const uint8_t* ptr, FX_STRSIZE size) | 34 m_Length = size; |
35 { | 35 } |
36 m_Ptr = ptr; | 36 |
37 m_Length = size; | 37 CFX_ByteStringC(const FX_CHAR* ptr) { |
38 } | 38 m_Ptr = (const uint8_t*)ptr; |
39 | 39 m_Length = ptr ? FXSYS_strlen(ptr) : 0; |
40 CFX_ByteStringC(const FX_CHAR* ptr) | 40 } |
41 { | 41 |
42 m_Ptr = (const uint8_t*)ptr; | 42 // |ch| must be an lvalue that outlives the the CFX_ByteStringC. However, |
43 m_Length = ptr ? FXSYS_strlen(ptr) : 0; | 43 // the use of char rvalues are not caught at compile time. They are |
44 } | 44 // implicitly promoted to CFX_ByteString (see below) and then the |
45 | 45 // CFX_ByteStringC is constructed from the CFX_ByteString via the alternate |
46 // |ch| must be an lvalue that outlives the the CFX_ByteStringC. However, | 46 // constructor below. The CFX_ByteString then typically goes out of scope |
47 // the use of char rvalues are not caught at compile time. They are | 47 // and |m_Ptr| may be left pointing to invalid memory. Beware. |
48 // implicitly promoted to CFX_ByteString (see below) and then the | 48 // TODO(tsepez): Mark single-argument string constructors as explicit. |
49 // CFX_ByteStringC is constructed from the CFX_ByteString via the alternate | 49 CFX_ByteStringC(FX_CHAR& ch) { |
50 // constructor below. The CFX_ByteString then typically goes out of scope | 50 m_Ptr = (const uint8_t*)&ch; |
51 // and |m_Ptr| may be left pointing to invalid memory. Beware. | 51 m_Length = 1; |
52 // TODO(tsepez): Mark single-argument string constructors as explicit. | 52 } |
53 CFX_ByteStringC(FX_CHAR& ch) | 53 |
54 { | 54 CFX_ByteStringC(const FX_CHAR* ptr, FX_STRSIZE len) { |
55 m_Ptr = (const uint8_t*)&ch; | 55 m_Ptr = (const uint8_t*)ptr; |
56 m_Length = 1; | 56 m_Length = (len == -1) ? FXSYS_strlen(ptr) : len; |
57 } | 57 } |
58 | 58 |
59 CFX_ByteStringC(const FX_CHAR* ptr, FX_STRSIZE len) | 59 CFX_ByteStringC(const CFX_ByteStringC& src) { |
60 { | 60 m_Ptr = src.m_Ptr; |
61 m_Ptr = (const uint8_t*)ptr; | 61 m_Length = src.m_Length; |
62 m_Length = (len == -1) ? FXSYS_strlen(ptr) : len; | 62 } |
63 } | 63 |
64 | 64 CFX_ByteStringC(const CFX_ByteString& src); |
65 CFX_ByteStringC(const CFX_ByteStringC& src) | 65 |
66 { | 66 CFX_ByteStringC& operator=(const FX_CHAR* src) { |
67 m_Ptr = src.m_Ptr; | 67 m_Ptr = (const uint8_t*)src; |
68 m_Length = src.m_Length; | 68 m_Length = m_Ptr ? FXSYS_strlen(src) : 0; |
69 } | 69 return *this; |
70 | 70 } |
71 CFX_ByteStringC(const CFX_ByteString& src); | 71 |
72 | 72 CFX_ByteStringC& operator=(const CFX_ByteStringC& src) { |
73 CFX_ByteStringC& operator = (const FX_CHAR* src) | 73 m_Ptr = src.m_Ptr; |
74 { | 74 m_Length = src.m_Length; |
75 m_Ptr = (const uint8_t*)src; | 75 return *this; |
76 m_Length = m_Ptr ? FXSYS_strlen(src) : 0; | 76 } |
77 return *this; | 77 |
78 } | 78 CFX_ByteStringC& operator=(const CFX_ByteString& src); |
79 | 79 |
80 CFX_ByteStringC& operator = (const CFX_ByteStringC& src) | 80 bool operator==(const char* ptr) const { |
81 { | 81 return FXSYS_strlen(ptr) == m_Length && |
82 m_Ptr = src.m_Ptr; | 82 FXSYS_memcmp(ptr, m_Ptr, m_Length) == 0; |
83 m_Length = src.m_Length; | 83 } |
84 return *this; | 84 bool operator==(const CFX_ByteStringC& other) const { |
85 } | 85 return other.m_Length == m_Length && |
86 | 86 FXSYS_memcmp(other.m_Ptr, m_Ptr, m_Length) == 0; |
87 CFX_ByteStringC& operator = (const CFX_ByteString& src); | 87 } |
88 | 88 bool operator!=(const char* ptr) const { return !(*this == ptr); } |
89 bool operator== (const char* ptr) const { | 89 bool operator!=(const CFX_ByteStringC& other) const { |
90 return FXSYS_strlen(ptr) == m_Length && | 90 return !(*this == other); |
91 FXSYS_memcmp(ptr, m_Ptr, m_Length) == 0; | 91 } |
92 } | 92 |
93 bool operator== (const CFX_ByteStringC& other) const { | 93 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const; |
94 return other.m_Length == m_Length && | 94 |
95 FXSYS_memcmp(other.m_Ptr, m_Ptr, m_Length) == 0; | 95 const uint8_t* GetPtr() const { return m_Ptr; } |
96 } | 96 |
97 bool operator!= (const char* ptr) const { return !(*this == ptr); } | 97 const FX_CHAR* GetCStr() const { return (const FX_CHAR*)m_Ptr; } |
98 bool operator!= (const CFX_ByteStringC& other) const { | 98 |
99 return !(*this == other); | 99 FX_STRSIZE GetLength() const { return m_Length; } |
100 } | 100 |
101 | 101 bool IsEmpty() const { return m_Length == 0; } |
102 FX_DWORD» » GetID(FX_STRSIZE start_pos = 0) const; | 102 |
103 | 103 uint8_t GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } |
104 const uint8_t*» » GetPtr() const | 104 |
105 { | 105 CFX_ByteStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { |
106 return m_Ptr; | 106 if (index < 0) { |
107 } | 107 index = 0; |
108 | 108 } |
109 const FX_CHAR*» » GetCStr() const | 109 if (index > m_Length) { |
110 { | 110 return CFX_ByteStringC(); |
111 return (const FX_CHAR*)m_Ptr; | 111 } |
112 } | 112 if (count < 0 || count > m_Length - index) { |
113 | 113 count = m_Length - index; |
114 FX_STRSIZE» » GetLength() const | 114 } |
115 { | 115 return CFX_ByteStringC(m_Ptr + index, count); |
116 return m_Length; | 116 } |
117 } | 117 |
118 | 118 const uint8_t& operator[](size_t index) const { return m_Ptr[index]; } |
119 bool» » » IsEmpty() const | 119 |
120 { | 120 bool operator<(const CFX_ByteStringC& that) const { |
121 return m_Length == 0; | 121 int result = memcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)); |
122 } | 122 return result < 0 || (result == 0 && m_Length < that.m_Length); |
123 | 123 } |
124 uint8_t» » » GetAt(FX_STRSIZE index) const | 124 |
125 { | 125 protected: |
126 return m_Ptr[index]; | 126 const uint8_t* m_Ptr; |
127 } | 127 FX_STRSIZE m_Length; |
128 | 128 |
129 CFX_ByteStringC» Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const | 129 private: |
130 { | 130 void* operator new(size_t) throw() { return NULL; } |
131 if (index < 0) { | |
132 index = 0; | |
133 } | |
134 if (index > m_Length) { | |
135 return CFX_ByteStringC(); | |
136 } | |
137 if (count < 0 || count > m_Length - index) { | |
138 count = m_Length - index; | |
139 } | |
140 return CFX_ByteStringC(m_Ptr + index, count); | |
141 } | |
142 | |
143 const uint8_t& operator[] (size_t index) const | |
144 { | |
145 return m_Ptr[index]; | |
146 } | |
147 | |
148 bool operator< (const CFX_ByteStringC& that) const | |
149 { | |
150 int result = memcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)
); | |
151 return result < 0 || (result == 0 && m_Length < that.m_Length); | |
152 } | |
153 | |
154 protected: | |
155 const uint8_t*» » m_Ptr; | |
156 FX_STRSIZE» » m_Length; | |
157 | |
158 private: | |
159 void*» » » operator new (size_t) throw() | |
160 { | |
161 return NULL; | |
162 } | |
163 }; | 131 }; |
164 inline bool operator== (const char* lhs, const CFX_ByteStringC& rhs) { | 132 inline bool operator==(const char* lhs, const CFX_ByteStringC& rhs) { |
165 return rhs == lhs; | 133 return rhs == lhs; |
166 } | 134 } |
167 inline bool operator!= (const char* lhs, const CFX_ByteStringC& rhs) { | 135 inline bool operator!=(const char* lhs, const CFX_ByteStringC& rhs) { |
168 return rhs != lhs; | 136 return rhs != lhs; |
169 } | 137 } |
170 #define FX_BSTRC(str) CFX_ByteStringC(str, sizeof str-1) | 138 #define FX_BSTRC(str) CFX_ByteStringC(str, sizeof str - 1) |
171 #define FXBSTR_ID(c1, c2, c3, c4) ((c1 << 24) | (c2 << 16) | (c3 << 8) | (c4)) | 139 #define FXBSTR_ID(c1, c2, c3, c4) ((c1 << 24) | (c2 << 16) | (c3 << 8) | (c4)) |
172 | 140 |
173 // A mutable string with shared buffers using copy-on-write semantics that | 141 // A mutable string with shared buffers using copy-on-write semantics that |
174 // avoids the cost of std::string's iterator stability guarantees. | 142 // avoids the cost of std::string's iterator stability guarantees. |
175 class CFX_ByteString | 143 class CFX_ByteString { |
176 { | 144 public: |
177 public: | 145 typedef FX_CHAR value_type; |
178 typedef FX_CHAR value_type; | 146 |
179 | 147 CFX_ByteString() : m_pData(nullptr) {} |
180 CFX_ByteString() : m_pData(nullptr) { } | 148 |
181 | 149 // Copy constructor. |
182 // Copy constructor. | 150 CFX_ByteString(const CFX_ByteString& str); |
183 CFX_ByteString(const CFX_ByteString& str); | 151 |
184 | 152 // Move constructor. |
185 // Move constructor. | 153 inline CFX_ByteString(CFX_ByteString&& other) { |
186 inline CFX_ByteString(CFX_ByteString&& other) { | 154 m_pData = other.m_pData; |
187 m_pData = other.m_pData; | 155 other.m_pData = nullptr; |
188 other.m_pData = nullptr; | 156 } |
189 } | 157 |
190 | 158 CFX_ByteString(char ch); |
191 CFX_ByteString(char ch); | 159 CFX_ByteString(const FX_CHAR* ptr) |
192 CFX_ByteString(const FX_CHAR* ptr) | 160 : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) {} |
193 : CFX_ByteString(ptr, ptr ? FXSYS_strlen(ptr) : 0) { } | 161 |
194 | 162 CFX_ByteString(const FX_CHAR* ptr, FX_STRSIZE len); |
195 CFX_ByteString(const FX_CHAR* ptr, FX_STRSIZE len); | 163 CFX_ByteString(const uint8_t* ptr, FX_STRSIZE len); |
196 CFX_ByteString(const uint8_t* ptr, FX_STRSIZE len); | 164 |
197 | 165 CFX_ByteString(const CFX_ByteStringC& bstrc); |
198 CFX_ByteString(const CFX_ByteStringC& bstrc); | 166 CFX_ByteString(const CFX_ByteStringC& bstrc1, const CFX_ByteStringC& bstrc2); |
199 CFX_ByteString(const CFX_ByteStringC& bstrc1, const CFX_ByteStringC& bstrc2)
; | 167 |
200 | 168 ~CFX_ByteString(); |
201 ~CFX_ByteString(); | 169 |
202 | 170 static CFX_ByteString FromUnicode(const FX_WCHAR* ptr, FX_STRSIZE len = -1); |
203 static CFX_ByteString FromUnicode(const FX_WCHAR* ptr, FX_STRSIZE len
= -1); | 171 |
204 | 172 static CFX_ByteString FromUnicode(const CFX_WideString& str); |
205 static CFX_ByteString FromUnicode(const CFX_WideString& str); | 173 |
206 | 174 // Explicit conversion to raw string |
207 // Explicit conversion to raw string | 175 const FX_CHAR* c_str() const { return m_pData ? m_pData->m_String : ""; } |
208 const FX_CHAR* c_str() const | 176 |
209 { | 177 // Implicit conversion to C-style string -- deprecated |
210 return m_pData ? m_pData->m_String : ""; | 178 operator const FX_CHAR*() const { return m_pData ? m_pData->m_String : ""; } |
211 } | 179 |
212 | 180 operator const uint8_t*() const { |
213 // Implicit conversion to C-style string -- deprecated | 181 return m_pData ? (const uint8_t*)m_pData->m_String : NULL; |
214 operator const FX_CHAR*() const | 182 } |
215 { | 183 |
216 return m_pData ? m_pData->m_String : ""; | 184 FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } |
217 } | 185 |
218 | 186 bool IsEmpty() const { return !GetLength(); } |
219 operator const uint8_t*() const | 187 |
220 { | 188 int Compare(const CFX_ByteStringC& str) const; |
221 return m_pData ? (const uint8_t*)m_pData->m_String : NULL; | 189 |
222 } | 190 bool Equal(const char* ptr) const; |
223 | 191 bool Equal(const CFX_ByteStringC& str) const; |
224 FX_STRSIZE GetLength() const | 192 bool Equal(const CFX_ByteString& other) const; |
225 { | 193 |
226 return m_pData ? m_pData->m_nDataLength : 0; | 194 bool EqualNoCase(const CFX_ByteStringC& str) const; |
227 } | 195 |
228 | 196 bool operator==(const char* ptr) const { return Equal(ptr); } |
229 bool IsEmpty() const | 197 bool operator==(const CFX_ByteStringC& str) const { return Equal(str); } |
230 { | 198 bool operator==(const CFX_ByteString& other) const { return Equal(other); } |
231 return !GetLength(); | 199 |
232 } | 200 bool operator!=(const char* ptr) const { return !(*this == ptr); } |
233 | 201 bool operator!=(const CFX_ByteStringC& str) const { return !(*this == str); } |
234 int Compare(const CFX_ByteStringC& s
tr) const; | 202 bool operator!=(const CFX_ByteString& other) const { |
235 | 203 return !(*this == other); |
236 | 204 } |
237 bool Equal(const char* ptr) const; | 205 |
238 bool Equal(const CFX_ByteStringC& str) const; | 206 bool operator<(const CFX_ByteString& str) const { |
239 bool Equal(const CFX_ByteString& other) const; | 207 int result = FXSYS_memcmp(c_str(), str.c_str(), |
240 | 208 std::min(GetLength(), str.GetLength())); |
241 bool EqualNoCase(const CFX_ByteStringC& str) const; | 209 return result < 0 || (result == 0 && GetLength() < str.GetLength()); |
242 | 210 } |
243 bool operator== (const char* ptr) const { return Equal(ptr); } | 211 |
244 bool operator== (const CFX_ByteStringC& str) const { return Equal(str); } | 212 void Empty(); |
245 bool operator== (const CFX_ByteString& other) const { return Equal(other); } | 213 |
246 | 214 const CFX_ByteString& operator=(const FX_CHAR* str); |
247 bool operator!= (const char* ptr) const { return !(*this == ptr); } | 215 |
248 bool operator!= (const CFX_ByteStringC& str) const { | 216 const CFX_ByteString& operator=(const CFX_ByteStringC& bstrc); |
249 return !(*this == str); | 217 |
250 } | 218 const CFX_ByteString& operator=(const CFX_ByteString& stringSrc); |
251 bool operator!= (const CFX_ByteString& other) const { | 219 |
252 return !(*this == other); | 220 const CFX_ByteString& operator=(const CFX_BinaryBuf& buf); |
253 } | 221 |
254 | 222 void Load(const uint8_t* str, FX_STRSIZE len); |
255 bool operator< (const CFX_ByteString& str) const | 223 |
256 { | 224 const CFX_ByteString& operator+=(FX_CHAR ch); |
257 int result = FXSYS_memcmp(c_str(), str.c_str(), std::min(GetLength(), st
r.GetLength())); | 225 |
258 return result < 0 || (result == 0 && GetLength() < str.GetLength()); | 226 const CFX_ByteString& operator+=(const FX_CHAR* str); |
259 } | 227 |
260 | 228 const CFX_ByteString& operator+=(const CFX_ByteString& str); |
261 void Empty(); | 229 |
262 | 230 const CFX_ByteString& operator+=(const CFX_ByteStringC& bstrc); |
263 const CFX_ByteString& operator = (const FX_CHAR* str); | 231 |
264 | 232 uint8_t GetAt(FX_STRSIZE nIndex) const { |
265 const CFX_ByteString& operator = (const CFX_ByteStringC& bstrc); | 233 return m_pData ? m_pData->m_String[nIndex] : 0; |
266 | 234 } |
267 const CFX_ByteString& operator = (const CFX_ByteString& stringSrc); | 235 |
268 | 236 uint8_t operator[](FX_STRSIZE nIndex) const { |
269 const CFX_ByteString& operator = (const CFX_BinaryBuf& buf); | 237 return m_pData ? m_pData->m_String[nIndex] : 0; |
270 | 238 } |
271 void Load(const uint8_t* str, FX_STRS
IZE len); | 239 |
272 | 240 void SetAt(FX_STRSIZE nIndex, FX_CHAR ch); |
273 const CFX_ByteString& operator += (FX_CHAR ch); | 241 |
274 | 242 FX_STRSIZE Insert(FX_STRSIZE index, FX_CHAR ch); |
275 const CFX_ByteString& operator += (const FX_CHAR* str); | 243 |
276 | 244 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); |
277 const CFX_ByteString& operator += (const CFX_ByteString& str); | 245 |
278 | 246 void Format(const FX_CHAR* lpszFormat, ...); |
279 const CFX_ByteString& operator += (const CFX_ByteStringC& bstrc); | 247 |
280 | 248 void FormatV(const FX_CHAR* lpszFormat, va_list argList); |
281 uint8_t GetAt(FX_STRSIZE nIndex) const | 249 |
282 { | 250 void Reserve(FX_STRSIZE len); |
283 return m_pData ? m_pData->m_String[nIndex] : 0; | 251 |
284 } | 252 FX_CHAR* GetBuffer(FX_STRSIZE len); |
285 | 253 |
286 uint8_t operator[](FX_STRSIZE nIndex) co
nst | 254 void ReleaseBuffer(FX_STRSIZE len = -1); |
287 { | 255 |
288 return m_pData ? m_pData->m_String[nIndex] : 0; | 256 CFX_ByteString Mid(FX_STRSIZE first) const; |
289 } | 257 |
290 | 258 CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count) const; |
291 void SetAt(FX_STRSIZE nIndex, FX_CHAR
ch); | 259 |
292 | 260 CFX_ByteString Left(FX_STRSIZE count) const; |
293 FX_STRSIZE Insert(FX_STRSIZE index, FX_CHAR ch); | 261 |
294 | 262 CFX_ByteString Right(FX_STRSIZE count) const; |
295 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE coun
t = 1); | 263 |
296 | 264 FX_STRSIZE Find(const CFX_ByteStringC& lpszSub, FX_STRSIZE start = 0) const; |
297 | 265 |
298 void Format(const FX_CHAR* lpszFormat
, ... ); | 266 FX_STRSIZE Find(FX_CHAR ch, FX_STRSIZE start = 0) const; |
299 | 267 |
300 void FormatV(const FX_CHAR* lpszForma
t, va_list argList); | 268 FX_STRSIZE ReverseFind(FX_CHAR ch) const; |
301 | 269 |
302 | 270 void MakeLower(); |
303 void Reserve(FX_STRSIZE len); | 271 |
304 | 272 void MakeUpper(); |
305 FX_CHAR* GetBuffer(FX_STRSIZE len); | 273 |
306 | 274 void TrimRight(); |
307 void ReleaseBuffer(FX_STRSIZE len = -
1); | 275 |
308 | 276 void TrimRight(FX_CHAR chTarget); |
309 CFX_ByteString Mid(FX_STRSIZE first) const; | 277 |
310 | 278 void TrimRight(const CFX_ByteStringC& lpszTargets); |
311 CFX_ByteString Mid(FX_STRSIZE first, FX_STRSIZE count)
const; | 279 |
312 | 280 void TrimLeft(); |
313 CFX_ByteString Left(FX_STRSIZE count) const; | 281 |
314 | 282 void TrimLeft(FX_CHAR chTarget); |
315 CFX_ByteString Right(FX_STRSIZE count) const; | 283 |
316 | 284 void TrimLeft(const CFX_ByteStringC& lpszTargets); |
317 FX_STRSIZE Find(const CFX_ByteStringC& lpszSub, FX_
STRSIZE start = 0) const; | 285 |
318 | 286 FX_STRSIZE Replace(const CFX_ByteStringC& lpszOld, |
319 FX_STRSIZE Find(FX_CHAR ch, FX_STRSIZE start = 0) c
onst; | 287 const CFX_ByteStringC& lpszNew); |
320 | 288 |
321 FX_STRSIZE ReverseFind(FX_CHAR ch) const; | 289 FX_STRSIZE Remove(FX_CHAR ch); |
322 | 290 |
323 void MakeLower(); | 291 CFX_WideString UTF8Decode() const; |
324 | 292 |
325 void MakeUpper(); | 293 void ConvertFrom(const CFX_WideString& str, CFX_CharMap* pCharMap = NULL); |
326 | 294 |
327 void TrimRight(); | 295 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const; |
328 | 296 |
329 void TrimRight(FX_CHAR chTarget); | 297 #define FXFORMAT_SIGNED 1 |
330 | 298 #define FXFORMAT_HEX 2 |
331 void TrimRight(const CFX_ByteStringC&
lpszTargets); | 299 #define FXFORMAT_CAPITAL 4 |
332 | 300 |
333 void TrimLeft(); | 301 static CFX_ByteString FormatInteger(int i, FX_DWORD flags = 0); |
334 | 302 static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0); |
335 void TrimLeft(FX_CHAR chTarget); | 303 |
336 | 304 protected: |
337 void TrimLeft(const CFX_ByteStringC&
lpszTargets); | 305 // To ensure ref counts do not overflow, consider the worst possible case: |
338 | 306 // the entire address space contains nothing but pointers to this object. |
339 FX_STRSIZE Replace(const CFX_ByteStringC& lpszOld,
const CFX_ByteStringC& lpszNew); | 307 // Since the count increments with each new pointer, the largest value is |
340 | 308 // the number of pointers that can fit into the address space. The size of |
341 FX_STRSIZE Remove(FX_CHAR ch); | 309 // the address space itself is a good upper bound on it; we need not go |
342 | 310 // larger. |
343 CFX_WideString UTF8Decode() const; | 311 class StringData { |
344 | 312 public: |
345 void ConvertFrom(const CFX_WideString
& str, CFX_CharMap* pCharMap = NULL); | 313 static StringData* Create(int nLen); |
346 | 314 void Retain() { ++m_nRefs; } |
347 FX_DWORD GetID(FX_STRSIZE start_pos = 0) const; | 315 void Release() { |
348 | 316 if (--m_nRefs <= 0) |
349 #define FXFORMAT_SIGNED 1 | 317 FX_Free(this); |
350 #define FXFORMAT_HEX 2 | 318 } |
351 #define FXFORMAT_CAPITAL 4 | 319 |
352 | 320 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support. |
353 static CFX_ByteString FormatInteger(int i, FX_DWORD flags = 0); | 321 FX_STRSIZE m_nDataLength; |
354 static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0); | 322 FX_STRSIZE m_nAllocLength; |
355 | 323 FX_CHAR m_String[1]; |
356 protected: | 324 |
357 // To ensure ref counts do not overflow, consider the worst possible case: | 325 private: |
358 // the entire address space contains nothing but pointers to this object. | 326 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen) |
359 // Since the count increments with each new pointer, the largest value is | 327 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) { |
360 // the number of pointers that can fit into the address space. The size of | 328 FXSYS_assert(dataLen >= 0); |
361 // the address space itself is a good upper bound on it; we need not go | 329 FXSYS_assert(allocLen >= 0); |
362 // larger. | 330 FXSYS_assert(dataLen <= allocLen); |
363 class StringData { | 331 m_String[dataLen] = 0; |
364 public: | 332 } |
365 static StringData* Create(int nLen); | 333 ~StringData() = delete; |
366 void Retain() { ++m_nRefs; } | 334 }; |
367 void Release() { if (--m_nRefs <= 0) FX_Free(this); } | 335 |
368 | 336 void AllocCopy(CFX_ByteString& dest, |
369 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support. | 337 FX_STRSIZE nCopyLen, |
370 FX_STRSIZE m_nDataLength; | 338 FX_STRSIZE nCopyIndex) const; |
371 FX_STRSIZE m_nAllocLength; | 339 void AssignCopy(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData); |
372 FX_CHAR m_String[1]; | 340 void ConcatCopy(FX_STRSIZE nSrc1Len, |
373 | 341 const FX_CHAR* lpszSrc1Data, |
374 private: | 342 FX_STRSIZE nSrc2Len, |
375 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen) | 343 const FX_CHAR* lpszSrc2Data); |
376 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) { | 344 void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_CHAR* lpszSrcData); |
377 FXSYS_assert(dataLen >= 0); | 345 void CopyBeforeWrite(); |
378 FXSYS_assert(allocLen >= 0); | 346 void AllocBeforeWrite(FX_STRSIZE nLen); |
379 FXSYS_assert(dataLen <= allocLen); | 347 |
380 m_String[dataLen] = 0; | 348 StringData* m_pData; |
381 } | 349 friend class fxcrt_ByteStringConcatInPlace_Test; |
382 ~StringData() = delete; | |
383 }; | |
384 | |
385 void AllocCopy(CFX_ByteString& dest,
FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const; | |
386 void AssignCopy(FX_STRSIZE nSrcLen, c
onst FX_CHAR* lpszSrcData); | |
387 void ConcatCopy(FX_STRSIZE nSrc1Len,
const FX_CHAR* lpszSrc1Data, FX_STRSIZE nSrc2Len, const FX_CHAR* lpszSrc2Data); | |
388 void ConcatInPlace(FX_STRSIZE nSrcLen
, const FX_CHAR* lpszSrcData); | |
389 void CopyBeforeWrite(); | |
390 void AllocBeforeWrite(FX_STRSIZE nLen
); | |
391 | |
392 StringData* m_pData; | |
393 friend class fxcrt_ByteStringConcatInPlace_Test; | |
394 }; | 350 }; |
395 inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src) | 351 inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src) { |
396 { | 352 m_Ptr = (const uint8_t*)src; |
397 m_Ptr = (const uint8_t*)src; | 353 m_Length = src.GetLength(); |
398 m_Length = src.GetLength(); | 354 } |
399 } | 355 inline CFX_ByteStringC& CFX_ByteStringC::operator=(const CFX_ByteString& src) { |
400 inline CFX_ByteStringC& CFX_ByteStringC::operator = (const CFX_ByteString& src) | 356 m_Ptr = (const uint8_t*)src; |
401 { | 357 m_Length = src.GetLength(); |
402 m_Ptr = (const uint8_t*)src; | 358 return *this; |
403 m_Length = src.GetLength(); | 359 } |
| 360 |
| 361 inline bool operator==(const char* lhs, const CFX_ByteString& rhs) { |
| 362 return rhs == lhs; |
| 363 } |
| 364 inline bool operator==(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { |
| 365 return rhs == lhs; |
| 366 } |
| 367 inline bool operator!=(const char* lhs, const CFX_ByteString& rhs) { |
| 368 return rhs != lhs; |
| 369 } |
| 370 inline bool operator!=(const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { |
| 371 return rhs != lhs; |
| 372 } |
| 373 |
| 374 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, |
| 375 const CFX_ByteStringC& str2) { |
| 376 return CFX_ByteString(str1, str2); |
| 377 } |
| 378 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, |
| 379 const FX_CHAR* str2) { |
| 380 return CFX_ByteString(str1, str2); |
| 381 } |
| 382 inline CFX_ByteString operator+(const FX_CHAR* str1, |
| 383 const CFX_ByteStringC& str2) { |
| 384 return CFX_ByteString(str1, str2); |
| 385 } |
| 386 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, FX_CHAR ch) { |
| 387 return CFX_ByteString(str1, CFX_ByteStringC(ch)); |
| 388 } |
| 389 inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteStringC& str2) { |
| 390 return CFX_ByteString(ch, str2); |
| 391 } |
| 392 inline CFX_ByteString operator+(const CFX_ByteString& str1, |
| 393 const CFX_ByteString& str2) { |
| 394 return CFX_ByteString(str1, str2); |
| 395 } |
| 396 inline CFX_ByteString operator+(const CFX_ByteString& str1, FX_CHAR ch) { |
| 397 return CFX_ByteString(str1, CFX_ByteStringC(ch)); |
| 398 } |
| 399 inline CFX_ByteString operator+(FX_CHAR ch, const CFX_ByteString& str2) { |
| 400 return CFX_ByteString(ch, str2); |
| 401 } |
| 402 inline CFX_ByteString operator+(const CFX_ByteString& str1, |
| 403 const FX_CHAR* str2) { |
| 404 return CFX_ByteString(str1, str2); |
| 405 } |
| 406 inline CFX_ByteString operator+(const FX_CHAR* str1, |
| 407 const CFX_ByteString& str2) { |
| 408 return CFX_ByteString(str1, str2); |
| 409 } |
| 410 inline CFX_ByteString operator+(const CFX_ByteString& str1, |
| 411 const CFX_ByteStringC& str2) { |
| 412 return CFX_ByteString(str1, str2); |
| 413 } |
| 414 inline CFX_ByteString operator+(const CFX_ByteStringC& str1, |
| 415 const CFX_ByteString& str2) { |
| 416 return CFX_ByteString(str1, str2); |
| 417 } |
| 418 class CFX_WideStringC { |
| 419 public: |
| 420 typedef FX_WCHAR value_type; |
| 421 |
| 422 CFX_WideStringC() { |
| 423 m_Ptr = NULL; |
| 424 m_Length = 0; |
| 425 } |
| 426 |
| 427 CFX_WideStringC(const FX_WCHAR* ptr) { |
| 428 m_Ptr = ptr; |
| 429 m_Length = ptr ? FXSYS_wcslen(ptr) : 0; |
| 430 } |
| 431 |
| 432 CFX_WideStringC(FX_WCHAR& ch) { |
| 433 m_Ptr = &ch; |
| 434 m_Length = 1; |
| 435 } |
| 436 |
| 437 CFX_WideStringC(const FX_WCHAR* ptr, FX_STRSIZE len) { |
| 438 m_Ptr = ptr; |
| 439 m_Length = (len == -1) ? FXSYS_wcslen(ptr) : len; |
| 440 } |
| 441 |
| 442 CFX_WideStringC(const CFX_WideStringC& src) { |
| 443 m_Ptr = src.m_Ptr; |
| 444 m_Length = src.m_Length; |
| 445 } |
| 446 |
| 447 CFX_WideStringC(const CFX_WideString& src); |
| 448 |
| 449 CFX_WideStringC& operator=(const FX_WCHAR* src) { |
| 450 m_Ptr = src; |
| 451 m_Length = FXSYS_wcslen(src); |
404 return *this; | 452 return *this; |
405 } | 453 } |
406 | 454 |
407 inline bool operator== (const char* lhs, const CFX_ByteString& rhs) { | 455 CFX_WideStringC& operator=(const CFX_WideStringC& src) { |
408 return rhs == lhs; | 456 m_Ptr = src.m_Ptr; |
409 } | 457 m_Length = src.m_Length; |
410 inline bool operator== (const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { | 458 return *this; |
411 return rhs == lhs; | 459 } |
412 } | 460 |
413 inline bool operator!= (const char* lhs, const CFX_ByteString& rhs) { | 461 CFX_WideStringC& operator=(const CFX_WideString& src); |
414 return rhs != lhs; | 462 |
415 } | 463 bool operator==(const wchar_t* ptr) const { |
416 inline bool operator!= (const CFX_ByteStringC& lhs, const CFX_ByteString& rhs) { | 464 return FXSYS_wcslen(ptr) == m_Length && wmemcmp(ptr, m_Ptr, m_Length) == 0; |
417 return rhs != lhs; | 465 } |
418 } | 466 bool operator==(const CFX_WideStringC& str) const { |
419 | 467 return str.m_Length == m_Length && wmemcmp(str.m_Ptr, m_Ptr, m_Length) == 0; |
420 inline CFX_ByteString operator + (const CFX_ByteStringC& str1, const CFX_ByteStr
ingC& str2) | 468 } |
421 { | 469 bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } |
422 return CFX_ByteString(str1, str2); | 470 bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } |
423 } | 471 |
424 inline CFX_ByteString operator + (const CFX_ByteStringC& str1, const FX_CHAR* st
r2) | 472 const FX_WCHAR* GetPtr() const { return m_Ptr; } |
425 { | 473 |
426 return CFX_ByteString(str1, str2); | 474 FX_STRSIZE GetLength() const { return m_Length; } |
427 } | 475 |
428 inline CFX_ByteString operator + (const FX_CHAR* str1, const CFX_ByteStringC& st
r2) | 476 bool IsEmpty() const { return m_Length == 0; } |
429 { | 477 |
430 return CFX_ByteString(str1, str2); | 478 FX_WCHAR GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } |
431 } | 479 |
432 inline CFX_ByteString operator + (const CFX_ByteStringC& str1, FX_CHAR ch) | 480 CFX_WideStringC Left(FX_STRSIZE count) const { |
433 { | 481 if (count < 1) { |
434 return CFX_ByteString(str1, CFX_ByteStringC(ch)); | 482 return CFX_WideStringC(); |
435 } | 483 } |
436 inline CFX_ByteString operator + (FX_CHAR ch, const CFX_ByteStringC& str2) | 484 if (count > m_Length) { |
437 { | 485 count = m_Length; |
438 return CFX_ByteString(ch, str2); | 486 } |
439 } | 487 return CFX_WideStringC(m_Ptr, count); |
440 inline CFX_ByteString operator + (const CFX_ByteString& str1, const CFX_ByteStri
ng& str2) | 488 } |
441 { | 489 |
442 return CFX_ByteString(str1, str2); | 490 CFX_WideStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { |
443 } | 491 if (index < 0) { |
444 inline CFX_ByteString operator + (const CFX_ByteString& str1, FX_CHAR ch) | 492 index = 0; |
445 { | 493 } |
446 return CFX_ByteString(str1, CFX_ByteStringC(ch)); | 494 if (index > m_Length) { |
447 } | 495 return CFX_WideStringC(); |
448 inline CFX_ByteString operator + (FX_CHAR ch, const CFX_ByteString& str2) | 496 } |
449 { | 497 if (count < 0 || count > m_Length - index) { |
450 return CFX_ByteString(ch, str2); | 498 count = m_Length - index; |
451 } | 499 } |
452 inline CFX_ByteString operator + (const CFX_ByteString& str1, const FX_CHAR* str
2) | 500 return CFX_WideStringC(m_Ptr + index, count); |
453 { | 501 } |
454 return CFX_ByteString(str1, str2); | 502 |
455 } | 503 CFX_WideStringC Right(FX_STRSIZE count) const { |
456 inline CFX_ByteString operator + (const FX_CHAR* str1, const CFX_ByteString& str
2) | 504 if (count < 1) { |
457 { | 505 return CFX_WideStringC(); |
458 return CFX_ByteString(str1, str2); | 506 } |
459 } | 507 if (count > m_Length) { |
460 inline CFX_ByteString operator + (const CFX_ByteString& str1, const CFX_ByteStri
ngC& str2) | 508 count = m_Length; |
461 { | 509 } |
462 return CFX_ByteString(str1, str2); | 510 return CFX_WideStringC(m_Ptr + m_Length - count, count); |
463 } | 511 } |
464 inline CFX_ByteString operator + (const CFX_ByteStringC& str1, const CFX_ByteStr
ing& str2) | 512 |
465 { | 513 const FX_WCHAR& operator[](size_t index) const { return m_Ptr[index]; } |
466 return CFX_ByteString(str1, str2); | 514 |
467 } | 515 bool operator<(const CFX_WideStringC& that) const { |
468 class CFX_WideStringC | 516 int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)); |
469 { | 517 return result < 0 || (result == 0 && m_Length < that.m_Length); |
470 public: | 518 } |
471 typedef FX_WCHAR value_type; | 519 |
472 | 520 protected: |
473 CFX_WideStringC() | 521 const FX_WCHAR* m_Ptr; |
474 { | 522 FX_STRSIZE m_Length; |
475 m_Ptr = NULL; | 523 |
476 m_Length = 0; | 524 private: |
477 } | 525 void* operator new(size_t) throw() { return NULL; } |
478 | |
479 CFX_WideStringC(const FX_WCHAR* ptr) | |
480 { | |
481 m_Ptr = ptr; | |
482 m_Length = ptr ? FXSYS_wcslen(ptr) : 0; | |
483 } | |
484 | |
485 CFX_WideStringC(FX_WCHAR& ch) | |
486 { | |
487 m_Ptr = &ch; | |
488 m_Length = 1; | |
489 } | |
490 | |
491 CFX_WideStringC(const FX_WCHAR* ptr, FX_STRSIZE len) | |
492 { | |
493 m_Ptr = ptr; | |
494 m_Length = (len == -1) ? FXSYS_wcslen(ptr) : len; | |
495 } | |
496 | |
497 CFX_WideStringC(const CFX_WideStringC& src) | |
498 { | |
499 m_Ptr = src.m_Ptr; | |
500 m_Length = src.m_Length; | |
501 } | |
502 | |
503 CFX_WideStringC(const CFX_WideString& src); | |
504 | |
505 CFX_WideStringC& operator = (const FX_WCHAR* src) | |
506 { | |
507 m_Ptr = src; | |
508 m_Length = FXSYS_wcslen(src); | |
509 return *this; | |
510 } | |
511 | |
512 CFX_WideStringC& operator = (const CFX_WideStringC& src) | |
513 { | |
514 m_Ptr = src.m_Ptr; | |
515 m_Length = src.m_Length; | |
516 return *this; | |
517 } | |
518 | |
519 CFX_WideStringC& operator = (const CFX_WideString& src); | |
520 | |
521 bool operator== (const wchar_t* ptr) const { | |
522 return FXSYS_wcslen(ptr) == m_Length && | |
523 wmemcmp(ptr, m_Ptr, m_Length) == 0; | |
524 } | |
525 bool operator== (const CFX_WideStringC& str) const { | |
526 return str.m_Length == m_Length && | |
527 wmemcmp(str.m_Ptr, m_Ptr, m_Length) == 0; | |
528 } | |
529 bool operator!= (const wchar_t* ptr) const { return !(*this == ptr); } | |
530 bool operator!= (const CFX_WideStringC& str) const { | |
531 return !(*this == str); | |
532 } | |
533 | |
534 const FX_WCHAR*» » GetPtr() const | |
535 { | |
536 return m_Ptr; | |
537 } | |
538 | |
539 FX_STRSIZE» » GetLength() const | |
540 { | |
541 return m_Length; | |
542 } | |
543 | |
544 bool» » » IsEmpty() const | |
545 { | |
546 return m_Length == 0; | |
547 } | |
548 | |
549 FX_WCHAR» » GetAt(FX_STRSIZE index) const | |
550 { | |
551 return m_Ptr[index]; | |
552 } | |
553 | |
554 CFX_WideStringC» Left(FX_STRSIZE count) const | |
555 { | |
556 if (count < 1) { | |
557 return CFX_WideStringC(); | |
558 } | |
559 if (count > m_Length) { | |
560 count = m_Length; | |
561 } | |
562 return CFX_WideStringC(m_Ptr, count); | |
563 } | |
564 | |
565 CFX_WideStringC» Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const | |
566 { | |
567 if (index < 0) { | |
568 index = 0; | |
569 } | |
570 if (index > m_Length) { | |
571 return CFX_WideStringC(); | |
572 } | |
573 if (count < 0 || count > m_Length - index) { | |
574 count = m_Length - index; | |
575 } | |
576 return CFX_WideStringC(m_Ptr + index, count); | |
577 } | |
578 | |
579 CFX_WideStringC» Right(FX_STRSIZE count) const | |
580 { | |
581 if (count < 1) { | |
582 return CFX_WideStringC(); | |
583 } | |
584 if (count > m_Length) { | |
585 count = m_Length; | |
586 } | |
587 return CFX_WideStringC(m_Ptr + m_Length - count, count); | |
588 } | |
589 | |
590 const FX_WCHAR& operator[] (size_t index) const | |
591 { | |
592 return m_Ptr[index]; | |
593 } | |
594 | |
595 bool operator< (const CFX_WideStringC& that) const | |
596 { | |
597 int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length
)); | |
598 return result < 0 || (result == 0 && m_Length < that.m_Length); | |
599 } | |
600 | |
601 protected: | |
602 const FX_WCHAR*» » m_Ptr; | |
603 FX_STRSIZE» » m_Length; | |
604 | |
605 private: | |
606 void*» » » operator new (size_t) throw() | |
607 { | |
608 return NULL; | |
609 } | |
610 }; | 526 }; |
611 inline bool operator== (const wchar_t* lhs, const CFX_WideStringC& rhs) { | 527 inline bool operator==(const wchar_t* lhs, const CFX_WideStringC& rhs) { |
612 return rhs == lhs; | 528 return rhs == lhs; |
613 } | 529 } |
614 inline bool operator!= (const wchar_t* lhs, const CFX_WideStringC& rhs) { | 530 inline bool operator!=(const wchar_t* lhs, const CFX_WideStringC& rhs) { |
615 return rhs != lhs; | 531 return rhs != lhs; |
616 } | 532 } |
617 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1) | 533 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1) |
618 | 534 |
619 // A mutable string with shared buffers using copy-on-write semantics that | 535 // A mutable string with shared buffers using copy-on-write semantics that |
620 // avoids the cost of std::string's iterator stability guarantees. | 536 // avoids the cost of std::string's iterator stability guarantees. |
621 class CFX_WideString | 537 class CFX_WideString { |
622 { | 538 public: |
623 public: | 539 typedef FX_WCHAR value_type; |
624 typedef FX_WCHAR value_type; | 540 |
625 | 541 CFX_WideString() : m_pData(nullptr) {} |
626 CFX_WideString() : m_pData(nullptr) { } | 542 |
627 | 543 // Copy constructor. |
628 // Copy constructor. | 544 CFX_WideString(const CFX_WideString& str); |
629 CFX_WideString(const CFX_WideString& str); | 545 |
630 | 546 // Move constructor. |
631 // Move constructor. | 547 inline CFX_WideString(CFX_WideString&& other) { |
632 inline CFX_WideString(CFX_WideString&& other) { | 548 m_pData = other.m_pData; |
633 m_pData = other.m_pData; | 549 other.m_pData = nullptr; |
634 other.m_pData = nullptr; | 550 } |
635 } | 551 |
636 | 552 CFX_WideString(const FX_WCHAR* ptr) |
637 CFX_WideString(const FX_WCHAR* ptr) | 553 : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) {} |
638 : CFX_WideString(ptr, ptr ? FXSYS_wcslen(ptr) : 0) { } | 554 |
639 | 555 CFX_WideString(const FX_WCHAR* ptr, FX_STRSIZE len); |
640 CFX_WideString(const FX_WCHAR* ptr, FX_STRSIZE len); | 556 |
641 | 557 CFX_WideString(FX_WCHAR ch); |
642 CFX_WideString(FX_WCHAR ch); | 558 |
643 | 559 CFX_WideString(const CFX_WideStringC& str); |
644 CFX_WideString(const CFX_WideStringC& str); | 560 |
645 | 561 CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2); |
646 CFX_WideString(const CFX_WideStringC& str1, const CFX_WideStringC& str2); | 562 |
647 | 563 ~CFX_WideString(); |
648 ~CFX_WideString(); | 564 |
649 | 565 static CFX_WideString FromLocal(const char* str, FX_STRSIZE len = -1); |
650 static CFX_WideString FromLocal(const char* str, FX_STRSIZE len = -1); | 566 |
651 | 567 static CFX_WideString FromUTF8(const char* str, FX_STRSIZE len); |
652 static CFX_WideString FromUTF8(const char* str, FX_STRSIZE len); | 568 |
653 | 569 static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZE len); |
654 static CFX_WideString FromUTF16LE(const unsigned short* str, FX_STRSIZ
E len); | 570 |
655 | 571 static FX_STRSIZE WStringLength(const unsigned short* str); |
656 static FX_STRSIZE WStringLength(const unsigned short* str); | 572 |
657 | 573 // Explicit conversion to raw string |
658 // Explicit conversion to raw string | 574 const FX_WCHAR* c_str() const { return m_pData ? m_pData->m_String : L""; } |
659 const FX_WCHAR* c_str() const | 575 |
660 { | 576 // Implicit conversion to C-style wide string -- deprecated |
661 return m_pData ? m_pData->m_String : L""; | 577 operator const FX_WCHAR*() const { return m_pData ? m_pData->m_String : L""; } |
662 } | 578 |
663 | 579 void Empty(); |
664 // Implicit conversion to C-style wide string -- deprecated | 580 |
665 operator const FX_WCHAR*() const | 581 FX_BOOL IsEmpty() const { return !GetLength(); } |
666 { | 582 |
667 return m_pData ? m_pData->m_String : L""; | 583 FX_STRSIZE GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; } |
668 } | 584 |
669 | 585 const CFX_WideString& operator=(const FX_WCHAR* str); |
670 void Empty(); | 586 |
671 | 587 const CFX_WideString& operator=(const CFX_WideString& stringSrc); |
672 | 588 |
673 FX_BOOL IsEmpty() const | 589 const CFX_WideString& operator=(const CFX_WideStringC& stringSrc); |
674 { | 590 |
675 return !GetLength(); | 591 const CFX_WideString& operator+=(const FX_WCHAR* str); |
676 } | 592 |
677 | 593 const CFX_WideString& operator+=(FX_WCHAR ch); |
678 FX_STRSIZE GetLength() const | 594 |
679 { | 595 const CFX_WideString& operator+=(const CFX_WideString& str); |
680 return m_pData ? m_pData->m_nDataLength : 0; | 596 |
681 } | 597 const CFX_WideString& operator+=(const CFX_WideStringC& str); |
682 | 598 |
683 const CFX_WideString& operator = (const FX_WCHAR* str); | 599 bool operator==(const wchar_t* ptr) const { return Equal(ptr); } |
684 | 600 bool operator==(const CFX_WideStringC& str) const { return Equal(str); } |
685 const CFX_WideString& operator =(const CFX_WideString& stringSrc); | 601 bool operator==(const CFX_WideString& other) const { return Equal(other); } |
686 | 602 |
687 const CFX_WideString& operator =(const CFX_WideStringC& stringSrc); | 603 bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } |
688 | 604 bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } |
689 const CFX_WideString& operator += (const FX_WCHAR* str); | 605 bool operator!=(const CFX_WideString& other) const { |
690 | 606 return !(*this == other); |
691 const CFX_WideString& operator += (FX_WCHAR ch); | 607 } |
692 | 608 |
693 const CFX_WideString& operator += (const CFX_WideString& str); | 609 bool operator<(const CFX_WideString& str) const { |
694 | 610 int result = |
695 const CFX_WideString& operator += (const CFX_WideStringC& str); | 611 wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.GetLength())); |
696 | 612 return result < 0 || (result == 0 && GetLength() < str.GetLength()); |
697 bool operator== (const wchar_t* ptr) const { return Equal(ptr); } | 613 } |
698 bool operator== (const CFX_WideStringC& str) const { return Equal(str); } | 614 |
699 bool operator== (const CFX_WideString& other) const { return Equal(other); } | 615 FX_WCHAR GetAt(FX_STRSIZE nIndex) const { |
700 | 616 return m_pData ? m_pData->m_String[nIndex] : 0; |
701 bool operator!= (const wchar_t* ptr) const { return !(*this == ptr); } | 617 } |
702 bool operator!= (const CFX_WideStringC& str) const { | 618 |
703 return !(*this == str); | 619 FX_WCHAR operator[](FX_STRSIZE nIndex) const { |
704 } | 620 return m_pData ? m_pData->m_String[nIndex] : 0; |
705 bool operator!= (const CFX_WideString& other) const { | 621 } |
706 return !(*this == other); | 622 |
707 } | 623 void SetAt(FX_STRSIZE nIndex, FX_WCHAR ch); |
708 | 624 |
709 bool operator< (const CFX_WideString& str) const { | 625 int Compare(const FX_WCHAR* str) const; |
710 int result = wmemcmp(c_str(), str.c_str(), std::min(GetLength(), str.Get
Length())); | 626 |
711 return result < 0 || (result == 0 && GetLength() < str.GetLength()); | 627 int Compare(const CFX_WideString& str) const; |
712 } | 628 |
713 | 629 int CompareNoCase(const FX_WCHAR* str) const; |
714 FX_WCHAR GetAt(FX_STRSIZE nIndex) const | 630 |
715 { | 631 bool Equal(const wchar_t* ptr) const; |
716 return m_pData ? m_pData->m_String[nIndex] : 0; | 632 bool Equal(const CFX_WideStringC& str) const; |
717 } | 633 bool Equal(const CFX_WideString& other) const; |
718 | 634 |
719 FX_WCHAR operator[](FX_STRSIZE nIndex) const | 635 CFX_WideString Mid(FX_STRSIZE first) const; |
720 { | 636 |
721 return m_pData ? m_pData->m_String[nIndex] : 0; | 637 CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count) const; |
722 } | 638 |
723 | 639 CFX_WideString Left(FX_STRSIZE count) const; |
724 void SetAt(FX_STRSIZE nIndex, FX_WCHA
R ch); | 640 |
725 | 641 CFX_WideString Right(FX_STRSIZE count) const; |
726 int Compare(const FX_WCHAR* str) con
st; | 642 |
727 | 643 FX_STRSIZE Insert(FX_STRSIZE index, FX_WCHAR ch); |
728 int Compare(const CFX_WideString& st
r) const; | 644 |
729 | 645 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE count = 1); |
730 int CompareNoCase(const FX_WCHAR* st
r) const; | 646 |
731 | 647 void Format(const FX_WCHAR* lpszFormat, ...); |
732 bool Equal(const wchar_t* ptr) const; | 648 |
733 bool Equal(const CFX_WideStringC& str) const; | 649 void FormatV(const FX_WCHAR* lpszFormat, va_list argList); |
734 bool Equal(const CFX_WideString& other) const; | 650 |
735 | 651 void MakeLower(); |
736 CFX_WideString Mid(FX_STRSIZE first) const; | 652 |
737 | 653 void MakeUpper(); |
738 CFX_WideString Mid(FX_STRSIZE first, FX_STRSIZE count)
const; | 654 |
739 | 655 void TrimRight(); |
740 CFX_WideString Left(FX_STRSIZE count) const; | 656 |
741 | 657 void TrimRight(FX_WCHAR chTarget); |
742 CFX_WideString Right(FX_STRSIZE count) const; | 658 |
743 | 659 void TrimRight(const FX_WCHAR* lpszTargets); |
744 FX_STRSIZE Insert(FX_STRSIZE index, FX_WCHAR ch); | 660 |
745 | 661 void TrimLeft(); |
746 FX_STRSIZE Delete(FX_STRSIZE index, FX_STRSIZE coun
t = 1); | 662 |
747 | 663 void TrimLeft(FX_WCHAR chTarget); |
748 void Format(const FX_WCHAR* lpszForma
t, ... ); | 664 |
749 | 665 void TrimLeft(const FX_WCHAR* lpszTargets); |
750 void FormatV(const FX_WCHAR* lpszForm
at, va_list argList); | 666 |
751 | 667 void Reserve(FX_STRSIZE len); |
752 void MakeLower(); | 668 |
753 | 669 FX_WCHAR* GetBuffer(FX_STRSIZE len); |
754 void MakeUpper(); | 670 |
755 | 671 void ReleaseBuffer(FX_STRSIZE len = -1); |
756 void TrimRight(); | 672 |
757 | 673 int GetInteger() const; |
758 void TrimRight(FX_WCHAR chTarget); | 674 |
759 | 675 FX_FLOAT GetFloat() const; |
760 void TrimRight(const FX_WCHAR* lpszTa
rgets); | 676 |
761 | 677 FX_STRSIZE Find(const FX_WCHAR* lpszSub, FX_STRSIZE start = 0) const; |
762 void TrimLeft(); | 678 |
763 | 679 FX_STRSIZE Find(FX_WCHAR ch, FX_STRSIZE start = 0) const; |
764 void TrimLeft(FX_WCHAR chTarget); | 680 |
765 | 681 FX_STRSIZE Replace(const FX_WCHAR* lpszOld, const FX_WCHAR* lpszNew); |
766 void TrimLeft(const FX_WCHAR* lpszTar
gets); | 682 |
767 | 683 FX_STRSIZE Remove(FX_WCHAR ch); |
768 void Reserve(FX_STRSIZE len); | 684 |
769 | 685 CFX_ByteString UTF8Encode() const; |
770 FX_WCHAR* GetBuffer(FX_STRSIZE len); | 686 |
771 | 687 CFX_ByteString UTF16LE_Encode() const; |
772 void ReleaseBuffer(FX_STRSIZE len = -
1); | 688 |
773 | 689 void ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL); |
774 int GetInteger() const; | 690 |
775 | 691 protected: |
776 FX_FLOAT GetFloat() const; | 692 class StringData { |
777 | 693 public: |
778 FX_STRSIZE Find(const FX_WCHAR* lpszSub, FX_STRSIZE
start = 0) const; | 694 static StringData* Create(int nLen); |
779 | 695 void Retain() { ++m_nRefs; } |
780 FX_STRSIZE Find(FX_WCHAR ch, FX_STRSIZE start = 0)
const; | 696 void Release() { |
781 | 697 if (--m_nRefs <= 0) |
782 FX_STRSIZE Replace(const FX_WCHAR* lpszOld, const F
X_WCHAR* lpszNew); | 698 FX_Free(this); |
783 | 699 } |
784 FX_STRSIZE Remove(FX_WCHAR ch); | 700 |
785 | 701 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support. |
786 CFX_ByteString UTF8Encode() const; | 702 FX_STRSIZE m_nDataLength; |
787 | 703 FX_STRSIZE m_nAllocLength; |
788 CFX_ByteString UTF16LE_Encode() const; | 704 FX_WCHAR m_String[1]; |
789 | 705 |
790 void ConvertFrom(const CFX_ByteString
& str, CFX_CharMap* pCharMap = NULL); | 706 private: |
791 | 707 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen) |
792 protected: | 708 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) { |
793 class StringData { | 709 FXSYS_assert(dataLen >= 0); |
794 public: | 710 FXSYS_assert(allocLen >= 0); |
795 static StringData* Create(int nLen); | 711 FXSYS_assert(dataLen <= allocLen); |
796 void Retain() { ++m_nRefs; } | 712 m_String[dataLen] = 0; |
797 void Release() { if (--m_nRefs <= 0) FX_Free(this); } | 713 } |
798 | 714 ~StringData() = delete; |
799 intptr_t m_nRefs; // Would prefer ssize_t, but no windows support. | 715 }; |
800 FX_STRSIZE m_nDataLength; | 716 |
801 FX_STRSIZE m_nAllocLength; | 717 void CopyBeforeWrite(); |
802 FX_WCHAR m_String[1]; | 718 void AllocBeforeWrite(FX_STRSIZE nLen); |
803 | 719 void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszSrcData); |
804 private: | 720 void ConcatCopy(FX_STRSIZE nSrc1Len, |
805 StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen) | 721 const FX_WCHAR* lpszSrc1Data, |
806 : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) { | 722 FX_STRSIZE nSrc2Len, |
807 FXSYS_assert(dataLen >= 0); | 723 const FX_WCHAR* lpszSrc2Data); |
808 FXSYS_assert(allocLen >= 0); | 724 void AssignCopy(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszSrcData); |
809 FXSYS_assert(dataLen <= allocLen); | 725 void AllocCopy(CFX_WideString& dest, |
810 m_String[dataLen] = 0; | 726 FX_STRSIZE nCopyLen, |
811 } | 727 FX_STRSIZE nCopyIndex) const; |
812 ~StringData() = delete; | 728 |
813 }; | 729 StringData* m_pData; |
814 | 730 friend class fxcrt_WideStringConcatInPlace_Test; |
815 void CopyBeforeWrite(); | |
816 void AllocBeforeWrite(FX_STRSIZE nLen); | |
817 void ConcatInPlace(FX_STRSIZE nSrcLen, const FX_WCHAR* lp
szSrcData); | |
818 void ConcatCopy(FX_STRSIZE nSrc1Len, const FX_WCHAR* lpsz
Src1Data, FX_STRSIZE nSrc2Len, const FX_WCHAR* lpszSrc2Data); | |
819 void AssignCopy(FX_STRSIZE nSrcLen, const FX_WCHAR* lpszS
rcData); | |
820 void AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen,
FX_STRSIZE nCopyIndex) const; | |
821 | |
822 StringData* m_pData; | |
823 friend class fxcrt_WideStringConcatInPlace_Test; | |
824 }; | 731 }; |
825 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src) | 732 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src) { |
826 { | 733 m_Ptr = src.c_str(); |
827 m_Ptr = src.c_str(); | 734 m_Length = src.GetLength(); |
828 m_Length = src.GetLength(); | 735 } |
829 } | 736 inline CFX_WideStringC& CFX_WideStringC::operator=(const CFX_WideString& src) { |
830 inline CFX_WideStringC& CFX_WideStringC::operator = (const CFX_WideString& src) | 737 m_Ptr = src.c_str(); |
831 { | 738 m_Length = src.GetLength(); |
832 m_Ptr = src.c_str(); | 739 return *this; |
833 m_Length = src.GetLength(); | 740 } |
834 return *this; | 741 |
835 } | 742 inline CFX_WideString operator+(const CFX_WideStringC& str1, |
836 | 743 const CFX_WideStringC& str2) { |
837 inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideStr
ingC& str2) | 744 return CFX_WideString(str1, str2); |
838 { | 745 } |
839 return CFX_WideString(str1, str2); | 746 inline CFX_WideString operator+(const CFX_WideStringC& str1, |
840 } | 747 const FX_WCHAR* str2) { |
841 inline CFX_WideString operator + (const CFX_WideStringC& str1, const FX_WCHAR* s
tr2) | 748 return CFX_WideString(str1, str2); |
842 { | 749 } |
843 return CFX_WideString(str1, str2); | 750 inline CFX_WideString operator+(const FX_WCHAR* str1, |
844 } | 751 const CFX_WideStringC& str2) { |
845 inline CFX_WideString operator + (const FX_WCHAR* str1, const CFX_WideStringC& s
tr2) | 752 return CFX_WideString(str1, str2); |
846 { | 753 } |
847 return CFX_WideString(str1, str2); | 754 inline CFX_WideString operator+(const CFX_WideStringC& str1, FX_WCHAR ch) { |
848 } | 755 return CFX_WideString(str1, CFX_WideStringC(ch)); |
849 inline CFX_WideString operator + (const CFX_WideStringC& str1, FX_WCHAR ch) | 756 } |
850 { | 757 inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideStringC& str2) { |
851 return CFX_WideString(str1, CFX_WideStringC(ch)); | 758 return CFX_WideString(ch, str2); |
852 } | 759 } |
853 inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideStringC& str2) | 760 inline CFX_WideString operator+(const CFX_WideString& str1, |
854 { | 761 const CFX_WideString& str2) { |
855 return CFX_WideString(ch, str2); | 762 return CFX_WideString(str1, str2); |
856 } | 763 } |
857 inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideStri
ng& str2) | 764 inline CFX_WideString operator+(const CFX_WideString& str1, FX_WCHAR ch) { |
858 { | 765 return CFX_WideString(str1, CFX_WideStringC(ch)); |
859 return CFX_WideString(str1, str2); | 766 } |
860 } | 767 inline CFX_WideString operator+(FX_WCHAR ch, const CFX_WideString& str2) { |
861 inline CFX_WideString operator + (const CFX_WideString& str1, FX_WCHAR ch) | 768 return CFX_WideString(ch, str2); |
862 { | 769 } |
863 return CFX_WideString(str1, CFX_WideStringC(ch)); | 770 inline CFX_WideString operator+(const CFX_WideString& str1, |
864 } | 771 const FX_WCHAR* str2) { |
865 inline CFX_WideString operator + (FX_WCHAR ch, const CFX_WideString& str2) | 772 return CFX_WideString(str1, str2); |
866 { | 773 } |
867 return CFX_WideString(ch, str2); | 774 inline CFX_WideString operator+(const FX_WCHAR* str1, |
868 } | 775 const CFX_WideString& str2) { |
869 inline CFX_WideString operator + (const CFX_WideString& str1, const FX_WCHAR* st
r2) | 776 return CFX_WideString(str1, str2); |
870 { | 777 } |
871 return CFX_WideString(str1, str2); | 778 inline CFX_WideString operator+(const CFX_WideString& str1, |
872 } | 779 const CFX_WideStringC& str2) { |
873 inline CFX_WideString operator + (const FX_WCHAR* str1, const CFX_WideString& st
r2) | 780 return CFX_WideString(str1, str2); |
874 { | 781 } |
875 return CFX_WideString(str1, str2); | 782 inline CFX_WideString operator+(const CFX_WideStringC& str1, |
876 } | 783 const CFX_WideString& str2) { |
877 inline CFX_WideString operator + (const CFX_WideString& str1, const CFX_WideStri
ngC& str2) | 784 return CFX_WideString(str1, str2); |
878 { | 785 } |
879 return CFX_WideString(str1, str2); | 786 inline bool operator==(const wchar_t* lhs, const CFX_WideString& rhs) { |
880 } | 787 return rhs == lhs; |
881 inline CFX_WideString operator + (const CFX_WideStringC& str1, const CFX_WideStr
ing& str2) | 788 } |
882 { | 789 inline bool operator==(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { |
883 return CFX_WideString(str1, str2); | 790 return rhs == lhs; |
884 } | 791 } |
885 inline bool operator== (const wchar_t* lhs, const CFX_WideString& rhs) { | 792 inline bool operator!=(const wchar_t* lhs, const CFX_WideString& rhs) { |
886 return rhs == lhs; | 793 return rhs != lhs; |
887 } | 794 } |
888 inline bool operator== (const CFX_WideStringC& lhs, const CFX_WideString& rhs) { | 795 inline bool operator!=(const CFX_WideStringC& lhs, const CFX_WideString& rhs) { |
889 return rhs == lhs; | 796 return rhs != lhs; |
890 } | |
891 inline bool operator!= (const wchar_t* lhs, const CFX_WideString& rhs) { | |
892 return rhs != lhs; | |
893 } | |
894 inline bool operator!= (const CFX_WideStringC& lhs, const CFX_WideString& rhs) { | |
895 return rhs != lhs; | |
896 } | 797 } |
897 FX_FLOAT FX_atof(const CFX_ByteStringC& str); | 798 FX_FLOAT FX_atof(const CFX_ByteStringC& str); |
898 void FX_atonum(const CFX_ByteStringC& str, FX_BOOL& bInteger, void* pData); | 799 void FX_atonum(const CFX_ByteStringC& str, FX_BOOL& bInteger, void* pData); |
899 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_CHAR* buf); | 800 FX_STRSIZE FX_ftoa(FX_FLOAT f, FX_CHAR* buf); |
900 CFX_ByteString» FX_UTF8Encode(const FX_WCHAR* pwsStr, FX_STRSIZE len); | 801 CFX_ByteString FX_UTF8Encode(const FX_WCHAR* pwsStr, FX_STRSIZE len); |
901 inline CFX_ByteString» FX_UTF8Encode(const CFX_WideStringC& wsStr) | 802 inline CFX_ByteString FX_UTF8Encode(const CFX_WideStringC& wsStr) { |
902 { | 803 return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength()); |
903 return FX_UTF8Encode(wsStr.GetPtr(), wsStr.GetLength()); | 804 } |
904 } | 805 inline CFX_ByteString FX_UTF8Encode(const CFX_WideString& wsStr) { |
905 inline CFX_ByteString» FX_UTF8Encode(const CFX_WideString &wsStr) | 806 return FX_UTF8Encode(wsStr.c_str(), wsStr.GetLength()); |
906 { | |
907 return FX_UTF8Encode(wsStr.c_str(), wsStr.GetLength()); | |
908 } | 807 } |
909 | 808 |
910 #endif // CORE_INCLUDE_FXCRT_FX_STRING_H_ | 809 #endif // CORE_INCLUDE_FXCRT_FX_STRING_H_ |
OLD | NEW |