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