Skip to content

Commit

Permalink
Adjust type support macro naming
Browse files Browse the repository at this point in the history
Invert the condition: SCN_TYPE_FOO -> SCN_DISABLE_TYPE_FOO
Also, define defaults in config.h (all enabled), and
don't add definitions in CMake if type not disabled.

As a drive-by fix, also improve some error messages in reader_float
  • Loading branch information
eliaskosunen committed Nov 2, 2023
1 parent 2f2e848 commit 11d5be1
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 87 deletions.
46 changes: 23 additions & 23 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,29 +36,29 @@ option(SCN_BUILD_BUILDTIME "Generate build time test target" OFF)

option(SCN_USE_BUNDLED_FAST_FLOAT "Use lemire/fast_float bundled with scnlib" ON)

option(SCN_TYPE_SCHAR "Enable schar" ON)
option(SCN_TYPE_SHORT "Enable short" ON)
option(SCN_TYPE_INT "Enable int" ON)
option(SCN_TYPE_LONG "Enable long" ON)
option(SCN_TYPE_LONG_LONG "Enable long long" ON)
option(SCN_TYPE_UCHAR "Enable uchar" ON)
option(SCN_TYPE_USHORT "Enable ushort" ON)
option(SCN_TYPE_UINT "Enable uint" ON)
option(SCN_TYPE_ULONG "Enable ulong" ON)
option(SCN_TYPE_ULONG_LONG "Enable ulong long" ON)
option(SCN_TYPE_BOOL "Enable bool" ON)
option(SCN_TYPE_CHAR "Enable char" ON)
option(SCN_TYPE_CODE_POINT "Enable code_point" ON)
option(SCN_TYPE_FLOAT "Enable float" ON)
option(SCN_TYPE_DOUBLE "Enable double" ON)
option(SCN_TYPE_LONG_DOUBLE "Enable long double" ON)
option(SCN_TYPE_BUFFER "Enable span" ON)
option(SCN_TYPE_STRING "Enable std::string" ON)
option(SCN_TYPE_STRING_VIEW "Enable string_view" ON)
option(SCN_TYPE_CUSTOM "Enable user types" ON)

option(SCN_USE_FROM_CHARS "Fall back to std::from_chars" ON)
option(SCN_USE_CSTD "Fall back to strtod" ON)
option(SCN_DISABLE_TYPE_SCHAR "Disable scanning of signed char" OFF)
option(SCN_DISABLE_TYPE_SHORT "Disable scanning of short" OFF)
option(SCN_DISABLE_TYPE_INT "Disable scanning of int" OFF)
option(SCN_DISABLE_TYPE_LONG "Disable scanning of long" OFF)
option(SCN_DISABLE_TYPE_LONG_LONG "Disable scanning of long long" OFF)
option(SCN_DISABLE_TYPE_UCHAR "Disable scanning of unsigned char" OFF)
option(SCN_DISABLE_TYPE_USHORT "Disable scanning of unsigned short" OFF)
option(SCN_DISABLE_TYPE_UINT "Disable scanning of unsigned int" OFF)
option(SCN_DISABLE_TYPE_ULONG "Disable scanning of unsigned long" OFF)
option(SCN_DISABLE_TYPE_ULONG_LONG "Disable scanning of unsigned long long" OFF)
option(SCN_DISABLE_TYPE_BOOL "Disable scanning of bool" OFF)
option(SCN_DISABLE_TYPE_CHAR "Disable scanning of char" OFF)
option(SCN_DISABLE_TYPE_CODE_POINT "Disable scanning of code_point" OFF)
option(SCN_DISABLE_TYPE_FLOAT "Disable scanning of float" OFF)
option(SCN_DISABLE_TYPE_DOUBLE "Disable scanning of double" OFF)
option(SCN_DISABLE_TYPE_LONG_DOUBLE "Disable scanning of long double" OFF)
option(SCN_DISABLE_TYPE_BUFFER "Disable scanning of span" OFF)
option(SCN_DISABLE_TYPE_STRING "Disable scanning of std::string" OFF)
option(SCN_DISABLE_TYPE_STRING_VIEW "Disable scanning of string_view" OFF)
option(SCN_DISABLE_TYPE_CUSTOM "Disable scanning of user types" OFF)

