📄 sfstrtof.h
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* All rights reserved. *//* * AT&T Labs Research * Glenn Fowler & Phong Vo * * common header and implementation for * * strtof strtod strtold sfdscan * strntof strntod strntold * * define these macros to instantiate an implementation: * * S2F_function the function name * S2F_static <0:export =0:extern >0:static * S2F_type 0:float 1:double 2:long.double * S2F_size 1 for interface with size_t second arg * S2F_scan 1 for alternate interface with these arguments: * void* handle * int (*getchar)(void* handle, int flag) * exactly one extra (*getchar)() is done, i.e., * the caller must do the pushback * flag==0 get next char * flag==1 no number seen * return 0 on error or EOF */#include "sfhdr.h"#include "FEATURE/float"/* * the default is _sfdscan for standalone sfio compatibility */#if !defined(S2F_function)#define S2F_function _sfdscan#define S2F_static 1#define S2F_type 2#define S2F_scan 1#ifndef elementsof#define elementsof(a) (sizeof(a)/sizeof(a[0]))#endif#endif#if S2F_type == 2 && _ast_fltmax_double#undef S2F_type#define S2F_type 1#endif#if S2F_type == 0#define S2F_number float#define S2F_ldexp ldexp#define S2F_pow10 _Sffpow10#define S2F_huge _Sffhuge#define S2F_min (FLT_MIN)#define S2F_max (FLT_MAX)#define S2F_exp_10_min (FLT_MIN_10_EXP)#define S2F_exp_10_max (FLT_MAX_10_EXP)#define S2F_exp_2_min (FLT_MIN_EXP)#define S2F_exp_2_max (FLT_MAX_EXP)#endif#if S2F_type == 1#define S2F_number double#define S2F_ldexp ldexp#define S2F_pow10 _Sfdpow10#define S2F_huge _Sfdhuge#define S2F_min (DBL_MIN)#define S2F_max (DBL_MAX)#define S2F_exp_10_min (DBL_MIN_10_EXP)#define S2F_exp_10_max (DBL_MAX_10_EXP)#define S2F_exp_2_min (DBL_MIN_EXP)#define S2F_exp_2_max (DBL_MAX_EXP)#endif#if S2F_type == 2#define S2F_number long double#define S2F_ldexp ldexpl#define S2F_pow10 _Sflpow10#define S2F_huge _Sflhuge#define S2F_min (LDBL_MIN)#define S2F_max (LDBL_MAX)#define S2F_exp_10_min (LDBL_MIN_10_EXP)#define S2F_exp_10_max (LDBL_MAX_10_EXP)#define S2F_exp_2_min (LDBL_MIN_EXP)#define S2F_exp_2_max (LDBL_MAX_EXP)#endif#if -S2F_exp_10_min < S2F_exp_10_max#define S2F_exp_10_abs (-S2F_exp_10_min)#else#define S2F_exp_10_abs S2F_exp_10_max#endif#define S2F_batch _ast_flt_unsigned_max_t#if S2F_scantypedef int (*S2F_get_f)_ARG_((void*, int));#define ERR(e)#define GET(p) (*get)(p,0)#define NON(p) (*get)(p,1)#define PUT(p)#define REV(p,t,b)#define SET(p,t,b)#else#define ERR(e) (errno=(e))#define NON(p)#if S2F_size#define GET(p) (((p)<(z))?(*p++):(back=0))#define PUT(p) (end?(*end=(char*)p-back):(char*)0)#define REV(p,t,b) (p=t,back=b)#define SET(p,t,b) (t=p,b=back)#else#define GET(p) (*p++)#define PUT(p) (end?(*end=(char*)p-1):(char*)0)#define REV(p,t,b) (p=t)#define SET(p,t,b) (t=p)#endif#endiftypedef struct S2F_part_s{ S2F_batch batch; int digits;} S2F_part_t;#if !defined(ERANGE)#define ERANGE EINVAL#endif#if S2F_static > 0static#else#if S2F_static < 0 || !defined(S2F_static)#if defined(__EXPORT__)#define extern __EXPORT__#endifextern#undef extern#endif#endifS2F_number#if S2F_scan#if __STD_CS2F_function(void* s, S2F_get_f get)#elseS2F_function(s, get) void* s; S2F_get_f get;#endif#else#if S2F_size#if __STD_CS2F_function(const char* str, size_t size, char** end)#elseS2F_function(str, size, end) char* str; size_t size; char** end;#endif#else#if __STD_CS2F_function(const char* str, char** end)#elseS2F_function(str, end) char* str; char** end;#endif#endif#endif{#if !S2F_scan register unsigned char* s = (unsigned char*)str;#if S2F_size register unsigned char* z = s + size; int back = 1; int b;#endif unsigned char* t;#endif register S2F_batch n; register int c; register int digits; register int m; register unsigned char* cv; int negative; int enegative; int fraction; int decimal = 0; int thousand = 0; int part = 0; S2F_number v; S2F_number p; S2F_part_t parts[16]; /* * radix char and thousands separator are locale specific */ SFSETLOCALE(&decimal, &thousand); SFCVINIT(); /* * skip initial blanks */ do c = GET(s); while (isspace(c)); SET(s, t, b); /* * get the sign */ if ((negative = (c == '-')) || c == '+') c = GET(s); /* * drop leading 0's */ digits = 0; fraction = -1; if (c == '0') { c = GET(s); if (c == 'x' || c == 'X') { /* * hex floating point -- easy */ cv = _Sfcv36; v = 0; for (;;) { c = GET(s); if ((part = cv[c]) < 16) { digits++; v *= 16; v += part; } else if (c == decimal) { decimal = -1; fraction = digits; } else break; } m = 0; if (c == 'p' || c == 'P') { c = GET(s); if ((enegative = c == '-') || c == '+') c = GET(s); while (c >= '0' && c <= '9') { m = (m << 3) + (m << 1) + (c - '0'); c = GET(s); } if (enegative) m = -m; } /* * consume the optional suffix */ switch (c) { case 'f': case 'F': case 'l': case 'L': c = GET(s); break; } PUT(s); if (v == 0) return v; if (fraction >= 0) m -= 4 * (digits - fraction); if (m < S2F_exp_2_min) { if ((m -= S2F_exp_2_min) < S2F_exp_2_min) { ERR(ERANGE); return 0; } v = S2F_ldexp(v, S2F_exp_2_min); } else if (m > S2F_exp_2_max) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; } v = S2F_ldexp(v, m); goto check; } while (c == '0') c = GET(s); } else if (c == decimal) { decimal = -1; fraction = 0; for (;;) { c = GET(s); if (c != '0') break; digits++; } } else if (c == 'i' || c == 'I') { if ((c = GET(s)) != 'n' && c != 'N' || (c = GET(s)) != 'f' && c != 'F') { REV(s, t, b); PUT(s); return 0; } c = GET(s); SET(s, t, b); if (((c) == 'i' || c == 'I') && ((c = GET(s)) == 'n' || c == 'N') && ((c = GET(s)) == 'i' || c == 'I') && ((c = GET(s)) == 't' || c == 'T') && ((c = GET(s)) == 'y' || c == 'Y')) { c = GET(s); SET(s, t, b); } REV(s, t, b); PUT(s); return negative ? -S2F_huge : S2F_huge; } else if (c == 'n' || c == 'N') { if ((c = GET(s)) != 'a' && c != 'A' || (c = GET(s)) != 'n' && c != 'N') { REV(s, t, b); PUT(s); return 0; } do c = GET(s); while (c && !isspace(c)); PUT(s); return negative ? -S2F_huge : S2F_huge; } else if (c < '1' || c > '9') { REV(s, t, b); PUT(s); NON(s); return 0; } /* * consume the integral and fractional parts */ n = 0; m = 0; for (;;) { if (c >= '0' && c <= '9') { digits++; n = (n << 3) + (n << 1) + (c - '0'); if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts)) { parts[part].batch = n; n = 0; parts[part].digits = digits; part++; } } else if (m && (digits - m) != 3) break; else if (c == decimal) { decimal = -1; m = 0; fraction = digits; } else if (c != thousand) break; else if (!(m = digits)) break; c = GET(s); } /* * don't forget the last part */ if (n && part < elementsof(parts)) { parts[part].batch = n; parts[part].digits = digits; part++; } /* * consume the exponent */ if (fraction >= 0) digits = fraction; if (c == 'e' || c == 'E') { c = GET(s); if ((enegative = (c == '-')) || c == '+') c = GET(s); n = 0; while (c >= '0' && c <= '9') { n = (n << 3) + (n << 1) + (c - '0'); c = GET(s); } if (enegative) digits -= n; else digits += n; } /* * consume the optional suffix */ switch (c) { case 'f': case 'F': case 'l': case 'L': c = GET(s); break; } PUT(s); /* * adjust for at most one multiply per part * and at most one divide overall */ if (!part) return 0; else if ((m = parts[part-1].digits - digits) > 0) digits += m; else m = 0; /* * combine the parts */ v = 0; while (part--) { p = parts[part].batch; c = digits - parts[part].digits; if (c > S2F_exp_10_max) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; } if (c > 0) {#if _ast_mpy_overflow_fpe if ((S2F_max / p) < S2F_pow10[c]) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; }#endif p *= S2F_pow10[c]; } v += p; } if (m) { while (m > S2F_exp_10_max) { m -= S2F_exp_10_max; v /= S2F_pow10[S2F_exp_10_max]; }#if _ast_div_underflow_fpe if ((S2F_min * p) > S2F_pow10[c]) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; }#endif v /= S2F_pow10[m]; } /* * check the range */ check: if (v < S2F_min) { ERR(ERANGE); v = 0; } else if (v > S2F_max) { ERR(ERANGE); v = S2F_huge; } /* * done */ return negative ? -v : v;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -