Make strtoll and strtod malloc-free
Some checks failed
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=OFF (push) Successful in 19s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=OFF (push) Successful in 18s
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=ON (push) Failing after 22s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=ON (push) Failing after 20s
CMake / ubuntu-latest - shared=OFF, pthread=ON, posix=ON (push) Failing after 19s
CMake / ubuntu-latest - shared=ON, pthread=ON, posix=ON (push) Failing after 20s
Some checks failed
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=OFF (push) Successful in 19s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=OFF (push) Successful in 18s
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=ON (push) Failing after 22s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=ON (push) Failing after 20s
CMake / ubuntu-latest - shared=OFF, pthread=ON, posix=ON (push) Failing after 19s
CMake / ubuntu-latest - shared=ON, pthread=ON, posix=ON (push) Failing after 20s
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
@@ -41,6 +41,10 @@ foreach(TARGET ${PROJECT_NAME}_shared ${PROJECT_NAME}_static)
|
||||
else()
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(${TARGET} PRIVATE m)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Install libraries
|
||||
|
2
build.sh
2
build.sh
@@ -4,7 +4,7 @@ set -e
|
||||
|
||||
BUILD_DIR="BUILD"
|
||||
INSTALL_DIR="$(pwd)/install"
|
||||
CFLAGS="-std=c99 -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token"
|
||||
CFLAGS="-std=c99 -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token -lm"
|
||||
BUILD_SHARED=1
|
||||
PTHREAD_SUPPORT=1
|
||||
POSIX_SUPPORT=1
|
||||
|
193
src/dcfg.c
193
src/dcfg.c
@@ -44,6 +44,7 @@
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -65,70 +66,154 @@ void pthread_mutex_unlock(pthread_mutex_t *);
|
||||
|
||||
int64_t dcfg_strtoll(const char *s, char **end, int base)
|
||||
{
|
||||
size_t n = strlen(s);
|
||||
char *clean = malloc(n + 1);
|
||||
if (!clean) {
|
||||
errno = ENOMEM;
|
||||
char const *p = s;
|
||||
while (isspace((unsigned char)*p))
|
||||
p++;
|
||||
bool neg = false;
|
||||
if (*p == '+' || *p == '-') {
|
||||
neg = (*p == '-');
|
||||
p++;
|
||||
}
|
||||
|
||||
if (base == 0) {
|
||||
if (*p == '0') {
|
||||
if (p[1] == 'x' || p[1] == 'X') {
|
||||
base = 16;
|
||||
p += 2;
|
||||
} else {
|
||||
base = 8;
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
base = 10;
|
||||
}
|
||||
} else if (base == 16 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
|
||||
p += 2;
|
||||
}
|
||||
|
||||
int64_t val = 0;
|
||||
char const *q = p, *last = p;
|
||||
while (*q) {
|
||||
char c = *q;
|
||||
if (c == '_' || c == '\'') {
|
||||
q++;
|
||||
continue;
|
||||
}
|
||||
int d;
|
||||
if (c >= '0' && c <= '9')
|
||||
d = c - '0';
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
d = c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
d = c - 'A' + 10;
|
||||
else
|
||||
break;
|
||||
if (d >= base)
|
||||
break;
|
||||
val = val * base + d;
|
||||
last = q + 1;
|
||||
q++;
|
||||
}
|
||||
if (last == p) {
|
||||
if (end)
|
||||
*end = (char *)s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t w = 0;
|
||||
for (size_t r = 0; r < n && s[r]; ++r)
|
||||
if (s[r] != '_' && s[r] != '\'')
|
||||
clean[w++] = s[r];
|
||||
clean[w] = '\0';
|
||||
|
||||
char *tmp_end;
|
||||
int64_t v = strtoll(clean, &tmp_end, base);
|
||||
|
||||
if (end) {
|
||||
size_t consumed = (size_t)(tmp_end - clean);
|
||||
size_t i = 0, c = 0;
|
||||
while (i < n && c < consumed) {
|
||||
if (s[i] != '_' && s[i] != '\'')
|
||||
++c;
|
||||
++i;
|
||||
}
|
||||
*end = (char *)s + i;
|
||||
}
|
||||
free(clean);
|
||||
return v;
|
||||
if (end)
|
||||
*end = (char *)last;
|
||||
return neg ? -val : val;
|
||||
}
|
||||
|
||||
double dcfg_strtod(char const *s, char **end)
|
||||
{
|
||||
size_t n = strlen(s);
|
||||
char *clean = malloc(n + 1);
|
||||
if (!clean) {
|
||||
errno = ENOMEM;
|
||||
char const *p = s;
|
||||
while (isspace((unsigned char)*p))
|
||||
p++;
|
||||
bool neg = false;
|
||||
if (*p == '+' || *p == '-') {
|
||||
neg = (*p == '-');
|
||||
p++;
|
||||
}
|
||||
|
||||
char const *fd = strchr(p, '.');
|
||||
char const *fc = strchr(p, ',');
|
||||
char dec = '.';
|
||||
if (!fd && fc)
|
||||
dec = ',';
|
||||
else if (fd && fc && fc < fd)
|
||||
dec = ',';
|
||||
|
||||
int64_t ip = 0;
|
||||
double frac = 0.0, div = 1.0;
|
||||
bool any = false, in_frac = false;
|
||||
bool in_exp = false, exp_any = false;
|
||||
int exp_sign = 1, exp_val = 0;
|
||||
char const *last = p;
|
||||
size_t i = p - s;
|
||||
|
||||
for (;; ++i) {
|
||||
char c = s[i];
|
||||
if (!c)
|
||||
break;
|
||||
if (!in_exp) {
|
||||
if (c == '_' || c == '\'')
|
||||
continue;
|
||||
if (!in_frac && c == dec) {
|
||||
in_frac = true;
|
||||
last = s + i + 1;
|
||||
continue;
|
||||
}
|
||||
if (!in_frac && (c == '.' || c == ','))
|
||||
continue;
|
||||
if (c >= '0' && c <= '9') {
|
||||
any = true;
|
||||
int d = c - '0';
|
||||
if (!in_frac)
|
||||
ip = ip * 10 + d;
|
||||
else {
|
||||
frac = frac * 10 + d;
|
||||
div *= 10.0;
|
||||
}
|
||||
last = s + i + 1;
|
||||
continue;
|
||||
}
|
||||
if ((c == 'e' || c == 'E') && any) {
|
||||
in_exp = true;
|
||||
last = s + i + 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if ((c == '+' || c == '-') && !exp_any) {
|
||||
if (c == '-')
|
||||
exp_sign = -1;
|
||||
last = s + i + 1;
|
||||
continue;
|
||||
}
|
||||
if (c >= '0' && c <= '9') {
|
||||
exp_any = true;
|
||||
exp_val = exp_val * 10 + (c - '0');
|
||||
last = s + i + 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any) {
|
||||
if (end)
|
||||
*end = (char *)s;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
size_t w = 0;
|
||||
for (size_t r = 0; r < n && s[r]; ++r)
|
||||
if (s[r] != '_' && s[r] != '\'')
|
||||
clean[w++] = s[r];
|
||||
clean[w] = '\0';
|
||||
|
||||
char *tmp_end;
|
||||
double v = strtod(clean, &tmp_end);
|
||||
|
||||
if (end) {
|
||||
size_t consumed = (size_t)(tmp_end - clean);
|
||||
size_t i = 0, c = 0;
|
||||
while (i < n && c < consumed) {
|
||||
if (s[i] != '_' && s[i] != '\'')
|
||||
++c;
|
||||
++i;
|
||||
}
|
||||
*end = (char *)s + i;
|
||||
}
|
||||
free(clean);
|
||||
return v;
|
||||
double result = (double)ip + frac / div;
|
||||
if (in_exp && exp_any)
|
||||
result *= pow(10.0, exp_sign * exp_val);
|
||||
if (neg)
|
||||
result = -result;
|
||||
if (end)
|
||||
*end = (char *)last;
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef dcfg_Value Value;
|
||||
@@ -526,7 +611,7 @@ static void skip_ws_and_comments(Lexer *lx)
|
||||
while (lx->ch != -1) {
|
||||
if (lx->ch == '*' && lx->next == '/') {
|
||||
lex_advance(lx);
|
||||
lex_advance(lx); /* / */
|
||||
lex_advance(lx);
|
||||
break;
|
||||
}
|
||||
lex_advance(lx);
|
||||
@@ -575,7 +660,7 @@ static Token lex_number(Lexer *lx)
|
||||
|
||||
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
|
||||
lex_advance(lx);
|
||||
if (lx->ch == '.') {
|
||||
if (lx->ch == '.' || lx->ch == ',') {
|
||||
real = true;
|
||||
lex_advance(lx);
|
||||
while (isdigit_cp(lx->ch) || lx->ch == '_' || lx->ch == '\'')
|
||||
@@ -1449,7 +1534,7 @@ dcfg_ValueType dcfg_Value_type_ex(dcfg_Value *value, bool evaluate)
|
||||
{
|
||||
if (!value)
|
||||
return dcfg_ValueType_Nil;
|
||||
(void)evaluate; /* eval ignored for now */
|
||||
(void)evaluate;
|
||||
return value->type;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user