option(SCN_DISABLE_FROM_CHARS "Disallow falling back on std::from_chars when scanning floating-point values" OFF)
option(SCN_DISABLE_STRTOD "Disallow falling back on std::strtod when scanning floating-point values" OFF)

file(READ include/scn/detail/config.h config_h)
if (NOT config_h MATCHES "SCN_VERSION SCN_COMPILER\\(([0-9]+), ([0-9]+), ([0-9]+)\\)")
Expand Down
37 changes: 36 additions & 1 deletion cmake/flags.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
function(get_config_flags flags)
set(${flags}
$<$<BOOL:${SCN_DISABLE_TYPE_SCHAR}>: -DSCN_DISABLE_TYPE_SCHAR=1>
$<$<BOOL:${SCN_DISABLE_TYPE_SHORT}>: -DSCN_DISABLE_TYPE_SHORT=1>
$<$<BOOL:${SCN_DISABLE_TYPE_INT}>: -DSCN_DISABLE_TYPE_INT=1>
$<$<BOOL:${SCN_DISABLE_TYPE_LONG}>: -DSCN_DISABLE_TYPE_LONG=1>
$<$<BOOL:${SCN_DISABLE_TYPE_LONG_LONG}>: -DSCN_DISABLE_TYPE_LONG_LONG=1>
$<$<BOOL:${SCN_DISABLE_TYPE_UCHAR}>: -DSCN_DISABLE_TYPE_UCHAR=1>
$<$<BOOL:${SCN_DISABLE_TYPE_USHORT}>: -DSCN_DISABLE_TYPE_USHORT=1>
$<$<BOOL:${SCN_DISABLE_TYPE_UINT}>: -DSCN_DISABLE_TYPE_UINT=1>
$<$<BOOL:${SCN_DISABLE_TYPE_ULONG}>: -DSCN_DISABLE_TYPE_ULONG=1>
$<$<BOOL:${SCN_DISABLE_TYPE_ULONG_LONG}>: -DSCN_DISABLE_TYPE_ULONG_LONG=1>
$<$<BOOL:${SCN_DISABLE_TYPE_BOOL}>: -DSCN_DISABLE_TYPE_BOOL=1>
$<$<BOOL:${SCN_DISABLE_TYPE_CHAR}>: -DSCN_DISABLE_TYPE_CHAR=1>
$<$<BOOL:${SCN_DISABLE_TYPE_CODE_POINT}>: -DSCN_DISABLE_TYPE_CODE_POINT=1>
$<$<BOOL:${SCN_DISABLE_TYPE_FLOAT}>: -DSCN_DISABLE_TYPE_FLOAT=1>
$<$<BOOL:${SCN_DISABLE_TYPE_DOUBLE}>: -DSCN_DISABLE_TYPE_DOUBLE=1>
$<$<BOOL:${SCN_DISABLE_TYPE_LONG_DOUBLE}>:-DSCN_DISABLE_TYPE_LONG_DOUBLE=1>
$<$<BOOL:${SCN_DISABLE_TYPE_BUFFER}>: -DSCN_DISABLE_TYPE_BUFFER=1>
$<$<BOOL:${SCN_DISABLE_TYPE_STRING}>: -DSCN_DISABLE_TYPE_STRING=1>
$<$<BOOL:${SCN_DISABLE_TYPE_STRING_VIEW}>:-DSCN_DISABLE_TYPE_STRING_VIEW=1>
$<$<BOOL:${SCN_DISABLE_TYPE_CUSTOM}>: -DSCN_DISABLE_TYPE_CUSTOM=1>

$<$<BOOL:${SCN_DISABLE_FROM_CHARS}>: -DSCN_DISABLE_FROM_CHARS=1>
$<$<BOOL:${SCN_DISABLE_STRTOD}>: -DSCN_DISABLE_STRTOD=1>
PARENT_SCOPE
)
endfunction()

function(get_gcc_warning_flags flags)
set(${flags}
-ftemplate-backtrace-limit=0
Expand Down Expand Up @@ -178,6 +207,9 @@ function(set_interface_flags target)
target_link_libraries(${target} INTERFACE --coverage)
endif ()
endif ()
get_config_flags(config_flags)
target_compile_options(${target} INTERFACE ${config_flags})

disable_msvc_secure_flags(${target} INTERFACE)
set_bigobj_flags(${target} INTERFACE)
target_compile_features(${target} INTERFACE cxx_std_11)
Expand All @@ -202,7 +234,7 @@ function(set_private_flags target)
if (NOT SCN_USE_EXCEPTIONS)
get_disable_exceptions_flags(noexceptions_flags)
target_compile_options(${target} PRIVATE ${noexceptions_flags})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND SCN_CXX_FRONTEND STREQUAL "MSVC")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND SCN_CXX_FRONTEND STREQUAL "MSVC")
# clang-cl requires explicitly enabling exceptions
target_compile_options(${target} PUBLIC /EHsc)
endif ()
Expand All @@ -220,6 +252,9 @@ function(set_private_flags target)
endif ()
endif ()

get_config_flags(config_flags)
target_compile_options(${target} PUBLIC ${config_flags})

disable_msvc_secure_flags(${target} PRIVATE)
set_bigobj_flags(${target} PRIVATE)

Expand Down
166 changes: 115 additions & 51 deletions include/scn/detail/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,50 +113,112 @@ namespace scn {
void (*scan)();
};

template<typename T, typename CharT>
struct type_enabled { static constexpr bool value = SCN_TYPE_CUSTOM; };

template<typename CharT> struct type_enabled<signed char, CharT> { static constexpr bool value = SCN_TYPE_SCHAR; };
template<typename CharT> struct type_enabled<short, CharT> { static constexpr bool value = SCN_TYPE_SHORT; };
template<typename CharT> struct type_enabled<int, CharT> { static constexpr bool value = SCN_TYPE_INT; };
template<typename CharT> struct type_enabled<long, CharT> { static constexpr bool value = SCN_TYPE_LONG; };
template<typename CharT> struct type_enabled<long long, CharT> { static constexpr bool value = SCN_TYPE_LONG_LONG; };
template<typename CharT> struct type_enabled<unsigned char, CharT> { static constexpr bool value = SCN_TYPE_UCHAR; };
template<typename CharT> struct type_enabled<unsigned short, CharT> { static constexpr bool value = SCN_TYPE_USHORT; };
template<typename CharT> struct type_enabled<unsigned int, CharT> { static constexpr bool value = SCN_TYPE_UINT; };
template<typename CharT> struct type_enabled<unsigned long, CharT> { static constexpr bool value = SCN_TYPE_ULONG; };
template<typename CharT> struct type_enabled<unsigned long long, CharT> { static constexpr bool value = SCN_TYPE_ULONG_LONG; };
template<typename CharT> struct type_enabled<bool, CharT> { static constexpr bool value = SCN_TYPE_BOOL; };
template<typename CharT> struct type_enabled<CharT, CharT> { static constexpr bool value = SCN_TYPE_CHAR; };
template<typename CharT> struct type_enabled<code_point, CharT> { static constexpr bool value = SCN_TYPE_CODE_POINT; };
template<typename CharT> struct type_enabled<float, CharT> { static constexpr bool value = SCN_TYPE_FLOAT; };
template<typename CharT> struct type_enabled<double, CharT> { static constexpr bool value = SCN_TYPE_DOUBLE; };
template<typename CharT> struct type_enabled<long double, CharT> { static constexpr bool value = SCN_TYPE_LONG_DOUBLE; };
template<typename CharT> struct type_enabled<span<CharT>, CharT> { static constexpr bool value = SCN_TYPE_BUFFER; };
template<typename CharT> struct type_enabled<std::basic_string<CharT>, CharT> { static constexpr bool value = SCN_TYPE_STRING; };
template<typename CharT> struct type_enabled<basic_string_view<CharT>, CharT> { static constexpr bool value = SCN_TYPE_STRING_VIEW; };
template <typename T, typename CharT>
struct is_type_disabled {
static constexpr bool value = SCN_DISABLE_TYPE_CUSTOM;
};

template <typename CharT>
struct is_type_disabled<signed char, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_SCHAR;
};
template <typename CharT>
struct is_type_disabled<short, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_SHORT;
};
template <typename CharT>
struct is_type_disabled<int, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_INT;
};
template <typename CharT>
struct is_type_disabled<long, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_LONG;
};
template <typename CharT>
struct is_type_disabled<long long, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_LONG_LONG;
};
template <typename CharT>
struct is_type_disabled<unsigned char, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_UCHAR;
};
template <typename CharT>
struct is_type_disabled<unsigned short, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_USHORT;
};
template <typename CharT>
struct is_type_disabled<unsigned int, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_UINT;
};
template <typename CharT>
struct is_type_disabled<unsigned long, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_ULONG;
};
template <typename CharT>
struct is_type_disabled<unsigned long long, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_ULONG_LONG;
};
template <typename CharT>
struct is_type_disabled<bool, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_BOOL;
};
template <typename CharT>
struct is_type_disabled<CharT, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_CHAR;
};
template <typename CharT>
struct is_type_disabled<code_point, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_CODE_POINT;
};
template <typename CharT>
struct is_type_disabled<float, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_FLOAT;
};
template <typename CharT>
struct is_type_disabled<double, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_DOUBLE;
};
template <typename CharT>
struct is_type_disabled<long double, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_LONG_DOUBLE;
};
template <typename CharT>
struct is_type_disabled<span<CharT>, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_BUFFER;
};
template <typename CharT>
struct is_type_disabled<std::basic_string<CharT>, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_STRING;
};
template <typename CharT>
struct is_type_disabled<basic_string_view<CharT>, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_STRING_VIEW;
};
#if SCN_HAS_STRING_VIEW
template<typename CharT> struct type_enabled<std::basic_string_view<CharT>, CharT> { static constexpr bool value = SCN_TYPE_STRING_VIEW; };
template <typename CharT>
struct is_type_disabled<std::basic_string_view<CharT>, CharT> {
static constexpr bool value = SCN_DISABLE_TYPE_STRING_VIEW;
};
#endif

template <typename Context, typename ParseCtx, typename T>
error scan_custom_arg(void* arg, Context& ctx, ParseCtx& pctx) noexcept
{
static_assert(type_enabled<T, typename ParseCtx::char_type>::value, "arg type is disabled");
static_assert(
!is_type_disabled<T, typename ParseCtx::char_type>::value,
"Scanning of custom types is disabled by "
"SCN_DISABLE_TYPE_CUSTOM");

return visitor_boilerplate<scanner<T>>(*static_cast<T*>(arg), ctx,
pctx);
}

struct monostate {
};
struct monostate {};

template <typename Ctx>
struct ctx_tag {
};
struct ctx_tag {};
template <typename ParseCtx>
struct parse_ctx_tag {
};
struct parse_ctx_tag {};

