Aer/engine/lib/utils.c
belliash 2d99881240
All checks were successful
The build was successful.
Get rid of manual optimisation technique.
This optimisation technique results in non insignificant speed boost on some old x86 architectures. Novadays, we should rely on compiler optimisation.
2018-08-21 06:27:07 +02:00

513 lines
10 KiB
C

#include "ph7int.h"
PH7_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) {
const char *zCur, *zEnd;
#ifdef UNTRUST
if(SX_EMPTY_STR(zSrc)) {
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
/* Jump leading white spaces */
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
zCur = zSrc;
if(pReal) {
*pReal = FALSE;
}
for(;;) {
if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) {
break;
}
zSrc++;
};
if(zSrc < zEnd && zSrc > zCur) {
int c = zSrc[0];
if(c == '.') {
zSrc++;
if(pReal) {
*pReal = TRUE;
}
if(pzTail) {
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
zSrc++;
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
}
}
} else if(c == 'e' || c == 'E') {
zSrc++;
if(pReal) {
*pReal = TRUE;
}
if(pzTail) {
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
}
}
}
if(pzTail) {
/* Point to the non numeric part */
*pzTail = zSrc;
}
return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */;
}
#define SXINT32_MIN_STR "2147483648"
#define SXINT32_MAX_STR "2147483647"
#define SXINT64_MIN_STR "9223372036854775808"
#define SXINT64_MAX_STR "9223372036854775807"
PH7_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
int isNeg = FALSE;
const char *zEnd;
sxi32 nVal = 0;
sxi16 i;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
i = 10;
if((sxu32)(zEnd - zSrc) >= 10) {
/* Handle overflow */
i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9;
}
for(;;) {
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
break;
}
nVal = nVal * 10 + (zSrc[0] - '0') ;
--i ;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = (char *)zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi32 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
int isNeg = FALSE;
const char *zEnd;
sxi64 nVal;
sxi16 i;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
i = 19;
if((sxu32)(zEnd - zSrc) >= 19) {
i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ;
}
nVal = 0;
for(;;) {
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
break;
}
nVal = nVal * 10 + (zSrc[0] - '0') ;
--i ;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = (char *)zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyHexToint(sxi32 c) {
switch(c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'A':
case 'a':
return 10;
case 'B':
case 'b':
return 11;
case 'C':
case 'c':
return 12;
case 'D':
case 'd':
return 13;
case 'E':
case 'e':
return 14;
case 'F':
case 'f':
return 15;
}
return -1;
}
PH7_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (*zSrc == '-' || *zSrc == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X')) {
/* Bypass hex prefix */
zSrc += sizeof(char) * 2;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
}
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
int c;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || !SyisDigit(zSrc[0])) {
break;
}
if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) {
break;
}
nVal = nVal * 8 + c;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
int c;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B')) {
/* Bypass binary prefix */
zSrc += sizeof(char) * 2;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) {
break;
}
c = zSrc[0] - '0';
nVal = (nVal << 1) + c;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
#define SXDBL_DIG 15
#define SXDBL_MAX_EXP 308
#define SXDBL_MIN_EXP_PLUS 307
static const sxreal aTab[] = {
10,
1.0e2,
1.0e4,
1.0e8,
1.0e16,
1.0e32,
1.0e64,
1.0e128,
1.0e256
};
sxu8 neg = FALSE;
sxreal Val = 0.0;
const char *zEnd;
sxi32 Lim, exp;
sxreal *p = 0;
#ifdef UNTRUST
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxreal *)pOutVal = 0.0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
neg = zSrc[0] == '-' ? TRUE : FALSE ;
zSrc++;
}
Lim = SXDBL_DIG ;
for(;;) {
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
break ;
}
Val = Val * 10.0 + (zSrc[0] - '0') ;
zSrc++ ;
--Lim;
}
if(zSrc < zEnd && (zSrc[0] == '.' || zSrc[0] == ',')) {
sxreal dec = 1.0;
zSrc++;
for(;;) {
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
break ;
}
Val = Val * 10.0 + (zSrc[0] - '0') ;
dec *= 10.0;
zSrc++ ;
--Lim;
}
Val /= dec;
}
if(neg == TRUE && Val != 0.0) {
Val = -Val ;
}
if(Lim <= 0) {
/* jump overflow digit */
while(zSrc < zEnd) {
if(zSrc[0] == 'e' || zSrc[0] == 'E') {
break;
}
zSrc++;
}
}
neg = FALSE;
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
zSrc++;
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
neg = zSrc[0] == '-' ? TRUE : FALSE ;
zSrc++;
}
exp = 0;
while(zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP) {
exp = exp * 10 + (zSrc[0] - '0');
zSrc++;
}
if(neg) {
if(exp > SXDBL_MIN_EXP_PLUS) {
exp = SXDBL_MIN_EXP_PLUS ;
}
} else if(exp > SXDBL_MAX_EXP) {
exp = SXDBL_MAX_EXP;
}
for(p = (sxreal *)aTab ; exp ; exp >>= 1, p++) {
if(exp & 01) {
if(neg) {
Val /= *p ;
} else {
Val *= *p;
}
}
}
}
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
*(sxreal *)pOutVal = Val;
}
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyRealPath(const char *zPath, char **fPath) {
#ifdef __WINNT__
if(GetFullPathName(zPath, PATH_MAX, fPath, NULL) != 0) {
#else
if(realpath(zPath, fPath) == NULL) {
#endif
return PH7_IO_ERR;
}
return PH7_OK;
}