Commit 7dd6a8a1 by Maarten L. Hekkelman

fixes and updated submodules

parent 96725ae8
[submodule "regex"]
path = regex
url = https://github.com/boostorg/regex
[submodule "gxrio"]
path = gxrio
url = https://github.com/mhekkel/gxrio.git
......@@ -94,6 +94,7 @@ endif()
# Start by finding out if std:regex is usable. Note that the current
# implementation in GCC is not acceptable, it crashes on long lines.
# The implementation in libc++ (clang) and MSVC seem to be OK.
check_cxx_source_compiles("
#include <iostream>
#ifndef __GLIBCXX__
......@@ -119,7 +120,7 @@ set(CMAKE_THREAD_PREFER_PTHREAD)
set(THREADS_PREFER_PTHREAD_FLAG)
find_package(Threads)
find_package(gxrio REQUIRED)
add_git_submodule(gxrio EXCLUDE_FROM_ALL)
include(FindFilesystem)
list(APPEND CIFPP_REQUIRED_LIBRARIES ${STDCPPFS_LIBRARY})
......@@ -315,9 +316,9 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcifpp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Unit tests
option(CIFPP_BUILD_TESTS "Build test exectuables" OFF)
option(ENABLE_TESTING "Build test exectuables" OFF)
if(CIFPP_BUILD_TESTS)
if(ENABLE_TESTING)
enable_testing()
find_package(Boost REQUIRED)
......
......@@ -16,5 +16,7 @@ function(add_git_submodule dir)
COMMAND_ERROR_IS_FATAL ANY)
endif()
set(ENABLE_TESTING OFF)
add_subdirectory(${dir} ${ARGV})
endfunction(add_git_submodule)
\ No newline at end of file
Subproject commit 4587355dd281665f7d489360553d2f7564f398e4
......@@ -72,7 +72,10 @@ class item
item(std::string_view name, const T &value, int precision)
: m_name(name)
{
auto r = cif::to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, cif::chars_format::fixed, precision);
using namespace std;
using namespace cif;
auto r = to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, chars_format::fixed, precision);
if (r.ec != std::errc())
throw std::runtime_error("Could not format number");
......@@ -88,7 +91,10 @@ class item
item(const std::string_view name, const T &value)
: m_name(name)
{
auto r = cif::to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, cif::chars_format::general);
using namespace std;
using namespace cif;
auto r = to_chars(m_buffer, m_buffer + sizeof(m_buffer) - 1, value, chars_format::general);
if (r.ec != std::errc())
throw std::runtime_error("Could not format number");
......@@ -303,7 +309,7 @@ struct item_handle
void assign_value(const item &value);
};
// So sad that the gcc implementation of from_chars does not support floats yet...
// So sad that older gcc implementations of from_chars did not support floats yet...
template <typename T>
struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> and not std::is_same_v<T, bool>>>
......@@ -316,12 +322,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
value_type result = {};
std::from_chars_result r;
if constexpr (std::is_floating_point_v<T>)
r = cif::from_chars(txt.data(), txt.data() + txt.size(), result);
else
r = std::from_chars(txt.data(), txt.data() + txt.size(), result);
std::from_chars_result r = selected_charconv<value_type>::from_chars(txt.data(), txt.data() + txt.size(), result);
if (r.ec != std::errc())
{
......@@ -350,12 +351,7 @@ struct item_handle::item_value_as<T, std::enable_if_t<std::is_arithmetic_v<T> an
{
value_type v = {};
std::from_chars_result r;
if constexpr (std::is_floating_point_v<T>)
r = cif::from_chars(txt.data(), txt.data() + txt.size(), v);
else
r = std::from_chars(txt.data(), txt.data() + txt.size(), v);
std::from_chars_result r = selected_charconv<value_type>::from_chars(txt.data(), txt.data() + txt.size(), v);
if (r.ec != std::errc())
{
......
......@@ -33,6 +33,10 @@
#include <tuple>
#include <vector>
#if __has_include(<experimental/type_traits>)
#include <experimental/type_traits>
#endif
namespace cif
{
......@@ -205,13 +209,18 @@ std::vector<std::string> word_wrap(const std::string &text, size_t width);
// --------------------------------------------------------------------
/// std::from_chars for floating point types.
/// These are optional, there's a selected_charconv class below that selects
/// the best option to used based on support by the stl library
/// I.e. that in case of GNU < 12 (or something) the cif implementation will
/// be used, all other cases will use the stl version.
template <typename FloatType, std::enable_if_t<std::is_floating_point_v<FloatType>, int> = 0>
std::from_chars_result from_chars(const char *first, const char *last, FloatType &value)
{
std::from_chars_result result{first, {}};
std::from_chars_result result{ first, {} };
enum State {
enum State
{
IntegerSign,
Integer,
Fraction,
......@@ -412,5 +421,38 @@ std::to_chars_result to_chars(char *first, char *last, FloatType &value, chars_f
return result;
}
template <typename T>
struct my_charconv
{
static std::from_chars_result from_chars(const char *a, const char *b, T &d)
{
return cif::from_chars(a, b, d);
}
static std::to_chars_result to_chars(char *first, char *last, T &value, chars_format fmt)
{
return cif::to_chars(first, last, value, fmt);
}
};
template <typename T>
struct std_charconv
{
static std::from_chars_result from_chars(const char *a, const char *b, T &d)
{
return std::from_chars(a, b, d);
}
static std::to_chars_result to_chars(char *first, char *last, T &value, chars_format fmt)
{
return std::to_chars(first, last, value, fmt);
}
};
template <typename T>
using from_chars_function = decltype(std::from_chars(std::declval<const char *>(), std::declval<const char *>(), std::declval<T &>()));
template <typename T>
using selected_charconv = typename std::conditional_t<std::experimental::is_detected_v<from_chars_function, T>, std_charconv<T>, my_charconv<T>>;
} // namespace cif
\ No newline at end of file
......@@ -99,6 +99,24 @@ type_validator::~type_validator()
delete m_rx;
}
template <typename T>
struct my_from_chars
{
static std::from_chars_result from_chars(const char *a, const char *b, T &d)
{
return cif::from_chars(a, b, d);
}
};
template <typename T>
struct std_from_chars
{
static std::from_chars_result from_chars(const char *a, const char *b, T &d)
{
return std::from_chars(a, b, d);
}
};
int type_validator::compare(std::string_view a, std::string_view b) const
{
int result = 0;
......@@ -115,8 +133,13 @@ int type_validator::compare(std::string_view a, std::string_view b) const
{
double da, db;
auto ra = cif::from_chars(a.begin(), a.end(), da);
auto rb = cif::from_chars(b.begin(), b.end(), db);
using namespace cif;
using namespace std;
std::from_chars_result ra, rb;
ra = selected_charconv<double>::from_chars(a.begin(), a.end(), da);
rb = selected_charconv<double>::from_chars(b.begin(), b.end(), db);
if (ra.ec == std::errc() and rb.ec == std::errc())
{
......@@ -218,12 +241,12 @@ void item_validator::operator()(std::string_view value) const
if (not value.empty() and value != "?" and value != ".")
{
if (m_type != nullptr and not regex_match(value.begin(), value.end(), *m_type->m_rx))
throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{value} + "' does not match type expression for type " + m_type->m_name);
throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{ value } + "' does not match type expression for type " + m_type->m_name);
if (not m_enums.empty())
{
if (m_enums.count(std::string{value}) == 0)
throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{value} + "' is not in the list of allowed values");
if (m_enums.count(std::string{ value }) == 0)
throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{ value } + "' is not in the list of allowed values");
}
}
}
......@@ -245,7 +268,7 @@ void category_validator::addItemValidator(item_validator &&v)
const item_validator *category_validator::get_validator_for_item(std::string_view tag) const
{
const item_validator *result = nullptr;
auto i = m_item_validators.find(item_validator{std::string(tag)});
auto i = m_item_validators.find(item_validator{ std::string(tag) });
if (i != m_item_validators.end())
result = &*i;
else if (VERBOSE > 4)
......@@ -266,7 +289,7 @@ const type_validator *validator::get_validator_for_type(std::string_view typeCod
{
const type_validator *result = nullptr;
auto i = m_type_validators.find(type_validator{std::string(typeCode), DDL_PrimitiveType::Char, {}});
auto i = m_type_validators.find(type_validator{ std::string(typeCode), DDL_PrimitiveType::Char, {} });
if (i != m_type_validators.end())
result = &*i;
else if (VERBOSE > 4)
......@@ -284,7 +307,7 @@ void validator::add_category_validator(category_validator &&v)
const category_validator *validator::get_validator_for_category(std::string_view category) const
{
const category_validator *result = nullptr;
auto i = m_category_validators.find(category_validator{std::string(category)});
auto i = m_category_validators.find(category_validator{ std::string(category) });
if (i != m_category_validators.end())
result = &*i;
else if (VERBOSE > 4)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment