Skip to content

Commit

Permalink
Merge pull request #367 from beached/v3
Browse files Browse the repository at this point in the history
Added base class example and loosened over constraints on some types
  • Loading branch information
beached authored Jan 8, 2023
2 parents a430b4a + b4c4c81 commit 14f343c
Show file tree
Hide file tree
Showing 45 changed files with 303 additions and 94 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.12.0"
VERSION "3.14.0"
DESCRIPTION "Static JSON parsing in C++"
HOMEPAGE_URL "https://github.com/beached/daw_json_link"
LANGUAGES C CXX )
Expand Down
36 changes: 36 additions & 0 deletions docs/cookbook/json_value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Json Value

The `json_value` type is a lazy pull parser. It provides lookup and extraction mechanisms for when the regular mappings cannot work or doing data exploration. One such example is the [variant_on_members.cpp](../../tests/src/variant_on_members.cpp) where the structure of the member is used to determine which parser to use. For types that use a tag or member to discriminate this isn't necessary as there are `json_variant_...` mappings for that. The use of `json_value` is not encouraged except when in conjunction with the mappings such as the `json_raw` mapping when existing mappings do not work, or data discovery.


The general query interface to `json_value` is via `operator[]`. This can be used with a JSON Path to extract a new `json_value`. e.g

```cpp
auto type_jv = jv["value.type"];
assert( type_kv );
auto type = as<int>( type_jv );
```
The example extracts the "type" member of "value" and returns a new `json_value`. If it is not found, the `operator bool` will evaluate to false. It is also false if the "type" member had a value of `null`. If one wants to know if it was found or not, `has_more( )` will return false as the return is a default constructed `json_value`. Following that, one can use the `as` function to parse the value. `from_json` will, also, work here.
There are several ways to parse from a `json_value`. The most succinct is the `T as<T>( json_value )` free function, but there is an `json_value::as<T>( ) const` member function too. The `from_json` interface used for parsing from string data works too. Finally, one can cast to their desired type.
One can also check the type of the current value via several members such as `is_class`, `is_null`, `is_array`, `is_number`, `is_string`, and `is_bool`. There is also `type( )` member that returns an enum of the basic JSON types that can be switched over.
The `json_value` type is a range and one can iterate over classes or arrays. The value_type is a `json_pair` type that has a `name` and a `value` member. The name is an `optional<string_view>`. When iterating over an array, the name will be `nullopt`. The value member is a `json_value`. The `json_pair`, also, fulfills the tuple protocol and can get used with structured bindings.
```cpp
for( auto [name,value]: my_jv_of_class ) {
std::cout << "name:" << *name << " value: " << value.get_string_view( ) << '\n';
}
```

The following is equivalent

```cpp
auto jv = other_jv[5]["a"]["b"][2];
```

```cpp
auto jv = other_jv["[5].a.b[2]"];
```
2 changes: 1 addition & 1 deletion extern/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ include( FetchContent )
FetchContent_Declare(
daw_header_libraries
GIT_REPOSITORY https://github.com/beached/header_libraries.git
GIT_TAG v2.76.3
GIT_TAG v2.84.1
)

