summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile18
-rw-r--r--config.mk1
-rw-r--r--pk.h.in10
-rw-r--r--pkstn.h246
-rw-r--r--test/pkstn.c104
-rw-r--r--test/pkstn.cpp104
6 files changed, 483 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index b36c2dd..3e6ceef 100644
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,7 @@ SRC = \
pkstr.h \
pkev.h \
pkarr.h \
+ pkstn.h \
test/pkmacros.c \
test/pkmacros.cpp \
test/pkmem-types.c \
@@ -24,6 +25,8 @@ SRC = \
test/pkev.cpp \
test/pkarr.c\
test/pkarr.cpp \
+ test/pkstn.c\
+ test/pkstn.cpp \
OBJ = $(SRC:%.c=.o)
PPOBJ = $(SRC:%.cpp=.so)
@@ -37,12 +40,14 @@ all: options .WAIT clean .WAIT \
pkstr \
pkev \
pkarr \
+ pkstn \
test-pkmem-types test-pkmem-types-cpp \
test-pkmem test-pkmem-cpp \
test-pkmacros test-pkmacros-cpp \
test-pkstr test-pkstr-cpp \
test-pkev test-pkev-cpp \
test-pkarr test-pkarr-cpp \
+ test-pkstn test-pkstn-cpp \
options:
@echo at-suite build options:
@@ -78,12 +83,15 @@ pkev: pkev.gch pkev.gchpp
pkarr: pkmem pkarr.gch pkarr.gchpp
+pkstn: pkstn.gch pkstn.gchpp
+
build: pkmacros
build: pkmem-types
build: pkmem
build: pkstr
build: pkev
build: pkarr
+build: pkstn
echo "#ifndef PK_SINGLE_HEADER_FILE_H\n#define PK_SINGLE_HEADER_FILE_H" > pk.h
cat pk.h.in \
pkmacros.h \
@@ -92,6 +100,7 @@ build: pkarr
pkstr.h \
pkev.h \
pkarr.h \
+ pkstn.h \
>> pk.h
echo "#endif /* PK_SINGLE_HEADER_FILE_H */" >> pk.h
sed -i -r \
@@ -138,6 +147,12 @@ test-pkarr: test/pkarr.o
test-pkarr-cpp: test/pkarr.so
$(CXX) -g -O0 -std=c++23 $(CPPFLAGS) -o test/$@ $^ $(LDFLAGS)
+test-pkstn: test/pkstn.o
+ $(CC) -g -O0 -std=c2x $(CFLAGS) -o test/$@ $^ $(LDFLAGS)
+
+test-pkstn-cpp: test/pkstn.so
+ $(CXX) -g -O0 -std=c++23 $(CPPFLAGS) -o test/$@ $^ $(LDFLAGS)
+
test: pkmacros pkmem-types pkmem pkstr pkev pkarr
test: test-pkmacros test-pkmacros-cpp
test: test-pkmem-types test-pkmem-types-cpp
@@ -145,6 +160,7 @@ test: test-pkmem test-pkmem-cpp
test: test-pkstr test-pkstr-cpp
test: test-pkev test-pkev-cpp
test: test-pkarr test-pkarr-cpp
+test: test-pkstn test-pkstn-cpp
test:
@echo ""
./test/test-pkmacros ; echo Result: $$? "\n"
@@ -159,6 +175,8 @@ test:
./test/test-pkev-cpp ; echo Result: $$? "\n"
./test/test-pkarr ; echo Result: $$? "\n"
./test/test-pkarr-cpp ; echo Result: $$? "\n"
+ ./test/test-pkstn ; echo Result: $$? "\n"
+ ./test/test-pkstn-cpp ; echo Result: $$? "\n"
clean:
rm -f *.plist *.gch *.gchpp *.o *.so test/*.o test/*.so test/test-*
diff --git a/config.mk b/config.mk
index b337c90..ca23f51 100644
--- a/config.mk
+++ b/config.mk
@@ -21,6 +21,7 @@ SHARED_FLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L \
-DPK_IMPL_STR \
-DPK_IMPL_EV \
-DPK_IMPL_ARR \
+ -DPK_IMPL_STN \
CPPFLAGS += -Wall $(INCS) $(SHARED_FLAGS)
CFLAGS += -Wall $(INCS) $(SHARED_FLAGS)
diff --git a/pk.h.in b/pk.h.in
index 0ca132b..ef61ecd 100644
--- a/pk.h.in
+++ b/pk.h.in
@@ -28,6 +28,7 @@
* # define PK_IMPL_STR
* # define PK_IMPL_EV
* # define PK_IMPL_ARR
+* # define PK_IMPL_STN
* #include "pk.h"
* ```
*
@@ -163,6 +164,12 @@
* d[0] = ...;
* ```
*
+********************************************************************************
+* pkstn.h: def PK_IMPL_STN before including pk.h to enable ad-hoc.
+*
+* Provides a thorough interface for interacting with the `stoi` family of
+* procedures.
+*
*******************************************************************************/
#define PK_VERSION "@@PK_VERSION@@"
@@ -183,4 +190,7 @@
# ifndef PK_IMPL_ARR
# define PK_IMPL_ARR
# endif
+# ifndef PK_IMPL_STN
+# define PK_IMPL_STN
+# endif
#endif
diff --git a/pkstn.h b/pkstn.h
new file mode 100644
index 0000000..fd9233d
--- /dev/null
+++ b/pkstn.h
@@ -0,0 +1,246 @@
+#ifndef PK_PK_STN_H
+#define PK_PK_STN_H
+
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+enum PK_STN_ERR {
+ PK_STN_ERR_SUCCESS,
+ PK_STN_ERR_OVERFLOW,
+ PK_STN_ERR_UNDERFLOW,
+ PK_STN_ERR_INCONVERTIBLE
+};
+
+enum PK_STN_ERR pk_stn_int64_t(int64_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_uint64_t(uint64_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_int32_t(int32_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_uint32_t(uint32_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_int16_t(int16_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_uint16_t(uint16_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_int8_t(int8_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_uint8_t(uint8_t *i, char const *s, int base);
+enum PK_STN_ERR pk_stn_float(float *f, char const *s);
+enum PK_STN_ERR pk_stn_double(double *d, char const *s);
+enum PK_STN_ERR pk_stn_float_e(float *f, char const *s, char **pEnd);
+enum PK_STN_ERR pk_stn_double_e(double *d, char const *s, char **pEnd);
+
+#endif /* PK_PK_STN_H */
+
+#ifdef PK_IMPL_STN
+
+enum PK_STN_ERR
+pk_stn_int64_t(int64_t *i, char const *s, int base)
+{
+ char *end;
+ long long l;
+ errno = 0;
+ l = strtoll(s, &end, base);
+ if (errno == ERANGE && l == LLONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LLONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_uint64_t(uint64_t *i, char const *s, int base)
+{
+ char *end;
+ unsigned long long l;
+ errno = 0;
+ l = strtoull(s, &end, base);
+ if (errno == ERANGE && l == LLONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LLONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_int32_t(int32_t *i, char const *s, int base)
+{
+ char *end;
+ long l;
+ errno = 0;
+ l = strtol(s, &end, base);
+ if (errno == ERANGE && l == LONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_uint32_t(uint32_t *i, char const *s, int base)
+{
+ char *end;
+ unsigned long l;
+ errno = 0;
+ l = strtoul(s, &end, base);
+ if (errno == ERANGE && l == LONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_int16_t(int16_t *i, char const *s, int base)
+{
+ char *end;
+ long l;
+ errno = 0;
+ l = strtol(s, &end, base);
+ if (errno == ERANGE && l == LONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_uint16_t(uint16_t *i, char const *s, int base)
+{
+ char *end;
+ unsigned long l;
+ errno = 0;
+ l = strtoul(s, &end, base);
+ if (errno == ERANGE && l == LONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_int8_t(int8_t *i, char const *s, int base)
+{
+ char *end;
+ long l;
+ errno = 0;
+ l = strtol(s, &end, base);
+ if (errno == ERANGE && l == LONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_uint8_t(uint8_t *i, char const *s, int base)
+{
+ char *end;
+ unsigned long l;
+ errno = 0;
+ l = strtoul(s, &end, base);
+ if (errno == ERANGE && l == LONG_MAX) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == LONG_MIN) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || *end != '\0') {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *i = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_float(float *f, char const *s)
+{
+ char *end;
+ return pk_stn_float_e(f, s, &end);
+}
+
+enum PK_STN_ERR
+pk_stn_double(double *d, char const *s)
+{
+ char *end;
+ return pk_stn_double_e(d, s, &end);
+}
+
+enum PK_STN_ERR
+pk_stn_float_e(float *f, char const *s, char **pEnd)
+{
+ float l;
+ errno = 0;
+ l = strtof(s, pEnd);
+ if (errno == ERANGE && l == HUGE_VALF) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == -HUGE_VALF) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || &s == (const char **)pEnd) {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *f = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+enum PK_STN_ERR
+pk_stn_double_e(double *d, char const *s, char **pEnd)
+{
+ double l;
+ errno = 0;
+ l = strtod(s, pEnd);
+ if (errno == ERANGE && l == HUGE_VAL) {
+ return PK_STN_ERR_OVERFLOW;
+ }
+ if (errno == ERANGE && l == -HUGE_VAL) {
+ return PK_STN_ERR_UNDERFLOW;
+ }
+ if (*s == '\0' || &s == (const char **)pEnd) {
+ return PK_STN_ERR_INCONVERTIBLE;
+ }
+ *d = l;
+ return PK_STN_ERR_SUCCESS;
+}
+
+#endif /* PK_IMPL_STN */
diff --git a/test/pkstn.c b/test/pkstn.c
new file mode 100644
index 0000000..97ec8a9
--- /dev/null
+++ b/test/pkstn.c
@@ -0,0 +1,104 @@
+
+#include "../pkstn.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ (void)argc;
+ (void)argv;
+ enum PK_STN_ERR res = {0};
+
+ // stn_int64_t
+ {
+ int64_t i = {0};
+ res = pk_stn_int64_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int64_t res: %ld\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint64_t
+ {
+ uint64_t i = {0};
+ res = pk_stn_uint64_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint64_t res: %lu\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_int32_t
+ {
+ int32_t i = {0};
+ res = pk_stn_int32_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int32_t res: %d\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint32_t
+ {
+ uint32_t i = {0};
+ res = pk_stn_uint32_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint32_t res: %u\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_int16_t
+ {
+ int16_t i = {0};
+ res = pk_stn_int16_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int16_t res: %d\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint16_t
+ {
+ uint16_t i = {0};
+ res = pk_stn_uint16_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint16_t res: %u\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_int8_t
+ {
+ int8_t i = {0};
+ res = pk_stn_int8_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int8_t res: %d\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint8_t
+ {
+ uint8_t i = {0};
+ res = pk_stn_uint8_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint8_t res: %u\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_float
+ {
+ float f = {0};
+ res = pk_stn_float(&f, "-1");
+ fprintf(stdout, "pkstn: stn_float res: %f\n", f);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != f) exit(1);
+ }
+
+ // stn_double
+ {
+ double f = {0};
+ res = pk_stn_double(&f, "-1");
+ fprintf(stdout, "pkstn: stn_double res: %f\n", f);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != f) exit(1);
+ }
+
+ return 0;
+}
diff --git a/test/pkstn.cpp b/test/pkstn.cpp
new file mode 100644
index 0000000..261fb56
--- /dev/null
+++ b/test/pkstn.cpp
@@ -0,0 +1,104 @@
+
+#include "../pkstn.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ (void)argc;
+ (void)argv;
+ enum PK_STN_ERR res = {};
+
+ // stn_int64_t
+ {
+ int64_t i = {0};
+ res = pk_stn_int64_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int64_t res: %ld\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint64_t
+ {
+ uint64_t i = {0};
+ res = pk_stn_uint64_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint64_t res: %lu\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_int32_t
+ {
+ int32_t i = {0};
+ res = pk_stn_int32_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int32_t res: %d\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint32_t
+ {
+ uint32_t i = {0};
+ res = pk_stn_uint32_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint32_t res: %u\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_int16_t
+ {
+ int16_t i = {0};
+ res = pk_stn_int16_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int16_t res: %d\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint16_t
+ {
+ uint16_t i = {0};
+ res = pk_stn_uint16_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint16_t res: %u\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_int8_t
+ {
+ int8_t i = {0};
+ res = pk_stn_int8_t(&i, "-1", 0);
+ fprintf(stdout, "pkstn: stn_int8_t res: %d\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != i) exit(1);
+ }
+
+ // stn_uint8_t
+ {
+ uint8_t i = {0};
+ res = pk_stn_uint8_t(&i, "1", 0);
+ fprintf(stdout, "pkstn: stn_uint8_t res: %u\n", i);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (1 != i) exit(1);
+ }
+
+ // stn_float
+ {
+ float f = {0};
+ res = pk_stn_float(&f, "-1");
+ fprintf(stdout, "pkstn: stn_float res: %f\n", f);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != f) exit(1);
+ }
+
+ // stn_double
+ {
+ double f = {0};
+ res = pk_stn_double(&f, "-1");
+ fprintf(stdout, "pkstn: stn_double res: %f\n", f);
+ if (res != PK_STN_ERR_SUCCESS) exit(1);
+ if (-1 != f) exit(1);
+ }
+
+ return 0;
+}