/*-
* Copyright ( c ) 1990 , 1993
* The Regents of the University of California . All rights reserved .
*
* This code is derived from software contributed to Berkeley by
* Chris Torek .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1 . Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2 . Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3 . Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*/
#include <ctype.h>
#include <stdlib.h>
#include "local.h"
#define BUF 513 /* Maximum length of numeric string. */
size_t parsefloat(FILE *fp, char *buf, char *end) {
char *commit, *p;
int infnanpos = 0 ;
enum {
S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
unsigned char c;
int gotmantdig = 0 , ishex = 0 ;
/*
* We set commit = p whenever the string we have read so far
* constitutes a valid representation of a floating point
* number by itself . At some point , the parse will complete
* or fail , and we will ungetc ( ) back to the last commit point .
* To ensure that the file offset gets updated properly , it is
* always necessary to read at least one character that doesn ' t
* match ; thus , we can ' t short - circuit " infinity " or " nan ( . . . ) " .
*/
commit = buf - 1 ;
for (p = buf; p < end; ) {
c = *fp->_p;
reswitch:
switch (state) {
case S_START:
state = S_GOTSIGN;
if (c == '-' || c == '+' )
break ;
else
goto reswitch;
case S_GOTSIGN:
switch (c) {
case '0' :
state = S_MAYBEHEX;
commit = p;
break ;
case 'I' :
case 'i' :
state = S_INF;
break ;
case 'N' :
case 'n' :
state = S_NAN;
break ;
default :
state = S_DIGITS;
goto reswitch;
}
break ;
case S_INF:
if (infnanpos > 6 ||
(c != "nfinity" [infnanpos] &&
c != "NFINITY" [infnanpos]))
goto parsedone;
if (infnanpos == 1 || infnanpos == 6 )
commit = p; /* inf or infinity */
infnanpos++;
break ;
case S_NAN:
switch (infnanpos) {
case -1 : /* XXX kludge to deal with nan(...) */
goto parsedone;
case 0 :
if (c != 'A' && c != 'a' )
goto parsedone;
break ;
case 1 :
if (c != 'N' && c != 'n' )
goto parsedone;
else
commit = p;
break ;
case 2 :
if (c != '(' )
goto parsedone;
break ;
default :
if (c == ')' ) {
commit = p;
infnanpos = -2 ;
} else if (!isalnum(c) && c != '_' )
goto parsedone;
break ;
}
infnanpos++;
break ;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x' ) {
ishex = 1 ;
break ;
} else { /* we saw a '0', but no 'x' */
gotmantdig = 1 ;
goto reswitch;
}
case S_DIGITS:
if ((ishex && isxdigit(c)) || isdigit(c))
gotmantdig = 1 ;
else {
state = S_FRAC;
if (c != '.' )
goto reswitch;
}
if (gotmantdig)
commit = p;
break ;
case S_FRAC:
if (((c == 'E' || c == 'e' ) && !ishex) ||
((c == 'P' || c == 'p' ) && ishex)) {
if (!gotmantdig)
goto parsedone;
else
state = S_EXP;
} else if ((ishex && isxdigit(c)) || isdigit(c)) {
commit = p;
gotmantdig = 1 ;
} else
goto parsedone;
break ;
case S_EXP:
state = S_EXPDIGITS;
if (c == '-' || c == '+' )
break ;
else
goto reswitch;
case S_EXPDIGITS:
if (isdigit(c))
commit = p;
else
goto parsedone;
break ;
default :
abort();
}
*p++ = c;
if (--fp->_r > 0 )
fp->_p++;
else if (__srefill(fp))
break ; /* EOF */
}
parsedone:
while (commit < --p)
(void )ungetc(*(unsigned char *)p, fp);
*++commit = '\0' ;
return commit - buf;
}
size_t wparsefloat(FILE *fp, wchar_t *buf, wchar_t *end) {
wchar_t *commit, *p;
int infnanpos = 0 ;
enum {
S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
wint_t c;
int gotmantdig = 0 , ishex = 0 ;
/*
* We set commit = p whenever the string we have read so far
* constitutes a valid representation of a floating point
* number by itself . At some point , the parse will complete
* or fail , and we will ungetc ( ) back to the last commit point .
* To ensure that the file offset gets updated properly , it is
* always necessary to read at least one character that doesn ' t
* match ; thus , we can ' t short - circuit " infinity " or " nan ( . . . ) " .
*/
commit = buf - 1 ;
c = WEOF;
for (p = buf; p < end; ) {
if ((c = __fgetwc_unlock(fp)) == WEOF)
break ;
reswitch:
switch (state) {
case S_START:
state = S_GOTSIGN;
if (c == '-' || c == '+' )
break ;
else
goto reswitch;
case S_GOTSIGN:
switch (c) {
case '0' :
state = S_MAYBEHEX;
commit = p;
break ;
case 'I' :
case 'i' :
state = S_INF;
break ;
case 'N' :
case 'n' :
state = S_NAN;
break ;
default :
state = S_DIGITS;
goto reswitch;
}
break ;
case S_INF:
if (infnanpos > 6 ||
(c != (wint_t)"nfinity" [infnanpos] &&
c != (wint_t)"NFINITY" [infnanpos]))
goto parsedone;
if (infnanpos == 1 || infnanpos == 6 )
commit = p; /* inf or infinity */
infnanpos++;
break ;
case S_NAN:
switch (infnanpos) {
case -1 : /* XXX kludge to deal with nan(...) */
goto parsedone;
case 0 :
if (c != 'A' && c != 'a' )
goto parsedone;
break ;
case 1 :
if (c != 'N' && c != 'n' )
goto parsedone;
else
commit = p;
break ;
case 2 :
if (c != '(' )
goto parsedone;
break ;
default :
if (c == ')' ) {
commit = p;
infnanpos = -2 ;
} else if (!iswalnum(c) && c != '_' )
goto parsedone;
break ;
}
infnanpos++;
break ;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x' ) {
ishex = 1 ;
break ;
} else { /* we saw a '0', but no 'x' */
gotmantdig = 1 ;
goto reswitch;
}
case S_DIGITS:
if ((ishex && iswxdigit(c)) || iswdigit(c))
gotmantdig = 1 ;
else {
state = S_FRAC;
if (c != L'.' )
goto reswitch;
}
if (gotmantdig)
commit = p;
break ;
case S_FRAC:
if (((c == 'E' || c == 'e' ) && !ishex) ||
((c == 'P' || c == 'p' ) && ishex)) {
if (!gotmantdig)
goto parsedone;
else
state = S_EXP;
} else if ((ishex && iswxdigit(c)) || iswdigit(c)) {
commit = p;
gotmantdig = 1 ;
} else
goto parsedone;
break ;
case S_EXP:
state = S_EXPDIGITS;
if (c == '-' || c == '+' )
break ;
else
goto reswitch;
case S_EXPDIGITS:
if (iswdigit(c))
commit = p;
else
goto parsedone;
break ;
default :
abort();
}
*p++ = c;
c = WEOF;
}
parsedone:
if (c != WEOF)
ungetwc(c, fp);
while (commit < --p)
ungetwc(*p, fp);
*++commit = '\0' ;
return (int )(commit - buf);
}
Messung V0.5 in Prozent C=89 H=91 G=89
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-28)
¤
*© Formatika GbR, Deutschland