------------------------------------------------------------------ */ decFloatFromString -- conversion from numeric string */ / result is the decFloat format number which gets the result of */ the conversion */ string is the character string which should contain a valid */ number (which may be a special value), \0-terminated */
| 774 | /* If bad syntax is detected, the result will be a quiet NaN. */ |
| 775 | /* ------------------------------------------------------------------ */ |
| 776 | decFloat * decFloatFromString(decFloat *result, const char *string, |
| 777 | decContext *set) { |
| 778 | Int digits; // count of digits in coefficient |
| 779 | const char *dotchar=NULL; // where dot was found [NULL if none] |
| 780 | const char *cfirst=string; // -> first character of decimal part |
| 781 | const char *c; // work |
| 782 | uByte *ub; // .. |
| 783 | uInt uiwork; // for macros |
| 784 | bcdnum num; // collects data for finishing |
| 785 | uInt error=DEC_Conversion_syntax; // assume the worst |
| 786 | uByte buffer[ROUNDUP(DECSTRING+11, 8)]; // room for most coefficents, |
| 787 | // some common rounding, +3, & pad |
| 788 | #if DECTRACE |
| 789 | // printf("FromString %s ...\n", string); |
| 790 | #endif |
| 791 | |
| 792 | for(;;) { // once-only 'loop' |
| 793 | num.sign=0; // assume non-negative |
| 794 | num.msd=buffer; // MSD is here always |
| 795 | |
| 796 | // detect and validate the coefficient, including any leading, |
| 797 | // trailing, or embedded '.' |
| 798 | // [could test four-at-a-time here (saving 10% for decQuads), |
| 799 | // but that risks storage violation because the position of the |
| 800 | // terminator is unknown] |
| 801 | for (c=string;; c++) { // -> input character |
| 802 | if (((unsigned)(*c-'0'))<=9) continue; // '0' through '9' is good |
| 803 | if (*c=='\0') break; // most common non-digit |
| 804 | if (*c=='.') { |
| 805 | if (dotchar!=NULL) break; // not first '.' |
| 806 | dotchar=c; // record offset into decimal part |
| 807 | continue;} |
| 808 | if (c==string) { // first in string... |
| 809 | if (*c=='-') { // valid - sign |
| 810 | cfirst++; |
| 811 | num.sign=DECFLOAT_Sign; |
| 812 | continue;} |
| 813 | if (*c=='+') { // valid + sign |
| 814 | cfirst++; |
| 815 | continue;} |
| 816 | } |
| 817 | // *c is not a digit, terminator, or a valid +, -, or '.' |
| 818 | break; |
| 819 | } // c loop |
| 820 | |
| 821 | digits=(uInt)(c-cfirst); // digits (+1 if a dot) |
| 822 | |
| 823 | if (digits>0) { // had digits and/or dot |
| 824 | const char *clast=c-1; // note last coefficient char position |
| 825 | Int exp=0; // exponent accumulator |
| 826 | if (*c!='\0') { // something follows the coefficient |
| 827 | uInt edig; // unsigned work |
| 828 | // had some digits and more to come; expect E[+|-]nnn now |
| 829 | const char *firstexp; // exponent first non-zero |
| 830 | if (*c!='E' && *c!='e') break; |
| 831 | c++; // to (optional) sign |
| 832 | if (*c=='-' || *c=='+') c++; // step over sign (c=clast+2) |
| 833 | if (*c=='\0') break; // no digits! (e.g., '1.2E') |
no test coverage detected