class value {
public:
Expand Down Expand Up @@ -365,85 +427,85 @@ namespace scn {
case detail::none_type:
break;

#if SCN_TYPE_SCHAR
#if !SCN_DISABLE_TYPE_SCHAR
case detail::schar_type:
return vis(arg.m_value.template get_as<signed char>());
#endif
#if SCN_TYPE_SHORT
#if !SCN_DISABLE_TYPE_SHORT
case detail::short_type:
return vis(arg.m_value.template get_as<short>());
#endif
#if SCN_TYPE_INT
#if !SCN_DISABLE_TYPE_INT
case detail::int_type:
return vis(arg.m_value.template get_as<int>());
#endif
#if SCN_TYPE_LONG
#if !SCN_DISABLE_TYPE_LONG
case detail::long_type:
return vis(arg.m_value.template get_as<long>());
#endif
#if SCN_TYPE_LONG_LONG
#if !SCN_DISABLE_TYPE_LONG_LONG
case detail::long_long_type:
return vis(arg.m_value.template get_as<long long>());
#endif
#if SCN_TYPE_UCHAR
#if !SCN_DISABLE_TYPE_UCHAR
case detail::uchar_type:
return vis(arg.m_value.template get_as<unsigned char>());
#endif
#if SCN_TYPE_USHORT
#if !SCN_DISABLE_TYPE_USHORT
case detail::ushort_type:
return vis(arg.m_value.template get_as<unsigned short>());
#endif
#if SCN_TYPE_UINT
#if !SCN_DISABLE_TYPE_UINT
case detail::uint_type:
return vis(arg.m_value.template get_as<unsigned int>());
#endif
#if SCN_TYPE_ULONG
#if !SCN_DISABLE_TYPE_ULONG
case detail::ulong_type:
return vis(arg.m_value.template get_as<unsigned long>());
#endif
#if SCN_TYPE_ULONG_LONG
#if !SCN_DISABLE_TYPE_ULONG_LONG
case detail::ulong_long_type:
return vis(arg.m_value.template get_as<unsigned long long>());
#endif
#if SCN_TYPE_BOOL
#if !SCN_DISABLE_TYPE_BOOL
case detail::bool_type:
return vis(arg.m_value.template get_as<bool>());
#endif
#if SCN_TYPE_CHAR
#if !SCN_DISABLE_TYPE_CHAR
case detail::char_type:
return vis(arg.m_value.template get_as<CharT>());
#endif
#if SCN_TYPE_CODE_POINT
#if !SCN_DISABLE_TYPE_CODE_POINT
case detail::code_point_type:
return vis(arg.m_value.template get_as<code_point>());
#endif
#if SCN_TYPE_FLOAT
#if !SCN_DISABLE_TYPE_FLOAT
case detail::float_type:
return vis(arg.m_value.template get_as<float>());
#endif
#if SCN_TYPE_DOUBLE
#if !SCN_DISABLE_TYPE_DOUBLE
case detail::double_type:
return vis(arg.m_value.template get_as<double>());
#endif
#if SCN_TYPE_LONG_DOUBLE
#if !SCN_DISABLE_TYPE_LONG_DOUBLE
case detail::long_double_type:
return vis(arg.m_value.template get_as<long double>());
#endif
#if SCN_TYPE_BUFFER
#if !SCN_DISABLE_TYPE_BUFFER
case detail::buffer_type:
return vis(arg.m_value.template get_as<span<CharT>>());
#endif
#if SCN_TYPE_STRING
#if !SCN_DISABLE_TYPE_STRING
case detail::string_type:
return vis(
arg.m_value.template get_as<std::basic_string<CharT>>());
#endif
#if SCN_TYPE_STRING_VIEW
#if !SCN_DISABLE_TYPE_STRING_VIEW
case detail::string_view_type:
return vis(
arg.m_value.template get_as<basic_string_view<CharT>>());
#endif
#if SCN_TYPE_CUSTOM
#if !SCN_DISABLE_TYPE_CUSTOM
case detail::custom_type:
return vis(typename basic_arg<CharT>::handle(
arg.m_value.get_custom()));
Expand All @@ -466,7 +528,9 @@ namespace scn {
SCN_DECLVAL(priority_tag<1>)));
static const type value = value_type::type_tag;

static_assert(type_enabled<T, CharT>::value, "arg type is disabled");
static_assert(
!is_type_disabled<T, CharT>::value,
"Scanning of this type is disabled by SCN_DISABLE_TYPE_*");
};

template <typename CharT>
Expand Down
Loading

0 comments on commit 11d5be1

Please sign in to comment.