Skip to content

Commit

Permalink
Move NumberUtils to an ABI stable, statically linked library
Browse files Browse the repository at this point in the history
Signed-off-by: L. E. Segovia <13498015+amyspark@users.noreply.github.com>
  • Loading branch information
amyspark committed Nov 16, 2021
1 parent e7c3aac commit fcb15ab
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 179 deletions.
2 changes: 1 addition & 1 deletion src/OpenColorIO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ target_link_libraries(OpenColorIO
${OCIO_HALF_LIB}
pystring::pystring
sampleicc::sampleicc
utils::from_chars
from_chars_helpers
utils::strings
yaml-cpp
)
Expand Down
19 changes: 14 additions & 5 deletions src/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,22 @@ set_property(TARGET ${OCIO_HALF_LIB} APPEND PROPERTY

# from_chars shim (via fast_float or strtod_l)

add_library(utils::from_chars INTERFACE IMPORTED GLOBAL)
set(SOURCES
NumberUtils.cpp
)

set_target_properties(utils::from_chars PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/.."
add_library(from_chars_helpers STATIC ${SOURCES})

target_include_directories(from_chars_helpers
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/.."
)

if (OCIO_USE_FAST_FLOAT)
target_compile_definitions(utils::from_chars INTERFACE USE_FAST_FLOAT)
target_link_libraries(utils::from_chars INTERFACE fast_float::fast_float)
target_compile_definitions(from_chars_helpers PUBLIC USE_FAST_FLOAT)
target_link_libraries(from_chars_helpers PUBLIC fast_float::fast_float)
endif()

set_target_properties(from_chars_helpers PROPERTIES
COMPILE_FLAGS "${PLATFORM_COMPILE_FLAGS}"
)
174 changes: 174 additions & 0 deletions src/utils/NumberUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenColorIO Project.

#include "NumberUtils.h"

#ifdef USE_FAST_FLOAT
#include <fast_float/fast_float.h>
#endif

#include <cstdlib>
#include <locale>

namespace NumberUtils
{

struct Locale
{
#ifdef _WIN32
Locale() : local(_create_locale(LC_ALL, "C"))
{
}
~Locale()
{
_free_locale(local);
}
_locale_t local;
#else
Locale() : local(newlocale(LC_ALL_MASK, "C", NULL))
{
}
~Locale()
{
freelocale(local);
}
locale_t local;
#endif
};

static const Locale loc;

#ifdef USE_FAST_FLOAT
from_chars_result from_chars(const char *first, const char *last, float &value) noexcept
{
// By design that's not supported by from_chars() so handle it here.
if (first && *first == '+')
++first;

const auto ret = fast_float::from_chars(first, last, value);
return {ret.ptr, ret.ec};
}

from_chars_result from_chars(const char *first, const char *last, double &value) noexcept
{
// By design that's not supported by from_chars() so handle it here.
if (first && *first == '+')
++first;

const auto ret = fast_float::from_chars(first, last, value);
return {ret.ptr, ret.ec};
}

#else
from_chars_result from_chars(const char *first, const char *last, double &value) noexcept
{
errno = 0;
if (!first || !last || first == last)
{
return {first, std::errc::invalid_argument};
}

char *endptr = nullptr;

double
#ifdef _WIN32
tempval = _strtod_l(first, &endptr, loc.local);
#else
tempval = ::strtod_l(first, &endptr, loc.local);
#endif

if (errno != 0)
{
return {first + (endptr - first), std::errc::result_out_of_range};
}
else if (endptr == first)
{
return {first, std::errc::invalid_argument};
}
else if (endptr <= last)
{
value = tempval;
return {first + (endptr - first), {}};
}
else
{
return {first, std::errc::argument_out_of_domain};
}
}

from_chars_result from_chars(const char *first, const char *last, float &value) noexcept
{
errno = 0;
if (!first || !last || first == last)
{
return {first, std::errc::invalid_argument};
}

char *endptr = nullptr;

float
#ifdef _WIN32
tempval = _strtof_l(first, &endptr, loc.local);
#elif __APPLE__
// On OSX, strtod_l is for some reason drastically faster than strtof_l.
tempval = static_cast<float>(::strtod_l(first, &endptr, loc.local));
#else
tempval = ::strtof_l(first, &endptr, loc.local);
#endif

if (errno != 0)
{
return {first + (endptr - first), std::errc::result_out_of_range};
}
else if (endptr == first)
{
return {first, std::errc::invalid_argument};
}
else if (endptr <= last)
{
value = tempval;
return {first + (endptr - first), {}};
}
else
{
return {first, std::errc::argument_out_of_domain};
}
}
#endif // USE_FAST_FLOAT

from_chars_result from_chars(const char *first, const char *last, long int &value) noexcept
{
errno = 0;
if (!first || !last || first == last)
{
return {first, std::errc::invalid_argument};
}

char *endptr = nullptr;

long int
#ifdef _WIN32
tempval = _strtol_l(first, &endptr, 0, loc.local);
#else
tempval = ::strtol_l(first, &endptr, 0, loc.local);
#endif

if (errno != 0)
{
return {first + (endptr - first), std::errc::result_out_of_range};
}
else if (endptr == first)
{
return {first, std::errc::invalid_argument};
}
else if (endptr <= last)
{
value = tempval;
return {first + (endptr - first), {}};
}
else
{
return {first, std::errc::argument_out_of_domain};
}
}
} // namespace NumberUtils
Loading

0 comments on commit fcb15ab

Please sign in to comment.