diff --git a/CMakeLists.txt b/CMakeLists.txt index a75ad6dd..fa5f2a81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) -project(fast_float VERSION 8.2.3 LANGUAGES CXX) +project(fast_float VERSION 8.2.3 LANGUAGES CXX C) set(FASTFLOAT_CXX_STANDARD 11 CACHE STRING "the C++ standard to use for fastfloat") set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD}) option(FASTFLOAT_TEST "Enable tests" OFF) @@ -32,6 +32,8 @@ endif() add_library(fast_float INTERFACE) +add_subdirectory(src) + option(FASTFLOAT_BENCHMARKS "Enable benchmarks" OFF) if(FASTFLOAT_BENCHMARKS) diff --git a/include/fast_float/fast_float_strtod.h b/include/fast_float/fast_float_strtod.h new file mode 100644 index 00000000..066a5013 --- /dev/null +++ b/include/fast_float/fast_float_strtod.h @@ -0,0 +1,31 @@ +#ifndef FAST_FLOAT_STRTOD_H__ +#define FAST_FLOAT_STRTOD_H__ + +#if defined(__cplusplus) +extern "C" { +#endif +/** + * @brief Convert a string to a double using the fast_float library. This is + * a C-compatible wrapper around the fast_float parsing functionality, designed + * to mimic the behavior of the standard strtod function. + * + * This function parses the initial portion of the null-terminated string `nptr` + * and converts it to a `double`, similar to the standard `strtod` function but + * utilizing the high-performance fast_float library for parsing. + * + * On successful conversion, the result is returned. If parsing fails, errno is + * set to EINVAL and 0.0 is returned. + * + * @param nptr Pointer to the null-terminated string to be parsed. + * @param endptr If not NULL, a pointer to store the address of the first + * character after the parsed number. If parsing fails, it points + * to the beginning of the string. + * @return The converted double value on success, or 0.0 on failure. + */ +double fast_float_strtod(const char *in, char **out); + +#if defined(__cplusplus) +} +#endif + +#endif /* FAST_FLOAT_STRTOD_H__ */ \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..dcb7ddf8 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(fast_float_strtod STATIC fast_float_strtod.cpp) +target_link_libraries(fast_float_strtod PRIVATE fast_float) + +if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT WIN32) OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "13" AND NOT WIN32)) + target_link_options(fast_float_strtod PRIVATE -nostdlib++) +endif() + +add_library(FastFloat::fast_float_strtod ALIAS fast_float_strtod) +target_include_directories( + fast_float_strtod + INTERFACE + $ + $ +) \ No newline at end of file diff --git a/src/fast_float_strtod.cpp b/src/fast_float_strtod.cpp new file mode 100644 index 00000000..c8dbb65b --- /dev/null +++ b/src/fast_float_strtod.cpp @@ -0,0 +1,24 @@ +#include "fast_float/fast_float_strtod.h" +#include "fast_float/fast_float.h" +#include +#include +#include + +extern "C" double fast_float_strtod(const char *nptr, char **endptr) { + double result = 0.0; + + // Parse the string using fast_float's from_chars function + auto parse_result = fast_float::from_chars(nptr, nptr + strlen(nptr), result); + + // Check if parsing encountered an error + if (parse_result.ec != std::errc{}) { + errno = EINVAL; + } + + // Update endptr if provided + if (endptr != nullptr) { + *endptr = const_cast(parse_result.ptr); + } + + return result; +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a053581c..4d6dfdf7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -108,3 +108,10 @@ endif(FASTFLOAT_EXHAUSTIVE) add_subdirectory(build_tests) add_subdirectory(bloat_analysis) + +add_executable(strtod_test strtod_test.c) +if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT WIN32) OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "13" AND NOT WIN32)) + target_link_options(strtod_test PUBLIC -nostdlib++) +endif() +target_link_libraries(strtod_test PUBLIC fast_float_strtod) +add_test(NAME strtod_test COMMAND strtod_test) diff --git a/tests/strtod_test.c b/tests/strtod_test.c new file mode 100644 index 00000000..e552c691 --- /dev/null +++ b/tests/strtod_test.c @@ -0,0 +1,28 @@ +#include "fast_float/fast_float_strtod.h" +#include +#include +#include + +int main() { + // Test successful conversion + const char *str1 = "3.14159"; + char *end1; + errno = 0; + double d1 = fast_float_strtod(str1, &end1); + printf("Input: %s\n", str1); + printf("Converted: %f\n", d1); + printf("End pointer: %s\n", end1); + printf("errno: %d\n", errno); + + // Test invalid input + const char *str2 = "invalid"; + char *end2; + errno = 0; + double d2 = fast_float_strtod(str2, &end2); + printf("\nInput: %s\n", str2); + printf("Converted: %f\n", d2); + printf("End pointer: %s\n", end2); + printf("errno: %d\n", errno); + + return 0; +} \ No newline at end of file