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