OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "core/include/fxcrt/fx_ext.h" | |
10 #include "core/include/fxcrt/fx_xml.h" | |
11 #include "xfa/src/fgas/localization/fgas_localeimp.h" | |
12 | |
13 #define FX_LOCALECATEGORY_DateHash 0xbde9abde | |
14 #define FX_LOCALECATEGORY_TimeHash 0x2d71b00f | |
15 #define FX_LOCALECATEGORY_DateTimeHash 0x158c72ed | |
16 #define FX_LOCALECATEGORY_NumHash 0x0b4ff870 | |
17 #define FX_LOCALECATEGORY_TextHash 0x2d08af85 | |
18 #define FX_LOCALECATEGORY_ZeroHash 0x568cb500 | |
19 #define FX_LOCALECATEGORY_NullHash 0x052931bb | |
20 | |
21 struct FX_LOCALESUBCATEGORYINFO { | |
22 uint32_t uHash; | |
23 const FX_WCHAR* pName; | |
24 int32_t eSubCategory; | |
25 }; | |
26 | |
27 static const FX_LOCALESUBCATEGORYINFO g_FXLocaleDateTimeSubCatData[] = { | |
28 {0x14da2125, L"default", FX_LOCALEDATETIMESUBCATEGORY_Default}, | |
29 {0x9041d4b0, L"short", FX_LOCALEDATETIMESUBCATEGORY_Short}, | |
30 {0xa084a381, L"medium", FX_LOCALEDATETIMESUBCATEGORY_Medium}, | |
31 {0xcdce56b3, L"full", FX_LOCALEDATETIMESUBCATEGORY_Full}, | |
32 {0xf6b4afb0, L"long", FX_LOCALEDATETIMESUBCATEGORY_Long}, | |
33 }; | |
34 static const int32_t g_iFXLocaleDateTimeSubCatCount = | |
35 sizeof(g_FXLocaleDateTimeSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO); | |
36 | |
37 static const FX_LOCALESUBCATEGORYINFO g_FXLocaleNumSubCatData[] = { | |
38 {0x46f95531, L"percent", FX_LOCALENUMPATTERN_Percent}, | |
39 {0x4c4e8acb, L"currency", FX_LOCALENUMPATTERN_Currency}, | |
40 {0x54034c2f, L"decimal", FX_LOCALENUMPATTERN_Decimal}, | |
41 {0x7568e6ae, L"integer", FX_LOCALENUMPATTERN_Integer}, | |
42 }; | |
43 static const int32_t g_iFXLocaleNumSubCatCount = | |
44 sizeof(g_FXLocaleNumSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO); | |
45 | |
46 struct FX_LOCALETIMEZONEINFO { | |
47 FX_DWORD uHash; | |
48 int16_t iHour; | |
49 int16_t iMinute; | |
50 }; | |
51 | |
52 static const FX_LOCALETIMEZONEINFO g_FXLocaleTimeZoneData[] = { | |
53 {FXBSTR_ID(0, 'C', 'D', 'T'), -5, 0}, {FXBSTR_ID(0, 'C', 'S', 'T'), -6, 0}, | |
54 {FXBSTR_ID(0, 'E', 'D', 'T'), -4, 0}, {FXBSTR_ID(0, 'E', 'S', 'T'), -5, 0}, | |
55 {FXBSTR_ID(0, 'M', 'D', 'T'), -6, 0}, {FXBSTR_ID(0, 'M', 'S', 'T'), -7, 0}, | |
56 {FXBSTR_ID(0, 'P', 'D', 'T'), -7, 0}, {FXBSTR_ID(0, 'P', 'S', 'T'), -8, 0}, | |
57 }; | |
58 | |
59 static const CFX_WideStringC gs_wsTextSymbols = FX_WSTRC(L"AXO09"); | |
60 static const CFX_WideStringC gs_wsTimeSymbols = FX_WSTRC(L"hHkKMSFAzZ"); | |
61 static const CFX_WideStringC gs_wsDateSymbols = FX_WSTRC(L"DJMEeGgYwW"); | |
62 static const CFX_WideStringC gs_wsConstChars = FX_WSTRC(L",-:/. "); | |
63 | |
64 static FX_STRSIZE FX_Local_Find(const CFX_WideStringC& wsSymbols, | |
65 FX_WCHAR ch, | |
66 FX_STRSIZE nStart = 0) { | |
67 FX_STRSIZE nLength = wsSymbols.GetLength(); | |
68 if (nLength < 1 || nStart > nLength) { | |
69 return -1; | |
70 } | |
71 const FX_WCHAR* lpsz = | |
72 (const FX_WCHAR*)FXSYS_wcschr(wsSymbols.GetPtr() + nStart, ch); | |
73 return (lpsz == NULL) ? -1 : (FX_STRSIZE)(lpsz - wsSymbols.GetPtr()); | |
74 } | |
75 static const FX_WCHAR* const gs_LocalNumberSymbols[] = { | |
76 L"decimal", L"grouping", L"percent", L"minus", | |
77 L"zero", L"currencySymbol", L"currencyName", | |
78 }; | |
79 IFX_Locale* IFX_Locale::Create(CXML_Element* pLocaleData) { | |
80 return new CFX_Locale(pLocaleData); | |
81 } | |
82 CFX_Locale::CFX_Locale(CXML_Element* pLocaleData) { | |
83 m_pElement = pLocaleData; | |
84 } | |
85 CFX_Locale::~CFX_Locale() {} | |
86 CFX_WideString CFX_Locale::GetName() { | |
87 return CFX_WideString(); | |
88 } | |
89 static CFX_WideString FX_GetXMLContent(const CFX_ByteStringC& bsSpace, | |
90 CXML_Element* pxmlElement, | |
91 const CFX_ByteStringC& bsTag, | |
92 const CFX_WideStringC& wsName) { | |
93 CXML_Element* pDatePattern = NULL; | |
94 int32_t nCount = pxmlElement->CountElements(bsSpace, bsTag); | |
95 int32_t i = 0; | |
96 for (; i < nCount; i++) { | |
97 pDatePattern = pxmlElement->GetElement(bsSpace, bsTag, i); | |
98 if (pDatePattern->GetAttrValue("name") == wsName) { | |
99 break; | |
100 } | |
101 } | |
102 if (i < nCount && pDatePattern) { | |
103 return pDatePattern->GetContent(0); | |
104 } | |
105 return L""; | |
106 } | |
107 void CFX_Locale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType, | |
108 CFX_WideString& wsNumSymbol) const { | |
109 if (!m_pElement) { | |
110 return; | |
111 } | |
112 CFX_ByteString bsSpace; | |
113 CFX_WideString wsName = gs_LocalNumberSymbols[eType]; | |
114 CXML_Element* pNumberSymbols = | |
115 m_pElement->GetElement(bsSpace, "numberSymbols"); | |
116 if (!pNumberSymbols) { | |
117 return; | |
118 } | |
119 wsNumSymbol = | |
120 FX_GetXMLContent(bsSpace, pNumberSymbols, "numberSymbol", wsName); | |
121 } | |
122 void CFX_Locale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const { | |
123 if (!m_pElement) { | |
124 return; | |
125 } | |
126 CFX_ByteString bsSpace; | |
127 CXML_Element* pNumberSymbols = | |
128 m_pElement->GetElement(bsSpace, "dateTimeSymbols"); | |
129 if (!pNumberSymbols) { | |
130 return; | |
131 } | |
132 wsDtSymbol = pNumberSymbols->GetContent(0); | |
133 } | |
134 static void FX_GetCalendarSymbol(CXML_Element* pXmlElement, | |
135 const CFX_ByteString& symbol_type, | |
136 int32_t index, | |
137 FX_BOOL bAbbr, | |
138 CFX_WideString& wsName) { | |
139 CFX_ByteString bsSpace; | |
140 CFX_ByteString pstrSymbolNames = symbol_type + "Names"; | |
141 CXML_Element* pChild = pXmlElement->GetElement(bsSpace, "calendarSymbols"); | |
142 if (!pChild) { | |
143 return; | |
144 } | |
145 CXML_Element* pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames); | |
146 if (!pSymbolNames) { | |
147 return; | |
148 } | |
149 if (pSymbolNames->GetAttrInteger("abbr") != bAbbr) { | |
150 pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames, 1); | |
151 } | |
152 if (pSymbolNames && pSymbolNames->GetAttrInteger("abbr") == bAbbr) { | |
153 CXML_Element* pSymbolName = | |
154 pSymbolNames->GetElement(bsSpace, symbol_type, index); | |
155 if (pSymbolName) { | |
156 wsName = pSymbolName->GetContent(0); | |
157 } | |
158 } | |
159 } | |
160 void CFX_Locale::GetMonthName(int32_t nMonth, | |
161 CFX_WideString& wsMonthName, | |
162 FX_BOOL bAbbr) const { | |
163 if (!m_pElement) { | |
164 return; | |
165 } | |
166 FX_GetCalendarSymbol(m_pElement, "month", nMonth, bAbbr, wsMonthName); | |
167 } | |
168 void CFX_Locale::GetDayName(int32_t nWeek, | |
169 CFX_WideString& wsDayName, | |
170 FX_BOOL bAbbr) const { | |
171 if (!m_pElement) { | |
172 return; | |
173 } | |
174 FX_GetCalendarSymbol(m_pElement, "day", nWeek, bAbbr, wsDayName); | |
175 } | |
176 void CFX_Locale::GetMeridiemName(CFX_WideString& wsMeridiemName, | |
177 FX_BOOL bAM) const { | |
178 if (!m_pElement) { | |
179 return; | |
180 } | |
181 FX_GetCalendarSymbol(m_pElement, "meridiem", bAM ? 0 : 1, FALSE, | |
182 wsMeridiemName); | |
183 } | |
184 static int32_t FX_ParseTimeZone(const FX_WCHAR* pStr, | |
185 int32_t iLen, | |
186 FX_TIMEZONE& tz) { | |
187 tz.tzHour = 0; | |
188 tz.tzMinute = 0; | |
189 if (iLen < 0) { | |
190 return 0; | |
191 } | |
192 int32_t iStart = 1; | |
193 int32_t iEnd = iStart + 2; | |
194 while (iStart < iLen && iStart < iEnd) { | |
195 tz.tzHour = tz.tzHour * 10 + pStr[iStart++] - '0'; | |
196 } | |
197 if (iStart < iLen && pStr[iStart] == ':') { | |
198 iStart++; | |
199 } | |
200 iEnd = iStart + 2; | |
201 while (iStart < iLen && iStart < iEnd) { | |
202 tz.tzMinute = tz.tzMinute * 10 + pStr[iStart++] - '0'; | |
203 } | |
204 if (pStr[0] == '-') { | |
205 tz.tzHour = -tz.tzHour; | |
206 } | |
207 return iStart; | |
208 } | |
209 void CFX_Locale::GetTimeZone(FX_TIMEZONE& tz) const { | |
210 tz.tzHour = 0; | |
211 tz.tzMinute = 0; | |
212 if (!m_pElement) { | |
213 return; | |
214 } | |
215 CXML_Element* pxmlTimeZone = m_pElement->GetElement("", "timeZone"); | |
216 if (pxmlTimeZone) { | |
217 CFX_WideString wsTimeZone = pxmlTimeZone->GetContent(0); | |
218 FX_ParseTimeZone(wsTimeZone, wsTimeZone.GetLength(), tz); | |
219 } | |
220 } | |
221 void CFX_Locale::GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD) const { | |
222 if (!m_pElement) { | |
223 return; | |
224 } | |
225 FX_GetCalendarSymbol(m_pElement, "era", bAD ? 0 : 1, FALSE, wsEraName); | |
226 } | |
227 static void FX_GetPattern(CXML_Element* pXmlElement, | |
228 const CFX_ByteString& bsCategory, | |
229 const CFX_WideString& wsSubCategory, | |
230 CFX_WideString& wsPattern) { | |
231 CFX_ByteString bsSpace; | |
232 CXML_Element* pDatePatterns = | |
233 pXmlElement->GetElement(bsSpace, bsCategory + "s"); | |
234 if (!pDatePatterns) { | |
235 return; | |
236 } | |
237 wsPattern = | |
238 FX_GetXMLContent(bsSpace, pDatePatterns, bsCategory, wsSubCategory); | |
239 } | |
240 static void FX_GetDateTimePattern(CXML_Element* pXmlElement, | |
241 const CFX_ByteString& bsCategory, | |
242 FX_LOCALEDATETIMESUBCATEGORY eType, | |
243 CFX_WideString& wsPattern) { | |
244 CFX_WideString wsType = g_FXLocaleDateTimeSubCatData[eType].pName; | |
245 FX_GetPattern(pXmlElement, bsCategory, wsType, wsPattern); | |
246 } | |
247 void CFX_Locale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType, | |
248 CFX_WideString& wsPattern) const { | |
249 if (!m_pElement) { | |
250 return; | |
251 } | |
252 FX_GetDateTimePattern(m_pElement, "datePattern", eType, wsPattern); | |
253 } | |
254 void CFX_Locale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType, | |
255 CFX_WideString& wsPattern) const { | |
256 if (!m_pElement) { | |
257 return; | |
258 } | |
259 FX_GetDateTimePattern(m_pElement, "timePattern", eType, wsPattern); | |
260 } | |
261 void CFX_Locale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType, | |
262 CFX_WideString& wsPattern) const { | |
263 CFX_WideString wsType = g_FXLocaleNumSubCatData[eType].pName; | |
264 FX_GetPattern(m_pElement, "numberPattern", wsType, wsPattern); | |
265 } | |
266 static FX_BOOL FX_IsDigit(FX_WCHAR c) { | |
267 return c >= '0' && c <= '9'; | |
268 } | |
269 static FX_BOOL FX_IsAlpha(FX_WCHAR c) { | |
270 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); | |
271 } | |
272 static FX_BOOL FX_IsSpace(FX_WCHAR c) { | |
273 return (c == 0x20) || (c == 0x0d) || (c == 0x0a) || (c == 0x09); | |
274 } | |
275 static const FX_FLOAT gs_fraction_scales[] = { | |
276 0.1f, 0.01f, 0.001f, 0.0001f, | |
277 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, | |
278 0.000000001f, 0.0000000001f, 0.00000000001f}; | |
279 static const int32_t gs_fraction_count = | |
280 sizeof(gs_fraction_scales) / sizeof(FX_FLOAT); | |
281 | |
282 class CFX_LCNumeric { | |
283 public: | |
284 CFX_LCNumeric(); | |
285 CFX_LCNumeric(int64_t integral, | |
286 uint32_t fractional = 0, | |
287 int32_t exponent = 0); | |
288 CFX_LCNumeric(FX_FLOAT dbRetValue); | |
289 CFX_LCNumeric(double dbvalue); | |
290 CFX_LCNumeric(CFX_WideString& wsNumeric); | |
291 | |
292 FX_FLOAT GetFloat() const; | |
293 double GetDouble() const; | |
294 CFX_WideString ToString() const; | |
295 CFX_WideString ToString(int32_t nTreading, FX_BOOL bTrimTailZeros) const; | |
296 | |
297 int64_t m_Integral; | |
298 uint32_t m_Fractional; | |
299 int32_t m_Exponent; | |
300 }; | |
301 | |
302 static FX_BOOL FX_WStringToNumeric(const CFX_WideString& wsValue, | |
303 CFX_LCNumeric& lcnum) { | |
304 lcnum.m_Integral = 0; | |
305 lcnum.m_Fractional = 0; | |
306 lcnum.m_Exponent = 0; | |
307 | |
308 if (wsValue.IsEmpty()) | |
309 return FALSE; | |
310 | |
311 const int32_t nIntegralMaxLen = 17; | |
312 int32_t cc = 0; | |
313 bool bNegative = false; | |
314 bool bExpSign = false; | |
315 const FX_WCHAR* str = (const FX_WCHAR*)wsValue; | |
316 int32_t len = wsValue.GetLength(); | |
317 while (cc < len && FX_IsSpace(str[cc])) | |
318 cc++; | |
319 | |
320 if (cc >= len) | |
321 return FALSE; | |
322 | |
323 if (str[cc] == '+') { | |
324 cc++; | |
325 } else if (str[cc] == '-') { | |
326 bNegative = true; | |
327 cc++; | |
328 } | |
329 int32_t nIntegralLen = 0; | |
330 while (cc < len) { | |
331 if (str[cc] == '.') | |
332 break; | |
333 | |
334 if (!FX_IsDigit(str[cc])) { | |
335 if ((str[cc] == 'E' || str[cc] == 'e')) | |
336 break; | |
337 else | |
338 return FALSE; | |
339 } | |
340 if (nIntegralLen < nIntegralMaxLen) { | |
341 lcnum.m_Integral = lcnum.m_Integral * 10 + str[cc] - '0'; | |
342 nIntegralLen++; | |
343 } | |
344 cc++; | |
345 } | |
346 | |
347 lcnum.m_Integral = bNegative ? -lcnum.m_Integral : lcnum.m_Integral; | |
348 if (cc < len && str[cc] == '.') { | |
349 int scale = 0; | |
350 double fraction = 0.0; | |
351 cc++; | |
352 while (cc < len) { | |
353 if (scale >= gs_fraction_count) { | |
354 while (cc < len) { | |
355 if (!FX_IsDigit(str[cc])) | |
356 break; | |
357 cc++; | |
358 } | |
359 } | |
360 if (!FX_IsDigit(str[cc])) { | |
361 if ((str[cc] == 'E' || str[cc] == 'e')) | |
362 break; | |
363 else | |
364 return FALSE; | |
365 } | |
366 fraction += gs_fraction_scales[scale] * (str[cc] - '0'); | |
367 scale++; | |
368 cc++; | |
369 } | |
370 lcnum.m_Fractional = (FX_DWORD)(fraction * 4294967296.0); | |
371 } | |
372 if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) { | |
373 cc++; | |
374 if (cc < len) { | |
375 if (str[cc] == '+') { | |
376 cc++; | |
377 } else if (str[cc] == '-') { | |
378 bExpSign = true; | |
379 cc++; | |
380 } | |
381 } | |
382 while (cc < len) { | |
383 if (FX_IsDigit(str[cc])) | |
384 return FALSE; | |
385 lcnum.m_Exponent = lcnum.m_Exponent * 10 + str[cc] - '0'; | |
386 cc++; | |
387 } | |
388 lcnum.m_Exponent = bExpSign ? -lcnum.m_Exponent : lcnum.m_Exponent; | |
389 } | |
390 return TRUE; | |
391 } | |
392 | |
393 CFX_LCNumeric::CFX_LCNumeric() { | |
394 m_Integral = 0; | |
395 m_Fractional = 0; | |
396 m_Exponent = 0; | |
397 } | |
398 CFX_LCNumeric::CFX_LCNumeric(int64_t integral, | |
399 FX_DWORD fractional, | |
400 int32_t exponent) { | |
401 m_Integral = integral; | |
402 m_Fractional = fractional; | |
403 m_Exponent = exponent; | |
404 } | |
405 CFX_LCNumeric::CFX_LCNumeric(FX_FLOAT dbRetValue) { | |
406 m_Integral = (int64_t)dbRetValue; | |
407 m_Fractional = (FX_DWORD)(((dbRetValue > 0) ? (dbRetValue - m_Integral) | |
408 : (m_Integral - dbRetValue)) * | |
409 4294967296); | |
410 m_Exponent = 0; | |
411 } | |
412 CFX_LCNumeric::CFX_LCNumeric(double dbvalue) { | |
413 m_Integral = (int64_t)dbvalue; | |
414 m_Fractional = (FX_DWORD)( | |
415 ((dbvalue > 0) ? (dbvalue - m_Integral) : (m_Integral - dbvalue)) * | |
416 4294967296); | |
417 m_Exponent = 0; | |
418 } | |
419 CFX_LCNumeric::CFX_LCNumeric(CFX_WideString& wsNumeric) { | |
420 FX_WStringToNumeric(wsNumeric, *this); | |
421 } | |
422 FX_FLOAT CFX_LCNumeric::GetFloat() const { | |
423 FX_FLOAT dbRetValue = m_Fractional / 4294967296.0f; | |
424 dbRetValue = m_Integral + (m_Integral >= 0 ? dbRetValue : -dbRetValue); | |
425 if (m_Exponent != 0) { | |
426 dbRetValue *= FXSYS_pow(10, (FX_FLOAT)m_Exponent); | |
427 } | |
428 return dbRetValue; | |
429 } | |
430 double CFX_LCNumeric::GetDouble() const { | |
431 double value = m_Fractional / 4294967296.0; | |
432 value = m_Integral + (m_Integral >= 0 ? value : -value); | |
433 if (m_Exponent != 0) { | |
434 value *= FXSYS_pow(10, (FX_FLOAT)m_Exponent); | |
435 } | |
436 return value; | |
437 } | |
438 | |
439 CFX_WideString CFX_LCNumeric::ToString() const { | |
440 return ToString(8, TRUE); | |
441 } | |
442 | |
443 CFX_WideString CFX_LCNumeric::ToString(int32_t nTreading, | |
444 FX_BOOL bTrimTailZeros) const { | |
445 CFX_WideString wsFormat; | |
446 wsFormat.Format(L"%%.%df", nTreading); | |
447 CFX_WideString wsResult; | |
448 wsResult.Format(wsFormat.c_str(), GetDouble()); | |
449 if (bTrimTailZeros && nTreading > 0) { | |
450 wsResult.TrimRight(L"0"); | |
451 wsResult.TrimRight(L"."); | |
452 } | |
453 return wsResult; | |
454 } | |
455 | |
456 IFX_FormatString* IFX_FormatString::Create(IFX_LocaleMgr* pLocaleMgr, | |
457 FX_BOOL bUseLCID) { | |
458 if (!pLocaleMgr) { | |
459 return NULL; | |
460 } | |
461 return new CFX_FormatString(pLocaleMgr, bUseLCID); | |
462 } | |
463 CFX_FormatString::CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID) | |
464 : m_pLocaleMgr(pLocaleMgr), m_bUseLCID(bUseLCID) {} | |
465 CFX_FormatString::~CFX_FormatString() {} | |
466 void CFX_FormatString::SplitFormatString(const CFX_WideString& wsFormatString, | |
467 CFX_WideStringArray& wsPatterns) { | |
468 int32_t iStrLen = wsFormatString.GetLength(); | |
469 const FX_WCHAR* pStr = (const FX_WCHAR*)wsFormatString; | |
470 const FX_WCHAR* pToken = pStr; | |
471 const FX_WCHAR* pEnd = pStr + iStrLen; | |
472 FX_BOOL iQuote = FALSE; | |
473 while (TRUE) { | |
474 if (pStr >= pEnd) { | |
475 CFX_WideString sub(pToken, pStr - pToken); | |
476 wsPatterns.Add(sub); | |
477 return; | |
478 } else if (*pStr == '\'') { | |
479 iQuote = !iQuote; | |
480 } else if (*pStr == L'|' && !iQuote) { | |
481 CFX_WideString sub(pToken, pStr - pToken); | |
482 wsPatterns.Add(sub); | |
483 pToken = pStr + 1; | |
484 } | |
485 pStr++; | |
486 } | |
487 } | |
488 static CFX_WideString FX_GetLiteralText(const FX_WCHAR* pStrPattern, | |
489 int32_t& iPattern, | |
490 int32_t iLenPattern) { | |
491 CFX_WideString wsOutput; | |
492 if (pStrPattern[iPattern] != '\'') { | |
493 return wsOutput; | |
494 } | |
495 iPattern++; | |
496 int32_t iQuote = 1; | |
497 while (iPattern < iLenPattern) { | |
498 if (pStrPattern[iPattern] == '\'') { | |
499 iQuote++; | |
500 if ((iPattern + 1 >= iLenPattern) || | |
501 ((pStrPattern[iPattern + 1] != '\'') && (iQuote % 2 == 0))) { | |
502 break; | |
503 } else { | |
504 iQuote++; | |
505 } | |
506 iPattern++; | |
507 } else if (pStrPattern[iPattern] == '\\' && (iPattern + 1 < iLenPattern) && | |
508 pStrPattern[iPattern + 1] == 'u') { | |
509 int32_t iKeyValue = 0; | |
510 iPattern += 2; | |
511 int32_t i = 0; | |
512 while (iPattern < iLenPattern && i++ < 4) { | |
513 FX_WCHAR ch = pStrPattern[iPattern++]; | |
514 if ((ch >= '0' && ch <= '9')) { | |
515 iKeyValue = iKeyValue * 16 + ch - '0'; | |
516 } else if ((ch >= 'a' && ch <= 'f')) { | |
517 iKeyValue = iKeyValue * 16 + ch - 'a' + 10; | |
518 } else if ((ch >= 'A' && ch <= 'F')) { | |
519 iKeyValue = iKeyValue * 16 + ch - 'A' + 10; | |
520 } | |
521 } | |
522 if (iKeyValue != 0) { | |
523 wsOutput += (FX_WCHAR)(iKeyValue & 0x0000FFFF); | |
524 } | |
525 continue; | |
526 } | |
527 wsOutput += pStrPattern[iPattern++]; | |
528 } | |
529 return wsOutput; | |
530 } | |
531 static CFX_WideString FX_GetLiteralTextReverse(const FX_WCHAR* pStrPattern, | |
532 int32_t& iPattern) { | |
533 CFX_WideString wsOutput; | |
534 if (pStrPattern[iPattern] != '\'') { | |
535 return wsOutput; | |
536 } | |
537 iPattern--; | |
538 int32_t iQuote = 1; | |
539 while (iPattern >= 0) { | |
540 if (pStrPattern[iPattern] == '\'') { | |
541 iQuote++; | |
542 if (iPattern - 1 >= 0 || | |
543 ((pStrPattern[iPattern - 1] != '\'') && (iQuote % 2 == 0))) { | |
544 break; | |
545 } else { | |
546 iQuote++; | |
547 } | |
548 iPattern--; | |
549 } else if (pStrPattern[iPattern] == '\\' && | |
550 pStrPattern[iPattern + 1] == 'u') { | |
551 iPattern--; | |
552 int32_t iKeyValue = 0; | |
553 int32_t iLen = wsOutput.GetLength(); | |
554 int32_t i = 1; | |
555 for (; i < iLen && i < 5; i++) { | |
556 FX_WCHAR ch = wsOutput[i]; | |
557 if ((ch >= '0' && ch <= '9')) { | |
558 iKeyValue = iKeyValue * 16 + ch - '0'; | |
559 } else if ((ch >= 'a' && ch <= 'f')) { | |
560 iKeyValue = iKeyValue * 16 + ch - 'a' + 10; | |
561 } else if ((ch >= 'A' && ch <= 'F')) { | |
562 iKeyValue = iKeyValue * 16 + ch - 'A' + 10; | |
563 } | |
564 } | |
565 if (iKeyValue != 0) { | |
566 wsOutput.Delete(0, i); | |
567 wsOutput = (FX_WCHAR)(iKeyValue & 0x0000FFFF) + wsOutput; | |
568 } | |
569 continue; | |
570 } | |
571 wsOutput = pStrPattern[iPattern--] + wsOutput; | |
572 } | |
573 return wsOutput; | |
574 } | |
575 FX_LOCALECATEGORY CFX_FormatString::GetCategory( | |
576 const CFX_WideString& wsPattern) { | |
577 FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown; | |
578 int32_t ccf = 0; | |
579 int32_t iLenf = wsPattern.GetLength(); | |
580 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern; | |
581 FX_BOOL bBraceOpen = FALSE; | |
582 while (ccf < iLenf) { | |
583 if (pStr[ccf] == '\'') { | |
584 FX_GetLiteralText(pStr, ccf, iLenf); | |
585 } else if (!bBraceOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) { | |
586 CFX_WideString wsCategory(pStr[ccf]); | |
587 ccf++; | |
588 while (TRUE) { | |
589 if (ccf == iLenf) { | |
590 return eCategory; | |
591 } | |
592 if (pStr[ccf] == '.' || pStr[ccf] == '(') { | |
593 break; | |
594 } | |
595 if (pStr[ccf] == '{') { | |
596 bBraceOpen = TRUE; | |
597 break; | |
598 } | |
599 wsCategory += pStr[ccf]; | |
600 ccf++; | |
601 } | |
602 FX_DWORD dwHash = | |
603 FX_HashCode_String_GetW(wsCategory, wsCategory.GetLength()); | |
604 if (dwHash == FX_LOCALECATEGORY_DateHash) { | |
605 if (eCategory == FX_LOCALECATEGORY_Time) { | |
606 return FX_LOCALECATEGORY_DateTime; | |
607 } | |
608 eCategory = FX_LOCALECATEGORY_Date; | |
609 } else if (dwHash == FX_LOCALECATEGORY_TimeHash) { | |
610 if (eCategory == FX_LOCALECATEGORY_Date) { | |
611 return FX_LOCALECATEGORY_DateTime; | |
612 } | |
613 eCategory = FX_LOCALECATEGORY_Time; | |
614 } else if (dwHash == FX_LOCALECATEGORY_DateTimeHash) { | |
615 return FX_LOCALECATEGORY_DateTime; | |
616 } else if (dwHash == FX_LOCALECATEGORY_TextHash) { | |
617 return FX_LOCALECATEGORY_Text; | |
618 } else if (dwHash == FX_LOCALECATEGORY_NumHash) { | |
619 return FX_LOCALECATEGORY_Num; | |
620 } else if (dwHash == FX_LOCALECATEGORY_ZeroHash) { | |
621 return FX_LOCALECATEGORY_Zero; | |
622 } else if (dwHash == FX_LOCALECATEGORY_NullHash) { | |
623 return FX_LOCALECATEGORY_Null; | |
624 } | |
625 } else if (pStr[ccf] == '}') { | |
626 bBraceOpen = FALSE; | |
627 } | |
628 ccf++; | |
629 } | |
630 return eCategory; | |
631 } | |
632 static FX_WORD FX_WStringToLCID(const FX_WCHAR* pstrLCID) { | |
633 if (!pstrLCID) { | |
634 return 0; | |
635 } | |
636 wchar_t* pEnd; | |
637 return (FX_WORD)wcstol((wchar_t*)pstrLCID, &pEnd, 16); | |
638 } | |
639 FX_WORD CFX_FormatString::GetLCID(const CFX_WideString& wsPattern) { | |
640 return FX_WStringToLCID(GetLocaleName(wsPattern)); | |
641 } | |
642 CFX_WideString CFX_FormatString::GetLocaleName( | |
643 const CFX_WideString& wsPattern) { | |
644 int32_t ccf = 0; | |
645 int32_t iLenf = wsPattern.GetLength(); | |
646 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern; | |
647 while (ccf < iLenf) { | |
648 if (pStr[ccf] == '\'') { | |
649 FX_GetLiteralText(pStr, ccf, iLenf); | |
650 } else if (pStr[ccf] == '(') { | |
651 ccf++; | |
652 CFX_WideString wsLCID; | |
653 while (ccf < iLenf && pStr[ccf] != ')') { | |
654 wsLCID += pStr[ccf++]; | |
655 } | |
656 return wsLCID; | |
657 } | |
658 ccf++; | |
659 } | |
660 return CFX_WideString(); | |
661 } | |
662 IFX_Locale* CFX_FormatString::GetTextFormat(const CFX_WideString& wsPattern, | |
663 const CFX_WideStringC& wsCategory, | |
664 CFX_WideString& wsPurgePattern) { | |
665 IFX_Locale* pLocale = NULL; | |
666 int32_t ccf = 0; | |
667 int32_t iLenf = wsPattern.GetLength(); | |
668 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern; | |
669 FX_BOOL bBrackOpen = FALSE; | |
670 while (ccf < iLenf) { | |
671 if (pStr[ccf] == '\'') { | |
672 int32_t iCurChar = ccf; | |
673 FX_GetLiteralText(pStr, ccf, iLenf); | |
674 wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1); | |
675 } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) { | |
676 CFX_WideString wsSearchCategory(pStr[ccf]); | |
677 ccf++; | |
678 while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && | |
679 pStr[ccf] != '(') { | |
680 wsSearchCategory += pStr[ccf]; | |
681 ccf++; | |
682 } | |
683 if (wsSearchCategory != wsCategory) { | |
684 continue; | |
685 } | |
686 while (ccf < iLenf) { | |
687 if (pStr[ccf] == '(') { | |
688 ccf++; | |
689 CFX_WideString wsLCID; | |
690 while (ccf < iLenf && pStr[ccf] != ')') { | |
691 wsLCID += pStr[ccf++]; | |
692 } | |
693 pLocale = GetPatternLocale(wsLCID); | |
694 } else if (pStr[ccf] == '{') { | |
695 bBrackOpen = TRUE; | |
696 break; | |
697 } | |
698 ccf++; | |
699 } | |
700 } else if (pStr[ccf] != '}') { | |
701 wsPurgePattern += pStr[ccf]; | |
702 } | |
703 ccf++; | |
704 } | |
705 if (!bBrackOpen) { | |
706 wsPurgePattern = wsPattern; | |
707 } | |
708 if (!pLocale) { | |
709 pLocale = m_pLocaleMgr->GetDefLocale(); | |
710 } | |
711 return pLocale; | |
712 } | |
713 #define FX_NUMSTYLE_Percent 0x01 | |
714 #define FX_NUMSTYLE_Exponent 0x02 | |
715 #define FX_NUMSTYLE_DotVorv 0x04 | |
716 IFX_Locale* CFX_FormatString::GetNumericFormat(const CFX_WideString& wsPattern, | |
717 int32_t& iDotIndex, | |
718 FX_DWORD& dwStyle, | |
719 CFX_WideString& wsPurgePattern) { | |
720 dwStyle = 0; | |
721 IFX_Locale* pLocale = NULL; | |
722 int32_t ccf = 0; | |
723 int32_t iLenf = wsPattern.GetLength(); | |
724 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern; | |
725 FX_BOOL bFindDot = FALSE; | |
726 FX_BOOL bBrackOpen = FALSE; | |
727 while (ccf < iLenf) { | |
728 if (pStr[ccf] == '\'') { | |
729 int32_t iCurChar = ccf; | |
730 FX_GetLiteralText(pStr, ccf, iLenf); | |
731 wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1); | |
732 } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) { | |
733 CFX_WideString wsCategory(pStr[ccf]); | |
734 ccf++; | |
735 while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && | |
736 pStr[ccf] != '(') { | |
737 wsCategory += pStr[ccf]; | |
738 ccf++; | |
739 } | |
740 if (wsCategory != FX_WSTRC(L"num")) { | |
741 bBrackOpen = TRUE; | |
742 ccf = 0; | |
743 continue; | |
744 } | |
745 while (ccf < iLenf) { | |
746 if (pStr[ccf] == '(') { | |
747 ccf++; | |
748 CFX_WideString wsLCID; | |
749 while (ccf < iLenf && pStr[ccf] != ')') { | |
750 wsLCID += pStr[ccf++]; | |
751 } | |
752 pLocale = GetPatternLocale(wsLCID); | |
753 } else if (pStr[ccf] == '{') { | |
754 bBrackOpen = TRUE; | |
755 break; | |
756 } else if (pStr[ccf] == '.') { | |
757 CFX_WideString wsSubCategory; | |
758 ccf++; | |
759 while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') { | |
760 wsSubCategory += pStr[ccf++]; | |
761 } | |
762 FX_DWORD dwSubHash = | |
763 FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength()); | |
764 FX_LOCALENUMSUBCATEGORY eSubCategory = FX_LOCALENUMPATTERN_Decimal; | |
765 for (int32_t i = 0; i < g_iFXLocaleNumSubCatCount; i++) { | |
766 if (g_FXLocaleNumSubCatData[i].uHash == dwSubHash) { | |
767 eSubCategory = (FX_LOCALENUMSUBCATEGORY)g_FXLocaleNumSubCatData[i] | |
768 .eSubCategory; | |
769 break; | |
770 } | |
771 } | |
772 wsSubCategory.Empty(); | |
773 if (!pLocale) { | |
774 pLocale = m_pLocaleMgr->GetDefLocale(); | |
775 } | |
776 FXSYS_assert(pLocale != NULL); | |
777 pLocale->GetNumPattern(eSubCategory, wsSubCategory); | |
778 iDotIndex = wsSubCategory.Find('.'); | |
779 if (iDotIndex > 0) { | |
780 iDotIndex += wsPurgePattern.GetLength(); | |
781 bFindDot = TRUE; | |
782 dwStyle |= FX_NUMSTYLE_DotVorv; | |
783 } | |
784 wsPurgePattern += wsSubCategory; | |
785 if (eSubCategory == FX_LOCALENUMPATTERN_Percent) { | |
786 dwStyle |= FX_NUMSTYLE_Percent; | |
787 } | |
788 continue; | |
789 } | |
790 ccf++; | |
791 } | |
792 } else if (pStr[ccf] == 'E') { | |
793 dwStyle |= FX_NUMSTYLE_Exponent; | |
794 wsPurgePattern += pStr[ccf]; | |
795 } else if (pStr[ccf] == '%') { | |
796 dwStyle |= FX_NUMSTYLE_Percent; | |
797 wsPurgePattern += pStr[ccf]; | |
798 } else if (pStr[ccf] != '}') { | |
799 wsPurgePattern += pStr[ccf]; | |
800 } | |
801 if (!bFindDot) { | |
802 if (pStr[ccf] == '.' || pStr[ccf] == 'V' || pStr[ccf] == 'v') { | |
803 bFindDot = TRUE; | |
804 iDotIndex = wsPurgePattern.GetLength() - 1; | |
805 dwStyle |= FX_NUMSTYLE_DotVorv; | |
806 } | |
807 } | |
808 ccf++; | |
809 } | |
810 if (!bFindDot) { | |
811 iDotIndex = wsPurgePattern.GetLength(); | |
812 } | |
813 if (!pLocale) { | |
814 pLocale = m_pLocaleMgr->GetDefLocale(); | |
815 } | |
816 return pLocale; | |
817 } | |
818 static FX_BOOL FX_GetNumericDotIndex(const CFX_WideString& wsNum, | |
819 const CFX_WideString& wsDotSymbol, | |
820 int32_t& iDotIndex) { | |
821 int32_t ccf = 0; | |
822 int32_t iLenf = wsNum.GetLength(); | |
823 const FX_WCHAR* pStr = (const FX_WCHAR*)wsNum; | |
824 int32_t iLenDot = wsDotSymbol.GetLength(); | |
825 while (ccf < iLenf) { | |
826 if (pStr[ccf] == '\'') { | |
827 FX_GetLiteralText(pStr, ccf, iLenf); | |
828 } else if (ccf + iLenDot <= iLenf && | |
829 !FXSYS_wcsncmp(pStr + ccf, (const FX_WCHAR*)wsDotSymbol, | |
830 iLenDot)) { | |
831 iDotIndex = ccf; | |
832 return TRUE; | |
833 } | |
834 ccf++; | |
835 } | |
836 iDotIndex = wsNum.Find('.'); | |
837 if (iDotIndex < 0) { | |
838 iDotIndex = iLenf; | |
839 return FALSE; | |
840 } | |
841 return TRUE; | |
842 } | |
843 FX_BOOL CFX_FormatString::ParseText(const CFX_WideString& wsSrcText, | |
844 const CFX_WideString& wsPattern, | |
845 CFX_WideString& wsValue) { | |
846 wsValue.Empty(); | |
847 if (wsSrcText.IsEmpty() || wsPattern.IsEmpty()) { | |
848 return FALSE; | |
849 } | |
850 CFX_WideString wsTextFormat; | |
851 GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat); | |
852 if (wsTextFormat.IsEmpty()) { | |
853 return FALSE; | |
854 } | |
855 int32_t iText = 0, iPattern = 0; | |
856 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText; | |
857 int32_t iLenText = wsSrcText.GetLength(); | |
858 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat; | |
859 int32_t iLenPattern = wsTextFormat.GetLength(); | |
860 while (iPattern < iLenPattern && iText < iLenText) { | |
861 switch (pStrPattern[iPattern]) { | |
862 case '\'': { | |
863 CFX_WideString wsLiteral = | |
864 FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); | |
865 int32_t iLiteralLen = wsLiteral.GetLength(); | |
866 if (iText + iLiteralLen > iLenText || | |
867 FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral, | |
868 iLiteralLen)) { | |
869 wsValue = wsSrcText; | |
870 return FALSE; | |
871 } | |
872 iText += iLiteralLen; | |
873 iPattern++; | |
874 break; | |
875 } | |
876 case 'A': | |
877 if (FX_IsAlpha(pStrText[iText])) { | |
878 wsValue += pStrText[iText]; | |
879 iText++; | |
880 } | |
881 iPattern++; | |
882 break; | |
883 case 'X': | |
884 wsValue += pStrText[iText]; | |
885 iText++; | |
886 iPattern++; | |
887 break; | |
888 case 'O': | |
889 case '0': | |
890 if (FX_IsDigit(pStrText[iText]) || FX_IsAlpha(pStrText[iText])) { | |
891 wsValue += pStrText[iText]; | |
892 iText++; | |
893 } | |
894 iPattern++; | |
895 break; | |
896 case '9': | |
897 if (FX_IsDigit(pStrText[iText])) { | |
898 wsValue += pStrText[iText]; | |
899 iText++; | |
900 } | |
901 iPattern++; | |
902 break; | |
903 default: | |
904 if (pStrPattern[iPattern] != pStrText[iText]) { | |
905 wsValue = wsSrcText; | |
906 return FALSE; | |
907 } | |
908 iPattern++; | |
909 iText++; | |
910 break; | |
911 } | |
912 } | |
913 return iPattern == iLenPattern && iText == iLenText; | |
914 } | |
915 FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum, | |
916 const CFX_WideString& wsPattern, | |
917 FX_FLOAT& fValue) { | |
918 fValue = 0.0f; | |
919 if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) { | |
920 return FALSE; | |
921 } | |
922 int32_t dot_index_f = -1; | |
923 FX_DWORD dwFormatStyle = 0; | |
924 CFX_WideString wsNumFormat; | |
925 IFX_Locale* pLocale = | |
926 GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat); | |
927 if (!pLocale || wsNumFormat.IsEmpty()) { | |
928 return FALSE; | |
929 } | |
930 int32_t iExponent = 0; | |
931 CFX_WideString wsDotSymbol; | |
932 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol); | |
933 CFX_WideString wsGroupSymbol; | |
934 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); | |
935 int32_t iGroupLen = wsGroupSymbol.GetLength(); | |
936 CFX_WideString wsMinus; | |
937 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus); | |
938 int32_t iMinusLen = wsMinus.GetLength(); | |
939 int cc = 0, ccf = 0; | |
940 const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum; | |
941 int len = wsSrcNum.GetLength(); | |
942 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat; | |
943 int lenf = wsNumFormat.GetLength(); | |
944 double dbRetValue = 0; | |
945 double coeff = 1; | |
946 FX_BOOL bHavePercentSymbol = FALSE; | |
947 FX_BOOL bNeg = FALSE; | |
948 FX_BOOL bReverseParse = FALSE; | |
949 int32_t dot_index = 0; | |
950 if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) && | |
951 (dwFormatStyle & FX_NUMSTYLE_DotVorv)) { | |
952 bReverseParse = TRUE; | |
953 } | |
954 bReverseParse = FALSE; | |
955 if (bReverseParse) { | |
956 ccf = lenf - 1; | |
957 cc = len - 1; | |
958 while (ccf > dot_index_f && cc >= 0) { | |
959 switch (strf[ccf]) { | |
960 case '\'': { | |
961 CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf); | |
962 int32_t iLiteralLen = wsLiteral.GetLength(); | |
963 cc -= iLiteralLen - 1; | |
964 if (cc < 0 || FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, | |
965 iLiteralLen)) { | |
966 return FALSE; | |
967 } | |
968 cc--; | |
969 ccf--; | |
970 break; | |
971 } | |
972 case '9': | |
973 if (!FX_IsDigit(str[cc])) { | |
974 return FALSE; | |
975 } | |
976 dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1; | |
977 coeff *= 0.1; | |
978 cc--; | |
979 ccf--; | |
980 break; | |
981 case 'z': | |
982 if (cc >= 0) { | |
983 dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1; | |
984 coeff *= 0.1; | |
985 cc--; | |
986 } | |
987 ccf--; | |
988 break; | |
989 case 'Z': | |
990 if (str[cc] != ' ') { | |
991 dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1; | |
992 coeff *= 0.1; | |
993 } | |
994 cc--; | |
995 ccf--; | |
996 break; | |
997 case 'S': | |
998 if (str[cc] == '+' || str[cc] == ' ') { | |
999 cc--; | |
1000 } else { | |
1001 cc -= iMinusLen - 1; | |
1002 if (cc < 0 || | |
1003 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1004 return FALSE; | |
1005 } | |
1006 cc--; | |
1007 bNeg = TRUE; | |
1008 } | |
1009 ccf--; | |
1010 break; | |
1011 case 's': | |
1012 if (str[cc] == '+') { | |
1013 cc--; | |
1014 } else { | |
1015 cc -= iMinusLen - 1; | |
1016 if (cc < 0 || | |
1017 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1018 return FALSE; | |
1019 } | |
1020 cc--; | |
1021 bNeg = TRUE; | |
1022 } | |
1023 ccf--; | |
1024 break; | |
1025 case 'E': { | |
1026 if (cc >= dot_index) { | |
1027 return FALSE; | |
1028 } | |
1029 FX_BOOL bExpSign = FALSE; | |
1030 while (cc >= 0) { | |
1031 if (str[cc] == 'E' || str[cc] == 'e') { | |
1032 break; | |
1033 } | |
1034 if (FX_IsDigit(str[cc])) { | |
1035 iExponent = iExponent + (str[cc] - '0') * 10; | |
1036 cc--; | |
1037 continue; | |
1038 } else if (str[cc] == '+') { | |
1039 cc--; | |
1040 continue; | |
1041 } else if (cc - iMinusLen + 1 > 0 && | |
1042 !FXSYS_wcsncmp(str + (cc - iMinusLen + 1), | |
1043 (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1044 bExpSign = TRUE; | |
1045 cc -= iMinusLen; | |
1046 } else { | |
1047 return FALSE; | |
1048 } | |
1049 } | |
1050 cc--; | |
1051 iExponent = bExpSign ? -iExponent : iExponent; | |
1052 ccf--; | |
1053 } break; | |
1054 case '$': { | |
1055 CFX_WideString wsSymbol; | |
1056 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, | |
1057 wsSymbol); | |
1058 int32_t iSymbolLen = wsSymbol.GetLength(); | |
1059 cc -= iSymbolLen - 1; | |
1060 if (cc < 0 || | |
1061 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) { | |
1062 return FALSE; | |
1063 } | |
1064 cc--; | |
1065 ccf--; | |
1066 } break; | |
1067 case 'r': | |
1068 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') { | |
1069 if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { | |
1070 bNeg = TRUE; | |
1071 cc -= 2; | |
1072 } | |
1073 ccf -= 2; | |
1074 } else { | |
1075 ccf--; | |
1076 } | |
1077 break; | |
1078 case 'R': | |
1079 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') { | |
1080 if (str[cc] == ' ') { | |
1081 cc++; | |
1082 } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { | |
1083 bNeg = TRUE; | |
1084 cc -= 2; | |
1085 } | |
1086 ccf -= 2; | |
1087 } else { | |
1088 ccf--; | |
1089 } | |
1090 break; | |
1091 case 'b': | |
1092 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') { | |
1093 if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { | |
1094 bNeg = TRUE; | |
1095 cc -= 2; | |
1096 } | |
1097 ccf -= 2; | |
1098 } else { | |
1099 ccf--; | |
1100 } | |
1101 break; | |
1102 case 'B': | |
1103 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') { | |
1104 if (str[cc] == ' ') { | |
1105 cc++; | |
1106 } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { | |
1107 bNeg = TRUE; | |
1108 cc -= 2; | |
1109 } | |
1110 ccf -= 2; | |
1111 } else { | |
1112 ccf--; | |
1113 } | |
1114 break; | |
1115 case '.': | |
1116 case 'V': | |
1117 case 'v': | |
1118 return FALSE; | |
1119 case '%': { | |
1120 CFX_WideString wsSymbol; | |
1121 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
1122 int32_t iSysmbolLen = wsSymbol.GetLength(); | |
1123 cc -= iSysmbolLen - 1; | |
1124 if (cc < 0 || | |
1125 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) { | |
1126 return FALSE; | |
1127 } | |
1128 cc--; | |
1129 ccf--; | |
1130 bHavePercentSymbol = TRUE; | |
1131 } break; | |
1132 case '8': | |
1133 while (ccf < lenf && strf[ccf] == '8') { | |
1134 ccf++; | |
1135 } | |
1136 while (cc < len && FX_IsDigit(str[cc])) { | |
1137 dbRetValue = (str[cc] - '0') * coeff + dbRetValue; | |
1138 coeff *= 0.1; | |
1139 cc++; | |
1140 } | |
1141 break; | |
1142 case ',': { | |
1143 if (cc >= 0) { | |
1144 cc -= iGroupLen - 1; | |
1145 if (cc >= 0 && | |
1146 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol, | |
1147 iGroupLen) == 0) { | |
1148 cc--; | |
1149 } else { | |
1150 cc += iGroupLen - 1; | |
1151 } | |
1152 } | |
1153 ccf--; | |
1154 } break; | |
1155 case '(': | |
1156 if (str[cc] == L'(') { | |
1157 bNeg = TRUE; | |
1158 } else if (str[cc] != L' ') { | |
1159 return FALSE; | |
1160 } | |
1161 cc--; | |
1162 ccf--; | |
1163 break; | |
1164 case ')': | |
1165 if (str[cc] == L')') { | |
1166 bNeg = TRUE; | |
1167 } else if (str[cc] != L' ') { | |
1168 return FALSE; | |
1169 } | |
1170 cc--; | |
1171 ccf--; | |
1172 break; | |
1173 default: | |
1174 if (strf[ccf] != str[cc]) { | |
1175 return FALSE; | |
1176 } | |
1177 cc--; | |
1178 ccf--; | |
1179 } | |
1180 } | |
1181 dot_index = cc + 1; | |
1182 } | |
1183 ccf = dot_index_f - 1; | |
1184 cc = dot_index - 1; | |
1185 coeff = 1; | |
1186 while (ccf >= 0 && cc >= 0) { | |
1187 switch (strf[ccf]) { | |
1188 case '\'': { | |
1189 CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf); | |
1190 int32_t iLiteralLen = wsLiteral.GetLength(); | |
1191 cc -= iLiteralLen - 1; | |
1192 if (cc < 0 || | |
1193 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) { | |
1194 return FALSE; | |
1195 } | |
1196 cc--; | |
1197 ccf--; | |
1198 break; | |
1199 } | |
1200 case '9': | |
1201 if (!FX_IsDigit(str[cc])) { | |
1202 return FALSE; | |
1203 } | |
1204 dbRetValue = dbRetValue + (str[cc] - '0') * coeff; | |
1205 coeff *= 10; | |
1206 cc--; | |
1207 ccf--; | |
1208 break; | |
1209 case 'z': | |
1210 if (FX_IsDigit(str[cc])) { | |
1211 dbRetValue = dbRetValue + (str[cc] - '0') * coeff; | |
1212 coeff *= 10; | |
1213 cc--; | |
1214 } | |
1215 ccf--; | |
1216 break; | |
1217 case 'Z': | |
1218 if (str[cc] != ' ') { | |
1219 if (FX_IsDigit(str[cc])) { | |
1220 dbRetValue = dbRetValue + (str[cc] - '0') * coeff; | |
1221 coeff *= 10; | |
1222 cc--; | |
1223 } | |
1224 } else { | |
1225 cc--; | |
1226 } | |
1227 ccf--; | |
1228 break; | |
1229 case 'S': | |
1230 if (str[cc] == '+' || str[cc] == ' ') { | |
1231 cc--; | |
1232 } else { | |
1233 cc -= iMinusLen - 1; | |
1234 if (cc < 0 || | |
1235 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1236 return FALSE; | |
1237 } | |
1238 cc--; | |
1239 bNeg = TRUE; | |
1240 } | |
1241 ccf--; | |
1242 break; | |
1243 case 's': | |
1244 if (str[cc] == '+') { | |
1245 cc--; | |
1246 } else { | |
1247 cc -= iMinusLen - 1; | |
1248 if (cc < 0 || | |
1249 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1250 return FALSE; | |
1251 } | |
1252 cc--; | |
1253 bNeg = TRUE; | |
1254 } | |
1255 ccf--; | |
1256 break; | |
1257 case 'E': { | |
1258 if (cc >= dot_index) { | |
1259 return FALSE; | |
1260 } | |
1261 FX_BOOL bExpSign = FALSE; | |
1262 while (cc >= 0) { | |
1263 if (str[cc] == 'E' || str[cc] == 'e') { | |
1264 break; | |
1265 } | |
1266 if (FX_IsDigit(str[cc])) { | |
1267 iExponent = iExponent + (str[cc] - '0') * 10; | |
1268 cc--; | |
1269 continue; | |
1270 } else if (str[cc] == '+') { | |
1271 cc--; | |
1272 continue; | |
1273 } else if (cc - iMinusLen + 1 > 0 && | |
1274 !FXSYS_wcsncmp(str + (cc - iMinusLen + 1), | |
1275 (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1276 bExpSign = TRUE; | |
1277 cc -= iMinusLen; | |
1278 } else { | |
1279 return FALSE; | |
1280 } | |
1281 } | |
1282 cc--; | |
1283 iExponent = bExpSign ? -iExponent : iExponent; | |
1284 ccf--; | |
1285 } break; | |
1286 case '$': { | |
1287 CFX_WideString wsSymbol; | |
1288 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol); | |
1289 int32_t iSymbolLen = wsSymbol.GetLength(); | |
1290 cc -= iSymbolLen - 1; | |
1291 if (cc < 0 || | |
1292 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) { | |
1293 return FALSE; | |
1294 } | |
1295 cc--; | |
1296 ccf--; | |
1297 } break; | |
1298 case 'r': | |
1299 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') { | |
1300 if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { | |
1301 bNeg = TRUE; | |
1302 cc -= 2; | |
1303 } | |
1304 ccf -= 2; | |
1305 } else { | |
1306 ccf--; | |
1307 } | |
1308 break; | |
1309 case 'R': | |
1310 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') { | |
1311 if (str[cc] == ' ') { | |
1312 cc++; | |
1313 } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { | |
1314 bNeg = TRUE; | |
1315 cc -= 2; | |
1316 } | |
1317 ccf -= 2; | |
1318 } else { | |
1319 ccf--; | |
1320 } | |
1321 break; | |
1322 case 'b': | |
1323 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') { | |
1324 if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { | |
1325 bNeg = TRUE; | |
1326 cc -= 2; | |
1327 } | |
1328 ccf -= 2; | |
1329 } else { | |
1330 ccf--; | |
1331 } | |
1332 break; | |
1333 case 'B': | |
1334 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') { | |
1335 if (str[cc] == ' ') { | |
1336 cc++; | |
1337 } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { | |
1338 bNeg = TRUE; | |
1339 cc -= 2; | |
1340 } | |
1341 ccf -= 2; | |
1342 } else { | |
1343 ccf--; | |
1344 } | |
1345 break; | |
1346 case '.': | |
1347 case 'V': | |
1348 case 'v': | |
1349 return FALSE; | |
1350 case '%': { | |
1351 CFX_WideString wsSymbol; | |
1352 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
1353 int32_t iSysmbolLen = wsSymbol.GetLength(); | |
1354 cc -= iSysmbolLen - 1; | |
1355 if (cc < 0 || | |
1356 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) { | |
1357 return FALSE; | |
1358 } | |
1359 cc--; | |
1360 ccf--; | |
1361 bHavePercentSymbol = TRUE; | |
1362 } break; | |
1363 case '8': | |
1364 return FALSE; | |
1365 case ',': { | |
1366 if (cc >= 0) { | |
1367 cc -= iGroupLen - 1; | |
1368 if (cc >= 0 && | |
1369 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol, | |
1370 iGroupLen) == 0) { | |
1371 cc--; | |
1372 } else { | |
1373 cc += iGroupLen - 1; | |
1374 } | |
1375 } | |
1376 ccf--; | |
1377 } break; | |
1378 case '(': | |
1379 if (str[cc] == L'(') { | |
1380 bNeg = TRUE; | |
1381 } else if (str[cc] != L' ') { | |
1382 return FALSE; | |
1383 } | |
1384 cc--; | |
1385 ccf--; | |
1386 break; | |
1387 case ')': | |
1388 if (str[cc] == L')') { | |
1389 bNeg = TRUE; | |
1390 } else if (str[cc] != L' ') { | |
1391 return FALSE; | |
1392 } | |
1393 cc--; | |
1394 ccf--; | |
1395 break; | |
1396 default: | |
1397 if (strf[ccf] != str[cc]) { | |
1398 return FALSE; | |
1399 } | |
1400 cc--; | |
1401 ccf--; | |
1402 } | |
1403 } | |
1404 if (cc >= 0) { | |
1405 return FALSE; | |
1406 } | |
1407 if (!bReverseParse) { | |
1408 ccf = dot_index_f + 1; | |
1409 cc = (dot_index == len) ? len : dot_index + 1; | |
1410 coeff = 0.1; | |
1411 while (cc < len && ccf < lenf) { | |
1412 switch (strf[ccf]) { | |
1413 case '\'': { | |
1414 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf); | |
1415 int32_t iLiteralLen = wsLiteral.GetLength(); | |
1416 if (cc + iLiteralLen > len || | |
1417 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, | |
1418 iLiteralLen)) { | |
1419 return FALSE; | |
1420 } | |
1421 cc += iLiteralLen; | |
1422 ccf++; | |
1423 break; | |
1424 } | |
1425 case '9': | |
1426 if (!FX_IsDigit(str[cc])) { | |
1427 return FALSE; | |
1428 } | |
1429 { | |
1430 dbRetValue = dbRetValue + (str[cc] - '0') * coeff; | |
1431 coeff *= 0.1; | |
1432 } | |
1433 cc++; | |
1434 ccf++; | |
1435 break; | |
1436 case 'z': | |
1437 if (FX_IsDigit(str[cc])) { | |
1438 dbRetValue = dbRetValue + (str[cc] - '0') * coeff; | |
1439 coeff *= 0.1; | |
1440 cc++; | |
1441 } | |
1442 ccf++; | |
1443 break; | |
1444 case 'Z': | |
1445 if (str[cc] != ' ') { | |
1446 if (FX_IsDigit(str[cc])) { | |
1447 dbRetValue = dbRetValue + (str[cc] - '0') * coeff; | |
1448 coeff *= 0.1; | |
1449 cc++; | |
1450 } | |
1451 } else { | |
1452 cc++; | |
1453 } | |
1454 ccf++; | |
1455 break; | |
1456 case 'S': | |
1457 if (str[cc] == '+' || str[cc] == ' ') { | |
1458 cc++; | |
1459 } else { | |
1460 if (cc + iMinusLen > len || | |
1461 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1462 return FALSE; | |
1463 } | |
1464 bNeg = TRUE; | |
1465 cc += iMinusLen; | |
1466 } | |
1467 ccf++; | |
1468 break; | |
1469 case 's': | |
1470 if (str[cc] == '+') { | |
1471 cc++; | |
1472 } else { | |
1473 if (cc + iMinusLen > len || | |
1474 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1475 return FALSE; | |
1476 } | |
1477 bNeg = TRUE; | |
1478 cc += iMinusLen; | |
1479 } | |
1480 ccf++; | |
1481 break; | |
1482 case 'E': { | |
1483 if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) { | |
1484 return FALSE; | |
1485 } | |
1486 FX_BOOL bExpSign = FALSE; | |
1487 cc++; | |
1488 if (cc < len) { | |
1489 if (str[cc] == '+') { | |
1490 cc++; | |
1491 } else if (str[cc] == '-') { | |
1492 bExpSign = TRUE; | |
1493 cc++; | |
1494 } | |
1495 } | |
1496 while (cc < len) { | |
1497 if (!FX_IsDigit(str[cc])) { | |
1498 break; | |
1499 } | |
1500 iExponent = iExponent * 10 + str[cc] - '0'; | |
1501 cc++; | |
1502 } | |
1503 iExponent = bExpSign ? -iExponent : iExponent; | |
1504 ccf++; | |
1505 } break; | |
1506 case '$': { | |
1507 CFX_WideString wsSymbol; | |
1508 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, | |
1509 wsSymbol); | |
1510 int32_t iSymbolLen = wsSymbol.GetLength(); | |
1511 if (cc + iSymbolLen > len || | |
1512 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) { | |
1513 return FALSE; | |
1514 } | |
1515 cc += iSymbolLen; | |
1516 ccf++; | |
1517 } break; | |
1518 case 'c': | |
1519 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') { | |
1520 if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') { | |
1521 bNeg = TRUE; | |
1522 cc += 2; | |
1523 } | |
1524 ccf += 2; | |
1525 } | |
1526 break; | |
1527 case 'C': | |
1528 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') { | |
1529 if (str[cc] == ' ') { | |
1530 cc++; | |
1531 } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') { | |
1532 bNeg = TRUE; | |
1533 cc += 2; | |
1534 } | |
1535 ccf += 2; | |
1536 } | |
1537 break; | |
1538 case 'd': | |
1539 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') { | |
1540 if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') { | |
1541 bNeg = TRUE; | |
1542 cc += 2; | |
1543 } | |
1544 ccf += 2; | |
1545 } | |
1546 break; | |
1547 case 'D': | |
1548 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') { | |
1549 if (str[cc] == ' ') { | |
1550 cc++; | |
1551 } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') { | |
1552 bNeg = TRUE; | |
1553 cc += 2; | |
1554 } | |
1555 ccf += 2; | |
1556 } | |
1557 break; | |
1558 case '.': | |
1559 case 'V': | |
1560 case 'v': | |
1561 return FALSE; | |
1562 case '%': { | |
1563 CFX_WideString wsSymbol; | |
1564 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
1565 int32_t iSysmbolLen = wsSymbol.GetLength(); | |
1566 if (cc + iSysmbolLen <= len && | |
1567 !FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, | |
1568 iSysmbolLen)) { | |
1569 cc += iSysmbolLen; | |
1570 } | |
1571 ccf++; | |
1572 bHavePercentSymbol = TRUE; | |
1573 } break; | |
1574 case '8': { | |
1575 while (ccf < lenf && strf[ccf] == '8') { | |
1576 ccf++; | |
1577 } | |
1578 while (cc < len && FX_IsDigit(str[cc])) { | |
1579 dbRetValue = (str[cc] - '0') * coeff + dbRetValue; | |
1580 coeff *= 0.1; | |
1581 cc++; | |
1582 } | |
1583 } break; | |
1584 case ',': { | |
1585 if (cc + iGroupLen <= len && | |
1586 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol, | |
1587 iGroupLen) == 0) { | |
1588 cc += iGroupLen; | |
1589 } | |
1590 ccf++; | |
1591 } break; | |
1592 case '(': | |
1593 if (str[cc] == L'(') { | |
1594 bNeg = TRUE; | |
1595 } else if (str[cc] != L' ') { | |
1596 return FALSE; | |
1597 } | |
1598 cc++; | |
1599 ccf++; | |
1600 break; | |
1601 case ')': | |
1602 if (str[cc] == L')') { | |
1603 bNeg = TRUE; | |
1604 } else if (str[cc] != L' ') { | |
1605 return FALSE; | |
1606 } | |
1607 cc++; | |
1608 ccf++; | |
1609 break; | |
1610 default: | |
1611 if (strf[ccf] != str[cc]) { | |
1612 return FALSE; | |
1613 } | |
1614 cc++; | |
1615 ccf++; | |
1616 } | |
1617 } | |
1618 if (cc != len) { | |
1619 return FALSE; | |
1620 } | |
1621 } | |
1622 if (iExponent) { | |
1623 dbRetValue *= FXSYS_pow(10, (FX_FLOAT)iExponent); | |
1624 } | |
1625 if (bHavePercentSymbol) { | |
1626 dbRetValue /= 100.0; | |
1627 } | |
1628 if (bNeg) { | |
1629 dbRetValue = -dbRetValue; | |
1630 } | |
1631 fValue = (FX_FLOAT)dbRetValue; | |
1632 return TRUE; | |
1633 } | |
1634 void FX_ParseNumString(const CFX_WideString& wsNum, CFX_WideString& wsResult) { | |
1635 int32_t iCount = wsNum.GetLength(); | |
1636 const FX_WCHAR* pStr = (const FX_WCHAR*)wsNum; | |
1637 FX_WCHAR* pDst = wsResult.GetBuffer(iCount); | |
1638 int32_t nIndex = 0; | |
1639 FX_BOOL bMinus = FALSE; | |
1640 int32_t i = 0; | |
1641 for (i = 0; i < iCount; i++) { | |
1642 FX_WCHAR wc = pStr[i]; | |
1643 if (wc == '.') { | |
1644 break; | |
1645 } | |
1646 if ((wc == L'0' || wc == L' ' || wc == '+') && nIndex == 0) { | |
1647 continue; | |
1648 } | |
1649 if (wc == '-') { | |
1650 pDst[nIndex++] = wc; | |
1651 bMinus = TRUE; | |
1652 continue; | |
1653 } | |
1654 if (wc == L'0' && nIndex == 1 && bMinus) { | |
1655 continue; | |
1656 } | |
1657 pDst[nIndex++] = wc; | |
1658 } | |
1659 if (bMinus && nIndex == 1) { | |
1660 pDst[nIndex++] = '0'; | |
1661 } | |
1662 if (nIndex == 0) { | |
1663 wsResult.ReleaseBuffer(0); | |
1664 pDst = wsResult.GetBuffer(iCount + 1); | |
1665 pDst[nIndex++] = '0'; | |
1666 } | |
1667 int32_t j = 0; | |
1668 for (j = iCount - 1; j > i; j--) { | |
1669 FX_WCHAR wc = pStr[j]; | |
1670 if (wc != L'0' && wc != L' ') { | |
1671 break; | |
1672 } | |
1673 } | |
1674 if (j > i) { | |
1675 pDst[nIndex++] = '.'; | |
1676 FXSYS_wcsncpy(pDst + nIndex, pStr + i + 1, j - i); | |
1677 nIndex += j - i; | |
1678 } | |
1679 wsResult.ReleaseBuffer(nIndex); | |
1680 } | |
1681 FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum, | |
1682 const CFX_WideString& wsPattern, | |
1683 CFX_WideString& wsValue) { | |
1684 wsValue.Empty(); | |
1685 if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) { | |
1686 return FALSE; | |
1687 } | |
1688 int32_t dot_index_f = -1; | |
1689 FX_DWORD dwFormatStyle = 0; | |
1690 CFX_WideString wsNumFormat; | |
1691 IFX_Locale* pLocale = | |
1692 GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat); | |
1693 if (!pLocale || wsNumFormat.IsEmpty()) { | |
1694 return FALSE; | |
1695 } | |
1696 int32_t iExponent = 0; | |
1697 CFX_WideString wsDotSymbol; | |
1698 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol); | |
1699 CFX_WideString wsGroupSymbol; | |
1700 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); | |
1701 int32_t iGroupLen = wsGroupSymbol.GetLength(); | |
1702 CFX_WideString wsMinus; | |
1703 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus); | |
1704 int32_t iMinusLen = wsMinus.GetLength(); | |
1705 int cc = 0, ccf = 0; | |
1706 const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum; | |
1707 int len = wsSrcNum.GetLength(); | |
1708 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat; | |
1709 int lenf = wsNumFormat.GetLength(); | |
1710 FX_BOOL bHavePercentSymbol = FALSE; | |
1711 FX_BOOL bNeg = FALSE; | |
1712 FX_BOOL bReverseParse = FALSE; | |
1713 int32_t dot_index = 0; | |
1714 if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) && | |
1715 (dwFormatStyle & FX_NUMSTYLE_DotVorv)) { | |
1716 bReverseParse = TRUE; | |
1717 } | |
1718 bReverseParse = FALSE; | |
1719 ccf = dot_index_f - 1; | |
1720 cc = dot_index - 1; | |
1721 while (ccf >= 0 && cc >= 0) { | |
1722 switch (strf[ccf]) { | |
1723 case '\'': { | |
1724 CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf); | |
1725 int32_t iLiteralLen = wsLiteral.GetLength(); | |
1726 cc -= iLiteralLen - 1; | |
1727 if (cc < 0 || | |
1728 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) { | |
1729 return FALSE; | |
1730 } | |
1731 cc--; | |
1732 ccf--; | |
1733 break; | |
1734 } | |
1735 case '9': | |
1736 if (!FX_IsDigit(str[cc])) { | |
1737 return FALSE; | |
1738 } | |
1739 wsValue = CFX_WideStringC(str[cc]) + wsValue; | |
1740 cc--; | |
1741 ccf--; | |
1742 break; | |
1743 case 'z': | |
1744 if (FX_IsDigit(str[cc])) { | |
1745 wsValue = CFX_WideStringC(str[cc]) + wsValue; | |
1746 cc--; | |
1747 } | |
1748 ccf--; | |
1749 break; | |
1750 case 'Z': | |
1751 if (str[cc] != ' ') { | |
1752 if (FX_IsDigit(str[cc])) { | |
1753 wsValue = CFX_WideStringC(str[cc]) + wsValue; | |
1754 cc--; | |
1755 } | |
1756 } else { | |
1757 cc--; | |
1758 } | |
1759 ccf--; | |
1760 break; | |
1761 case 'S': | |
1762 if (str[cc] == '+' || str[cc] == ' ') { | |
1763 cc--; | |
1764 } else { | |
1765 cc -= iMinusLen - 1; | |
1766 if (cc < 0 || | |
1767 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1768 return FALSE; | |
1769 } | |
1770 cc--; | |
1771 bNeg = TRUE; | |
1772 } | |
1773 ccf--; | |
1774 break; | |
1775 case 's': | |
1776 if (str[cc] == '+') { | |
1777 cc--; | |
1778 } else { | |
1779 cc -= iMinusLen - 1; | |
1780 if (cc < 0 || | |
1781 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1782 return FALSE; | |
1783 } | |
1784 cc--; | |
1785 bNeg = TRUE; | |
1786 } | |
1787 ccf--; | |
1788 break; | |
1789 case 'E': { | |
1790 if (cc >= dot_index) { | |
1791 return FALSE; | |
1792 } | |
1793 FX_BOOL bExpSign = FALSE; | |
1794 while (cc >= 0) { | |
1795 if (str[cc] == 'E' || str[cc] == 'e') { | |
1796 break; | |
1797 } | |
1798 if (FX_IsDigit(str[cc])) { | |
1799 iExponent = iExponent + (str[cc] - '0') * 10; | |
1800 cc--; | |
1801 continue; | |
1802 } else if (str[cc] == '+') { | |
1803 cc--; | |
1804 continue; | |
1805 } else if (cc - iMinusLen + 1 > 0 && | |
1806 !FXSYS_wcsncmp(str + (cc - iMinusLen + 1), | |
1807 (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1808 bExpSign = TRUE; | |
1809 cc -= iMinusLen; | |
1810 } else { | |
1811 return FALSE; | |
1812 } | |
1813 } | |
1814 cc--; | |
1815 iExponent = bExpSign ? -iExponent : iExponent; | |
1816 ccf--; | |
1817 } break; | |
1818 case '$': { | |
1819 CFX_WideString wsSymbol; | |
1820 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol); | |
1821 int32_t iSymbolLen = wsSymbol.GetLength(); | |
1822 cc -= iSymbolLen - 1; | |
1823 if (cc < 0 || | |
1824 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) { | |
1825 return FALSE; | |
1826 } | |
1827 cc--; | |
1828 ccf--; | |
1829 } break; | |
1830 case 'r': | |
1831 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') { | |
1832 if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { | |
1833 bNeg = TRUE; | |
1834 cc -= 2; | |
1835 } | |
1836 ccf -= 2; | |
1837 } else { | |
1838 ccf--; | |
1839 } | |
1840 break; | |
1841 case 'R': | |
1842 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') { | |
1843 if (str[cc] == ' ') { | |
1844 cc++; | |
1845 } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') { | |
1846 bNeg = TRUE; | |
1847 cc -= 2; | |
1848 } | |
1849 ccf -= 2; | |
1850 } else { | |
1851 ccf--; | |
1852 } | |
1853 break; | |
1854 case 'b': | |
1855 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') { | |
1856 if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { | |
1857 bNeg = TRUE; | |
1858 cc -= 2; | |
1859 } | |
1860 ccf -= 2; | |
1861 } else { | |
1862 ccf--; | |
1863 } | |
1864 break; | |
1865 case 'B': | |
1866 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') { | |
1867 if (str[cc] == ' ') { | |
1868 cc++; | |
1869 } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') { | |
1870 bNeg = TRUE; | |
1871 cc -= 2; | |
1872 } | |
1873 ccf -= 2; | |
1874 } else { | |
1875 ccf--; | |
1876 } | |
1877 break; | |
1878 case '.': | |
1879 case 'V': | |
1880 case 'v': | |
1881 return FALSE; | |
1882 case '%': { | |
1883 CFX_WideString wsSymbol; | |
1884 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
1885 int32_t iSysmbolLen = wsSymbol.GetLength(); | |
1886 cc -= iSysmbolLen - 1; | |
1887 if (cc < 0 || | |
1888 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) { | |
1889 return FALSE; | |
1890 } | |
1891 cc--; | |
1892 ccf--; | |
1893 bHavePercentSymbol = TRUE; | |
1894 } break; | |
1895 case '8': | |
1896 return FALSE; | |
1897 case ',': { | |
1898 if (cc >= 0) { | |
1899 cc -= iGroupLen - 1; | |
1900 if (cc >= 0 && | |
1901 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol, | |
1902 iGroupLen) == 0) { | |
1903 cc--; | |
1904 } else { | |
1905 cc += iGroupLen - 1; | |
1906 } | |
1907 } | |
1908 ccf--; | |
1909 } break; | |
1910 case '(': | |
1911 if (str[cc] == L'(') { | |
1912 bNeg = TRUE; | |
1913 } else if (str[cc] != L' ') { | |
1914 return FALSE; | |
1915 } | |
1916 cc--; | |
1917 ccf--; | |
1918 break; | |
1919 case ')': | |
1920 if (str[cc] == L')') { | |
1921 bNeg = TRUE; | |
1922 } else if (str[cc] != L' ') { | |
1923 return FALSE; | |
1924 } | |
1925 cc--; | |
1926 ccf--; | |
1927 break; | |
1928 default: | |
1929 if (strf[ccf] != str[cc]) { | |
1930 return FALSE; | |
1931 } | |
1932 cc--; | |
1933 ccf--; | |
1934 } | |
1935 } | |
1936 if (cc >= 0) { | |
1937 if (str[cc] == '-') { | |
1938 bNeg = TRUE; | |
1939 cc--; | |
1940 } | |
1941 if (cc >= 0) { | |
1942 return FALSE; | |
1943 } | |
1944 } | |
1945 if (dot_index < len && (dwFormatStyle & FX_NUMSTYLE_DotVorv)) { | |
1946 wsValue += '.'; | |
1947 } | |
1948 if (!bReverseParse) { | |
1949 ccf = dot_index_f + 1; | |
1950 cc = (dot_index == len) ? len : dot_index + 1; | |
1951 while (cc < len && ccf < lenf) { | |
1952 switch (strf[ccf]) { | |
1953 case '\'': { | |
1954 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf); | |
1955 int32_t iLiteralLen = wsLiteral.GetLength(); | |
1956 if (cc + iLiteralLen > len || | |
1957 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, | |
1958 iLiteralLen)) { | |
1959 return FALSE; | |
1960 } | |
1961 cc += iLiteralLen; | |
1962 ccf++; | |
1963 break; | |
1964 } | |
1965 case '9': | |
1966 if (!FX_IsDigit(str[cc])) { | |
1967 return FALSE; | |
1968 } | |
1969 { wsValue += str[cc]; } | |
1970 cc++; | |
1971 ccf++; | |
1972 break; | |
1973 case 'z': | |
1974 if (FX_IsDigit(str[cc])) { | |
1975 wsValue += str[cc]; | |
1976 cc++; | |
1977 } | |
1978 ccf++; | |
1979 break; | |
1980 case 'Z': | |
1981 if (str[cc] != ' ') { | |
1982 if (FX_IsDigit(str[cc])) { | |
1983 wsValue += str[cc]; | |
1984 cc++; | |
1985 } | |
1986 } else { | |
1987 cc++; | |
1988 } | |
1989 ccf++; | |
1990 break; | |
1991 case 'S': | |
1992 if (str[cc] == '+' || str[cc] == ' ') { | |
1993 cc++; | |
1994 } else { | |
1995 if (cc + iMinusLen > len || | |
1996 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
1997 return FALSE; | |
1998 } | |
1999 bNeg = TRUE; | |
2000 cc += iMinusLen; | |
2001 } | |
2002 ccf++; | |
2003 break; | |
2004 case 's': | |
2005 if (str[cc] == '+') { | |
2006 cc++; | |
2007 } else { | |
2008 if (cc + iMinusLen > len || | |
2009 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) { | |
2010 return FALSE; | |
2011 } | |
2012 bNeg = TRUE; | |
2013 cc += iMinusLen; | |
2014 } | |
2015 ccf++; | |
2016 break; | |
2017 case 'E': { | |
2018 if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) { | |
2019 return FALSE; | |
2020 } | |
2021 FX_BOOL bExpSign = FALSE; | |
2022 cc++; | |
2023 if (cc < len) { | |
2024 if (str[cc] == '+') { | |
2025 cc++; | |
2026 } else if (str[cc] == '-') { | |
2027 bExpSign = TRUE; | |
2028 cc++; | |
2029 } | |
2030 } | |
2031 while (cc < len) { | |
2032 if (!FX_IsDigit(str[cc])) { | |
2033 break; | |
2034 } | |
2035 iExponent = iExponent * 10 + str[cc] - '0'; | |
2036 cc++; | |
2037 } | |
2038 iExponent = bExpSign ? -iExponent : iExponent; | |
2039 ccf++; | |
2040 } break; | |
2041 case '$': { | |
2042 CFX_WideString wsSymbol; | |
2043 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, | |
2044 wsSymbol); | |
2045 int32_t iSymbolLen = wsSymbol.GetLength(); | |
2046 if (cc + iSymbolLen > len || | |
2047 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) { | |
2048 return FALSE; | |
2049 } | |
2050 cc += iSymbolLen; | |
2051 ccf++; | |
2052 } break; | |
2053 case 'c': | |
2054 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') { | |
2055 if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') { | |
2056 bNeg = TRUE; | |
2057 cc += 2; | |
2058 } | |
2059 ccf += 2; | |
2060 } | |
2061 break; | |
2062 case 'C': | |
2063 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') { | |
2064 if (str[cc] == ' ') { | |
2065 cc++; | |
2066 } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') { | |
2067 bNeg = TRUE; | |
2068 cc += 2; | |
2069 } | |
2070 ccf += 2; | |
2071 } | |
2072 break; | |
2073 case 'd': | |
2074 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') { | |
2075 if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') { | |
2076 bNeg = TRUE; | |
2077 cc += 2; | |
2078 } | |
2079 ccf += 2; | |
2080 } | |
2081 break; | |
2082 case 'D': | |
2083 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') { | |
2084 if (str[cc] == ' ') { | |
2085 cc++; | |
2086 } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') { | |
2087 bNeg = TRUE; | |
2088 cc += 2; | |
2089 } | |
2090 ccf += 2; | |
2091 } | |
2092 break; | |
2093 case '.': | |
2094 case 'V': | |
2095 case 'v': | |
2096 return FALSE; | |
2097 case '%': { | |
2098 CFX_WideString wsSymbol; | |
2099 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
2100 int32_t iSysmbolLen = wsSymbol.GetLength(); | |
2101 if (cc + iSysmbolLen <= len && | |
2102 !FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, | |
2103 iSysmbolLen)) { | |
2104 cc += iSysmbolLen; | |
2105 } | |
2106 ccf++; | |
2107 bHavePercentSymbol = TRUE; | |
2108 } break; | |
2109 case '8': { | |
2110 while (ccf < lenf && strf[ccf] == '8') { | |
2111 ccf++; | |
2112 } | |
2113 while (cc < len && FX_IsDigit(str[cc])) { | |
2114 wsValue += str[cc]; | |
2115 cc++; | |
2116 } | |
2117 } break; | |
2118 case ',': { | |
2119 if (cc + iGroupLen <= len && | |
2120 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol, | |
2121 iGroupLen) == 0) { | |
2122 cc += iGroupLen; | |
2123 } | |
2124 ccf++; | |
2125 } break; | |
2126 case '(': | |
2127 if (str[cc] == L'(') { | |
2128 bNeg = TRUE; | |
2129 } else if (str[cc] != L' ') { | |
2130 return FALSE; | |
2131 } | |
2132 cc++; | |
2133 ccf++; | |
2134 break; | |
2135 case ')': | |
2136 if (str[cc] == L')') { | |
2137 bNeg = TRUE; | |
2138 } else if (str[cc] != L' ') { | |
2139 return FALSE; | |
2140 } | |
2141 cc++; | |
2142 ccf++; | |
2143 break; | |
2144 default: | |
2145 if (strf[ccf] != str[cc]) { | |
2146 return FALSE; | |
2147 } | |
2148 cc++; | |
2149 ccf++; | |
2150 } | |
2151 } | |
2152 if (cc != len) { | |
2153 return FALSE; | |
2154 } | |
2155 } | |
2156 if (iExponent || bHavePercentSymbol) { | |
2157 CFX_Decimal decimal = CFX_Decimal(wsValue); | |
2158 if (iExponent) { | |
2159 decimal = decimal * CFX_Decimal(FXSYS_pow(10, (FX_FLOAT)iExponent)); | |
2160 } | |
2161 if (bHavePercentSymbol) { | |
2162 decimal = decimal / CFX_Decimal(100); | |
2163 } | |
2164 wsValue = decimal; | |
2165 } | |
2166 if (bNeg) { | |
2167 wsValue = CFX_WideStringC('-') + wsValue; | |
2168 } | |
2169 return TRUE; | |
2170 } | |
2171 FX_DATETIMETYPE CFX_FormatString::GetDateTimeFormat( | |
2172 const CFX_WideString& wsPattern, | |
2173 IFX_Locale*& pLocale, | |
2174 CFX_WideString& wsDatePattern, | |
2175 CFX_WideString& wsTimePattern) { | |
2176 pLocale = NULL; | |
2177 CFX_WideString wsTempPattern; | |
2178 FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown; | |
2179 int32_t ccf = 0; | |
2180 int32_t iLenf = wsPattern.GetLength(); | |
2181 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern; | |
2182 int32_t iFindCategory = 0; | |
2183 FX_BOOL bBraceOpen = FALSE; | |
2184 while (ccf < iLenf) { | |
2185 if (pStr[ccf] == '\'') { | |
2186 int32_t iCurChar = ccf; | |
2187 FX_GetLiteralText(pStr, ccf, iLenf); | |
2188 wsTempPattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1); | |
2189 } else if (!bBraceOpen && iFindCategory != 3 && | |
2190 FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) { | |
2191 CFX_WideString wsCategory(pStr[ccf]); | |
2192 ccf++; | |
2193 while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' && | |
2194 pStr[ccf] != '(') { | |
2195 if (pStr[ccf] == 'T') { | |
2196 wsDatePattern = wsPattern.Left(ccf); | |
2197 wsTimePattern = wsPattern.Right(wsPattern.GetLength() - ccf); | |
2198 wsTimePattern.SetAt(0, ' '); | |
2199 if (!pLocale) { | |
2200 pLocale = m_pLocaleMgr->GetDefLocale(); | |
2201 } | |
2202 return FX_DATETIMETYPE_DateTime; | |
2203 } | |
2204 wsCategory += pStr[ccf]; | |
2205 ccf++; | |
2206 } | |
2207 if (!(iFindCategory & 1) && wsCategory == FX_WSTRC(L"date")) { | |
2208 iFindCategory |= 1; | |
2209 eCategory = FX_LOCALECATEGORY_Date; | |
2210 if (iFindCategory & 2) { | |
2211 iFindCategory = 4; | |
2212 } | |
2213 } else if (!(iFindCategory & 2) && wsCategory == FX_WSTRC(L"time")) { | |
2214 iFindCategory |= 2; | |
2215 eCategory = FX_LOCALECATEGORY_Time; | |
2216 } else if (wsCategory == FX_WSTRC(L"datetime")) { | |
2217 iFindCategory = 3; | |
2218 eCategory = FX_LOCALECATEGORY_DateTime; | |
2219 } else { | |
2220 continue; | |
2221 } | |
2222 while (ccf < iLenf) { | |
2223 if (pStr[ccf] == '(') { | |
2224 ccf++; | |
2225 CFX_WideString wsLCID; | |
2226 while (ccf < iLenf && pStr[ccf] != ')') { | |
2227 wsLCID += pStr[ccf++]; | |
2228 } | |
2229 pLocale = GetPatternLocale(wsLCID); | |
2230 } else if (pStr[ccf] == '{') { | |
2231 bBraceOpen = TRUE; | |
2232 break; | |
2233 } else if (pStr[ccf] == '.') { | |
2234 CFX_WideString wsSubCategory; | |
2235 ccf++; | |
2236 while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') { | |
2237 wsSubCategory += pStr[ccf++]; | |
2238 } | |
2239 FX_DWORD dwSubHash = | |
2240 FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength()); | |
2241 FX_LOCALEDATETIMESUBCATEGORY eSubCategory = | |
2242 FX_LOCALEDATETIMESUBCATEGORY_Medium; | |
2243 for (int32_t i = 0; i < g_iFXLocaleDateTimeSubCatCount; i++) { | |
2244 if (g_FXLocaleDateTimeSubCatData[i].uHash == dwSubHash) { | |
2245 eSubCategory = | |
2246 (FX_LOCALEDATETIMESUBCATEGORY)g_FXLocaleDateTimeSubCatData[i] | |
2247 .eSubCategory; | |
2248 break; | |
2249 } | |
2250 } | |
2251 if (!pLocale) { | |
2252 pLocale = m_pLocaleMgr->GetDefLocale(); | |
2253 } | |
2254 FXSYS_assert(pLocale != NULL); | |
2255 switch (eCategory) { | |
2256 case FX_LOCALECATEGORY_Date: | |
2257 pLocale->GetDatePattern(eSubCategory, wsDatePattern); | |
2258 wsDatePattern = wsTempPattern + wsDatePattern; | |
2259 break; | |
2260 case FX_LOCALECATEGORY_Time: | |
2261 pLocale->GetTimePattern(eSubCategory, wsTimePattern); | |
2262 wsTimePattern = wsTempPattern + wsTimePattern; | |
2263 break; | |
2264 case FX_LOCALECATEGORY_DateTime: | |
2265 pLocale->GetDatePattern(eSubCategory, wsDatePattern); | |
2266 wsDatePattern = wsTempPattern + wsDatePattern; | |
2267 pLocale->GetTimePattern(eSubCategory, wsTimePattern); | |
2268 break; | |
2269 default: | |
2270 break; | |
2271 } | |
2272 wsTempPattern.Empty(); | |
2273 continue; | |
2274 } | |
2275 ccf++; | |
2276 } | |
2277 } else if (pStr[ccf] == '}') { | |
2278 bBraceOpen = FALSE; | |
2279 if (!wsTempPattern.IsEmpty()) { | |
2280 if (eCategory == FX_LOCALECATEGORY_Time) { | |
2281 wsTimePattern = wsTempPattern; | |
2282 } else if (eCategory == FX_LOCALECATEGORY_Date) { | |
2283 wsDatePattern = wsTempPattern; | |
2284 } | |
2285 wsTempPattern.Empty(); | |
2286 } | |
2287 } else { | |
2288 wsTempPattern += pStr[ccf]; | |
2289 } | |
2290 ccf++; | |
2291 } | |
2292 if (!wsTempPattern.IsEmpty()) { | |
2293 if (eCategory == FX_LOCALECATEGORY_Date) { | |
2294 wsDatePattern += wsTempPattern; | |
2295 } else { | |
2296 wsTimePattern += wsTempPattern; | |
2297 } | |
2298 } | |
2299 if (!pLocale) { | |
2300 pLocale = m_pLocaleMgr->GetDefLocale(); | |
2301 } | |
2302 if (!iFindCategory) { | |
2303 wsTimePattern.Empty(); | |
2304 wsDatePattern = wsPattern; | |
2305 } | |
2306 return (FX_DATETIMETYPE)iFindCategory; | |
2307 } | |
2308 static FX_BOOL FX_ParseLocaleDate(const CFX_WideString& wsDate, | |
2309 const CFX_WideString& wsDatePattern, | |
2310 IFX_Locale* pLocale, | |
2311 CFX_Unitime& datetime, | |
2312 int32_t& cc) { | |
2313 int32_t year = 1900; | |
2314 int32_t month = 1; | |
2315 int32_t day = 1; | |
2316 int32_t ccf = 0; | |
2317 const FX_WCHAR* str = (const FX_WCHAR*)wsDate; | |
2318 int32_t len = wsDate.GetLength(); | |
2319 const FX_WCHAR* strf = (const FX_WCHAR*)wsDatePattern; | |
2320 int32_t lenf = wsDatePattern.GetLength(); | |
2321 while (cc < len && ccf < lenf) { | |
2322 if (strf[ccf] == '\'') { | |
2323 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf); | |
2324 int32_t iLiteralLen = wsLiteral.GetLength(); | |
2325 if (cc + iLiteralLen > len || | |
2326 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) { | |
2327 return FALSE; | |
2328 } | |
2329 cc += iLiteralLen; | |
2330 ccf++; | |
2331 continue; | |
2332 } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) { | |
2333 if (strf[ccf] != str[cc]) { | |
2334 return FALSE; | |
2335 } | |
2336 cc++; | |
2337 ccf++; | |
2338 continue; | |
2339 } | |
2340 FX_DWORD dwSymbolNum = 1; | |
2341 FX_DWORD dwSymbol = strf[ccf++]; | |
2342 while (ccf < lenf && strf[ccf] == dwSymbol) { | |
2343 ccf++; | |
2344 dwSymbolNum++; | |
2345 } | |
2346 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0'); | |
2347 if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) { | |
2348 if (!FX_IsDigit(str[cc])) { | |
2349 return FALSE; | |
2350 } | |
2351 day = str[cc++] - '0'; | |
2352 if (cc < len && FX_IsDigit(str[cc])) { | |
2353 day = day * 10 + str[cc++] - '0'; | |
2354 } | |
2355 } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) { | |
2356 if (!FX_IsDigit(str[cc])) { | |
2357 return FALSE; | |
2358 } | |
2359 day = str[cc++] - '0'; | |
2360 if (cc < len) { | |
2361 day = day * 10 + str[cc++] - '0'; | |
2362 } | |
2363 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) { | |
2364 int i = 0; | |
2365 while (cc < len && i < 3 && FX_IsDigit(str[cc])) { | |
2366 cc++; | |
2367 i++; | |
2368 } | |
2369 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) { | |
2370 cc += 3; | |
2371 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) { | |
2372 if (!FX_IsDigit(str[cc])) { | |
2373 return FALSE; | |
2374 } | |
2375 month = str[cc++] - '0'; | |
2376 if (cc < len && FX_IsDigit(str[cc])) { | |
2377 month = month * 10 + str[cc++] - '0'; | |
2378 } | |
2379 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { | |
2380 if (!FX_IsDigit(str[cc])) { | |
2381 return FALSE; | |
2382 } | |
2383 month = str[cc++] - '0'; | |
2384 if (cc < len) { | |
2385 month = month * 10 + str[cc++] - '0'; | |
2386 } | |
2387 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) { | |
2388 CFX_WideString wsMonthNameAbbr; | |
2389 FX_WORD i = 0; | |
2390 for (; i < 12; i++) { | |
2391 pLocale->GetMonthName(i, wsMonthNameAbbr, TRUE); | |
2392 if (wsMonthNameAbbr.IsEmpty()) { | |
2393 continue; | |
2394 } | |
2395 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsMonthNameAbbr, str + cc, | |
2396 wsMonthNameAbbr.GetLength())) { | |
2397 break; | |
2398 } | |
2399 } | |
2400 if (i < 12) { | |
2401 cc += wsMonthNameAbbr.GetLength(); | |
2402 month = i + 1; | |
2403 } | |
2404 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) { | |
2405 CFX_WideString wsMonthName; | |
2406 FX_WORD i = 0; | |
2407 for (; i < 12; i++) { | |
2408 pLocale->GetMonthName(i, wsMonthName, FALSE); | |
2409 if (wsMonthName.IsEmpty()) { | |
2410 continue; | |
2411 } | |
2412 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsMonthName, str + cc, | |
2413 wsMonthName.GetLength())) { | |
2414 break; | |
2415 } | |
2416 } | |
2417 if (i < 12) { | |
2418 cc += wsMonthName.GetLength(); | |
2419 month = i + 1; | |
2420 } | |
2421 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) { | |
2422 cc += 1; | |
2423 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) { | |
2424 CFX_WideString wsDayNameAbbr; | |
2425 FX_WORD i = 0; | |
2426 for (; i < 7; i++) { | |
2427 pLocale->GetDayName(i, wsDayNameAbbr, TRUE); | |
2428 if (wsDayNameAbbr.IsEmpty()) { | |
2429 continue; | |
2430 } | |
2431 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsDayNameAbbr, str + cc, | |
2432 wsDayNameAbbr.GetLength())) { | |
2433 break; | |
2434 } | |
2435 } | |
2436 if (i < 12) { | |
2437 cc += wsDayNameAbbr.GetLength(); | |
2438 } | |
2439 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) { | |
2440 CFX_WideString wsDayName; | |
2441 int32_t i = 0; | |
2442 for (; i < 7; i++) { | |
2443 pLocale->GetDayName(i, wsDayName, FALSE); | |
2444 if (wsDayName == L"") { | |
2445 continue; | |
2446 } | |
2447 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsDayName, str + cc, | |
2448 wsDayName.GetLength())) { | |
2449 break; | |
2450 } | |
2451 } | |
2452 if (i < 12) { | |
2453 cc += wsDayName.GetLength(); | |
2454 } | |
2455 } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) { | |
2456 cc += 1; | |
2457 } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) { | |
2458 cc += 2; | |
2459 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) { | |
2460 if (cc + 2 > len) { | |
2461 return FALSE; | |
2462 } | |
2463 if (!FX_IsDigit(str[cc])) { | |
2464 return FALSE; | |
2465 } | |
2466 year = str[cc++] - '0'; | |
2467 if (cc >= len || !FX_IsDigit(str[cc])) { | |
2468 return FALSE; | |
2469 } | |
2470 year = year * 10 + str[cc++] - '0'; | |
2471 if (year <= 29) { | |
2472 year += 2000; | |
2473 } else { | |
2474 year += 1900; | |
2475 } | |
2476 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) { | |
2477 int i = 0; | |
2478 year = 0; | |
2479 if (cc + 4 > len) { | |
2480 return FALSE; | |
2481 } | |
2482 while (i < 4) { | |
2483 if (!FX_IsDigit(str[cc])) { | |
2484 return FALSE; | |
2485 } | |
2486 year = year * 10 + str[cc] - '0'; | |
2487 cc++; | |
2488 i++; | |
2489 } | |
2490 } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) { | |
2491 cc += 1; | |
2492 } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) { | |
2493 cc += 2; | |
2494 } | |
2495 } | |
2496 if (cc < len) { | |
2497 return FALSE; | |
2498 } | |
2499 CFX_Unitime ut; | |
2500 ut.Set(year, month, day); | |
2501 datetime = datetime + ut; | |
2502 return cc; | |
2503 } | |
2504 static void FX_ResolveZone(uint8_t& wHour, | |
2505 uint8_t& wMinute, | |
2506 FX_TIMEZONE tzDiff, | |
2507 IFX_Locale* pLocale) { | |
2508 int32_t iMinuteDiff = wHour * 60 + wMinute; | |
2509 FX_TIMEZONE tzLocale; | |
2510 pLocale->GetTimeZone(tzLocale); | |
2511 iMinuteDiff += tzLocale.tzHour * 60 + | |
2512 (tzLocale.tzHour < 0 ? -tzLocale.tzMinute : tzLocale.tzMinute); | |
2513 iMinuteDiff -= tzDiff.tzHour * 60 + | |
2514 (tzDiff.tzHour < 0 ? -tzDiff.tzMinute : tzDiff.tzMinute); | |
2515 while (iMinuteDiff > 1440) { | |
2516 iMinuteDiff -= 1440; | |
2517 } | |
2518 while (iMinuteDiff < 0) { | |
2519 iMinuteDiff += 1440; | |
2520 } | |
2521 wHour = iMinuteDiff / 60; | |
2522 wMinute = iMinuteDiff % 60; | |
2523 } | |
2524 static FX_BOOL FX_ParseLocaleTime(const CFX_WideString& wsTime, | |
2525 const CFX_WideString& wsTimePattern, | |
2526 IFX_Locale* pLocale, | |
2527 CFX_Unitime& datetime, | |
2528 int32_t& cc) { | |
2529 uint8_t hour = 0; | |
2530 uint8_t minute = 0; | |
2531 uint8_t second = 0; | |
2532 FX_WORD millisecond = 0; | |
2533 int32_t ccf = 0; | |
2534 const FX_WCHAR* str = (const FX_WCHAR*)wsTime; | |
2535 int len = wsTime.GetLength(); | |
2536 const FX_WCHAR* strf = (const FX_WCHAR*)wsTimePattern; | |
2537 int lenf = wsTimePattern.GetLength(); | |
2538 FX_BOOL bHasA = FALSE; | |
2539 FX_BOOL bPM = FALSE; | |
2540 while (cc < len && ccf < lenf) { | |
2541 if (strf[ccf] == '\'') { | |
2542 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf); | |
2543 int32_t iLiteralLen = wsLiteral.GetLength(); | |
2544 if (cc + iLiteralLen > len || | |
2545 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) { | |
2546 return FALSE; | |
2547 } | |
2548 cc += iLiteralLen; | |
2549 ccf++; | |
2550 continue; | |
2551 } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) == -1) { | |
2552 if (strf[ccf] != str[cc]) { | |
2553 return FALSE; | |
2554 } | |
2555 cc++; | |
2556 ccf++; | |
2557 continue; | |
2558 } | |
2559 FX_DWORD dwSymbolNum = 1; | |
2560 FX_DWORD dwSymbol = strf[ccf++]; | |
2561 while (ccf < lenf && strf[ccf] == dwSymbol) { | |
2562 ccf++; | |
2563 dwSymbolNum++; | |
2564 } | |
2565 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0'); | |
2566 if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1') || | |
2567 dwSymbol == FXBSTR_ID(0, 0, 'H', '1') || | |
2568 dwSymbol == FXBSTR_ID(0, 0, 'h', '1') || | |
2569 dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) { | |
2570 if (!FX_IsDigit(str[cc])) { | |
2571 return FALSE; | |
2572 } | |
2573 hour = str[cc++] - '0'; | |
2574 if (cc < len && FX_IsDigit(str[cc])) { | |
2575 hour = hour * 10 + str[cc++] - '0'; | |
2576 } | |
2577 if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1') && hour == 24) { | |
2578 hour = 0; | |
2579 } | |
2580 } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2') || | |
2581 dwSymbol == FXBSTR_ID(0, 0, 'H', '2') || | |
2582 dwSymbol == FXBSTR_ID(0, 0, 'h', '2') || | |
2583 dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) { | |
2584 if (!FX_IsDigit(str[cc])) { | |
2585 return FALSE; | |
2586 } | |
2587 hour = str[cc++] - '0'; | |
2588 if (cc >= len) { | |
2589 return FALSE; | |
2590 } | |
2591 if (!FX_IsDigit(str[cc])) { | |
2592 return FALSE; | |
2593 } | |
2594 hour = hour * 10 + str[cc++] - '0'; | |
2595 if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2') && hour == 24) { | |
2596 hour = 0; | |
2597 } | |
2598 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) { | |
2599 if (!FX_IsDigit(str[cc])) { | |
2600 return FALSE; | |
2601 } | |
2602 minute = str[cc++] - '0'; | |
2603 if (cc < len && FX_IsDigit(str[cc])) { | |
2604 minute = minute * 10 + str[cc++] - '0'; | |
2605 } | |
2606 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { | |
2607 if (!FX_IsDigit(str[cc])) { | |
2608 return FALSE; | |
2609 } | |
2610 minute = str[cc++] - '0'; | |
2611 if (cc >= len) { | |
2612 return FALSE; | |
2613 } | |
2614 if (!FX_IsDigit(str[cc])) { | |
2615 return FALSE; | |
2616 } | |
2617 minute = minute * 10 + str[cc++] - '0'; | |
2618 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) { | |
2619 if (!FX_IsDigit(str[cc])) { | |
2620 return FALSE; | |
2621 } | |
2622 second = str[cc++] - '0'; | |
2623 if (cc < len && FX_IsDigit(str[cc])) { | |
2624 second = second * 10 + str[cc++] - '0'; | |
2625 } | |
2626 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) { | |
2627 if (!FX_IsDigit(str[cc])) { | |
2628 return FALSE; | |
2629 } | |
2630 second = str[cc++] - '0'; | |
2631 if (cc >= len) { | |
2632 return FALSE; | |
2633 } | |
2634 if (!FX_IsDigit(str[cc])) { | |
2635 return FALSE; | |
2636 } | |
2637 second = second * 10 + str[cc++] - '0'; | |
2638 } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) { | |
2639 if (cc + 3 >= len) { | |
2640 return FALSE; | |
2641 } | |
2642 int i = 0; | |
2643 while (i < 3) { | |
2644 if (!FX_IsDigit(str[cc])) { | |
2645 return FALSE; | |
2646 } | |
2647 millisecond = millisecond * 10 + str[cc++] - '0'; | |
2648 i++; | |
2649 } | |
2650 } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) { | |
2651 CFX_WideString wsAM; | |
2652 pLocale->GetMeridiemName(wsAM, TRUE); | |
2653 CFX_WideString wsPM; | |
2654 pLocale->GetMeridiemName(wsPM, FALSE); | |
2655 if ((cc + wsAM.GetLength() <= len) && | |
2656 (CFX_WideStringC(str + cc, wsAM.GetLength()) == wsAM)) { | |
2657 cc += wsAM.GetLength(); | |
2658 bHasA = TRUE; | |
2659 } else if ((cc + wsPM.GetLength() <= len) && | |
2660 (CFX_WideStringC(str + cc, wsPM.GetLength()) == wsPM)) { | |
2661 cc += wsPM.GetLength(); | |
2662 bHasA = TRUE; | |
2663 bPM = TRUE; | |
2664 } | |
2665 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) { | |
2666 if (cc + 3 > len) { | |
2667 continue; | |
2668 } | |
2669 FX_DWORD dwHash = str[cc++]; | |
2670 dwHash = (dwHash << 8) | str[cc++]; | |
2671 dwHash = (dwHash << 8) | str[cc++]; | |
2672 if (dwHash == FXBSTR_ID(0, 'G', 'M', 'T')) { | |
2673 FX_TIMEZONE tzDiff; | |
2674 tzDiff.tzHour = 0; | |
2675 tzDiff.tzMinute = 0; | |
2676 if (cc < len && (str[cc] == '-' || str[cc] == '+')) { | |
2677 cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff); | |
2678 } | |
2679 FX_ResolveZone(hour, minute, tzDiff, pLocale); | |
2680 } else { | |
2681 const FX_LOCALETIMEZONEINFO* pEnd = | |
2682 g_FXLocaleTimeZoneData + FX_ArraySize(g_FXLocaleTimeZoneData); | |
2683 const FX_LOCALETIMEZONEINFO* pTimeZoneInfo = | |
2684 std::lower_bound(g_FXLocaleTimeZoneData, pEnd, dwHash, | |
2685 [](const FX_LOCALETIMEZONEINFO& info, | |
2686 FX_DWORD hash) { return info.uHash < hash; }); | |
2687 if (pTimeZoneInfo < pEnd && dwHash == pTimeZoneInfo->uHash) { | |
2688 hour += pTimeZoneInfo->iHour; | |
2689 minute += pTimeZoneInfo->iHour > 0 ? pTimeZoneInfo->iMinute | |
2690 : -pTimeZoneInfo->iMinute; | |
2691 } | |
2692 } | |
2693 } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) { | |
2694 if (str[cc] != 'Z') { | |
2695 FX_TIMEZONE tzDiff; | |
2696 cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff); | |
2697 FX_ResolveZone(hour, minute, tzDiff, pLocale); | |
2698 } else { | |
2699 cc++; | |
2700 } | |
2701 } | |
2702 } | |
2703 if (bHasA) { | |
2704 if (bPM) { | |
2705 hour += 12; | |
2706 if (hour == 24) { | |
2707 hour = 12; | |
2708 } | |
2709 } else { | |
2710 if (hour == 12) { | |
2711 hour = 0; | |
2712 } | |
2713 } | |
2714 } | |
2715 CFX_Unitime ut; | |
2716 ut.Set(0, 0, 0, hour, minute, second, millisecond); | |
2717 datetime = datetime + ut; | |
2718 return cc; | |
2719 } | |
2720 FX_BOOL CFX_FormatString::ParseDateTime(const CFX_WideString& wsSrcDateTime, | |
2721 const CFX_WideString& wsPattern, | |
2722 FX_DATETIMETYPE eDateTimeType, | |
2723 CFX_Unitime& dtValue) { | |
2724 dtValue.Set(0); | |
2725 if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) { | |
2726 return FALSE; | |
2727 } | |
2728 CFX_WideString wsDatePattern, wsTimePattern; | |
2729 IFX_Locale* pLocale = NULL; | |
2730 FX_DATETIMETYPE eCategory = | |
2731 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); | |
2732 if (!pLocale) { | |
2733 return FALSE; | |
2734 } | |
2735 if (eCategory == FX_DATETIMETYPE_Unknown) { | |
2736 eCategory = eDateTimeType; | |
2737 } | |
2738 if (eCategory == FX_DATETIMETYPE_Unknown) { | |
2739 return FALSE; | |
2740 } | |
2741 if (eCategory == FX_DATETIMETYPE_TimeDate) { | |
2742 int32_t iStart = 0; | |
2743 if (!FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, | |
2744 iStart)) { | |
2745 return FALSE; | |
2746 } | |
2747 if (!FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, | |
2748 iStart)) { | |
2749 return FALSE; | |
2750 } | |
2751 } else { | |
2752 int32_t iStart = 0; | |
2753 if ((eCategory & FX_DATETIMETYPE_Date) && | |
2754 !FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue, | |
2755 iStart)) { | |
2756 return FALSE; | |
2757 } | |
2758 if ((eCategory & FX_DATETIMETYPE_Time) && | |
2759 !FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue, | |
2760 iStart)) { | |
2761 return FALSE; | |
2762 } | |
2763 } | |
2764 return TRUE; | |
2765 } | |
2766 FX_BOOL CFX_FormatString::ParseZero(const CFX_WideString& wsSrcText, | |
2767 const CFX_WideString& wsPattern) { | |
2768 CFX_WideString wsTextFormat; | |
2769 GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat); | |
2770 int32_t iText = 0, iPattern = 0; | |
2771 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText; | |
2772 int32_t iLenText = wsSrcText.GetLength(); | |
2773 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat; | |
2774 int32_t iLenPattern = wsTextFormat.GetLength(); | |
2775 while (iPattern < iLenPattern && iText < iLenText) { | |
2776 if (pStrPattern[iPattern] == '\'') { | |
2777 CFX_WideString wsLiteral = | |
2778 FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); | |
2779 int32_t iLiteralLen = wsLiteral.GetLength(); | |
2780 if (iText + iLiteralLen > iLenText || | |
2781 FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral, | |
2782 iLiteralLen)) { | |
2783 return FALSE; | |
2784 } | |
2785 iText += iLiteralLen; | |
2786 iPattern++; | |
2787 continue; | |
2788 } else if (pStrPattern[iPattern] != pStrText[iText]) { | |
2789 return FALSE; | |
2790 } else { | |
2791 iText++; | |
2792 iPattern++; | |
2793 } | |
2794 } | |
2795 return iPattern == iLenPattern && iText == iLenText; | |
2796 } | |
2797 FX_BOOL CFX_FormatString::ParseNull(const CFX_WideString& wsSrcText, | |
2798 const CFX_WideString& wsPattern) { | |
2799 CFX_WideString wsTextFormat; | |
2800 GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat); | |
2801 int32_t iText = 0, iPattern = 0; | |
2802 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText; | |
2803 int32_t iLenText = wsSrcText.GetLength(); | |
2804 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat; | |
2805 int32_t iLenPattern = wsTextFormat.GetLength(); | |
2806 while (iPattern < iLenPattern && iText < iLenText) { | |
2807 if (pStrPattern[iPattern] == '\'') { | |
2808 CFX_WideString wsLiteral = | |
2809 FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); | |
2810 int32_t iLiteralLen = wsLiteral.GetLength(); | |
2811 if (iText + iLiteralLen > iLenText || | |
2812 FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral, | |
2813 iLiteralLen)) { | |
2814 return FALSE; | |
2815 } | |
2816 iText += iLiteralLen; | |
2817 iPattern++; | |
2818 continue; | |
2819 } else if (pStrPattern[iPattern] != pStrText[iText]) { | |
2820 return FALSE; | |
2821 } else { | |
2822 iText++; | |
2823 iPattern++; | |
2824 } | |
2825 } | |
2826 return iPattern == iLenPattern && iText == iLenText; | |
2827 } | |
2828 FX_BOOL CFX_FormatString::FormatText(const CFX_WideString& wsSrcText, | |
2829 const CFX_WideString& wsPattern, | |
2830 CFX_WideString& wsOutput) { | |
2831 if (wsPattern.IsEmpty()) { | |
2832 return FALSE; | |
2833 } | |
2834 int32_t iLenText = wsSrcText.GetLength(); | |
2835 if (iLenText == 0) { | |
2836 return FALSE; | |
2837 } | |
2838 CFX_WideString wsTextFormat; | |
2839 GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat); | |
2840 int32_t iText = 0, iPattern = 0; | |
2841 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText; | |
2842 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat; | |
2843 int32_t iLenPattern = wsTextFormat.GetLength(); | |
2844 while (iPattern < iLenPattern) { | |
2845 switch (pStrPattern[iPattern]) { | |
2846 case '\'': { | |
2847 wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); | |
2848 iPattern++; | |
2849 break; | |
2850 } | |
2851 case 'A': | |
2852 if (iText >= iLenText || !FX_IsAlpha(pStrText[iText])) { | |
2853 return FALSE; | |
2854 } | |
2855 wsOutput += pStrText[iText++]; | |
2856 iPattern++; | |
2857 break; | |
2858 case 'X': | |
2859 if (iText >= iLenText) { | |
2860 return FALSE; | |
2861 } | |
2862 wsOutput += pStrText[iText++]; | |
2863 iPattern++; | |
2864 break; | |
2865 case 'O': | |
2866 case '0': | |
2867 if (iText >= iLenText || | |
2868 (!FX_IsDigit(pStrText[iText]) && !FX_IsAlpha(pStrText[iText]))) { | |
2869 return FALSE; | |
2870 } | |
2871 wsOutput += pStrText[iText++]; | |
2872 iPattern++; | |
2873 break; | |
2874 case '9': | |
2875 if (iText >= iLenText || !FX_IsDigit(pStrText[iText])) { | |
2876 return FALSE; | |
2877 } | |
2878 wsOutput += pStrText[iText++]; | |
2879 iPattern++; | |
2880 break; | |
2881 default: | |
2882 wsOutput += pStrPattern[iPattern++]; | |
2883 break; | |
2884 } | |
2885 } | |
2886 return iText == iLenText; | |
2887 } | |
2888 static int32_t FX_GetNumTrailingLimit(const CFX_WideString& wsFormat, | |
2889 int iDotPos, | |
2890 FX_BOOL& bTrimTailZeros) { | |
2891 if (iDotPos < 0) { | |
2892 return 0; | |
2893 } | |
2894 int32_t iCount = wsFormat.GetLength(); | |
2895 int32_t iTreading = 0; | |
2896 for (iDotPos++; iDotPos < iCount; iDotPos++) { | |
2897 FX_WCHAR wc = wsFormat[iDotPos]; | |
2898 if (wc == L'z' || wc == L'9' || wc == 'Z') { | |
2899 iTreading++; | |
2900 bTrimTailZeros = (wc == L'9' ? FALSE : TRUE); | |
2901 } | |
2902 } | |
2903 return iTreading; | |
2904 } | |
2905 FX_BOOL CFX_FormatString::FormatStrNum(const CFX_WideStringC& wsInputNum, | |
2906 const CFX_WideString& wsPattern, | |
2907 CFX_WideString& wsOutput) { | |
2908 if (wsInputNum.IsEmpty() || wsPattern.IsEmpty()) { | |
2909 return FALSE; | |
2910 } | |
2911 int32_t dot_index_f = -1; | |
2912 FX_DWORD dwNumStyle = 0; | |
2913 CFX_WideString wsNumFormat; | |
2914 IFX_Locale* pLocale = | |
2915 GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat); | |
2916 if (!pLocale || wsNumFormat.IsEmpty()) { | |
2917 return FALSE; | |
2918 } | |
2919 int32_t cc = 0, ccf = 0; | |
2920 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat; | |
2921 int lenf = wsNumFormat.GetLength(); | |
2922 CFX_WideString wsSrcNum = wsInputNum; | |
2923 wsSrcNum.TrimLeft('0'); | |
2924 if (wsSrcNum.IsEmpty() || wsSrcNum[0] == '.') { | |
2925 wsSrcNum.Insert(0, '0'); | |
2926 } | |
2927 CFX_Decimal decimal = CFX_Decimal(wsSrcNum); | |
2928 if (dwNumStyle & FX_NUMSTYLE_Percent) { | |
2929 decimal = decimal * CFX_Decimal(100); | |
2930 wsSrcNum = decimal; | |
2931 } | |
2932 int32_t exponent = 0; | |
2933 if (dwNumStyle & FX_NUMSTYLE_Exponent) { | |
2934 int fixed_count = 0; | |
2935 while (ccf < dot_index_f) { | |
2936 switch (strf[ccf]) { | |
2937 case '\'': | |
2938 FX_GetLiteralText(strf, ccf, dot_index_f); | |
2939 break; | |
2940 case '9': | |
2941 case 'z': | |
2942 case 'Z': | |
2943 fixed_count++; | |
2944 break; | |
2945 } | |
2946 ccf++; | |
2947 } | |
2948 int threshold = 1; | |
2949 while (fixed_count > 1) { | |
2950 threshold *= 10; | |
2951 fixed_count--; | |
2952 } | |
2953 if (decimal != CFX_Decimal(0)) { | |
2954 if (decimal < CFX_Decimal(threshold)) { | |
2955 decimal = decimal * CFX_Decimal(10); | |
2956 exponent = -1; | |
2957 while (decimal < CFX_Decimal(threshold)) { | |
2958 decimal = decimal * CFX_Decimal(10); | |
2959 exponent -= 1; | |
2960 } | |
2961 } else if (decimal > CFX_Decimal(threshold)) { | |
2962 threshold *= 10; | |
2963 while (decimal > CFX_Decimal(threshold)) { | |
2964 decimal = decimal / CFX_Decimal(10); | |
2965 exponent += 1; | |
2966 } | |
2967 } | |
2968 } | |
2969 } | |
2970 FX_BOOL bTrimTailZeros = FALSE; | |
2971 int32_t iTreading = | |
2972 FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros); | |
2973 int32_t scale = decimal.GetScale(); | |
2974 if (iTreading < scale) { | |
2975 decimal.SetScale(iTreading); | |
2976 wsSrcNum = decimal; | |
2977 } | |
2978 if (bTrimTailZeros && scale > 0 && iTreading > 0) { | |
2979 wsSrcNum.TrimRight(L"0"); | |
2980 wsSrcNum.TrimRight(L"."); | |
2981 } | |
2982 CFX_WideString wsGroupSymbol; | |
2983 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); | |
2984 FX_BOOL bNeg = FALSE; | |
2985 if (wsSrcNum[0] == '-') { | |
2986 bNeg = TRUE; | |
2987 wsSrcNum.Delete(0, 1); | |
2988 } | |
2989 FX_BOOL bAddNeg = FALSE; | |
2990 const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum; | |
2991 int len = wsSrcNum.GetLength(); | |
2992 int dot_index = wsSrcNum.Find('.'); | |
2993 if (dot_index == -1) { | |
2994 dot_index = len; | |
2995 } | |
2996 ccf = dot_index_f - 1; | |
2997 cc = dot_index - 1; | |
2998 while (ccf >= 0) { | |
2999 switch (strf[ccf]) { | |
3000 case '9': | |
3001 if (cc >= 0) { | |
3002 if (!FX_IsDigit(str[cc])) { | |
3003 return FALSE; | |
3004 } | |
3005 wsOutput = CFX_WideStringC(str[cc]) + wsOutput; | |
3006 cc--; | |
3007 } else { | |
3008 wsOutput = CFX_WideStringC(L'0') + wsOutput; | |
3009 } | |
3010 ccf--; | |
3011 break; | |
3012 case 'z': | |
3013 if (cc >= 0) { | |
3014 if (!FX_IsDigit(str[cc])) { | |
3015 return FALSE; | |
3016 } | |
3017 if (str[0] != '0') { | |
3018 wsOutput = CFX_WideStringC(str[cc]) + wsOutput; | |
3019 } | |
3020 cc--; | |
3021 } | |
3022 ccf--; | |
3023 break; | |
3024 case 'Z': | |
3025 if (cc >= 0) { | |
3026 if (!FX_IsDigit(str[cc])) { | |
3027 return FALSE; | |
3028 } | |
3029 if (str[0] == '0') { | |
3030 wsOutput = CFX_WideStringC(L' ') + wsOutput; | |
3031 } else { | |
3032 wsOutput = CFX_WideStringC(str[cc]) + wsOutput; | |
3033 } | |
3034 cc--; | |
3035 } else { | |
3036 wsOutput = CFX_WideStringC(L' ') + wsOutput; | |
3037 } | |
3038 ccf--; | |
3039 break; | |
3040 case 'S': | |
3041 if (bNeg) { | |
3042 CFX_WideString wsMinusSymbol; | |
3043 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol); | |
3044 wsOutput = wsMinusSymbol + wsOutput; | |
3045 bAddNeg = TRUE; | |
3046 } else { | |
3047 wsOutput = CFX_WideStringC(L' ') + wsOutput; | |
3048 } | |
3049 ccf--; | |
3050 break; | |
3051 case 's': | |
3052 if (bNeg) { | |
3053 CFX_WideString wsMinusSymbol; | |
3054 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol); | |
3055 wsOutput = wsMinusSymbol + wsOutput; | |
3056 bAddNeg = TRUE; | |
3057 } | |
3058 ccf--; | |
3059 break; | |
3060 case 'E': { | |
3061 CFX_WideString wsExp; | |
3062 wsExp.Format(L"E%+d", exponent); | |
3063 wsOutput = wsExp + wsOutput; | |
3064 } | |
3065 ccf--; | |
3066 break; | |
3067 case '$': { | |
3068 CFX_WideString wsSymbol; | |
3069 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol); | |
3070 wsOutput = wsSymbol + wsOutput; | |
3071 } | |
3072 ccf--; | |
3073 break; | |
3074 case 'r': | |
3075 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') { | |
3076 if (bNeg) { | |
3077 wsOutput = L"CR" + wsOutput; | |
3078 } | |
3079 ccf -= 2; | |
3080 bAddNeg = TRUE; | |
3081 } | |
3082 break; | |
3083 case 'R': | |
3084 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') { | |
3085 if (bNeg) { | |
3086 wsOutput = L"CR" + wsOutput; | |
3087 } else { | |
3088 wsOutput = L" " + wsOutput; | |
3089 } | |
3090 ccf -= 2; | |
3091 bAddNeg = TRUE; | |
3092 } | |
3093 break; | |
3094 case 'b': | |
3095 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') { | |
3096 if (bNeg) { | |
3097 wsOutput = L"db" + wsOutput; | |
3098 } | |
3099 ccf -= 2; | |
3100 bAddNeg = TRUE; | |
3101 } | |
3102 break; | |
3103 case 'B': | |
3104 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') { | |
3105 if (bNeg) { | |
3106 wsOutput = L"DB" + wsOutput; | |
3107 } else { | |
3108 wsOutput = L" " + wsOutput; | |
3109 } | |
3110 ccf -= 2; | |
3111 bAddNeg = TRUE; | |
3112 } | |
3113 break; | |
3114 case '%': { | |
3115 CFX_WideString wsSymbol; | |
3116 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
3117 wsOutput = wsSymbol + wsOutput; | |
3118 } | |
3119 ccf--; | |
3120 break; | |
3121 case ',': | |
3122 if (cc >= 0) { | |
3123 wsOutput = wsGroupSymbol + wsOutput; | |
3124 } | |
3125 ccf--; | |
3126 break; | |
3127 case '(': | |
3128 if (bNeg) { | |
3129 wsOutput = L"(" + wsOutput; | |
3130 } else { | |
3131 wsOutput = L" " + wsOutput; | |
3132 } | |
3133 bAddNeg = TRUE; | |
3134 ccf--; | |
3135 break; | |
3136 case ')': | |
3137 if (bNeg) { | |
3138 wsOutput = L")" + wsOutput; | |
3139 } else { | |
3140 wsOutput = L" " + wsOutput; | |
3141 } | |
3142 ccf--; | |
3143 break; | |
3144 case '\'': | |
3145 wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput; | |
3146 ccf--; | |
3147 break; | |
3148 default: | |
3149 wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput; | |
3150 ccf--; | |
3151 } | |
3152 } | |
3153 if (cc >= 0) { | |
3154 int nPos = dot_index % 3; | |
3155 wsOutput.Empty(); | |
3156 for (int32_t i = 0; i < dot_index; i++) { | |
3157 if (i % 3 == nPos && i != 0) { | |
3158 wsOutput += wsGroupSymbol; | |
3159 } | |
3160 wsOutput += wsSrcNum[i]; | |
3161 } | |
3162 if (dot_index < len) { | |
3163 CFX_WideString wsSymbol; | |
3164 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol); | |
3165 wsOutput += wsSymbol; | |
3166 wsOutput += wsSrcNum.Right(len - dot_index - 1); | |
3167 } | |
3168 if (bNeg) { | |
3169 CFX_WideString wsMinusymbol; | |
3170 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol); | |
3171 wsOutput = wsMinusymbol + wsOutput; | |
3172 } | |
3173 return FALSE; | |
3174 } | |
3175 if (dot_index_f == wsNumFormat.GetLength()) { | |
3176 if (!bAddNeg && bNeg) { | |
3177 CFX_WideString wsMinusymbol; | |
3178 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol); | |
3179 wsOutput = wsMinusymbol + wsOutput; | |
3180 } | |
3181 return TRUE; | |
3182 } | |
3183 CFX_WideString wsDotSymbol; | |
3184 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol); | |
3185 if (strf[dot_index_f] == 'V') { | |
3186 wsOutput += wsDotSymbol; | |
3187 } else if (strf[dot_index_f] == '.') { | |
3188 if (dot_index < len) { | |
3189 wsOutput += wsDotSymbol; | |
3190 } else { | |
3191 if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') { | |
3192 wsOutput += wsDotSymbol; | |
3193 } | |
3194 } | |
3195 } | |
3196 ccf = dot_index_f + 1; | |
3197 cc = dot_index + 1; | |
3198 while (ccf < lenf) { | |
3199 switch (strf[ccf]) { | |
3200 case '\'': | |
3201 wsOutput += FX_GetLiteralText(strf, ccf, lenf); | |
3202 ccf++; | |
3203 break; | |
3204 case '9': | |
3205 if (cc < len) { | |
3206 if (!FX_IsDigit(str[cc])) { | |
3207 return FALSE; | |
3208 } | |
3209 wsOutput += str[cc]; | |
3210 cc++; | |
3211 } else { | |
3212 wsOutput += L'0'; | |
3213 } | |
3214 ccf++; | |
3215 break; | |
3216 case 'z': | |
3217 if (cc < len) { | |
3218 if (!FX_IsDigit(str[cc])) { | |
3219 return FALSE; | |
3220 } | |
3221 wsOutput += str[cc]; | |
3222 cc++; | |
3223 } | |
3224 ccf++; | |
3225 break; | |
3226 case 'Z': | |
3227 if (cc < len) { | |
3228 if (!FX_IsDigit(str[cc])) { | |
3229 return FALSE; | |
3230 } | |
3231 wsOutput += str[cc]; | |
3232 cc++; | |
3233 } else { | |
3234 wsOutput += L'0'; | |
3235 } | |
3236 ccf++; | |
3237 break; | |
3238 case 'E': { | |
3239 CFX_WideString wsExp; | |
3240 wsExp.Format(L"E%+d", exponent); | |
3241 wsOutput += wsExp; | |
3242 } | |
3243 ccf++; | |
3244 break; | |
3245 case '$': { | |
3246 CFX_WideString wsSymbol; | |
3247 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol); | |
3248 wsOutput += wsSymbol; | |
3249 } | |
3250 ccf++; | |
3251 break; | |
3252 case 'c': | |
3253 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') { | |
3254 if (bNeg) { | |
3255 wsOutput += L"CR"; | |
3256 } | |
3257 ccf += 2; | |
3258 bAddNeg = TRUE; | |
3259 } | |
3260 break; | |
3261 case 'C': | |
3262 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') { | |
3263 if (bNeg) { | |
3264 wsOutput += L"CR"; | |
3265 } else { | |
3266 wsOutput += L" "; | |
3267 } | |
3268 ccf += 2; | |
3269 bAddNeg = TRUE; | |
3270 } | |
3271 break; | |
3272 case 'd': | |
3273 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') { | |
3274 if (bNeg) { | |
3275 wsOutput += L"db"; | |
3276 } | |
3277 ccf += 2; | |
3278 bAddNeg = TRUE; | |
3279 } | |
3280 break; | |
3281 case 'D': | |
3282 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') { | |
3283 if (bNeg) { | |
3284 wsOutput += L"DB"; | |
3285 } else { | |
3286 wsOutput += L" "; | |
3287 } | |
3288 ccf += 2; | |
3289 bAddNeg = TRUE; | |
3290 } | |
3291 break; | |
3292 case '%': { | |
3293 CFX_WideString wsSymbol; | |
3294 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
3295 wsOutput += wsSymbol; | |
3296 } | |
3297 ccf++; | |
3298 break; | |
3299 case '8': { | |
3300 while (ccf < lenf && strf[ccf] == '8') { | |
3301 ccf++; | |
3302 } | |
3303 while (cc < len && FX_IsDigit(str[cc])) { | |
3304 wsOutput += str[cc]; | |
3305 cc++; | |
3306 } | |
3307 } break; | |
3308 case ',': | |
3309 wsOutput += wsGroupSymbol; | |
3310 ccf++; | |
3311 break; | |
3312 case '(': | |
3313 if (bNeg) { | |
3314 wsOutput += '('; | |
3315 } else { | |
3316 wsOutput += ' '; | |
3317 } | |
3318 bAddNeg = TRUE; | |
3319 ccf++; | |
3320 break; | |
3321 case ')': | |
3322 if (bNeg) { | |
3323 wsOutput += ')'; | |
3324 } else { | |
3325 wsOutput += ' '; | |
3326 } | |
3327 ccf++; | |
3328 break; | |
3329 default: | |
3330 ccf++; | |
3331 } | |
3332 } | |
3333 if (!bAddNeg && bNeg) { | |
3334 CFX_WideString wsMinusymbol; | |
3335 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol); | |
3336 wsOutput = | |
3337 wsMinusymbol + wsOutput[0] + wsOutput.Mid(1, wsOutput.GetLength() - 1); | |
3338 } | |
3339 return TRUE; | |
3340 } | |
3341 FX_BOOL CFX_FormatString::FormatLCNumeric(CFX_LCNumeric& lcNum, | |
3342 const CFX_WideString& wsPattern, | |
3343 CFX_WideString& wsOutput) { | |
3344 int32_t dot_index_f = -1; | |
3345 FX_DWORD dwNumStyle = 0; | |
3346 CFX_WideString wsNumFormat; | |
3347 IFX_Locale* pLocale = | |
3348 GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat); | |
3349 if (!pLocale || wsNumFormat.IsEmpty()) { | |
3350 return FALSE; | |
3351 } | |
3352 int32_t cc = 0, ccf = 0; | |
3353 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat; | |
3354 int lenf = wsNumFormat.GetLength(); | |
3355 double dbOrgRaw = lcNum.GetDouble(); | |
3356 double dbRetValue = dbOrgRaw; | |
3357 if (dwNumStyle & FX_NUMSTYLE_Percent) { | |
3358 dbRetValue *= 100; | |
3359 } | |
3360 int32_t exponent = 0; | |
3361 if (dwNumStyle & FX_NUMSTYLE_Exponent) { | |
3362 int fixed_count = 0; | |
3363 while (ccf < dot_index_f) { | |
3364 switch (strf[ccf]) { | |
3365 case '\'': | |
3366 FX_GetLiteralText(strf, ccf, dot_index_f); | |
3367 break; | |
3368 case '9': | |
3369 case 'z': | |
3370 case 'Z': | |
3371 fixed_count++; | |
3372 break; | |
3373 } | |
3374 ccf++; | |
3375 } | |
3376 int threshold = 1; | |
3377 while (fixed_count > 1) { | |
3378 threshold *= 10; | |
3379 fixed_count--; | |
3380 } | |
3381 if (dbRetValue != 0) { | |
3382 if (dbRetValue < threshold) { | |
3383 dbRetValue *= 10; | |
3384 exponent = -1; | |
3385 while (dbRetValue < threshold) { | |
3386 dbRetValue *= 10; | |
3387 exponent -= 1; | |
3388 } | |
3389 } else if (dbRetValue > threshold) { | |
3390 threshold *= 10; | |
3391 while (dbRetValue > threshold) { | |
3392 dbRetValue /= 10; | |
3393 exponent += 1; | |
3394 } | |
3395 } | |
3396 } | |
3397 } | |
3398 if (dwNumStyle & (FX_NUMSTYLE_Percent | FX_NUMSTYLE_Exponent)) { | |
3399 lcNum = CFX_LCNumeric(dbRetValue); | |
3400 } | |
3401 FX_BOOL bTrimTailZeros = FALSE; | |
3402 int32_t iTreading = | |
3403 FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros); | |
3404 CFX_WideString wsNumeric = lcNum.ToString(iTreading, bTrimTailZeros); | |
3405 if (wsNumeric.IsEmpty()) { | |
3406 return FALSE; | |
3407 } | |
3408 CFX_WideString wsGroupSymbol; | |
3409 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol); | |
3410 FX_BOOL bNeg = FALSE; | |
3411 if (wsNumeric[0] == '-') { | |
3412 bNeg = TRUE; | |
3413 wsNumeric.Delete(0, 1); | |
3414 } | |
3415 FX_BOOL bAddNeg = FALSE; | |
3416 const FX_WCHAR* str = (const FX_WCHAR*)wsNumeric; | |
3417 int len = wsNumeric.GetLength(); | |
3418 int dot_index = wsNumeric.Find('.'); | |
3419 if (dot_index == -1) { | |
3420 dot_index = len; | |
3421 } | |
3422 ccf = dot_index_f - 1; | |
3423 cc = dot_index - 1; | |
3424 while (ccf >= 0) { | |
3425 switch (strf[ccf]) { | |
3426 case '9': | |
3427 if (cc >= 0) { | |
3428 wsOutput = CFX_WideStringC(str[cc]) + wsOutput; | |
3429 cc--; | |
3430 } else { | |
3431 wsOutput = CFX_WideStringC(L'0') + wsOutput; | |
3432 } | |
3433 ccf--; | |
3434 break; | |
3435 case 'z': | |
3436 if (cc >= 0) { | |
3437 if (lcNum.m_Integral != 0) { | |
3438 wsOutput = CFX_WideStringC(str[cc]) + wsOutput; | |
3439 } | |
3440 cc--; | |
3441 } | |
3442 ccf--; | |
3443 break; | |
3444 case 'Z': | |
3445 if (cc >= 0) { | |
3446 if (lcNum.m_Integral == 0) { | |
3447 wsOutput = CFX_WideStringC(L' ') + wsOutput; | |
3448 } else { | |
3449 wsOutput = CFX_WideStringC(str[cc]) + wsOutput; | |
3450 } | |
3451 cc--; | |
3452 } else { | |
3453 wsOutput = CFX_WideStringC(L' ') + wsOutput; | |
3454 } | |
3455 ccf--; | |
3456 break; | |
3457 case 'S': | |
3458 if (bNeg) { | |
3459 CFX_WideString wsMinusSymbol; | |
3460 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol); | |
3461 wsOutput = wsMinusSymbol + wsOutput; | |
3462 bAddNeg = TRUE; | |
3463 } else { | |
3464 wsOutput = CFX_WideStringC(L' ') + wsOutput; | |
3465 } | |
3466 ccf--; | |
3467 break; | |
3468 case 's': | |
3469 if (bNeg) { | |
3470 CFX_WideString wsMinusSymbol; | |
3471 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol); | |
3472 wsOutput = wsMinusSymbol + wsOutput; | |
3473 bAddNeg = TRUE; | |
3474 } | |
3475 ccf--; | |
3476 break; | |
3477 case 'E': { | |
3478 CFX_WideString wsExp; | |
3479 wsExp.Format(L"E%+d", exponent); | |
3480 wsOutput = wsExp + wsOutput; | |
3481 } | |
3482 ccf--; | |
3483 break; | |
3484 case '$': { | |
3485 CFX_WideString wsSymbol; | |
3486 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol); | |
3487 wsOutput = wsSymbol + wsOutput; | |
3488 } | |
3489 ccf--; | |
3490 break; | |
3491 case 'r': | |
3492 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') { | |
3493 if (bNeg) { | |
3494 wsOutput = L"CR" + wsOutput; | |
3495 } | |
3496 ccf -= 2; | |
3497 bAddNeg = TRUE; | |
3498 } | |
3499 break; | |
3500 case 'R': | |
3501 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') { | |
3502 if (bNeg) { | |
3503 wsOutput = L"CR" + wsOutput; | |
3504 } else { | |
3505 wsOutput = L" " + wsOutput; | |
3506 } | |
3507 ccf -= 2; | |
3508 bAddNeg = TRUE; | |
3509 } | |
3510 break; | |
3511 case 'b': | |
3512 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') { | |
3513 if (bNeg) { | |
3514 wsOutput = L"db" + wsOutput; | |
3515 } | |
3516 ccf -= 2; | |
3517 bAddNeg = TRUE; | |
3518 } | |
3519 break; | |
3520 case 'B': | |
3521 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') { | |
3522 if (bNeg) { | |
3523 wsOutput = L"DB" + wsOutput; | |
3524 } else { | |
3525 wsOutput = L" " + wsOutput; | |
3526 } | |
3527 ccf -= 2; | |
3528 bAddNeg = TRUE; | |
3529 } | |
3530 break; | |
3531 case '%': { | |
3532 CFX_WideString wsSymbol; | |
3533 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
3534 wsOutput = wsSymbol + wsOutput; | |
3535 } | |
3536 ccf--; | |
3537 break; | |
3538 case ',': | |
3539 if (cc >= 0) { | |
3540 wsOutput = wsGroupSymbol + wsOutput; | |
3541 } | |
3542 ccf--; | |
3543 break; | |
3544 case '(': | |
3545 if (bNeg) { | |
3546 wsOutput = L"(" + wsOutput; | |
3547 } else { | |
3548 wsOutput = L" " + wsOutput; | |
3549 } | |
3550 bAddNeg = TRUE; | |
3551 ccf--; | |
3552 break; | |
3553 case ')': | |
3554 if (bNeg) { | |
3555 wsOutput = L")" + wsOutput; | |
3556 } else { | |
3557 wsOutput = L" " + wsOutput; | |
3558 } | |
3559 ccf--; | |
3560 break; | |
3561 case '\'': | |
3562 wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput; | |
3563 ccf--; | |
3564 break; | |
3565 default: | |
3566 wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput; | |
3567 ccf--; | |
3568 } | |
3569 } | |
3570 if (cc >= 0) { | |
3571 int nPos = dot_index % 3; | |
3572 wsOutput.Empty(); | |
3573 for (int32_t i = 0; i < dot_index; i++) { | |
3574 if (i % 3 == nPos && i != 0) { | |
3575 wsOutput += wsGroupSymbol; | |
3576 } | |
3577 wsOutput += wsNumeric[i]; | |
3578 } | |
3579 if (dot_index < len) { | |
3580 CFX_WideString wsSymbol; | |
3581 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol); | |
3582 wsOutput += wsSymbol; | |
3583 wsOutput += wsNumeric.Right(len - dot_index - 1); | |
3584 } | |
3585 if (bNeg) { | |
3586 CFX_WideString wsMinusymbol; | |
3587 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol); | |
3588 wsOutput = wsMinusymbol + wsOutput; | |
3589 } | |
3590 return FALSE; | |
3591 } | |
3592 if (dot_index_f == wsNumFormat.GetLength()) { | |
3593 if (!bAddNeg && bNeg) { | |
3594 CFX_WideString wsMinusymbol; | |
3595 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol); | |
3596 wsOutput = wsMinusymbol + wsOutput; | |
3597 } | |
3598 return TRUE; | |
3599 } | |
3600 CFX_WideString wsDotSymbol; | |
3601 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol); | |
3602 if (strf[dot_index_f] == 'V') { | |
3603 wsOutput += wsDotSymbol; | |
3604 } else if (strf[dot_index_f] == '.') { | |
3605 if (dot_index < len) { | |
3606 wsOutput += wsDotSymbol; | |
3607 } else { | |
3608 if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') { | |
3609 wsOutput += wsDotSymbol; | |
3610 } | |
3611 } | |
3612 } | |
3613 ccf = dot_index_f + 1; | |
3614 cc = dot_index + 1; | |
3615 while (ccf < lenf) { | |
3616 switch (strf[ccf]) { | |
3617 case '\'': | |
3618 wsOutput += FX_GetLiteralText(strf, ccf, lenf); | |
3619 ccf++; | |
3620 break; | |
3621 case '9': | |
3622 if (cc < len) { | |
3623 wsOutput += str[cc]; | |
3624 cc++; | |
3625 } else { | |
3626 wsOutput += L'0'; | |
3627 } | |
3628 ccf++; | |
3629 break; | |
3630 case 'z': | |
3631 if (cc < len) { | |
3632 wsOutput += str[cc]; | |
3633 cc++; | |
3634 } | |
3635 ccf++; | |
3636 break; | |
3637 case 'Z': | |
3638 if (cc < len) { | |
3639 wsOutput += str[cc]; | |
3640 cc++; | |
3641 } else { | |
3642 wsOutput += L'0'; | |
3643 } | |
3644 ccf++; | |
3645 break; | |
3646 case 'E': { | |
3647 CFX_WideString wsExp; | |
3648 wsExp.Format(L"E%+d", exponent); | |
3649 wsOutput += wsExp; | |
3650 } | |
3651 ccf++; | |
3652 break; | |
3653 case '$': { | |
3654 CFX_WideString wsSymbol; | |
3655 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol); | |
3656 wsOutput += wsSymbol; | |
3657 } | |
3658 ccf++; | |
3659 break; | |
3660 case 'c': | |
3661 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') { | |
3662 if (bNeg) { | |
3663 wsOutput += L"CR"; | |
3664 } | |
3665 ccf += 2; | |
3666 bAddNeg = TRUE; | |
3667 } | |
3668 break; | |
3669 case 'C': | |
3670 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') { | |
3671 if (bNeg) { | |
3672 wsOutput += L"CR"; | |
3673 } else { | |
3674 wsOutput += L" "; | |
3675 } | |
3676 ccf += 2; | |
3677 bAddNeg = TRUE; | |
3678 } | |
3679 break; | |
3680 case 'd': | |
3681 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') { | |
3682 if (bNeg) { | |
3683 wsOutput += L"db"; | |
3684 } | |
3685 ccf += 2; | |
3686 bAddNeg = TRUE; | |
3687 } | |
3688 break; | |
3689 case 'D': | |
3690 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') { | |
3691 if (bNeg) { | |
3692 wsOutput += L"DB"; | |
3693 } else { | |
3694 wsOutput += L" "; | |
3695 } | |
3696 ccf += 2; | |
3697 bAddNeg = TRUE; | |
3698 } | |
3699 break; | |
3700 case '%': { | |
3701 CFX_WideString wsSymbol; | |
3702 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol); | |
3703 wsOutput += wsSymbol; | |
3704 } | |
3705 ccf++; | |
3706 break; | |
3707 case '8': { | |
3708 while (ccf < lenf && strf[ccf] == '8') { | |
3709 ccf++; | |
3710 } | |
3711 while (cc < len && FX_IsDigit(str[cc])) { | |
3712 wsOutput += str[cc]; | |
3713 cc++; | |
3714 } | |
3715 } break; | |
3716 case ',': | |
3717 wsOutput += wsGroupSymbol; | |
3718 ccf++; | |
3719 break; | |
3720 case '(': | |
3721 if (bNeg) { | |
3722 wsOutput += '('; | |
3723 } else { | |
3724 wsOutput += ' '; | |
3725 } | |
3726 bAddNeg = TRUE; | |
3727 ccf++; | |
3728 break; | |
3729 case ')': | |
3730 if (bNeg) { | |
3731 wsOutput += ')'; | |
3732 } else { | |
3733 wsOutput += ' '; | |
3734 } | |
3735 ccf++; | |
3736 break; | |
3737 default: | |
3738 ccf++; | |
3739 } | |
3740 } | |
3741 if (!bAddNeg && bNeg) { | |
3742 CFX_WideString wsMinusymbol; | |
3743 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol); | |
3744 wsOutput = | |
3745 wsOutput[0] + wsMinusymbol + wsOutput.Mid(1, wsOutput.GetLength() - 1); | |
3746 } | |
3747 return TRUE; | |
3748 } | |
3749 FX_BOOL CFX_FormatString::FormatNum(const CFX_WideString& wsSrcNum, | |
3750 const CFX_WideString& wsPattern, | |
3751 CFX_WideString& wsOutput) { | |
3752 if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) { | |
3753 return FALSE; | |
3754 } | |
3755 return FormatStrNum(wsSrcNum, wsPattern, wsOutput); | |
3756 } | |
3757 FX_BOOL CFX_FormatString::FormatNum(FX_FLOAT fNum, | |
3758 const CFX_WideString& wsPattern, | |
3759 CFX_WideString& wsOutput) { | |
3760 if (wsPattern.IsEmpty()) { | |
3761 return FALSE; | |
3762 } | |
3763 CFX_LCNumeric lcNum(fNum); | |
3764 return FormatLCNumeric(lcNum, wsPattern, wsOutput); | |
3765 } | |
3766 FX_BOOL FX_DateFromCanonical(const CFX_WideString& wsDate, | |
3767 CFX_Unitime& datetime) { | |
3768 int32_t year = 1900; | |
3769 int32_t month = 1; | |
3770 int32_t day = 1; | |
3771 FX_WORD wYear = 0; | |
3772 int cc_start = 0, cc = 0; | |
3773 const FX_WCHAR* str = (const FX_WCHAR*)wsDate; | |
3774 int len = wsDate.GetLength(); | |
3775 if (len > 10) { | |
3776 return FALSE; | |
3777 } | |
3778 while (cc < len && cc < 4) { | |
3779 if (!FX_IsDigit(str[cc])) { | |
3780 return FALSE; | |
3781 } | |
3782 wYear = wYear * 10 + str[cc++] - '0'; | |
3783 } | |
3784 year = wYear; | |
3785 if (cc < 4 || wYear < 1900) { | |
3786 return FALSE; | |
3787 } | |
3788 if (cc < len) { | |
3789 if (str[cc] == '-') { | |
3790 cc++; | |
3791 } | |
3792 cc_start = cc; | |
3793 uint8_t tmpM = 0; | |
3794 while (cc < len && cc < cc_start + 2) { | |
3795 if (!FX_IsDigit(str[cc])) { | |
3796 return FALSE; | |
3797 } | |
3798 tmpM = tmpM * 10 + str[cc++] - '0'; | |
3799 } | |
3800 month = tmpM; | |
3801 if (cc == cc_start + 1 || tmpM > 12 || tmpM < 1) { | |
3802 return FALSE; | |
3803 } | |
3804 if (cc < len) { | |
3805 if (str[cc] == '-') { | |
3806 cc++; | |
3807 } | |
3808 uint8_t tmpD = 0; | |
3809 cc_start = cc; | |
3810 while (cc < len && cc < cc_start + 2) { | |
3811 if (!FX_IsDigit(str[cc])) { | |
3812 return FALSE; | |
3813 } | |
3814 tmpD = tmpD * 10 + str[cc++] - '0'; | |
3815 } | |
3816 day = tmpD; | |
3817 if (tmpD < 1) { | |
3818 return FALSE; | |
3819 } | |
3820 if ((tmpM == 1 || tmpM == 3 || tmpM == 5 || tmpM == 7 || tmpM == 8 || | |
3821 tmpM == 10 || tmpM == 12) && | |
3822 tmpD > 31) { | |
3823 return FALSE; | |
3824 } | |
3825 if ((tmpM == 4 || tmpM == 6 || tmpM == 9 || tmpM == 11) && tmpD > 30) { | |
3826 return FALSE; | |
3827 } | |
3828 FX_BOOL iLeapYear; | |
3829 if ((wYear % 4 == 0 && wYear % 100 != 0) || wYear % 400 == 0) { | |
3830 iLeapYear = TRUE; | |
3831 } else { | |
3832 iLeapYear = FALSE; | |
3833 } | |
3834 if ((iLeapYear && tmpM == 2 && tmpD > 29) || | |
3835 (!iLeapYear && tmpM == 2 && tmpD > 28)) { | |
3836 return FALSE; | |
3837 } | |
3838 } | |
3839 } | |
3840 CFX_Unitime ut; | |
3841 ut.Set(year, month, day); | |
3842 datetime = datetime + ut; | |
3843 return TRUE; | |
3844 } | |
3845 FX_BOOL FX_TimeFromCanonical(const CFX_WideStringC& wsTime, | |
3846 CFX_Unitime& datetime, | |
3847 IFX_Locale* pLocale) { | |
3848 if (wsTime.GetLength() == 0) { | |
3849 return FALSE; | |
3850 } | |
3851 uint8_t hour = 0; | |
3852 uint8_t minute = 0; | |
3853 uint8_t second = 0; | |
3854 FX_WORD millisecond = 0; | |
3855 int cc_start = 0, cc = cc_start; | |
3856 const FX_WCHAR* str = (const FX_WCHAR*)wsTime.GetPtr(); | |
3857 int len = wsTime.GetLength(); | |
3858 while (cc < len && cc < 2) { | |
3859 if (!FX_IsDigit(str[cc])) { | |
3860 return FALSE; | |
3861 } | |
3862 hour = hour * 10 + str[cc++] - '0'; | |
3863 } | |
3864 if (cc < 2 || hour >= 24) { | |
3865 return FALSE; | |
3866 } | |
3867 if (cc < len) { | |
3868 if (str[cc] == ':') { | |
3869 cc++; | |
3870 } | |
3871 cc_start = cc; | |
3872 while (cc < len && cc < cc_start + 2) { | |
3873 if (!FX_IsDigit(str[cc])) { | |
3874 return FALSE; | |
3875 } | |
3876 minute = minute * 10 + str[cc++] - '0'; | |
3877 } | |
3878 if (cc == cc_start + 1 || minute >= 60) { | |
3879 return FALSE; | |
3880 } | |
3881 if (cc < len) { | |
3882 if (str[cc] == ':') { | |
3883 cc++; | |
3884 } | |
3885 cc_start = cc; | |
3886 while (cc < len && cc < cc_start + 2) { | |
3887 if (!FX_IsDigit(str[cc])) { | |
3888 return FALSE; | |
3889 } | |
3890 second = second * 10 + str[cc++] - '0'; | |
3891 } | |
3892 if (cc == cc_start + 1 || second >= 60) { | |
3893 return FALSE; | |
3894 } | |
3895 if (cc < len) { | |
3896 if (str[cc] == '.') { | |
3897 cc++; | |
3898 cc_start = cc; | |
3899 while (cc < len && cc < cc_start + 3) { | |
3900 if (!FX_IsDigit(str[cc])) { | |
3901 return FALSE; | |
3902 } | |
3903 millisecond = millisecond * 10 + str[cc++] - '0'; | |
3904 } | |
3905 if (cc < cc_start + 3 || millisecond >= 1000) { | |
3906 return FALSE; | |
3907 } | |
3908 } | |
3909 if (cc < len) { | |
3910 FX_TIMEZONE tzDiff; | |
3911 tzDiff.tzHour = 0; | |
3912 tzDiff.tzMinute = 0; | |
3913 if (str[cc] != 'Z') { | |
3914 cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff); | |
3915 } | |
3916 FX_ResolveZone(hour, minute, tzDiff, pLocale); | |
3917 } | |
3918 } | |
3919 } | |
3920 } | |
3921 CFX_Unitime ut; | |
3922 ut.Set(0, 0, 0, hour, minute, second, millisecond); | |
3923 datetime = datetime + ut; | |
3924 return TRUE; | |
3925 } | |
3926 static FX_WORD FX_GetSolarMonthDays(FX_WORD year, FX_WORD month) { | |
3927 if (month % 2) { | |
3928 return 31; | |
3929 } else if (month == 2) { | |
3930 return FX_IsLeapYear(year) ? 29 : 28; | |
3931 } | |
3932 return 30; | |
3933 } | |
3934 static FX_WORD FX_GetWeekDay(FX_WORD year, FX_WORD month, FX_WORD day) { | |
3935 FX_WORD g_month_day[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; | |
3936 FX_WORD nDays = | |
3937 (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400; | |
3938 nDays += g_month_day[month - 1] + day; | |
3939 if (FX_IsLeapYear(year) && month > 2) { | |
3940 nDays++; | |
3941 } | |
3942 return nDays % 7; | |
3943 } | |
3944 static FX_WORD FX_GetWeekOfMonth(FX_WORD year, FX_WORD month, FX_WORD day) { | |
3945 FX_WORD week_day = FX_GetWeekDay(year, month, 1); | |
3946 FX_WORD week_index = 0; | |
3947 week_index += day / 7; | |
3948 day = day % 7; | |
3949 if (week_day + day > 7) { | |
3950 week_index++; | |
3951 } | |
3952 return week_index; | |
3953 } | |
3954 static FX_WORD FX_GetWeekOfYear(FX_WORD year, FX_WORD month, FX_WORD day) { | |
3955 FX_WORD nDays = 0; | |
3956 for (FX_WORD i = 1; i < month; i++) { | |
3957 nDays += FX_GetSolarMonthDays(year, i); | |
3958 } | |
3959 nDays += day; | |
3960 FX_WORD week_day = FX_GetWeekDay(year, 1, 1); | |
3961 FX_WORD week_index = 1; | |
3962 week_index += nDays / 7; | |
3963 nDays = nDays % 7; | |
3964 if (week_day + nDays > 7) { | |
3965 week_index++; | |
3966 } | |
3967 return week_index; | |
3968 } | |
3969 static FX_BOOL FX_DateFormat(const CFX_WideString& wsDatePattern, | |
3970 IFX_Locale* pLocale, | |
3971 const CFX_Unitime& datetime, | |
3972 CFX_WideString& wsResult) { | |
3973 FX_BOOL bRet = TRUE; | |
3974 int32_t year = datetime.GetYear(); | |
3975 uint8_t month = datetime.GetMonth(); | |
3976 uint8_t day = datetime.GetDay(); | |
3977 int32_t ccf = 0; | |
3978 const FX_WCHAR* strf = (const FX_WCHAR*)wsDatePattern; | |
3979 int32_t lenf = wsDatePattern.GetLength(); | |
3980 while (ccf < lenf) { | |
3981 if (strf[ccf] == '\'') { | |
3982 wsResult += FX_GetLiteralText(strf, ccf, lenf); | |
3983 ccf++; | |
3984 continue; | |
3985 } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) { | |
3986 wsResult += strf[ccf++]; | |
3987 continue; | |
3988 } | |
3989 FX_DWORD dwSymbolNum = 1; | |
3990 FX_DWORD dwSymbol = strf[ccf++]; | |
3991 while (ccf < lenf && strf[ccf] == dwSymbol) { | |
3992 ccf++; | |
3993 dwSymbolNum++; | |
3994 } | |
3995 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0'); | |
3996 if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) { | |
3997 CFX_WideString wsDay; | |
3998 wsDay.Format(L"%d", day); | |
3999 wsResult += wsDay; | |
4000 } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) { | |
4001 CFX_WideString wsDay; | |
4002 wsDay.Format(L"%02d", day); | |
4003 wsResult += wsDay; | |
4004 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) { | |
4005 FX_WORD nDays = 0; | |
4006 for (int i = 1; i < month; i++) { | |
4007 nDays += FX_GetSolarMonthDays(year, i); | |
4008 } | |
4009 nDays += day; | |
4010 CFX_WideString wsDays; | |
4011 wsDays.Format(L"%d", nDays); | |
4012 wsResult += wsDays; | |
4013 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) { | |
4014 FX_WORD nDays = 0; | |
4015 for (int i = 1; i < month; i++) { | |
4016 nDays += FX_GetSolarMonthDays(year, i); | |
4017 } | |
4018 nDays += day; | |
4019 CFX_WideString wsDays; | |
4020 wsDays.Format(L"%03d", nDays); | |
4021 wsResult += wsDays; | |
4022 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) { | |
4023 CFX_WideString wsMonth; | |
4024 wsMonth.Format(L"%d", month); | |
4025 wsResult += wsMonth; | |
4026 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { | |
4027 CFX_WideString wsMonth; | |
4028 wsMonth.Format(L"%02d", month); | |
4029 wsResult += wsMonth; | |
4030 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) { | |
4031 CFX_WideString wsTemp; | |
4032 pLocale->GetMonthName(month - 1, wsTemp, TRUE); | |
4033 wsResult += wsTemp; | |
4034 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) { | |
4035 CFX_WideString wsTemp; | |
4036 pLocale->GetMonthName(month - 1, wsTemp, FALSE); | |
4037 wsResult += wsTemp; | |
4038 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) { | |
4039 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day); | |
4040 CFX_WideString wsWeekDay; | |
4041 wsWeekDay.Format(L"%d", wWeekDay + 1); | |
4042 wsResult += wsWeekDay; | |
4043 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) { | |
4044 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day); | |
4045 CFX_WideString wsTemp; | |
4046 pLocale->GetDayName(wWeekDay, wsTemp, TRUE); | |
4047 wsResult += wsTemp; | |
4048 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) { | |
4049 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day); | |
4050 if (pLocale) { | |
4051 CFX_WideString wsTemp; | |
4052 pLocale->GetDayName(wWeekDay, wsTemp, FALSE); | |
4053 wsResult += wsTemp; | |
4054 } | |
4055 } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) { | |
4056 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day); | |
4057 CFX_WideString wsWeekDay; | |
4058 wsWeekDay.Format(L"%d", wWeekDay ? wWeekDay : 7); | |
4059 wsResult += wsWeekDay; | |
4060 } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) { | |
4061 CFX_WideString wsTemp; | |
4062 pLocale->GetEraName(wsTemp, year < 0); | |
4063 wsResult += wsTemp; | |
4064 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) { | |
4065 CFX_WideString wsYear; | |
4066 wsYear.Format(L"%02d", year % 100); | |
4067 wsResult += wsYear; | |
4068 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) { | |
4069 CFX_WideString wsYear; | |
4070 wsYear.Format(L"%d", year); | |
4071 wsResult += wsYear; | |
4072 } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) { | |
4073 FX_WORD week_index = FX_GetWeekOfMonth(year, month, day); | |
4074 CFX_WideString wsWeekInMonth; | |
4075 wsWeekInMonth.Format(L"%d", week_index); | |
4076 wsResult += wsWeekInMonth; | |
4077 } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) { | |
4078 FX_WORD week_index = FX_GetWeekOfYear(year, month, day); | |
4079 CFX_WideString wsWeekInYear; | |
4080 wsWeekInYear.Format(L"%02d", week_index); | |
4081 wsResult += wsWeekInYear; | |
4082 } | |
4083 } | |
4084 return bRet; | |
4085 } | |
4086 static FX_BOOL FX_TimeFormat(const CFX_WideString& wsTimePattern, | |
4087 IFX_Locale* pLocale, | |
4088 const CFX_Unitime& datetime, | |
4089 CFX_WideString& wsResult) { | |
4090 FX_BOOL bGMT = FALSE; | |
4091 FX_BOOL bRet = TRUE; | |
4092 uint8_t hour = datetime.GetHour(); | |
4093 uint8_t minute = datetime.GetMinute(); | |
4094 uint8_t second = datetime.GetSecond(); | |
4095 FX_WORD millisecond = datetime.GetMillisecond(); | |
4096 int32_t ccf = 0; | |
4097 const FX_WCHAR* strf = (const FX_WCHAR*)wsTimePattern; | |
4098 int32_t lenf = wsTimePattern.GetLength(); | |
4099 FX_WORD wHour = hour; | |
4100 FX_BOOL bPM = FALSE; | |
4101 if (wsTimePattern.Find('A') != -1) { | |
4102 if (wHour >= 12) { | |
4103 bPM = TRUE; | |
4104 } | |
4105 } | |
4106 while (ccf < lenf) { | |
4107 if (strf[ccf] == '\'') { | |
4108 wsResult += FX_GetLiteralText(strf, ccf, lenf); | |
4109 ccf++; | |
4110 continue; | |
4111 } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) < 0) { | |
4112 wsResult += strf[ccf++]; | |
4113 continue; | |
4114 } | |
4115 FX_DWORD dwSymbolNum = 1; | |
4116 FX_DWORD dwSymbol = strf[ccf++]; | |
4117 while (ccf < lenf && strf[ccf] == dwSymbol) { | |
4118 ccf++; | |
4119 dwSymbolNum++; | |
4120 } | |
4121 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0'); | |
4122 if (dwSymbol == FXBSTR_ID(0, 0, 'h', '1')) { | |
4123 if (wHour > 12) { | |
4124 wHour -= 12; | |
4125 } | |
4126 CFX_WideString wsHour; | |
4127 wsHour.Format(L"%d", wHour == 0 ? 12 : wHour); | |
4128 wsResult += wsHour; | |
4129 } else if (dwSymbol == FXBSTR_ID(0, 0, 'h', '2')) { | |
4130 if (wHour > 12) { | |
4131 wHour -= 12; | |
4132 } | |
4133 CFX_WideString wsHour; | |
4134 wsHour.Format(L"%02d", wHour == 0 ? 12 : wHour); | |
4135 wsResult += wsHour; | |
4136 } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) { | |
4137 CFX_WideString wsHour; | |
4138 wsHour.Format(L"%d", wHour == 0 ? 24 : wHour); | |
4139 wsResult += wsHour; | |
4140 } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) { | |
4141 CFX_WideString wsHour; | |
4142 wsHour.Format(L"%02d", wHour == 0 ? 24 : wHour); | |
4143 wsResult += wsHour; | |
4144 } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1')) { | |
4145 if (wHour > 12) { | |
4146 wHour -= 12; | |
4147 } | |
4148 CFX_WideString wsHour; | |
4149 wsHour.Format(L"%d", wHour); | |
4150 wsResult += wsHour; | |
4151 } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '1')) { | |
4152 CFX_WideString wsHour; | |
4153 wsHour.Format(L"%d", wHour); | |
4154 wsResult += wsHour; | |
4155 } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2')) { | |
4156 if (wHour > 12) { | |
4157 wHour -= 12; | |
4158 } | |
4159 CFX_WideString wsHour; | |
4160 wsHour.Format(L"%02d", wHour); | |
4161 wsResult += wsHour; | |
4162 } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '2')) { | |
4163 CFX_WideString wsHour; | |
4164 wsHour.Format(L"%02d", wHour); | |
4165 wsResult += wsHour; | |
4166 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) { | |
4167 CFX_WideString wsMinute; | |
4168 wsMinute.Format(L"%d", minute); | |
4169 wsResult += wsMinute; | |
4170 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) { | |
4171 CFX_WideString wsMinute; | |
4172 wsMinute.Format(L"%02d", minute); | |
4173 wsResult += wsMinute; | |
4174 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) { | |
4175 CFX_WideString wsSecond; | |
4176 wsSecond.Format(L"%d", second); | |
4177 wsResult += wsSecond; | |
4178 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) { | |
4179 CFX_WideString wsSecond; | |
4180 wsSecond.Format(L"%02d", second); | |
4181 wsResult += wsSecond; | |
4182 } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) { | |
4183 CFX_WideString wsMilliseconds; | |
4184 wsMilliseconds.Format(L"%03d", millisecond); | |
4185 wsResult += wsMilliseconds; | |
4186 } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) { | |
4187 CFX_WideString wsMeridiem; | |
4188 pLocale->GetMeridiemName(wsMeridiem, !bPM); | |
4189 wsResult += wsMeridiem; | |
4190 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) { | |
4191 wsResult += FX_WSTRC(L"GMT"); | |
4192 FX_TIMEZONE tz; | |
4193 pLocale->GetTimeZone(tz); | |
4194 if (!bGMT && (tz.tzHour != 0 || tz.tzMinute != 0)) { | |
4195 if (tz.tzHour < 0) { | |
4196 wsResult += FX_WSTRC(L"-"); | |
4197 } else { | |
4198 wsResult += FX_WSTRC(L"+"); | |
4199 } | |
4200 CFX_WideString wsTimezone; | |
4201 wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute); | |
4202 wsResult += wsTimezone; | |
4203 } | |
4204 } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) { | |
4205 FX_TIMEZONE tz; | |
4206 pLocale->GetTimeZone(tz); | |
4207 if (!bGMT && tz.tzHour != 0 && tz.tzMinute != 0) { | |
4208 if (tz.tzHour < 0) { | |
4209 wsResult += FX_WSTRC(L"-"); | |
4210 } else { | |
4211 wsResult += FX_WSTRC(L"+"); | |
4212 } | |
4213 CFX_WideString wsTimezone; | |
4214 wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute); | |
4215 wsResult += wsTimezone; | |
4216 } | |
4217 } | |
4218 } | |
4219 return bRet; | |
4220 } | |
4221 static FX_BOOL FX_FormatDateTime(const CFX_Unitime& dt, | |
4222 const CFX_WideString& wsDatePattern, | |
4223 const CFX_WideString& wsTimePattern, | |
4224 FX_BOOL bDateFirst, | |
4225 IFX_Locale* pLocale, | |
4226 CFX_WideString& wsOutput) { | |
4227 FX_BOOL bRet = TRUE; | |
4228 CFX_WideString wsDateOut, wsTimeOut; | |
4229 if (!wsDatePattern.IsEmpty()) { | |
4230 bRet &= FX_DateFormat(wsDatePattern, pLocale, dt, wsDateOut); | |
4231 } | |
4232 if (!wsTimePattern.IsEmpty()) { | |
4233 bRet &= FX_TimeFormat(wsTimePattern, pLocale, dt, wsTimeOut); | |
4234 } | |
4235 wsOutput = bDateFirst ? wsDateOut + wsTimeOut : wsTimeOut + wsDateOut; | |
4236 return bRet; | |
4237 } | |
4238 FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime, | |
4239 const CFX_WideString& wsPattern, | |
4240 CFX_WideString& wsOutput) { | |
4241 if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) { | |
4242 return FALSE; | |
4243 } | |
4244 CFX_WideString wsDatePattern, wsTimePattern; | |
4245 IFX_Locale* pLocale = NULL; | |
4246 FX_DATETIMETYPE eCategory = | |
4247 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); | |
4248 if (pLocale == NULL || eCategory == FX_DATETIMETYPE_Unknown) { | |
4249 return FALSE; | |
4250 } | |
4251 CFX_Unitime dt(0); | |
4252 int32_t iT = wsSrcDateTime.Find(L"T"); | |
4253 if (iT < 0) { | |
4254 if (eCategory == FX_DATETIMETYPE_Date) { | |
4255 FX_DateFromCanonical(wsSrcDateTime, dt); | |
4256 } else if (eCategory == FX_DATETIMETYPE_Time) { | |
4257 FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale); | |
4258 } | |
4259 } else { | |
4260 FX_DateFromCanonical(wsSrcDateTime.Left(iT), dt); | |
4261 FX_TimeFromCanonical( | |
4262 wsSrcDateTime.Right(wsSrcDateTime.GetLength() - iT - 1), dt, pLocale); | |
4263 } | |
4264 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, | |
4265 eCategory != FX_DATETIMETYPE_TimeDate, pLocale, | |
4266 wsOutput); | |
4267 } | |
4268 FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime, | |
4269 const CFX_WideString& wsPattern, | |
4270 CFX_WideString& wsOutput, | |
4271 FX_DATETIMETYPE eDateTimeType) { | |
4272 if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) { | |
4273 return FALSE; | |
4274 } | |
4275 CFX_WideString wsDatePattern, wsTimePattern; | |
4276 IFX_Locale* pLocale = NULL; | |
4277 FX_DATETIMETYPE eCategory = | |
4278 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); | |
4279 if (!pLocale) { | |
4280 return FALSE; | |
4281 } | |
4282 if (eCategory == FX_DATETIMETYPE_Unknown) { | |
4283 if (eDateTimeType == FX_DATETIMETYPE_Time) { | |
4284 wsTimePattern = wsDatePattern; | |
4285 wsDatePattern.Empty(); | |
4286 } | |
4287 eCategory = eDateTimeType; | |
4288 } | |
4289 if (eCategory == FX_DATETIMETYPE_Unknown) { | |
4290 return FALSE; | |
4291 } | |
4292 CFX_Unitime dt(0); | |
4293 int32_t iT = wsSrcDateTime.Find(L"T"); | |
4294 if (iT < 0) { | |
4295 if (eCategory == FX_DATETIMETYPE_Date && | |
4296 FX_DateFromCanonical(wsSrcDateTime, dt)) { | |
4297 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale, | |
4298 wsOutput); | |
4299 } else if (eCategory == FX_DATETIMETYPE_Time && | |
4300 FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale)) { | |
4301 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale, | |
4302 wsOutput); | |
4303 } | |
4304 } else { | |
4305 CFX_WideStringC wsSrcDate((const FX_WCHAR*)wsSrcDateTime, iT); | |
4306 CFX_WideStringC wsSrcTime((const FX_WCHAR*)wsSrcDateTime + iT + 1, | |
4307 wsSrcDateTime.GetLength() - iT - 1); | |
4308 if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty()) { | |
4309 return FALSE; | |
4310 } | |
4311 if (FX_DateFromCanonical(wsSrcDate, dt) && | |
4312 FX_TimeFromCanonical(wsSrcTime, dt, pLocale)) { | |
4313 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, | |
4314 eCategory != FX_DATETIMETYPE_TimeDate, pLocale, | |
4315 wsOutput); | |
4316 } | |
4317 } | |
4318 return FALSE; | |
4319 } | |
4320 FX_BOOL CFX_FormatString::FormatDateTime(const CFX_Unitime& dt, | |
4321 const CFX_WideString& wsPattern, | |
4322 CFX_WideString& wsOutput) { | |
4323 if (wsPattern.IsEmpty()) { | |
4324 return FALSE; | |
4325 } | |
4326 CFX_WideString wsDatePattern, wsTimePattern; | |
4327 IFX_Locale* pLocale = NULL; | |
4328 FX_DATETIMETYPE eCategory = | |
4329 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern); | |
4330 if (!pLocale) { | |
4331 return FALSE; | |
4332 } | |
4333 return FX_FormatDateTime(dt, wsPattern, wsTimePattern, | |
4334 eCategory != FX_DATETIMETYPE_TimeDate, pLocale, | |
4335 wsOutput); | |
4336 } | |
4337 FX_BOOL CFX_FormatString::FormatZero(const CFX_WideString& wsPattern, | |
4338 CFX_WideString& wsOutput) { | |
4339 if (wsPattern.IsEmpty()) { | |
4340 return FALSE; | |
4341 } | |
4342 CFX_WideString wsTextFormat; | |
4343 GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat); | |
4344 int32_t iPattern = 0; | |
4345 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat; | |
4346 int32_t iLenPattern = wsTextFormat.GetLength(); | |
4347 while (iPattern < iLenPattern) { | |
4348 if (pStrPattern[iPattern] == '\'') { | |
4349 wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); | |
4350 iPattern++; | |
4351 continue; | |
4352 } else { | |
4353 wsOutput += pStrPattern[iPattern++]; | |
4354 continue; | |
4355 } | |
4356 } | |
4357 return TRUE; | |
4358 } | |
4359 FX_BOOL CFX_FormatString::FormatNull(const CFX_WideString& wsPattern, | |
4360 CFX_WideString& wsOutput) { | |
4361 if (wsPattern.IsEmpty()) { | |
4362 return FALSE; | |
4363 } | |
4364 CFX_WideString wsTextFormat; | |
4365 GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat); | |
4366 int32_t iPattern = 0; | |
4367 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat; | |
4368 int32_t iLenPattern = wsTextFormat.GetLength(); | |
4369 while (iPattern < iLenPattern) { | |
4370 if (pStrPattern[iPattern] == '\'') { | |
4371 wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern); | |
4372 iPattern++; | |
4373 continue; | |
4374 } else { | |
4375 wsOutput += pStrPattern[iPattern++]; | |
4376 continue; | |
4377 } | |
4378 } | |
4379 return TRUE; | |
4380 } | |
4381 IFX_Locale* CFX_FormatString::GetPatternLocale( | |
4382 const CFX_WideStringC& wsLocale) { | |
4383 if (m_bUseLCID) { | |
4384 } | |
4385 return m_pLocaleMgr->GetLocaleByName(wsLocale); | |
4386 } | |
4387 #define FXMATH_DECIMAL_SCALELIMIT 0x1c | |
4388 #define FXMATH_DECIMAL_NEGMASK (0x80000000L) | |
4389 #define FXMATH_DECIMAL_FORCEBOOL(x) (!(!(x))) | |
4390 #define FXMATH_DECIMAL_MAKEFLAGS(NEG, SCALE) \ | |
4391 (((SCALE) << 0x10) | ((NEG) ? FXMATH_DECIMAL_NEGMASK : 0)) | |
4392 #define FXMATH_DECIMAL_FLAGS2NEG(FLAGS) \ | |
4393 FXMATH_DECIMAL_FORCEBOOL((FLAGS)&FXMATH_DECIMAL_NEGMASK) | |
4394 #define FXMATH_DECIMAL_FLAGS2SCALE(FLAGS) \ | |
4395 ((uint8_t)(((FLAGS) & ~FXMATH_DECIMAL_NEGMASK) >> 0x10)) | |
4396 #define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x) >> 0x10 >> 0x10) | |
4397 #define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x) << 0x10 << 0x10) | |
4398 static inline uint8_t fxmath_decimal_helper_div10(uint64_t& phi, | |
4399 uint64_t& pmid, | |
4400 uint64_t& plo) { | |
4401 uint8_t retVal; | |
4402 pmid += FXMATH_DECIMAL_LSHIFT32BIT(phi % 0xA); | |
4403 phi /= 0xA; | |
4404 plo += FXMATH_DECIMAL_LSHIFT32BIT(pmid % 0xA); | |
4405 pmid /= 0xA; | |
4406 retVal = plo % 0xA; | |
4407 plo /= 0xA; | |
4408 return retVal; | |
4409 } | |
4410 static inline uint8_t fxmath_decimal_helper_div10_any(uint64_t nums[], | |
4411 uint8_t numcount) { | |
4412 uint8_t retVal = 0; | |
4413 for (int i = numcount - 1; i > 0; i--) { | |
4414 nums[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(nums[i] % 0xA); | |
4415 nums[i] /= 0xA; | |
4416 } | |
4417 if (numcount) { | |
4418 retVal = nums[0] % 0xA; | |
4419 nums[0] /= 0xA; | |
4420 } | |
4421 return retVal; | |
4422 } | |
4423 static inline void fxmath_decimal_helper_mul10(uint64_t& phi, | |
4424 uint64_t& pmid, | |
4425 uint64_t& plo) { | |
4426 plo *= 0xA; | |
4427 pmid = pmid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(plo); | |
4428 plo = (uint32_t)plo; | |
4429 phi = phi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(pmid); | |
4430 pmid = (uint32_t)pmid; | |
4431 } | |
4432 static inline void fxmath_decimal_helper_mul10_any(uint64_t nums[], | |
4433 uint8_t numcount) { | |
4434 nums[0] *= 0xA; | |
4435 for (int i = 1; i < numcount; i++) { | |
4436 nums[i] = nums[i] * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(nums[i - 1]); | |
4437 nums[i - 1] = (uint32_t)nums[i - 1]; | |
4438 } | |
4439 } | |
4440 static inline void fxmath_decimal_helper_normalize(uint64_t& phi, | |
4441 uint64_t& pmid, | |
4442 uint64_t& plo) { | |
4443 phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid); | |
4444 pmid = (uint32_t)pmid; | |
4445 pmid += FXMATH_DECIMAL_RSHIFT32BIT(plo); | |
4446 plo = (uint32_t)plo; | |
4447 phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid); | |
4448 pmid = (uint32_t)pmid; | |
4449 } | |
4450 static inline void fxmath_decimal_helper_normalize_any(uint64_t nums[], | |
4451 uint8_t len) { | |
4452 { | |
4453 for (int i = len - 2; i > 0; i--) { | |
4454 nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]); | |
4455 nums[i] = (uint32_t)nums[i]; | |
4456 } | |
4457 } | |
4458 { | |
4459 for (int i = 0; i < len - 1; i++) { | |
4460 nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]); | |
4461 nums[i] = (uint32_t)nums[i]; | |
4462 } | |
4463 } | |
4464 } | |
4465 static inline int8_t fxmath_decimal_helper_raw_compare(uint32_t hi1, | |
4466 uint32_t mid1, | |
4467 uint32_t lo1, | |
4468 uint32_t hi2, | |
4469 uint32_t mid2, | |
4470 uint32_t lo2) { | |
4471 int8_t retVal = 0; | |
4472 if (!retVal) { | |
4473 retVal += (hi1 > hi2 ? 1 : (hi1 < hi2 ? -1 : 0)); | |
4474 } | |
4475 if (!retVal) { | |
4476 retVal += (mid1 > mid2 ? 1 : (mid1 < mid2 ? -1 : 0)); | |
4477 } | |
4478 if (!retVal) { | |
4479 retVal += (lo1 > lo2 ? 1 : (lo1 < lo2 ? -1 : 0)); | |
4480 } | |
4481 return retVal; | |
4482 } | |
4483 static inline int8_t fxmath_decimal_helper_raw_compare_any(uint64_t a[], | |
4484 uint8_t al, | |
4485 uint64_t b[], | |
4486 uint8_t bl) { | |
4487 int8_t retVal = 0; | |
4488 for (int i = std::max(al - 1, bl - 1); i >= 0; i--) { | |
4489 uint64_t l = (i >= al ? 0 : a[i]), r = (i >= bl ? 0 : b[i]); | |
4490 retVal += (l > r ? 1 : (l < r ? -1 : 0)); | |
4491 if (retVal) { | |
4492 return retVal; | |
4493 } | |
4494 } | |
4495 return retVal; | |
4496 } | |
4497 static inline void fxmath_decimal_helper_dec_any(uint64_t a[], uint8_t al) { | |
4498 for (int i = 0; i < al; i++) { | |
4499 if (a[i]--) { | |
4500 return; | |
4501 } | |
4502 } | |
4503 } | |
4504 static inline void fxmath_decimal_helper_inc_any(uint64_t a[], uint8_t al) { | |
4505 for (int i = 0; i < al; i++) { | |
4506 a[i]++; | |
4507 if ((uint32_t)a[i] == a[i]) { | |
4508 return; | |
4509 } | |
4510 a[i] = 0; | |
4511 } | |
4512 } | |
4513 static inline void fxmath_decimal_helper_raw_mul(uint64_t a[], | |
4514 uint8_t al, | |
4515 uint64_t b[], | |
4516 uint8_t bl, | |
4517 uint64_t c[], | |
4518 uint8_t cl) { | |
4519 assert(al + bl <= cl); | |
4520 { | |
4521 for (int i = 0; i < cl; i++) { | |
4522 c[i] = 0; | |
4523 } | |
4524 } | |
4525 { | |
4526 for (int i = 0; i < al; i++) { | |
4527 for (int j = 0; j < bl; j++) { | |
4528 uint64_t m = (uint64_t)a[i] * b[j]; | |
4529 c[i + j] += (uint32_t)m; | |
4530 c[i + j + 1] += FXMATH_DECIMAL_RSHIFT32BIT(m); | |
4531 } | |
4532 } | |
4533 } | |
4534 { | |
4535 for (int i = 0; i < cl - 1; i++) { | |
4536 c[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(c[i]); | |
4537 c[i] = (uint32_t)c[i]; | |
4538 } | |
4539 } | |
4540 { | |
4541 for (int i = 0; i < cl; i++) { | |
4542 c[i] = (uint32_t)c[i]; | |
4543 } | |
4544 } | |
4545 } | |
4546 static inline void fxmath_decimal_helper_raw_div(uint64_t a[], | |
4547 uint8_t al, | |
4548 uint64_t b[], | |
4549 uint8_t bl, | |
4550 uint64_t c[], | |
4551 uint8_t cl) { | |
4552 int i; | |
4553 for (i = 0; i < cl; i++) { | |
4554 c[i] = 0; | |
4555 } | |
4556 uint64_t left[16] = {0}, right[16] = {0}; | |
4557 left[0] = 0; | |
4558 for (i = 0; i < al; i++) { | |
4559 right[i] = a[i]; | |
4560 } | |
4561 uint64_t tmp[16]; | |
4562 while (fxmath_decimal_helper_raw_compare_any(left, al, right, al) <= 0) { | |
4563 uint64_t cur[16]; | |
4564 for (i = 0; i < al; i++) { | |
4565 cur[i] = left[i] + right[i]; | |
4566 } | |
4567 for (i = al - 1; i >= 0; i--) { | |
4568 if (i) { | |
4569 cur[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(cur[i] % 2); | |
4570 } | |
4571 cur[i] /= 2; | |
4572 } | |
4573 fxmath_decimal_helper_raw_mul(cur, al, b, bl, tmp, 16); | |
4574 switch (fxmath_decimal_helper_raw_compare_any(tmp, 16, a, al)) { | |
4575 case -1: | |
4576 for (i = 0; i < 16; i++) { | |
4577 left[i] = cur[i]; | |
4578 } | |
4579 left[0]++; | |
4580 fxmath_decimal_helper_normalize_any(left, al); | |
4581 break; | |
4582 case 1: | |
4583 for (i = 0; i < 16; i++) { | |
4584 right[i] = cur[i]; | |
4585 } | |
4586 fxmath_decimal_helper_dec_any(right, al); | |
4587 break; | |
4588 case 0: | |
4589 for (i = 0; i < std::min(al, cl); i++) { | |
4590 c[i] = cur[i]; | |
4591 } | |
4592 return; | |
4593 } | |
4594 } | |
4595 for (i = 0; i < std::min(al, cl); i++) { | |
4596 c[i] = left[i]; | |
4597 } | |
4598 } | |
4599 static inline FX_BOOL fxmath_decimal_helper_outofrange(uint64_t a[], | |
4600 uint8_t al, | |
4601 uint8_t goal) { | |
4602 for (int i = goal; i < al; i++) { | |
4603 if (a[i]) { | |
4604 return TRUE; | |
4605 } | |
4606 } | |
4607 return FALSE; | |
4608 } | |
4609 static inline void fxmath_decimal_helper_shrinkintorange(uint64_t a[], | |
4610 uint8_t al, | |
4611 uint8_t goal, | |
4612 uint8_t& scale) { | |
4613 FX_BOOL bRoundUp = FALSE; | |
4614 while (scale != 0 && (scale > FXMATH_DECIMAL_SCALELIMIT || | |
4615 fxmath_decimal_helper_outofrange(a, al, goal))) { | |
4616 bRoundUp = fxmath_decimal_helper_div10_any(a, al) >= 5; | |
4617 scale--; | |
4618 } | |
4619 if (bRoundUp) { | |
4620 fxmath_decimal_helper_normalize_any(a, goal); | |
4621 fxmath_decimal_helper_inc_any(a, goal); | |
4622 } | |
4623 } | |
4624 static inline void fxmath_decimal_helper_truncate(uint64_t& phi, | |
4625 uint64_t& pmid, | |
4626 uint64_t& plo, | |
4627 uint8_t& scale, | |
4628 uint8_t minscale = 0) { | |
4629 while (scale > minscale) { | |
4630 uint64_t thi = phi, tmid = pmid, tlo = plo; | |
4631 if (fxmath_decimal_helper_div10(thi, tmid, tlo) != 0) { | |
4632 break; | |
4633 } | |
4634 phi = thi, pmid = tmid, plo = tlo; | |
4635 scale--; | |
4636 } | |
4637 } | |
4638 CFX_Decimal::CFX_Decimal() { | |
4639 m_uLo = m_uMid = m_uHi = m_uFlags = 0; | |
4640 } | |
4641 CFX_Decimal::CFX_Decimal(uint64_t val) { | |
4642 m_uLo = (uint32_t)val; | |
4643 m_uMid = (uint32_t)FXMATH_DECIMAL_RSHIFT32BIT(val); | |
4644 m_uHi = 0; | |
4645 m_uFlags = 0; | |
4646 } | |
4647 CFX_Decimal::CFX_Decimal(uint32_t val) { | |
4648 m_uLo = (uint32_t)val; | |
4649 m_uMid = m_uHi = 0; | |
4650 m_uFlags = 0; | |
4651 } | |
4652 CFX_Decimal::CFX_Decimal(uint32_t lo, | |
4653 uint32_t mid, | |
4654 uint32_t hi, | |
4655 FX_BOOL neg, | |
4656 uint8_t scale) { | |
4657 scale = (scale > FXMATH_DECIMAL_SCALELIMIT ? 0 : scale); | |
4658 m_uLo = lo; | |
4659 m_uMid = mid; | |
4660 m_uHi = hi; | |
4661 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(neg && IsNotZero(), scale); | |
4662 } | |
4663 CFX_Decimal::CFX_Decimal(int32_t val) { | |
4664 if (val >= 0) { | |
4665 *this = CFX_Decimal((uint32_t)val); | |
4666 } else { | |
4667 *this = CFX_Decimal((uint32_t)-val); | |
4668 SetNegate(); | |
4669 } | |
4670 } | |
4671 CFX_Decimal::CFX_Decimal(int64_t val) { | |
4672 if (val >= 0) { | |
4673 *this = CFX_Decimal((uint64_t)val); | |
4674 } else { | |
4675 *this = CFX_Decimal((uint64_t)-val); | |
4676 SetNegate(); | |
4677 } | |
4678 } | |
4679 CFX_Decimal::CFX_Decimal(FX_FLOAT val, uint8_t scale) { | |
4680 FX_FLOAT newval = fabs(val); | |
4681 uint64_t phi, pmid, plo; | |
4682 plo = (uint64_t)newval; | |
4683 pmid = (uint64_t)(newval / 1e32); | |
4684 phi = (uint64_t)(newval / 1e64); | |
4685 newval = FXSYS_fmod(newval, 1.0f); | |
4686 for (uint8_t iter = 0; iter < scale; iter++) { | |
4687 fxmath_decimal_helper_mul10(phi, pmid, plo); | |
4688 newval *= 10; | |
4689 plo += (uint64_t)newval; | |
4690 newval = FXSYS_fmod(newval, 1.0f); | |
4691 } | |
4692 plo += FXSYS_round(newval); | |
4693 fxmath_decimal_helper_normalize(phi, pmid, plo); | |
4694 m_uHi = (uint32_t)phi; | |
4695 m_uMid = (uint32_t)pmid; | |
4696 m_uLo = (uint32_t)plo; | |
4697 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale); | |
4698 } | |
4699 CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) { | |
4700 const FX_WCHAR* str = strObj.GetPtr(); | |
4701 const FX_WCHAR* strBound = str + strObj.GetLength(); | |
4702 FX_BOOL pointmet = 0; | |
4703 FX_BOOL negmet = 0; | |
4704 uint8_t scale = 0; | |
4705 m_uHi = m_uMid = m_uLo = 0; | |
4706 while (str != strBound && *str == ' ') { | |
4707 str++; | |
4708 } | |
4709 if (str != strBound && *str == '-') { | |
4710 negmet = 1; | |
4711 str++; | |
4712 } else if (str != strBound && *str == '+') { | |
4713 str++; | |
4714 } | |
4715 while (str != strBound && ((*str >= '0' && *str <= '9') || *str == '.') && | |
4716 scale < FXMATH_DECIMAL_SCALELIMIT) { | |
4717 if (*str == '.') { | |
4718 if (pointmet) { | |
4719 goto cont; | |
4720 } | |
4721 pointmet = 1; | |
4722 } else { | |
4723 m_uHi = m_uHi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uMid * 0xA); | |
4724 m_uMid = m_uMid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uLo * 0xA); | |
4725 m_uLo = m_uLo * 0xA + (*str - '0'); | |
4726 if (pointmet) { | |
4727 scale++; | |
4728 } | |
4729 } | |
4730 cont: | |
4731 str++; | |
4732 } | |
4733 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale); | |
4734 } | |
4735 | |
4736 CFX_Decimal::CFX_Decimal(const CFX_ByteStringC& strObj) { | |
4737 *this = CFX_Decimal(CFX_WideString::FromLocal(strObj)); | |
4738 } | |
4739 | |
4740 CFX_Decimal::operator CFX_WideString() const { | |
4741 CFX_WideString retString; | |
4742 CFX_WideString tmpbuf; | |
4743 uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo; | |
4744 while (phi || pmid || plo) { | |
4745 tmpbuf += fxmath_decimal_helper_div10(phi, pmid, plo) + '0'; | |
4746 } | |
4747 uint8_t outputlen = (uint8_t)tmpbuf.GetLength(); | |
4748 uint8_t scale = (uint8_t)FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); | |
4749 while (scale >= outputlen) { | |
4750 tmpbuf += '0'; | |
4751 outputlen++; | |
4752 } | |
4753 if (FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero()) { | |
4754 retString += '-'; | |
4755 } | |
4756 for (uint8_t idx = 0; idx < outputlen; idx++) { | |
4757 if (idx == (outputlen - scale) && scale != 0) { | |
4758 retString += '.'; | |
4759 } | |
4760 retString += tmpbuf[outputlen - 1 - idx]; | |
4761 } | |
4762 return retString; | |
4763 } | |
4764 CFX_Decimal::operator double() const { | |
4765 double pow = (double)(1 << 16) * (1 << 16); | |
4766 double base = | |
4767 ((double)m_uHi) * pow * pow + ((double)m_uMid) * pow + ((double)m_uLo); | |
4768 int8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); | |
4769 FX_BOOL bNeg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags); | |
4770 return (bNeg ? -1 : 1) * base * ::pow(10.0, -scale); | |
4771 } | |
4772 void CFX_Decimal::SetScale(uint8_t newscale) { | |
4773 uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); | |
4774 if (newscale > oldscale) { | |
4775 uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo; | |
4776 for (uint8_t iter = 0; iter < newscale - oldscale; iter++) { | |
4777 fxmath_decimal_helper_mul10(phi, pmid, plo); | |
4778 } | |
4779 m_uHi = (uint32_t)phi; | |
4780 m_uMid = (uint32_t)pmid; | |
4781 m_uLo = (uint32_t)plo; | |
4782 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( | |
4783 FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); | |
4784 } else if (newscale < oldscale) { | |
4785 uint64_t phi, pmid, plo; | |
4786 phi = 0, pmid = 0, plo = 5; | |
4787 { | |
4788 for (uint8_t iter = 0; iter < oldscale - newscale - 1; iter++) { | |
4789 fxmath_decimal_helper_mul10(phi, pmid, plo); | |
4790 } | |
4791 } | |
4792 phi += m_uHi; | |
4793 pmid += m_uMid; | |
4794 plo += m_uLo; | |
4795 fxmath_decimal_helper_normalize(phi, pmid, plo); | |
4796 { | |
4797 for (uint8_t iter = 0; iter < oldscale - newscale; iter++) { | |
4798 fxmath_decimal_helper_div10(phi, pmid, plo); | |
4799 } | |
4800 } | |
4801 m_uHi = (uint32_t)phi; | |
4802 m_uMid = (uint32_t)pmid; | |
4803 m_uLo = (uint32_t)plo; | |
4804 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( | |
4805 FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); | |
4806 } | |
4807 } | |
4808 uint8_t CFX_Decimal::GetScale() { | |
4809 uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); | |
4810 return oldscale; | |
4811 } | |
4812 void CFX_Decimal::SetAbs() { | |
4813 m_uFlags &= ~FXMATH_DECIMAL_NEGMASK; | |
4814 } | |
4815 void CFX_Decimal::SetNegate() { | |
4816 if (IsNotZero()) { | |
4817 m_uFlags ^= FXMATH_DECIMAL_NEGMASK; | |
4818 } | |
4819 } | |
4820 void CFX_Decimal::FloorOrCeil(FX_BOOL bFloor) { | |
4821 uint64_t nums[3] = {m_uLo, m_uMid, m_uHi}; | |
4822 FX_BOOL bDataLoss = FALSE; | |
4823 for (int i = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); i > 0; i--) { | |
4824 bDataLoss = fxmath_decimal_helper_div10_any(nums, 3) || bDataLoss; | |
4825 } | |
4826 if (bDataLoss && (bFloor ? FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) | |
4827 : !FXMATH_DECIMAL_FLAGS2NEG(m_uFlags))) { | |
4828 fxmath_decimal_helper_inc_any(nums, 3); | |
4829 } | |
4830 m_uHi = (uint32_t)nums[2]; | |
4831 m_uMid = (uint32_t)nums[1]; | |
4832 m_uLo = (uint32_t)nums[0]; | |
4833 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( | |
4834 FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), 0); | |
4835 } | |
4836 void CFX_Decimal::SetFloor() { | |
4837 FloorOrCeil(TRUE); | |
4838 } | |
4839 void CFX_Decimal::SetCeiling() { | |
4840 FloorOrCeil(FALSE); | |
4841 } | |
4842 void CFX_Decimal::SetTruncate() { | |
4843 FloorOrCeil(!FXMATH_DECIMAL_FLAGS2NEG(m_uFlags)); | |
4844 } | |
4845 void CFX_Decimal::Swap(CFX_Decimal& val) { | |
4846 uint32_t tmp; | |
4847 tmp = m_uHi; | |
4848 m_uHi = val.m_uHi; | |
4849 val.m_uHi = tmp; | |
4850 tmp = m_uMid; | |
4851 m_uMid = val.m_uMid; | |
4852 val.m_uMid = tmp; | |
4853 tmp = m_uLo; | |
4854 m_uLo = val.m_uLo; | |
4855 val.m_uLo = tmp; | |
4856 tmp = m_uFlags; | |
4857 m_uFlags = val.m_uFlags; | |
4858 val.m_uFlags = tmp; | |
4859 } | |
4860 int8_t CFX_Decimal::Compare(const CFX_Decimal& val) const { | |
4861 CFX_Decimal lhs = *this, rhs = val; | |
4862 int8_t retVal = 0; | |
4863 if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != | |
4864 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) { | |
4865 uint8_t scale = std::min(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags), | |
4866 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)); | |
4867 lhs.SetScale(scale); | |
4868 rhs.SetScale(scale); | |
4869 } | |
4870 retVal = -(FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) - | |
4871 FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags)); | |
4872 if (retVal) { | |
4873 return retVal; | |
4874 } | |
4875 retVal = fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo, | |
4876 rhs.m_uHi, rhs.m_uMid, rhs.m_uLo); | |
4877 return (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) ? -retVal : retVal); | |
4878 } | |
4879 CFX_Decimal CFX_Decimal::AddOrMinus(const CFX_Decimal& val, | |
4880 FX_BOOL isAdding) const { | |
4881 CFX_Decimal lhs = *this, rhs = val; | |
4882 if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != | |
4883 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) { | |
4884 uint8_t scale = std::max(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags), | |
4885 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)); | |
4886 lhs.SetScale(scale); | |
4887 rhs.SetScale(scale); | |
4888 } | |
4889 if (!isAdding) { | |
4890 rhs.SetNegate(); | |
4891 } | |
4892 if (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) == | |
4893 FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags)) { | |
4894 uint64_t phi = lhs.m_uHi, pmid = lhs.m_uMid, plo = lhs.m_uLo; | |
4895 phi += rhs.m_uHi; | |
4896 pmid += rhs.m_uMid; | |
4897 plo += rhs.m_uLo; | |
4898 fxmath_decimal_helper_normalize(phi, pmid, plo); | |
4899 if (FXMATH_DECIMAL_RSHIFT32BIT(phi) && | |
4900 FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != 0) { | |
4901 fxmath_decimal_helper_div10(phi, pmid, plo); | |
4902 lhs.m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( | |
4903 FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags), | |
4904 FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) - 1); | |
4905 } | |
4906 lhs.m_uHi = (uint32_t)phi; | |
4907 lhs.m_uMid = (uint32_t)pmid; | |
4908 lhs.m_uLo = (uint32_t)plo; | |
4909 return lhs; | |
4910 } else { | |
4911 if (fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo, | |
4912 rhs.m_uHi, rhs.m_uMid, | |
4913 rhs.m_uLo) < 0) { | |
4914 lhs.Swap(rhs); | |
4915 } | |
4916 lhs.m_uHi -= rhs.m_uHi; | |
4917 if (lhs.m_uMid < rhs.m_uMid) { | |
4918 lhs.m_uHi--; | |
4919 } | |
4920 lhs.m_uMid -= rhs.m_uMid; | |
4921 if (lhs.m_uLo < rhs.m_uLo) { | |
4922 if (!lhs.m_uMid) { | |
4923 lhs.m_uHi--; | |
4924 } | |
4925 lhs.m_uMid--; | |
4926 } | |
4927 lhs.m_uLo -= rhs.m_uLo; | |
4928 return lhs; | |
4929 } | |
4930 } | |
4931 CFX_Decimal CFX_Decimal::Multiply(const CFX_Decimal& val) const { | |
4932 uint64_t a[3] = {m_uLo, m_uMid, m_uHi}, | |
4933 b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}; | |
4934 uint64_t c[6]; | |
4935 fxmath_decimal_helper_raw_mul(a, 3, b, 3, c, 6); | |
4936 FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ | |
4937 FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags); | |
4938 uint8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) + | |
4939 FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags); | |
4940 fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale); | |
4941 return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg, | |
4942 scale); | |
4943 } | |
4944 CFX_Decimal CFX_Decimal::Divide(const CFX_Decimal& val) const { | |
4945 if (!val.IsNotZero()) { | |
4946 return CFX_Decimal(); | |
4947 } | |
4948 FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^ | |
4949 FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags); | |
4950 uint64_t a[7] = {m_uLo, m_uMid, m_uHi}, | |
4951 b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0}; | |
4952 uint8_t scale = 0; | |
4953 if (FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) < | |
4954 FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags)) { | |
4955 for (int i = FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags) - | |
4956 FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); | |
4957 i > 0; i--) { | |
4958 fxmath_decimal_helper_mul10_any(a, 7); | |
4959 } | |
4960 } else { | |
4961 scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) - | |
4962 FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags); | |
4963 } | |
4964 uint8_t minscale = scale; | |
4965 if (!IsNotZero()) { | |
4966 return CFX_Decimal(0, 0, 0, 0, minscale); | |
4967 } | |
4968 while (!a[6]) { | |
4969 fxmath_decimal_helper_mul10_any(a, 7); | |
4970 scale++; | |
4971 } | |
4972 fxmath_decimal_helper_div10_any(a, 7); | |
4973 scale--; | |
4974 fxmath_decimal_helper_raw_div(a, 6, b, 3, c, 7); | |
4975 fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale); | |
4976 fxmath_decimal_helper_truncate(c[2], c[1], c[0], scale, minscale); | |
4977 return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg, | |
4978 scale); | |
4979 } | |
4980 CFX_Decimal CFX_Decimal::Modulus(const CFX_Decimal& val) const { | |
4981 CFX_Decimal lhs = *this, rhs_abs = val; | |
4982 rhs_abs.SetAbs(); | |
4983 if (!rhs_abs.IsNotZero()) { | |
4984 return *this; | |
4985 } | |
4986 while (TRUE) { | |
4987 CFX_Decimal lhs_abs = lhs; | |
4988 lhs_abs.SetAbs(); | |
4989 if (lhs_abs < rhs_abs) { | |
4990 break; | |
4991 } | |
4992 CFX_Decimal quot = lhs / rhs_abs; | |
4993 quot.SetTruncate(); | |
4994 lhs = lhs - quot * rhs_abs; | |
4995 } | |
4996 return lhs; | |
4997 } | |
4998 bool CFX_Decimal::operator==(const CFX_Decimal& val) const { | |
4999 return Compare(val) == 0; | |
5000 } | |
5001 bool CFX_Decimal::operator<=(const CFX_Decimal& val) const { | |
5002 return Compare(val) <= 0; | |
5003 } | |
5004 bool CFX_Decimal::operator>=(const CFX_Decimal& val) const { | |
5005 return Compare(val) >= 0; | |
5006 } | |
5007 bool CFX_Decimal::operator!=(const CFX_Decimal& val) const { | |
5008 return Compare(val) != 0; | |
5009 } | |
5010 bool CFX_Decimal::operator<(const CFX_Decimal& val) const { | |
5011 return Compare(val) < 0; | |
5012 } | |
5013 bool CFX_Decimal::operator>(const CFX_Decimal& val) const { | |
5014 return Compare(val) > 0; | |
5015 } | |
5016 CFX_Decimal CFX_Decimal::operator+(const CFX_Decimal& val) const { | |
5017 return AddOrMinus(val, TRUE); | |
5018 } | |
5019 CFX_Decimal CFX_Decimal::operator-(const CFX_Decimal& val) const { | |
5020 return AddOrMinus(val, FALSE); | |
5021 } | |
5022 CFX_Decimal CFX_Decimal::operator*(const CFX_Decimal& val) const { | |
5023 return Multiply(val); | |
5024 } | |
5025 CFX_Decimal CFX_Decimal::operator/(const CFX_Decimal& val) const { | |
5026 return Divide(val); | |
5027 } | |
5028 CFX_Decimal CFX_Decimal::operator%(const CFX_Decimal& val) const { | |
5029 return Modulus(val); | |
5030 } | |
OLD | NEW |