Skip to content

Commit

Permalink
Merge pull request #345 from beached/v3
Browse files Browse the repository at this point in the history
Using if constexpr/static asserts in place of enable_if's
  • Loading branch information
beached authored Nov 12, 2022
2 parents 635143f + 4b1f034 commit 93d18da
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 164 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
cmake_minimum_required( VERSION 3.14 )

project( "daw-json-link"
VERSION "3.5.0"
VERSION "3.6.0"
DESCRIPTION "Static JSON parsing in C++"
HOMEPAGE_URL "https://github.com/beached/daw_json_link"
LANGUAGES C CXX )
Expand Down
26 changes: 10 additions & 16 deletions include/daw/json/daw_from_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,11 +486,9 @@ namespace daw::json {
/// @throws daw::json::json_exception
template<typename JsonElement, typename Container, typename Constructor,
bool KnownBounds, typename String, auto... PolicyFlags>
[[nodiscard]] constexpr auto
[[nodiscard]] constexpr Container
from_json_array( String &&json_data,
options::parse_flags_t<PolicyFlags...> )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container> {
options::parse_flags_t<PolicyFlags...> ) {
static_assert(
json_details::is_string_view_like_v<String>,
"String type must have a be a contiguous range of Characters" );
Expand Down Expand Up @@ -561,10 +559,10 @@ namespace daw::json {
/// @throws daw::json::json_exception
template<typename JsonElement, typename Container, typename Constructor,
bool KnownBounds, typename String>
[[nodiscard]] constexpr auto from_json_array( String &&json_data )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container> {

[[nodiscard]] constexpr Container from_json_array( String &&json_data ) {
static_assert(
json_details::is_string_view_like_v<String>,
"String type must have a be a contiguous range of Characters" );
return from_json_array<JsonElement, Container, Constructor, KnownBounds>(
DAW_FWD( json_data ), options::parse_flags<> );
}
Expand All @@ -584,11 +582,9 @@ namespace daw::json {
/// @throws daw::json::json_exception
template<typename JsonElement, typename Container, typename Constructor,
bool KnownBounds, typename String, auto... PolicyFlags>
[[nodiscard]] constexpr auto
[[nodiscard]] constexpr Container
from_json_array( String &&json_data, std::string_view member_path,
options::parse_flags_t<PolicyFlags...> )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container> {
options::parse_flags_t<PolicyFlags...> ) {
static_assert(
json_details::is_string_view_like_v<String>,
"String type must have a be a contiguous range of Characters" );
Expand Down Expand Up @@ -674,10 +670,8 @@ namespace daw::json {
/// @throws daw::json::json_exception
template<typename JsonElement, typename Container, typename Constructor,
bool KnownBounds, typename String>
[[nodiscard]] constexpr auto from_json_array( String &&json_data,
std::string_view member_path )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container> {
[[nodiscard]] constexpr Container
from_json_array( String &&json_data, std::string_view member_path ) {
static_assert(
json_details::is_string_view_like_v<String>,
"String type must have a be a contiguous range of Characters" );
Expand Down
22 changes: 7 additions & 15 deletions include/daw/json/daw_from_json_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,9 @@ namespace daw::json {
std::vector<json_details::from_json_result_t<JsonElement>>,
typename Constructor = use_default, bool KnownBounds = false,
typename String, auto... PolicyFlags>
[[nodiscard]] constexpr auto
[[nodiscard]] constexpr Container
from_json_array( String &&json_data, std::string_view member_path,
options::parse_flags_t<PolicyFlags...> )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container>;
options::parse_flags_t<PolicyFlags...> );

/// @brief Parse JSON data where the root item is an array
/// @tparam JsonElement The type of each element in array. Must be one of
Expand All @@ -236,10 +234,8 @@ namespace daw::json {
std::vector<json_details::from_json_result_t<JsonElement>>,
typename Constructor = use_default, bool KnownBounds = false,
typename String>
[[nodiscard]] constexpr auto from_json_array( String &&json_data,
std::string_view member_path )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container>;
[[nodiscard]] constexpr Container
from_json_array( String &&json_data, std::string_view member_path );

/// @brief Parse JSON data where the root item is an array
/// @tparam JsonElement The type of each element in array. Must be one of
Expand All @@ -256,11 +252,9 @@ namespace daw::json {
std::vector<json_details::from_json_result_t<JsonElement>>,
typename Constructor = use_default, bool KnownBounds = false,
typename String, auto... PolicyFlags>
[[nodiscard]] constexpr auto
[[nodiscard]] constexpr Container
from_json_array( String &&json_data,
options::parse_flags_t<PolicyFlags...> )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container>;
options::parse_flags_t<PolicyFlags...> );

/// @brief Parse JSON data where the root item is an array
/// @tparam JsonElement The type of each element in array. Must be one of
Expand All @@ -277,8 +271,6 @@ namespace daw::json {
std::vector<json_details::from_json_result_t<JsonElement>>,
typename Constructor = use_default, bool KnownBounds = false,
typename String>
[[nodiscard]] constexpr auto from_json_array( String &&json_data )
-> std::enable_if_t<json_details::is_string_view_like_v<String>,
Container>;
[[nodiscard]] constexpr Container from_json_array( String &&json_data );
} // namespace DAW_JSON_VER
} // namespace daw::json
10 changes: 6 additions & 4 deletions include/daw/json/daw_json_value_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,10 @@ namespace daw::json {
* from one past last, e.g. -1 is last item
* @return The name of the member or an empty optional
*/
template<typename Integer, std::enable_if_t<std::is_integral_v<Integer>,
std::nullptr_t> = nullptr>
template<typename Integer>
[[nodiscard]] std::optional<std::string_view> name_of( Integer index ) {
static_assert( std::is_integral_v<Integer>,
"Only integer indices are allowed" );
if constexpr( std::is_signed_v<Integer> ) {
if( index < 0 ) {
index = -index;
Expand Down Expand Up @@ -378,13 +379,14 @@ namespace daw::json {
}
};

basic_stateful_json_value( )->basic_stateful_json_value<>;
basic_stateful_json_value( ) -> basic_stateful_json_value<>;

template<json_options_t PolicyFlags, typename Allocator>
basic_stateful_json_value( basic_json_value<PolicyFlags, Allocator> )
-> basic_stateful_json_value<PolicyFlags, Allocator>;

basic_stateful_json_value( daw::string_view )->basic_stateful_json_value<>;
basic_stateful_json_value( daw::string_view )
-> basic_stateful_json_value<>;

using json_value_state = basic_stateful_json_value<>;
} // namespace DAW_JSON_VER
Expand Down
9 changes: 6 additions & 3 deletions include/daw/json/impl/daw_fp_fallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
namespace daw::json {
inline namespace DAW_JSON_VER {
namespace json_details {

/// @brief When normal FP parsing cannot handle the value, this method
/// used as a fallback for std floating point types. For others, it
/// provides either a customization point or will call the overload found
/// via ADL
template<typename Real, std::enable_if_t<std::is_floating_point_v<Real>,
std::nullptr_t> = nullptr>
DAW_ATTRIB_NOINLINE Real parse_with_strtod( char const *first,
char const *last ) {
DAW_ATTRIB_NOINLINE [[nodiscard]] Real
parse_with_strtod( char const *first, char const *last ) {
#if not defined( DAW_JSON_USE_STRTOD ) and defined( __cpp_lib_to_chars )
Real result;
std::from_chars_result fc_res = std::from_chars( first, last, result );
Expand Down
20 changes: 6 additions & 14 deletions include/daw/json/impl/daw_json_parse_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,20 +376,12 @@ namespace daw::json {
}

template<typename T>
inline constexpr JsonParseTypes number_parse_type_impl_v =
number_parse_type_impl_test<T>( );

template<typename T>
constexpr auto number_parse_type_test( )
-> std::enable_if_t<std::is_enum_v<T>, JsonParseTypes> {

return number_parse_type_impl_v<std::underlying_type_t<T>>;
}
template<typename T>
constexpr auto number_parse_type_test( )
-> std::enable_if_t<not std::is_enum_v<T>, JsonParseTypes> {

return number_parse_type_impl_v<T>;
DAW_ATTRIB_INLINE DAW_CONSTEVAL JsonParseTypes number_parse_type_test( ) {
if constexpr( std::is_enum_v<T> ) {
return number_parse_type_impl_test<std::underlying_type_t<T>>( );
} else {
return number_parse_type_impl_test<T>( );
}
}

template<typename T>
Expand Down
2 changes: 1 addition & 1 deletion include/daw/json/impl/daw_json_parse_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ namespace daw::json {
return DAW_LIKELY( first < last ) and *first == '"';
}

inline constexpr void trim_left( ) {
DAW_ATTRIB_INLINE constexpr void trim_left( ) {
if constexpr( is_unchecked_input ) {
trim_left_unchecked( );
} else {
Expand Down
46 changes: 29 additions & 17 deletions include/daw/json/impl/daw_json_parse_real.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace daw::json {
}

template<bool skip_end_check, typename Unsigned, typename CharT>
DAW_ATTRIB_FLATINLINE inline constexpr CharT *
[[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr CharT *
parse_digits_while_number( CharT *first, CharT *const last,
Unsigned &v ) {

Expand Down Expand Up @@ -83,9 +83,11 @@ namespace daw::json {
return first;
}

/// @brief Check if we have more significant digits that can be stored in
/// the type, usually uint64_t
template<typename ParseState, typename Result,
typename max_storage_digits, typename CharT>
inline constexpr bool
[[nodiscard]] inline constexpr bool
should_use_strtod( CharT *whole_first, CharT *whole_last,
CharT *fract_first, CharT *fract_last ) {
if constexpr( std::is_floating_point_v<Result> and
Expand All @@ -104,10 +106,9 @@ namespace daw::json {
}
}

template<typename Result, bool KnownRange, typename ParseState,
std::enable_if_t<KnownRange, std::nullptr_t> = nullptr>
template<typename Result, typename ParseState>
[[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr Result
parse_real( ParseState &parse_state ) {
parse_real_known( ParseState &parse_state ) {
using CharT = typename ParseState::CharT;
// [-]WHOLE[.FRACTION][(e|E)[+|-]EXPONENT]
daw_json_assert_weak(
Expand Down Expand Up @@ -213,7 +214,6 @@ namespace daw::json {
exponent += to_signed(
[&] {
unsigned_t exp_result = 0;
// TODO use zstringopt
if constexpr( ParseState::is_zero_terminated_string( ) ) {
auto dig = parse_digit( *exp_first );
while( dig < 10U ) {
Expand Down Expand Up @@ -245,24 +245,26 @@ namespace daw::json {
}
if constexpr( std::is_floating_point_v<Result> and
ParseState::precise_ieee754( ) ) {
use_strtod |= DAW_UNLIKELY( exponent > 22 );
use_strtod |= DAW_UNLIKELY( exponent < -22 );
use_strtod |=
DAW_UNLIKELY( significant_digits > 9007199254740992ULL );
// On std floating point types, check for conditions that cannot be
// precisely calculated using the normal method and use the fallback
// method(usually strtod/from_chars)
use_strtod |= exponent > 22;
use_strtod |= exponent < -22;
use_strtod |= significant_digits > 9007199254740992ULL;
if( DAW_UNLIKELY( use_strtod ) ) {
return json_details::parse_with_strtod<Result>( parse_state.first,
parse_state.last );
using json_details::parse_with_strtod;
return parse_with_strtod<Result>( parse_state.first,
parse_state.last );
}
}
return sign * power10<Result>(
ParseState::exec_tag,
static_cast<Result>( significant_digits ), exponent );
}

template<typename Result, bool KnownRange, typename ParseState,
std::enable_if_t<not KnownRange, std::nullptr_t> = nullptr>
template<typename Result, typename ParseState>
[[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr Result
parse_real( ParseState &parse_state ) {
parse_real_unknown( ParseState &parse_state ) {
// [-]WHOLE[.FRACTION][(e|E)[+|-]EXPONENT]
using CharT = typename ParseState::CharT;
daw_json_assert_weak(
Expand Down Expand Up @@ -452,14 +454,24 @@ namespace daw::json {
use_strtod |=
DAW_UNLIKELY( significant_digits > 9007199254740992ULL );
if( DAW_UNLIKELY( use_strtod ) ) {
return json_details::parse_with_strtod<Result>( orig_first,
orig_last );
using json_details::parse_with_strtod;
return parse_with_strtod<Result>( orig_first, orig_last );
}
}
return sign * power10<Result>(
ParseState::exec_tag,
static_cast<Result>( significant_digits ), exponent );
}

template<typename Result, bool KnownRange, typename ParseState>
[[nodiscard]] DAW_ATTRIB_FLATINLINE inline constexpr Result
parse_real( ParseState &parse_state ) {
if constexpr( KnownRange ) {
return parse_real_known<Result>( parse_state );
} else {
return parse_real_unknown<Result>( parse_state );
}
}
} // namespace json_details
} // namespace DAW_JSON_VER
} // namespace daw::json
27 changes: 18 additions & 9 deletions include/daw/json/impl/daw_json_parse_string_quote.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,10 @@ namespace daw::json {
first -= *( first - 1 ) == '\\' ? 1 : 0;
}

struct string_quote_parser {
namespace string_quote_parser {
template<typename ParseState>
[[nodiscard]] static constexpr auto parse_nq( ParseState &parse_state )
-> std::enable_if_t<ParseState::is_unchecked_input, std::size_t> {

[[nodiscard]] static constexpr std::size_t
parse_nq_uncheck( ParseState &parse_state ) {
using CharT = typename ParseState::CharT;
std::ptrdiff_t need_slow_path = -1;
CharT *first = parse_state.first;
Expand Down Expand Up @@ -137,8 +136,8 @@ namespace daw::json {
}

template<typename ParseState>
[[nodiscard]] static constexpr auto parse_nq( ParseState &parse_state )
-> std::enable_if_t<not ParseState::is_unchecked_input, std::size_t> {
[[nodiscard]] static constexpr std::size_t
parse_nq_check( ParseState &parse_state ) {

using CharT = typename ParseState::CharT;
std::ptrdiff_t need_slow_path = -1;
Expand Down Expand Up @@ -268,7 +267,17 @@ namespace daw::json {
parse_state.first = first;
return static_cast<std::size_t>( need_slow_path );
}
};
} // namespace json_details::string_quote
} // namespace DAW_JSON_VER

template<typename ParseState>
[[nodiscard]] DAW_ATTRIB_FLATTEN static constexpr std::size_t
parse_nq( ParseState &parse_state ) {
if constexpr( ParseState::is_unchecked_input ) {
return parse_nq_uncheck( parse_state );
} else {
return parse_nq_check( parse_state );
}
}
} // namespace string_quote_parser
} // namespace json_details::string_quote
} // namespace DAW_JSON_VER
} // namespace daw::json
Loading

0 comments on commit 93d18da

Please sign in to comment.