FetchContent_Declare(
Expand Down
18 changes: 18 additions & 0 deletions include/daw/json/concepts/daw_nullable_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ namespace daw::json {
#endif
}

constexpr nullable_type DAW_JSON_CPP23_STATIC_CALL_OP operator( )(
construct_nullable_with_pointer_t,
value_type *ptr ) DAW_JSON_CPP23_STATIC_CALL_OP_CONST noexcept {
return nullable_type( ptr );
}

constexpr nullable_type DAW_JSON_CPP23_STATIC_CALL_OP
operator( )( construct_nullable_with_empty_t )
DAW_JSON_CPP23_STATIC_CALL_OP_CONST noexcept {
Expand Down Expand Up @@ -187,6 +193,12 @@ namespace daw::json {
#endif
}

constexpr nullable_type DAW_JSON_CPP23_STATIC_CALL_OP operator( )(
construct_nullable_with_pointer_t,
value_type *ptr ) DAW_JSON_CPP23_STATIC_CALL_OP_CONST noexcept {
return nullable_type( ptr );
}

constexpr nullable_type DAW_JSON_CPP23_STATIC_CALL_OP
operator( )( construct_nullable_with_empty_t )
DAW_JSON_CPP23_STATIC_CALL_OP_CONST noexcept {
Expand Down Expand Up @@ -236,6 +248,12 @@ namespace daw::json {
#endif
}

constexpr nullable_type DAW_JSON_CPP23_STATIC_CALL_OP operator( )(
construct_nullable_with_pointer_t,
value_type *ptr ) DAW_JSON_CPP23_STATIC_CALL_OP_CONST noexcept {
return ptr;
}

DAW_JSON_CPP23_STATIC_CALL_OP constexpr nullable_type
operator( )( construct_nullable_with_empty_t )
DAW_JSON_CPP23_STATIC_CALL_OP_CONST noexcept {
Expand Down
21 changes: 18 additions & 3 deletions include/daw/json/concepts/daw_nullable_value_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,21 @@ namespace daw::json {

} // namespace nullable_impl

struct construct_nullable_with_value_t {};

struct construct_nullable_with_value_t {
explicit construct_nullable_with_value_t( ) = default;
};
inline constexpr auto construct_nullable_with_value =
construct_nullable_with_value_t{ };

struct construct_nullable_with_empty_t {};
struct construct_nullable_with_pointer_t {
explicit construct_nullable_with_pointer_t( ) = default;
};
inline constexpr auto construct_nullable_with_pointer =
construct_nullable_with_pointer_t{ };

struct construct_nullable_with_empty_t {
explicit construct_nullable_with_empty_t( ) = default;
};
inline constexpr auto construct_nullable_with_empty =
construct_nullable_with_empty_t{ };

Expand Down Expand Up @@ -122,6 +131,12 @@ namespace daw::json {
std::is_invocable_v<nullable_value_traits<T>,
construct_nullable_with_value_t, Args...>;

template<typename T, typename... Args>
inline constexpr bool is_nullable_pointer_constructible_v =
is_nullable_value_v<T> and
std::is_invocable_v<nullable_value_traits<T>,
construct_nullable_with_pointer_t, Args...>;

template<typename T, typename... Args>
inline constexpr bool is_nullable_value_nothrow_constructible_v =
is_nullable_value_constructible_v<T, Args...> and
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/daw_from_json_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "impl/daw_json_parse_policy.h"
#include "impl/daw_json_traits.h"

#include <ciso646>
#include <string_view>

namespace daw::json {
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/daw_json_event_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <daw/daw_move.h>
#include <daw/daw_string_view.h>

#include <ciso646>
#include <cstddef>
#include <string>
#include <utility>
Expand Down
5 changes: 2 additions & 3 deletions include/daw/json/daw_json_exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <daw/daw_unreachable.h>

#include <algorithm>
#include <ciso646>
#include <cstdio>
#include <cstdlib>
#include <exception>
Expand Down Expand Up @@ -272,7 +271,7 @@ namespace daw::json {
}

DAW_ATTRIB_NOINLINE [[nodiscard]] inline std::string reason( ) const {
#if defined( DAW_JSON_COMPILER_CLANG_COMPAT )
#if defined( DAW_HAS_CLANG )
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wswitch-enum"
#endif
Expand All @@ -289,7 +288,7 @@ namespace daw::json {
default:
return std::string( ( reason_message( m_reason ) ) );
}
#if defined( DAW_JSON_COMPILER_CLANG_COMPAT )
#if defined( DAW_HAS_CLANG )
#pragma clang diagnostic pop
#endif
}
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/daw_json_iostream.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

#include <daw/daw_traits.h>

#include <ciso646>
#include <iostream>
#include <type_traits>

Expand Down
43 changes: 12 additions & 31 deletions include/daw/json/daw_json_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,9 @@
#include <daw/daw_consteval.h>
#include <daw/daw_cpp_feature_check.h>

#if defined( _MSC_VER ) and not defined( __clang__ )
#define DAW_JSON_COMPILER_MSVC
#define DAW_JSON_COMPILER_MSVC_COMPAT
#elif defined( _MSC_VER ) and defined( __clang__ )
#define DAW_JSON_COMPILER_CLANG
#define DAW_JSON_COMPILER_CLANGCL
#define DAW_JSON_COMPILER_MSVC_COMPAT
#define DAW_JSON_COMPILER_CLANG_COMPAT
#elif defined( __GNUC__ ) and not defined( __clang__ )
#define DAW_JSON_COMPILER_GCC
#define DAW_JSON_COMPILER_GCC_COMPAT
#elif defined( __clang__ )
#define DAW_JSON_COMPILER_CLANG
#define DAW_JSON_COMPILER_CLANG_COMPAT
#define DAW_JSON_COMPILER_GCC_COMPAT
#endif

/// DAW_NO_FLATTEN disables any flatten attributes in code. This is disabled in
/// GCC by default as it cannot handle it
#if defined( DAW_JSON_COMPILER_GCC ) and not defined( DAW_JSON_FLATTEN )
#if defined( DAW_HAS_GCC ) and not defined( DAW_JSON_FLATTEN )
#if not defined( DAW_NO_FLATTEN )
#define DAW_NO_FLATTEN
#endif
Expand Down Expand Up @@ -76,7 +59,7 @@
// by defining DAW_JSON_PARSER_DIAGNOSTICS

// DAW_CAN_CONSTANT_EVAL is used to test if we are in a constant expression
#if defined( DAW_JSON_COMPILER_GCC_COMPAT )
#if defined( DAW_HAS_GCC_LIKE )
#define DAW_CAN_CONSTANT_EVAL( ... ) \
( __builtin_constant_p( __VA_ARGS__ ) == 1 )
#else
Expand All @@ -100,16 +83,14 @@
#endif
#endif
#endif
#if defined( __clang_major__ ) and __cplusplus >= 202002L
#if __clang_major__ >= 12
#if DAW_HAS_CLANG_VER_GTE( 12, 0 ) and DAW_CPP_VERSION >= 202002L
// Clang 12 supports enough of CNTTP string literals and compiles the tests
// successfully, but does not define the feature macro
#if not defined( DAW_JSON_CNTTP_JSON_NAME )
#define DAW_JSON_CNTTP_JSON_NAME
#endif
#endif
#endif
#endif

#if defined( __cpp_constexpr_dynamic_alloc )
#define CPP20CONSTEXPR constexpr
Expand All @@ -119,7 +100,7 @@
#endif

// Fix bug in MSVC
#if defined( DAW_JSON_COMPILER_MSVC )
#if defined( DAW_HAS_MSVC )
#define DAW_JSON_MAKE_LOC_INFO_CONSTEVAL constexpr
#else
#define DAW_JSON_MAKE_LOC_INFO_CONSTEVAL DAW_CONSTEVAL
Expand All @@ -138,24 +119,24 @@
// size is known up front. This is playing to the implementations prior to
// C++23 when range constructors are added to containers. It is disabled on
// MSVC as that impl does not work with it
#if defined( DAW_JSON_COMPILER_MSVC )
#if defined( DAW_HAS_MSVC )
#if not defined( DAW_JSON_DISABLE_RANDOM )
#define DAW_JSON_DISABLE_RANDOM
#endif
#endif

// DAW_JSON_HAS_BUILTIN_UADD is used to switch to a constexpr method of overflow
// addition when available
#if( defined( __GNUC__ ) and __GNUC__ >= 8 ) or defined( __clang__ ) or \
( DAW_HAS_BUILTIN( __builtin_uadd_overflow ) and \
DAW_HAS_BUILTIN( __builtin_uaddl_overflow ) and \
#if DAW_HAS_GCC_VER_GTE( 8, 0 ) or defined( DAW_HAS_CLANG ) or \
( DAW_HAS_BUILTIN( __builtin_uadd_overflow ) and \
DAW_HAS_BUILTIN( __builtin_uaddl_overflow ) and \
DAW_HAS_BUILTIN( __builtin_uaddll_overflow ) )
#define DAW_JSON_HAS_BUILTIN_UADD
#endif

// DAW_JSON_BUGFIX_FROM_JSON_001
// Defined for MSVC as it has been ICE'ing on daw_json_ensure in from_json
#if defined( DAW_JSON_COMPILER_MSVC )
#if defined( DAW_HAS_MSVC )
#define DAW_JSON_BUGFIX_FROM_JSON_001
#endif

Expand All @@ -164,21 +145,21 @@
// JSON Link uses the left->right guarantees in places like constructors so that
// less state is needed. In MSVC one must keep more state in places like
// parse_tuple_value
#if defined( DAW_JSON_COMPILER_MSVC )
#if defined( DAW_HAS_MSVC )
#define DAW_JSON_BUGFIX_MSVC_EVAL_ORDER_002
#endif

// DAW_JSON_BUGFIX_MSVC_KNOWN_LOC_ICE_003
// MSVC in C++20 mode will ICE when known locations is evaluated at compile time
#if( defined( DAW_JSON_COMPILER_MSVC ) and __cpp_constexpr > 201700L )
#if( defined( DAW_HAS_MSVC ) and __cpp_constexpr > 201700L )
#define DAW_JSON_BUGFIX_MSVC_KNOWN_LOC_ICE_003
#endif

/// This is in addition to the parse policy. Always do a full name match
/// instead of sometimes relying on the hash. This was enabled in MSVC due to
/// an issue that should be rechecked
#if not defined( NDEBUG ) or defined( DEBUG ) or \
defined( DAW_JSON_PARSER_DIAGNOSTICS ) or defined( DAW_JSON_COMPILER_MSVC )
defined( DAW_JSON_PARSER_DIAGNOSTICS ) or defined( DAW_HAS_MSVC )
#if not defined( DAW_JSON_ALWAYS_FULL_NAME_MATCH )
#define DAW_JSON_ALWAYS_FULL_NAME_MATCH
#endif
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/daw_json_value_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <daw/daw_string_view.h>
#include <daw/daw_uint_buffer.h>

#include <ciso646>
#include <cstddef>
#include <string_view>
#include <utility>
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/impl/daw_json_assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <daw/daw_string_view.h>

#include <algorithm>
#include <ciso646>
#include <cstdio>
#include <cstdlib>
#include <memory>
Expand Down
13 changes: 13 additions & 0 deletions include/daw/json/impl/daw_json_default_constuctor.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,19 @@ namespace daw::json {
return rtraits_t{ }( concepts::construct_nullable_with_value,
DAW_FWD( args )... );
}

template<typename Pointer,
std::enable_if_t<
concepts::is_nullable_pointer_constructible_v<T, Pointer *>,
std::nullptr_t> = nullptr>
[[nodiscard]] DAW_ATTRIB_INLINE
DAW_JSON_CPP23_STATIC_CALL_OP constexpr auto
operator( )( concepts::construct_nullable_with_pointer_t,
Pointer *ptr ) DAW_JSON_CPP23_STATIC_CALL_OP_CONST
noexcept(
concepts::is_nullable_value_nothrow_constructible_v<T, Pointer> ) {
return rtraits_t{ }( concepts::construct_nullable_with_pointer, ptr );
}
};
} // namespace DAW_JSON_VER
} // namespace daw::json
1 change: 0 additions & 1 deletion include/daw/json/impl/daw_json_link_types_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <daw/daw_utility.h>

#include <chrono>
#include <ciso646>
#include <optional>
#include <string>

Expand Down
1 change: 0 additions & 1 deletion include/daw/json/impl/daw_json_link_types_iso8601.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <daw/daw_string_view.h>

#include <chrono>
#include <ciso646>

namespace daw::json {
inline namespace DAW_JSON_VER {
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/impl/daw_json_location_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <daw/daw_uint_buffer.h>
#include <daw/daw_utility.h>

#include <ciso646>
#include <cstddef>
#include <iterator>
#include <utility>
Expand Down
1 change: 0 additions & 1 deletion include/daw/json/impl/daw_json_parse_array_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#include <daw/daw_attributes.h>

#include <ciso646>
#include <type_traits>

namespace daw::json {
Expand Down
8 changes: 3 additions & 5 deletions include/daw/json/impl/daw_json_parse_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <daw/daw_likely.h>
#include <daw/daw_traits.h>

#include <ciso646>
#include <cstddef>
#include <exception>
#include <type_traits>
Expand Down Expand Up @@ -230,17 +229,16 @@ namespace daw::json {
#endif

if constexpr( is_pinned_type_v<typename JsonClass::parse_to_t> ) {
/// Because the return type is pinned(no copy/move). We cannot rely
/// on NRVO. This requires on_exit_success that on some platforms
/// can cost a bunch because it checks std::uncaught_exceptions
auto const run_after_parse = daw::on_exit_success( [&] {
class_cleanup_now<
json_details::all_json_members_must_exist_v<T, ParseState>>(
parse_state, old_class_pos );
} );
(void)run_after_parse;

/*
* Rather than call directly use apply/tuple to evaluate
* left->right
*/
if constexpr( should_construct_explicitly_v<Constructor, T,
ParseState> ) {
return T{ parse_class_member<
Expand Down
Loading

0 comments on commit 14f343c

Please sign in to comment.