#ifndef PK_PK_STN_H #define PK_PK_STN_H #include #include #include #include #include enum PK_STN_RES { PK_STN_RES_SUCCESS, PK_STN_RES_OVERFLOW, PK_STN_RES_UNDERFLOW, PK_STN_RES_INCONVERTIBLE }; enum PK_STN_RES pk_stn_int64_t(int64_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_uint64_t(uint64_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_int32_t(int32_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_uint32_t(uint32_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_int16_t(int16_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_uint16_t(uint16_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_int8_t(int8_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_uint8_t(uint8_t *i, char const *s, char **pEnd, int base); enum PK_STN_RES pk_stn_float(float *f, char const *s, char **pEnd); enum PK_STN_RES pk_stn_double(double *d, char const *s, char **pEnd); #if defined(__cplusplus) template enum PK_STN_RES pk_stn(T *n, char const *s, char **pEnd, int base = 0) { if constexpr(std::is_same::value) { return pk_stn_int64_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_uint64_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_int32_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_uint32_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_int16_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_uint16_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_int8_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_uint8_t(n, s, pEnd, base); } if constexpr(std::is_same::value) { static_assert(sizeof(bool) == sizeof(uint8_t)); static_assert(alignof(bool) == alignof(uint8_t)); return pk_stn_uint8_t((uint8_t*)n, s, pEnd, base); } if constexpr(std::is_same::value) { return pk_stn_float(n, s, pEnd); } if constexpr(std::is_same::value) { return pk_stn_double(n, s, pEnd); } return (PK_STN_RES)-1; } #endif /* defined(__cplusplus) */ #endif /* PK_PK_STN_H */ #ifdef PK_IMPL_STN enum PK_STN_RES pk_stn_int64_t(int64_t *i, char const *s, char **pEnd, int base) { char *end; long long l; errno = 0; l = strtoll(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == LLONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_uint64_t(uint64_t *i, char const *s, char **pEnd, int base) { char *end; unsigned long long l; errno = 0; l = strtoull(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == ULLONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_int32_t(int32_t *i, char const *s, char **pEnd, int base) { char *end; long l; errno = 0; l = strtol(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == LONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_uint32_t(uint32_t *i, char const *s, char **pEnd, int base) { char *end; unsigned long l; errno = 0; l = strtoul(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == ULONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_int16_t(int16_t *i, char const *s, char **pEnd, int base) { char *end; long l; errno = 0; l = strtol(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == LONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_uint16_t(uint16_t *i, char const *s, char **pEnd, int base) { char *end; unsigned long l; errno = 0; l = strtoul(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == ULONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_int8_t(int8_t *i, char const *s, char **pEnd, int base) { char *end; long l; errno = 0; l = strtol(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == LONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_uint8_t(uint8_t *i, char const *s, char **pEnd, int base) { char *end; unsigned long l; errno = 0; l = strtoul(s, &end, base); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE) { if (l == ULONG_MAX) return PK_STN_RES_OVERFLOW; return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *i = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_float(float *f, char const *s, char **pEnd) { char *end; float l; errno = 0; l = strtof(s, &end); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE && l == HUGE_VALF) { return PK_STN_RES_OVERFLOW; } if (errno == ERANGE && l == -HUGE_VALF) { return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *f = l; return PK_STN_RES_SUCCESS; } enum PK_STN_RES pk_stn_double(double *d, char const *s, char **pEnd) { char *end; double l; errno = 0; l = strtod(s, &end); if (pEnd != nullptr) *pEnd = end; if (errno == ERANGE && l == HUGE_VAL) { return PK_STN_RES_OVERFLOW; } if (errno == ERANGE && l == -HUGE_VAL) { return PK_STN_RES_UNDERFLOW; } if (s == end) { return PK_STN_RES_INCONVERTIBLE; } *d = l; return PK_STN_RES_SUCCESS; } #endif /* PK_IMPL_STN */