DCL 4.0
Loading...
Searching...
No Matches
Numeric.cpp
Go to the documentation of this file.
1#include <dcl/Config.h>
2
3#include <errno.h>
4#include <stdio.h>
5#include <math.h> // HUGE_VAL
6#include <float.h> // FLT_MAX, FLT_MIN
7#include <ctype.h>
8#include <wctype.h>
9#include <wchar.h> // wcstol, wcstoul
10
11#include <dcl/_stdlib.h>
12
13#include <dcl/Object.h>
14#include <dcl/Numeric.h>
15#include "__xtoa.h"
16
17#if __DCL_HAVE_ALLOC_DEBUG
18#undef __DCL_ALLOC_LEVEL
19#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
20#endif
21
22#if __DCL_DEBUG
23#undef __THIS_FILE__
24static const char_t __THIS_FILE__[] = __T("dcl/Numeric.cpp");
25#endif
26
27__DCL_BEGIN_NAMESPACE
28#if 0
29static void formatHelper(String& strResult,
30 const String& strNumber,
31 const String& strFormat,
32 bool bThousandsSep /* = */
33 )
34{
35 if (strFormat.isEmpty())
36 {
37 strResult += strNumber;
38 return;
39 }
40
41 int nNumber = strNumber.length();
42 int nFormat = strFormat.length();
43 const char* psz = strNumber.cstr();
44 const char* pszFormat = strFormat.cstr();
45 if (/* *psz != '\0' && */ *psz == '-')
46 {
47 strResult += *psz;
48 psz++;
49 nNumber--;
50 }
51 if (*pszFormat != '\0' && *pszFormat != '#' && *pszFormat != '0')
52 {
53 // currency symbol
54 strResult += *pszFormat;
55 pszFormat++;
56 nFormat--;
57 }
58
59 int nGreateFormat = nFormat - nNumber;
60 if (nGreateFormat > 0)
61 {
62 int nThousandsPos = nFormat % 3;
63 int i = 0;
64 bool bEmpty = true;
65 for (; nGreateFormat--; i++)
66 {
67 if (*pszFormat == '0')
68 {
69 if (!bEmpty && bThousandsSep && ((i % 3) == nThousandsPos))
70 strResult += ',';
71
72 strResult += '0';
73 bEmpty = false;
74 }
75 else if (*pszFormat == '#')
76 {
77 if (!bEmpty && bThousandsSep && ((i % 3) == nThousandsPos))
78 {
79 strResult += ',';
80 }
81 }
82 pszFormat++;
83 }
84
85 for(; *psz ; i++)
86 {
87 if (!bEmpty && bThousandsSep && ((i % 3) == nThousandsPos))
88 strResult += ',';
89 strResult += *psz++;
90 bEmpty = false;
91 }
92 }
93 else
94 {
95 int nThousandsPos = nNumber % 3;
96 for(int i = 0; *psz ; i++)
97 {
98 if (i != 0 && bThousandsSep && ((i % 3) == nThousandsPos))
99 strResult += ',';
100 strResult += *psz++;
101 }
102 }
103}
104
105String formatDouble(double value, const char* pszFormat)
106{
107 __DCL_ASSERT(pszFormat != NULL);
108 String strFormat = pszFormat;
109 String strResult;
110 // 유효숫자리 계산
111
112 int nDigit = 17;
113 int nDecimalPoint = 0;
114 int nSign = 0;
115
116 char szBuf[_CVTBUFSIZE];
117 __DCL_VERIFY(_ecvt_s(szBuf, sizeof(szBuf), value, nDigit, &nDecimalPoint, &nSign) == 0);
118
119 if (nDecimalPoint <= 0)
120 nDigit = 0;
121 else
122 nDigit = nDecimalPoint;
123
124 int nFormatDecimalPoint = strFormat.find('.');
125 if (nFormatDecimalPoint >= 0)
126 nDigit += strFormat.length() - nFormatDecimalPoint - 1;
127
128 if (nDigit > 17) // double precision
129 nDigit = 17;
130
131 __DCL_VERIFY(_ecvt_s(szBuf, sizeof(szBuf), value, nDigit, &nDecimalPoint, &nSign) == 0);
132 String strDouble = szBuf;
133
134 if (nDecimalPoint < 0)
135 {
136 String strZero('0', abs(nDecimalPoint));
137 strDouble.insert(0, strZero);
138 strDouble.setLength(nDigit);
139 nDecimalPoint = 0;
140 }
141 else
142 {
143 if (nDigit < nDecimalPoint)
144 strDouble.append('0', nDecimalPoint - nDigit);
145 }
146
147 // 여기서부터는 문자열 처리
148 String strInt(strDouble, 0, nDecimalPoint);
149 String strDecimal(strDouble, nDecimalPoint, strDouble.length() - nDecimalPoint);
150
151 if (nSign)
152 strResult = '-';
153
154 if (!strDecimal.isEmpty() && strInt.isEmpty())
155 strInt = "0";
156
157 String strIntFormat;
158 String strDecimalFormat;
159
160 strIntFormat.assign(strFormat, 0, nFormatDecimalPoint);
161 strDecimalFormat.assign(strFormat,
162 nFormatDecimalPoint + 1, strFormat.length() - nFormatDecimalPoint - 1);
163
164 formatHelper(strResult, strInt, strIntFormat, (int)strFormat.find(',') >= 0);
165
166 // 소수부분의 마지막 부분부터 '0' 인 문자를 삭제한다.
167 strDecimal.trimRight('0');
168
169 // 소수부분이 비어있지 않으면..
170 if (!strDecimal.isEmpty() || nFormatDecimalPoint >= 0)
171 {
172 if (!(strDecimal.isEmpty()
173 && !strDecimalFormat.isEmpty()
174 && strDecimalFormat.at(0) == '#'))
175 {
176 strResult += '.';
177 formatHelper(strResult, strDecimal, strDecimalFormat, false);
178 }
179 }
180 return strResult;
181}
182
183// 이 함수는 소수점 아래에 대하여 포멧을 수행하지 않는다.
184// 이 함수를 호출하기전에 반드시 precision을 정해야 한다.
185// 가급적 이 함수를 호출하지 말것 .. Oracle NUMBER 의 경우 사용하기 위함.
186String formatDecimalString(const String& strNumber, const char* pszFormat)
187{
188 __DCL_ASSERT(pszFormat != NULL);
189
190 String strFormat = pszFormat;
191 String strResult;
192
193 int nDecimalPoint = strNumber.find('.');
194 int nFormatDecimalPoint = strFormat.find('.');
195
196 String strInt;
197 String strIntFormat;
198
199 if (nDecimalPoint >= 0)
200 strInt.assign(strNumber, 0, nDecimalPoint);
201 else
202 strInt = strNumber;
203
204 if (nFormatDecimalPoint >= 0)
205 strIntFormat.assign(strFormat, 0, nFormatDecimalPoint);
206 else
207 strIntFormat = strFormat;
208
209 formatHelper(strResult, strInt, strIntFormat, (int)strFormat.find(',') >= 0);
210
211 // 소수부분이 비어있지 않으면..
212 // 소부부분의 포멧팅을 수행하지 않는다 단지 복사한다.
213 if (nDecimalPoint >= 0 && (int)strNumber.length() > nDecimalPoint + 1)
214 {
215 strResult.append(strNumber, nDecimalPoint, strNumber.length() - nDecimalPoint);
216 }
217
218 return strResult;
219}
220
221String formatIntegerString(const char* pszIntegerValue, const char* pszFormat)
222{
223 __DCL_ASSERT(pszIntegerValue != NULL);
224 __DCL_ASSERT(pszFormat != NULL);
225
226 String strInt = pszIntegerValue;
227 String strFormat = pszFormat;
228 String strResult;
229
230 if (strInt == "0")
231 strInt.clear();
232
233 String strIntFormat;
234 String strDecimalFormat;
235 int nFormatDecimalPoint = strFormat.find('.');
236 if (nFormatDecimalPoint >= 0)
237 {
238 strIntFormat.assign(strFormat, 0, nFormatDecimalPoint);
239 strDecimalFormat.assign(strFormat,
240 nFormatDecimalPoint + 1, strFormat.length() - nFormatDecimalPoint - 1);
241 }
242 else
243 strIntFormat = strFormat;
244
245 formatHelper(strResult, strInt, strIntFormat, (int)strFormat.find(',') >= 0);
246 if (!strDecimalFormat.isEmpty() && strDecimalFormat.at(0) == '0')
247 {
248 strResult += '.';
249 formatHelper(strResult, "", strDecimalFormat, false);
250 }
251 return strResult;
252}
253#endif
255
256
258
259
261
262String Int32::toString(int32_t _n, unsigned _base)
263{
264 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
265 // 2진수일경우 32 + sign = 33
266 CharBuffer* buf = CharBuffer::create(40);
267 __int32tow(_n, buf->data(), _base);
268 buf->__dataLength = String::length(buf->data());
269 String s(buf);
270 buf->release();
271 return s;
272}
273
274String Int32::toString(int32_t _n, const wchar_t* _format)
275{
276 if (!_format)
277 _format = __T("%ld");
278
279 __DCL_ASSERT_PARAM(*_format != '\0');
280
281 return String::format(_format, _n);
282}
283
284int32_t Int32::parse(const wchar_t* _number, unsigned _base)
286{
287 __DCL_ASSERT(_number != NULL);
288 __DCL_ASSERT(_base > 1);
289
290 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
291 throw new NumericConvertException(_number, _base, 0);
292 }
293
294 NumericConvertException::Error error = NumericConvertException::NoError;
295 wchar_t* endptr = NULL;
296 long n = wcstol(_number, &endptr, _base);
297 if (LONG_MIN == n) {
298 error = NumericConvertException::Underflow;
299 } else if (LONG_MAX == n) {
300 error = NumericConvertException::Overflow;
301 }
302#if __WORDSIZE > 32
303 else if (n < INT32_MIN) {
304 error = NumericConvertException::Underflow;
305 } else if (INT32_MAX < n) {
306 error = NumericConvertException::Overflow;
307 }
308#endif
309
310 if (NumericConvertException::NoError != error) {
311 throw new NumericConvertException(
312 error,
313 _number,
314 _base
315 );
316 }
317
318 if ((endptr && *endptr != '\0') || errno == EINVAL) {
319 throw new NumericConvertException(
320 _number,
321 _base,
322 endptr ? (endptr - _number) : 0
323 );
324 }
325
326 return (int32_t)n;
327}
328
329int32_t Int32::parse(const wchar_t* _number, unsigned _base, int32_t _default)
330{
331 __DCL_ASSERT(_number != NULL);
332 __DCL_ASSERT(_base > 1);
333
334 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
335 return _default;
336 }
337
338 NumericConvertException::Error error = NumericConvertException::NoError;
339 wchar_t* endptr = NULL;
340 long n = wcstol(_number, &endptr, _base);
341 if (LONG_MIN == n) {
342 error = NumericConvertException::Underflow;
343 } else if (LONG_MAX == n) {
344 error = NumericConvertException::Overflow;
345 }
346 #if __WORDSIZE > 32
347 else if (n < INT32_MIN) {
348 error = NumericConvertException::Underflow;
349 } else if (INT32_MAX < n) {
350 error = NumericConvertException::Overflow;
351 }
352 #endif
353
354 if (NumericConvertException::NoError != error) {
355 return _default;
356 }
357
358 if ((endptr && *endptr != '\0') || errno == EINVAL) {
359 return _default;
360 }
361
362 return (int32_t)n;
363}
364
365ByteString Int32::toByteString(int32_t _n, unsigned _base)
366{
367 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
368 // 2진수일경우 32 + sign = 33
369 ByteBuffer* buf = ByteBuffer::create(40);
370 __int32toa(_n, buf->data(), _base);
371 buf->__dataLength = ByteString::length(buf->data());
372 ByteString s(buf);
373 buf->release();
374 return s;
375}
376
378
379String UInt32::toString(uint32_t _u, unsigned _base)
380{
381 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
382 // 2진수일경우 32 + sign = 33
383 CharBuffer* buf = CharBuffer::create(40);
384 __uint32tow(_u, buf->data(), _base);
385 buf->__dataLength = String::length(buf->data());
386 String s(buf);
387 buf->release();
388 return s;
389}
390
391String UInt32::toString(uint32_t _u, const wchar_t* _format)
392{
393 if (!_format)
394 _format = __T("%lu");
395
396 __DCL_ASSERT_PARAM(*_format != '\0');
397
398 return String::format(_format, _u);
399}
400
401uint32_t UInt32::parse(const wchar_t* _number, unsigned _base)
403{
404 __DCL_ASSERT(_number != NULL);
405 __DCL_ASSERT(_base > 1);
406
407 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
408 throw new NumericConvertException(_number, _base, 0);
409 }
410
411 NumericConvertException::Error error = NumericConvertException::NoError;
412 wchar_t* endptr = NULL;
413 unsigned long n = wcstoul(_number, &endptr, _base);
414 if (ULONG_MAX == n) {
415 error = NumericConvertException::Overflow;
416 }
417#if __WORDSIZE > 32
418 else if (UINT32_MAX < n) {
419 error = NumericConvertException::Overflow;
420 }
421#endif
422 if (NumericConvertException::NoError != error) {
423 throw new NumericConvertException(
424 error,
425 _number,
426 _base
427 );
428 }
429
430 if ((endptr && *endptr != '\0') || errno == EINVAL) {
431 throw new NumericConvertException(
432 _number,
433 _base,
434 endptr ? (endptr - _number) : 0
435 );
436 }
437
438 return (uint32_t) n;
439}
440
441uint32_t UInt32::parse(const wchar_t* _number, unsigned _base, uint32_t _default)
442{
443 __DCL_ASSERT(_number != NULL);
444 __DCL_ASSERT(_base > 1);
445
446 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
447 return _default;
448 }
449
450 NumericConvertException::Error error = NumericConvertException::NoError;
451 wchar_t* endptr = NULL;
452 unsigned long n = wcstoul(_number, &endptr, _base);
453 if (ULONG_MAX == n) {
454 error = NumericConvertException::Overflow;
455 }
456#if __WORDSIZE > 32
457 else if (UINT32_MAX < n) {
458 error = NumericConvertException::Overflow;
459 }
460#endif
461 if (NumericConvertException::NoError != error) {
462 return _default;
463 }
464
465 if ((endptr && *endptr != '\0') || errno == EINVAL) {
466 return _default;
467 }
468
469 return (uint32_t) n;
470}
471
472ByteString UInt32::toByteString(uint32_t _u, unsigned _base)
473{
474 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
475 // 2진수일경우 32 + sign = 33
476 ByteBuffer* buf = ByteBuffer::create(40);
477 __uint32toa(_u, buf->data(), _base);
478 buf->__dataLength = ByteString::length(buf->data());
479 ByteString s(buf);
480 buf->release();
481 return s;
482}
483
485
486String Int64::toString(int64_t _n, unsigned _base)
487{
488 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
489 // 2진수일경우 64 + sign = 65
490 CharBuffer* buf = CharBuffer::create(70);
491 __int64tow(_n, buf->data(), _base);
492 buf->__dataLength = String::length(buf->data());
493 String s(buf);
494 buf->release();
495 return s;
496}
497
498String Int64::toString(int64_t _n, const wchar_t* _format)
499{
500 if (!_format)
501 _format = __T("%lld");
502
503 __DCL_ASSERT_PARAM(*_format != '\0');
504
505 return String::format(_format, _n);
506}
507
508#if __DCL_WINDOWS
509#define wcstoll(nptr, endptr, base) _wcstoi64(nptr, endptr, base)
510#define wcstoull(nptr, endptr, base) _wcstoui64(nptr, endptr, base)
511#endif
512
513int64_t Int64::parse(const wchar_t* _number, unsigned _base)
515{
516 __DCL_ASSERT(_number != NULL);
517 __DCL_ASSERT(_base > 1);
518
519 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
520 throw new NumericConvertException(_number, _base, 0);
521 }
522
523 NumericConvertException::Error error = NumericConvertException::NoError;
524 wchar_t* endptr = NULL;
525 long long n = wcstoll(_number, &endptr, _base);
526 if (LLONG_MIN == n) {
527 error = NumericConvertException::Underflow;
528 } else if (LLONG_MAX == n) {
529 error = NumericConvertException::Overflow;
530 }
531
532 if (NumericConvertException::NoError != error) {
533 throw new NumericConvertException(
534 error,
535 _number,
536 _base
537 );
538 }
539
540 if ((endptr && *endptr != '\0') || errno == EINVAL) {
541 throw new NumericConvertException(
542 _number,
543 _base,
544 endptr ? (endptr - _number) : 0
545 );
546 }
547
548 return (int64_t) n;
549}
550
551int64_t Int64::parse(const wchar_t* _number, unsigned _base, int64_t _default)
553{
554 __DCL_ASSERT(_number != NULL);
555 __DCL_ASSERT(_base > 1);
556
557 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
558 return _default;
559 }
560
561 NumericConvertException::Error error = NumericConvertException::NoError;
562 wchar_t* endptr = NULL;
563 long long n = wcstoll(_number, &endptr, _base);
564 if (LLONG_MIN == n) {
565 error = NumericConvertException::Underflow;
566 } else if (LLONG_MAX == n) {
567 error = NumericConvertException::Overflow;
568 }
569
570 if (NumericConvertException::NoError != error) {
571 return _default;
572 }
573
574 if ((endptr && *endptr != '\0') || errno == EINVAL) {
575 return _default;
576 }
577
578 return (int64_t) n;
579}
580
581ByteString Int64::toByteString(int64_t _n, unsigned _base)
582{
583 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
584 // 2진수일경우 32 + sign = 33
585 ByteBuffer* buf = ByteBuffer::create(70);
586 __int64toa(_n, buf->data(), _base);
587 buf->__dataLength = ByteString::length(buf->data());
588 ByteString s(buf);
589 buf->release();
590 return s;
591}
592
594
595String UInt64::toString(uint64_t _u, unsigned _base)
596{
597 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
598 // 2진수일경우 64 + sign = 65
599 CharBuffer* buf = CharBuffer::create(70);
600 __uint64tow(_u, buf->data(), _base);
601 buf->__dataLength = String::length(buf->data());
602 String s(buf);
603 buf->release();
604 return s;
605}
606
607String UInt64::toString(uint64_t _u, const wchar_t* _format)
608{
609 if (!_format)
610 _format = __T("%ull");
611
612 __DCL_ASSERT(*_format != '\0');
613
614 return String::format(_format, _u);
615}
616
617uint64_t UInt64::parse(const wchar_t* _number, unsigned _base)
619{
620 __DCL_ASSERT(_number != NULL);
621 __DCL_ASSERT(_base > 1);
622
623 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
624 throw new NumericConvertException(_number, _base, 0);
625 }
626
627 NumericConvertException::Error error = NumericConvertException::NoError;
628 wchar_t* endptr = NULL;
629 unsigned long long n = wcstoull(_number, &endptr, _base);
630 if (ULLONG_MAX == n) {
631 error = NumericConvertException::Overflow;
632 }
633
634 if (NumericConvertException::NoError != error) {
635 throw new NumericConvertException(
636 error,
637 _number,
638 _base
639 );
640 }
641
642 if ((endptr && *endptr != '\0') || errno == EINVAL) {
643 throw new NumericConvertException(
644 _number,
645 _base,
646 endptr ? (endptr - _number) : 0
647 );
648 }
649
650 return (uint64_t) n;
651}
652
653uint64_t UInt64::parse(const wchar_t* _number, unsigned _base, uint64_t _default)
654{
655 __DCL_ASSERT(_number != NULL);
656 __DCL_ASSERT(_base > 1);
657
658 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
659 return _default;
660 }
661
662 NumericConvertException::Error error = NumericConvertException::NoError;
663 wchar_t* endptr = NULL;
664 unsigned long long n = wcstoull(_number, &endptr, _base);
665 if (ULONG_MAX == n) {
666 error = NumericConvertException::Overflow;
667 }
668
669 if (NumericConvertException::NoError != error) {
670 return _default;
671 }
672
673 if ((endptr && *endptr != '\0') || errno == EINVAL) {
674 return _default;
675 }
676
677 return (uint64_t) n;
678}
679
680ByteString UInt64::toByteString(uint64_t _n, unsigned _base)
681{
682 __DCL_ASSERT_PARAM(2 <= _base && _base <= 32);
683 // 2진수일경우 32 + sign = 33
684 ByteBuffer* buf = ByteBuffer::create(70);
685 __uint64toa(_n, buf->data(), _base);
686 buf->__dataLength = ByteString::length(buf->data());
687 ByteString s(buf);
688 buf->release();
689 return s;
690}
691
692// Lengths of Exponents and Mantissas
693// Type |Exponent length |Mantissa length | 문자열 길이
694// | | | 가수 | 지수
695//--------------------------------------------------------------------------------
696// float | 8 bits | 23 bits | 3 | 7
697// double | 11 bits | 52 bits | 4 | 15
698//
699
700//Range of Floating-Point Types
701//Type | Minimum value | Maximum value
702//--------------------------------------------------------------------------------
703//float | 1.175494351 E - 38 | 3.402823466 E + 38
704//double | 2.2250738585072014 E - 308 | 1.7976931348623158 E + 308
705
707#if 0
708String Single::toString(float _f)
709{
710 String s;
711 char* psz = s.getBuffer(_CVTBUFSIZE); // 9 + '.' + 'E' + '-' + 3 ==> 15
712 _gcvt_s(psz, _CVTBUFSIZE, f, 8);
713 s.releaseBuffer();
714 return s;
715}
716#endif
717
718String Single::toString(float _f, const wchar_t* _format)
719{
720 if (!_format)
721 _format = _f < INT64_MIN || INT64_MAX < _f ? __T("%e") : __T("%f");
722
723 __DCL_ASSERT(*_format != '\0');
724
725 return String::format(_format, _f);
726}
727
728float Single::parse(const wchar_t* _number)
730{
731 __DCL_ASSERT(_number != NULL);
732
733 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
734 throw new NumericConvertException(_number, 0, 0);
735 }
736
737 NumericConvertException::Error error = NumericConvertException::NoError;
738 wchar_t* endptr = NULL;
739 float n = wcstof(_number, &endptr);
740 if (+HUGE_VALF == n || -HUGE_VALF == n) {
741 error = NumericConvertException::Overflow;
742 } else if (!(FLT_MIN < n)) {
743 error = NumericConvertException::Underflow;
744 }
745
746 if (NumericConvertException::NoError != error) {
747 throw new NumericConvertException(
748 error,
749 _number,
750 0
751 );
752 }
753
754 if ((endptr && *endptr != '\0') || errno == EINVAL) {
755 throw new NumericConvertException(
756 _number,
757 0,
758 endptr ? (endptr - _number) : 0
759 );
760 }
761
762 return (float) n;
763}
764
765float Single::parse(const wchar_t* _number, float _default)
766{
767 __DCL_ASSERT(_number != NULL);
768
769 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
770 return _default;
771 }
772
773 NumericConvertException::Error error = NumericConvertException::NoError;
774 wchar_t* endptr = NULL;
775 float n = wcstof(_number, &endptr);
776 if (+HUGE_VALF == n || -HUGE_VALF == n) {
777 error = NumericConvertException::Overflow;
778 } else if (!(FLT_MIN < n)) {
779 error = NumericConvertException::Underflow;
780 }
781
782 if (NumericConvertException::NoError != error) {
783 return _default;
784 }
785
786 if ((endptr && *endptr != '\0') || errno == EINVAL) {
787 return _default;
788 }
789
790 return (float) n;
791}
792
793ByteString Single::toByteString(float _f, const char* _format)
794{
795 if (!_format)
796 _format = _f < INT64_MIN || INT64_MAX < _f ? "%e" : "%f";
797
798 __DCL_ASSERT(*_format != '\0');
799
800 return ByteString::format(_format, _f);
801}
802
804
805#if 0
806String Double::toString(double _d)
807{
808 String s;
809 char* psz = s.getBuffer(_CVTBUFSIZE); // 17 + '.' + 'E' + '-' + 3 ==> 23
810 _gcvt_s(psz, _CVTBUFSIZE, value, 16);
811 s.releaseBuffer();
812 return s;
813}
814#endif
815
816String Double::toString(double _d, const wchar_t* _format)
817{
818 if (!_format)
819 _format = _d < INT64_MIN || INT64_MAX < _d ? __T("%e") : __T("%f");
820
821 __DCL_ASSERT(*_format != '\0');
822
823 return String::format(_format, _d);
824}
825
826double Double::parse(const wchar_t* _number)
828{
829 __DCL_ASSERT(_number != NULL);
830
831 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
832 throw new NumericConvertException(_number, 0, 0);
833 }
834
835 NumericConvertException::Error error = NumericConvertException::NoError;
836 wchar_t* endptr = NULL;
837 double n = wcstod(_number, &endptr);
838 if (+HUGE_VAL == n || -HUGE_VAL == n) {
839 error = NumericConvertException::Overflow;
840 } else if (!(DBL_MIN < n)) {
841 error = NumericConvertException::Underflow;
842 }
843
844 if (NumericConvertException::NoError != error) {
845 throw new NumericConvertException(
846 error,
847 _number,
848 0
849 );
850 }
851
852 if ((endptr && *endptr != '\0') || errno == EINVAL) {
853 throw new NumericConvertException(
854 _number,
855 0,
856 endptr ? (endptr - _number) : 0
857 );
858 }
859
860 return (double) n;
861}
862
863double Double::parse(const wchar_t* _number, double _default)
864{
865 __DCL_ASSERT(_number != NULL);
866
867 if (*_number == __T('\0') || iswspace((wint_t)*_number)) {
868 return _default;
869 }
870
871 NumericConvertException::Error error = NumericConvertException::NoError;
872 wchar_t* endptr = NULL;
873 double n = wcstod(_number, &endptr);
874 if (+HUGE_VAL == n || -HUGE_VAL == n) {
875 error = NumericConvertException::Overflow;
876 } else if (!(DBL_MIN < n)) {
877 error = NumericConvertException::Underflow;
878 }
879
880 if (NumericConvertException::NoError != error) {
881 return _default;
882 }
883
884 if ((endptr && *endptr != '\0') || errno == EINVAL) {
885 return _default;
886 }
887
888 return (double) n;
889}
890
891ByteString Double::toByteString(double _d, const char* _format)
892{
893 if (!_format)
894 _format = _d < INT64_MIN || INT64_MAX < _d ? "%e" : "%f";
895
896 __DCL_ASSERT(*_format != '\0');
897
898 return ByteString::format(_format, _d);
899}
900
902
903const char* Decimal::FORMAT_STRING = "#,###.####";
904
905static String __GetDecimalString(double d)
906{
907#if 0
908 int nDigit = 16; // double procision
909 int nDecimalPoint = 0;
910 int nSign = 0;
911 char* psz = NULL;
912
913 char szBuf[_CVTBUFSIZE]; // buf[22];
914 __DCL_VERIFY(_ecvt_s(szBuf, sizeof(szBuf), d, nDigit, &nDecimalPoint, &nSign) == 0);
915
916 psz = szBuf;
917
918 char* p = psz + nDigit;
919 while(psz <= --p)
920 {
921 if (*p != '0')
922 break;
923 }
924
925 *(++p) = '\0';
926
927 int nLen = p - psz;
928
929 String str;
930 if (nLen > 0)
931 {
932 if (nSign)
933 str = '-';
934
935 if (nDecimalPoint < 0)
936 {
937 str += "0.";
938 str.append('0', -nDecimalPoint);
939 str += psz;
940 }
941 else
942 {
943 if (nDecimalPoint >= nLen)
944 {
945 str.append(psz);
946 if (nDecimalPoint > nLen)
947 str.append('0', nDecimalPoint - nLen);
948 str.append(".0");
949 }
950 else
951 {
952 str.append(psz, nDecimalPoint);
953 str.append('.');
954 str.append(psz + nDecimalPoint);
955 }
956 }
957 }
958 else
959 str = "0.0";
960
961 return str;
962#endif
963 return String();
964}
965
966const Decimal& Decimal::operator = (float value)
967{
968 m_value = __GetDecimalString(value);
969 return *this;
970}
971
972const Decimal& Decimal::operator = (double value)
973{
974 m_value = __GetDecimalString(value);
975 return *this;
976}
977
978String Decimal::toStringF(const Decimal& value,
979 const char* pszDecimalFormat // = NULL
980 )
981{
982#if 0
983 if (!pszDecimalFormat)
984 pszDecimalFormat = FORMAT_STRING;
985
986 __DCL_ASSERT(*pszDecimalFormat != '\0');
987
988 return formatDecimalString(
989 value.m_value,
990 pszDecimalFormat
991 );
992#endif
993 return String();
994}
995
996/*
997int32_t Decimal::toInt32() const
998{
999 return atoi(m_value);
1000}
1001
1002int64_t Decimal::toInt64() const
1003{
1004#if __DCL_WINDOWS
1005 return _atoi64(m_value);
1006#else
1007 return atoll(m_value);
1008#endif
1009}
1010
1011double Decimal::toDouble() const
1012{
1013 return atof(m_value);
1014}
1015*/
1016
1017__DCL_END_NAMESPACE
wchar_t * __int64tow(int64_t _n, wchar_t *_buf, unsigned _base)
Definition __xtoa.cpp:87
wchar_t * __uint64tow(uint64_t _n, wchar_t *_buf, unsigned _base)
Definition __xtoa.cpp:93
wchar_t * __uint32tow(uint32_t _n, wchar_t *_buf, unsigned _base)
Definition __xtoa.cpp:73
char * __int64toa(int64_t _n, char *_buf, unsigned _base)
Definition __xtoa.cpp:47
char * __int32toa(int32_t _n, char *_buf, unsigned _base)
Definition __xtoa.cpp:27
char * __uint32toa(uint32_t _n, char *_buf, unsigned _base)
Definition __xtoa.cpp:33
char * __uint64toa(uint64_t _n, char *_buf, unsigned _base)
Definition __xtoa.cpp:53
wchar_t * __int32tow(int32_t _n, wchar_t *_buf, unsigned _base)
Definition __xtoa.cpp:67
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
#define INT32_MAX
Definition Config.h:318
wchar_t char_t
Definition Config.h:275
#define INT32_MIN
Definition Config.h:313
#define INT64_MIN
Definition Config.h:314
#define UINT32_MAX
Definition Config.h:323
#define INT64_MAX
Definition Config.h:319
#define __DCL_THROWS1(e)
Definition Config.h:167
#define __DCL_ASSERT_PARAM(expr)
Definition Object.h:384
#define __DCL_VERIFY(expr)
Definition Object.h:373
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define __T(str)
Definition Object.h:44
ByteBuffer * buf
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
String toStringF(const char *pszDecimalFormat=NULL) const
Definition Numeric.inl:275
const Decimal & operator=(const Decimal &value)
Definition Numeric.inl:212
static const char * FORMAT_STRING
Definition Numeric.h:232
String m_value
Definition Numeric.h:199
static double parse(const wchar_t *_number) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:826
String toString() const
Definition Numeric.inl:147
static ByteString toByteString(double _f, const char *_format)
Definition Numeric.cpp:891
static ByteString toByteString(int32_t _n, unsigned _base=10)
Definition Numeric.cpp:365
String toString(unsigned _base=10) const
Definition Numeric.inl:87
static int32_t parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:284
static ByteString toByteString(int64_t _n, unsigned _base=10)
Definition Numeric.cpp:581
String toString(unsigned _base=10) const
Definition Numeric.inl:111
static int64_t parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:513
String toString() const
Definition Numeric.inl:135
static float parse(const wchar_t *_number) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:728
static ByteString toByteString(float _f, const char *_format)
Definition Numeric.cpp:793
static uint32_t parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:401
static ByteString toByteString(uint32_t _u, unsigned _base=10)
Definition Numeric.cpp:472
String toString(unsigned _base=10) const
Definition Numeric.inl:99
static ByteString toByteString(uint64_t _u, unsigned _base=10)
Definition Numeric.cpp:680
static uint64_t parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.cpp:617
String toString(unsigned _base=10) const
Definition Numeric.inl:123