DAW JSON Link
daw_json_value_state.h
Go to the documentation of this file.
1 // Copyright (c) Darrell Wright
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //
6 // Official repository: https://github.com/beached/daw_json_link
7 //
8 
9 #pragma once
10 
14 #include "impl/daw_json_value.h"
15 #include "impl/daw_murmur3.h"
16 #include "impl/version.h"
17 
18 #include <daw/daw_move.h>
19 #include <daw/daw_uint_buffer.h>
20 
21 #include <ciso646>
22 #include <cstddef>
23 #include <string_view>
24 #include <utility>
25 #include <vector>
26 
27 namespace daw::json {
28  inline namespace DAW_JSON_VER {
29  namespace json_details {
30  template<typename ParseState>
32  daw::string_view name;
33  daw::UInt32 hash_value;
35 
36  explicit constexpr basic_stateful_json_value_state(
37  daw::string_view Name, basic_json_value_iterator<ParseState> val )
38  : name( Name )
39  , hash_value( daw::name_hash( Name ) )
40  , location( DAW_MOVE( val ) ) {}
41 
42  [[nodiscard]] constexpr bool is_match( daw::string_view Name ) const {
43  return name == Name;
44  }
45 
46  [[nodiscard]] constexpr bool is_match( daw::string_view Name,
47  daw::UInt32 hash ) const {
48  if( hash != hash_value ) {
49  return false;
50  }
51  return name == Name;
52  }
53  };
54  } // namespace json_details
55 
57  daw::string_view name;
58  daw::UInt32 hash_value;
59 
60  constexpr json_member_name( std::string_view Name )
61  : name( std::data( Name ), std::size( Name ) )
62  , hash_value( daw::name_hash( name ) ) {}
63  };
64 
70  template<typename ParseState>
73  std::vector<json_details::basic_stateful_json_value_state<ParseState>>
74  m_locs{ };
75 
76  /***
77  * Move parser until member name matches key if needed
78  * @param member to move_to
79  * @return position of member or size
80  */
81  [[nodiscard]] constexpr std::size_t move_to( json_member_name member ) {
82  std::size_t pos = 0;
83  std::size_t const Sz = std::size( m_locs );
84  for( ; pos < Sz; ++pos ) {
85  if( m_locs[pos].is_match( member.name, member.hash_value ) ) {
86  return pos;
87  }
88  }
89 
90  auto it = [&] {
91  if( m_locs.empty( ) ) {
92  return m_value.begin( );
93  }
94  auto res = m_locs.back( ).location;
95  ++res;
96  return res;
97  }( );
98  auto const last = m_value.end( );
99  while( it != last ) {
100  auto name = it.name( );
101  daw_json_assert_weak( name, ErrorReason::MissingMemberName );
102  auto const &new_loc = m_locs.emplace_back(
103  daw::string_view( std::data( *name ), std::size( *name ) ), it );
104  if( new_loc.is_match( member.name ) ) {
105  return pos;
106  }
107  ++pos;
108  ++it;
109  }
110  return std::size( m_locs );
111  }
112 
113  /***
114  * Move parser until member index matches, if needed
115  * @param index position of member to move to
116  * @return position in members or size
117  */
118  [[nodiscard]] constexpr std::size_t move_to( std::size_t index ) {
119  if( index < std::size( m_locs ) ) {
120  return index;
121  }
122  auto it = [&] {
123  if( m_locs.empty( ) ) {
124  return m_value.begin( );
125  }
126  auto res = m_locs.back( ).location;
127  ++res;
128  return res;
129  }( );
130  auto last = m_value.end( );
131  std::size_t pos = std::size( m_locs );
132  while( it != last ) {
133  auto name = it.name( );
134  if( name ) {
135  m_locs.emplace_back(
136  daw::string_view( std::data( *name ), std::size( *name ) ), it );
137  } else {
138  m_locs.emplace_back( daw::string_view( ), it );
139  }
140  if( pos == index ) {
141  return pos;
142  }
143  ++pos;
144  ++it;
145  }
146  return std::size( m_locs );
147  }
148 
149  public:
151  : m_value( DAW_MOVE( val ) ) {
152 
153  daw_json_assert_weak( ( [&] {
154  auto t = m_value.type( );
155  return ( t == JsonBaseParseTypes::Class ) |
156  ( t == JsonBaseParseTypes::Array );
157  }( ) ),
158  ErrorReason::ExpectedArrayOrClassStart,
159  val.get_raw_state( ) );
160  }
161 
163  : basic_stateful_json_value( basic_json_value<ParseState>( "{}" ) ) {}
164 
165  constexpr basic_stateful_json_value( std::string_view json_data )
167  basic_json_value<ParseState>( json_data ) ) {}
172  constexpr void reset( basic_json_value<ParseState> val ) {
173  m_value = DAW_MOVE( val );
174  m_locs.clear( );
175  }
176 
177  /***
178  * Create a basic_json_member for the named member
179  * @pre name must be valid
180  * @param key name of member
181  * @return a new basic_json_member
182  */
183  [[nodiscard]] constexpr basic_json_value<ParseState>
184  operator[]( std::string_view key ) {
185  std::size_t pos = move_to( json_member_name( key ) );
186  daw_json_assert_weak( pos < std::size( m_locs ),
187  ErrorReason::UnknownMember );
188  return m_locs[pos].location->value;
189  }
190 
191  /***
192  * Create a basic_json_member for the named member
193  * @pre name must be valid
194  * @param member name of member
195  * @return a new basic_json_member
196  */
197  [[nodiscard]] constexpr basic_json_value<ParseState>
199  std::size_t pos = move_to( member );
200  daw_json_assert_weak( pos < std::size( m_locs ),
201  ErrorReason::UnknownMember );
202  return m_locs[pos].location->value;
203  }
204 
205  /***
206  * Create a basic_json_member for the named member
207  * @pre name must be valid
208  * @param key name of member
209  * @return a new basic_json_member for the JSON data or an empty one if
210  * the member does not exist
211  */
212  [[nodiscard]] constexpr basic_json_value<ParseState>
213  at( std::string_view key ) {
214  auto const k = std::string_view( std::data( key ), std::size( key ) );
215  std::size_t pos = move_to( k );
216  if( pos < std::size( m_locs ) ) {
217  return m_locs[pos].location->value;
218  }
219  return { };
220  }
221 
222  /***
223  * Count the number of elements/members in the JSON class or array
224  * This method is O(N) worst case and O(1) if the locations have already
225  * been determined
226  * @return number of members/elements
227  */
228  [[nodiscard]] std::size_t size( ) {
229  JsonBaseParseTypes const current_type = m_value.type( );
230  switch( current_type ) {
233  return move_to( daw::numeric_limits<std::size_t>::max( ) );
234  default:
235  return 0;
236  }
237  }
238 
239  /***
240  * Return the index of named member
241  * This method is O(N) worst case and O(1) if the locations have already
242  * @param key name of member
243  * @return the position of the member or the count of members if not
244  * present
245  */
246  [[nodiscard]] std::size_t index_of( std::string_view key ) {
247  auto const k = std::string_view( std::data( key ), std::size( key ) );
248  return move_to( k );
249  }
250 
251  /***
252  * Is the named member present
253  * This method is O(N) worst case and O(1) if the locations have already
254  * @param key name of member
255  * @return true if the member is present
256  */
257  [[nodiscard]] constexpr bool contains( std::string_view key ) {
258  auto const k =
259  std::string_view( std::data( key ), std::size( key ) );
260  return move_to( k ) < std::size( m_locs );
261  }
262 
263  /***
264  * Is the indexed member/element present
265  * This method is O(N) worst case and O(1) if the locations have already
266  * @param index position of member/element
267  * @return true if the member/element is present
268  */
269  [[nodiscard]] constexpr bool contains( std::size_t index ) {
270  return move_to( index ) < size( m_locs );
271  }
272 
273  /***
274  * Get the position of the named member
275  * @tparam Integer An integer type
276  * @param index position of member. If negative it returns the position
277  * from one past last, e.g. -1 is last item
278  * @return The name of the member or an empty optional
279  */
280  template<typename Integer,
281  std::enable_if_t<std::is_integral<Integer>::value,
282  std::nullptr_t> = nullptr>
283  [[nodiscard]] std::optional<std::string_view> name_of( Integer index ) {
284  if constexpr( std::is_signed<Integer>::value ) {
285  if( index < 0 ) {
286  index = -index;
287  auto sz = size( );
288  if( static_cast<std::size_t>( index ) >= sz ) {
289  return { };
290  }
291  sz -= static_cast<std::size_t>( index );
292  return std::string_view( std::data( m_locs[sz].name( ) ),
293  std::size( m_locs[sz].name( ) ) );
294  }
295  }
296  std::size_t pos = move_to( static_cast<std::size_t>( index ) );
297  if( pos < std::size( m_locs ) ) {
298  return std::string_view( std::data( m_locs[pos].name( ) ),
299  std::size( m_locs[pos].name( ) ) );
300  }
301  return { };
302  }
303 
304  /***
305  * basic_json_value for the indexed member
306  * @tparam Integer An integer type
307  * @param index position of member. If negative it returns the position
308  * from one past last, e.g. -1 is last item
309  * @pre index must exist
310  * @return A new basic_json_value for the indexed member
311  */
312  template<typename Integer,
313  std::enable_if_t<std::is_integral<Integer>::value,
314  std::nullptr_t> = nullptr>
315  [[nodiscard]] constexpr basic_json_value<ParseState>
316  operator[]( Integer index ) {
317  if constexpr( std::is_signed<Integer>::value ) {
318  if( index < 0 ) {
319  index = -index;
320  auto sz = size( );
321  daw_json_assert_weak( ( static_cast<std::size_t>( index ) < sz ),
322  ErrorReason::UnknownMember );
323  sz -= static_cast<std::size_t>( index );
324  return m_locs[sz].location->value;
325  }
326  }
327  std::size_t pos = move_to( static_cast<std::size_t>( index ) );
328  daw_json_assert_weak( pos < std::size( m_locs ),
329  ErrorReason::UnknownMember );
330  return m_locs[pos].location->value;
331  }
332 
333  /***
334  * basic_json_value for the indexed member
335  * @tparam Integer An integer type
336  * @param index position of member. If negative it returns the position
337  * from one past last, e.g. -1 is last item
338  * @return A new basic_json_value for the indexed member
339  */
340  template<typename Integer,
341  std::enable_if_t<std::is_integral<Integer>::value,
342  std::nullptr_t> = nullptr>
343  [[nodiscard]] constexpr std::optional<basic_json_value<ParseState>>
344  at( Integer index ) {
345  if constexpr( std::is_signed<Integer>::value ) {
346  if( index < 0 ) {
347  index = -index;
348  auto sz = size( );
349  if( static_cast<std::size_t>( index ) >= sz ) {
350  return { };
351  }
352  sz -= static_cast<std::size_t>( index );
353  return m_locs[sz].location->value( );
354  }
355  }
356  std::size_t pos = move_to( static_cast<std::size_t>( index ) );
357  if( pos < std::size( m_locs ) ) {
358  return m_locs[pos].location->value( );
359  }
360  return { };
361  }
362 
363  /***
364  * @return A copy of the underlying basic_json_value
365  */
366  [[nodiscard]] constexpr basic_json_value<ParseState>
367  get_json_value( ) const {
368  return m_value;
369  }
370  };
371 
374  } // namespace DAW_JSON_VER
375 } // namespace daw::json
Definition: daw_json_value.h:316
constexpr ParseState get_raw_state() const
Definition: daw_json_value.h:361
JsonBaseParseTypes type() const
Definition: daw_json_value.h:391
constexpr iterator begin() const
Definition: daw_json_value.h:370
constexpr iterator end() const
Definition: daw_json_value.h:382
Definition: daw_json_value_state.h:71
std::optional< std::string_view > name_of(Integer index)
Definition: daw_json_value_state.h:283
constexpr std::optional< basic_json_value< ParseState > > at(Integer index)
Definition: daw_json_value_state.h:344
constexpr basic_json_value< ParseState > operator[](std::string_view key)
Definition: daw_json_value_state.h:184
constexpr basic_stateful_json_value()
Definition: daw_json_value_state.h:162
constexpr bool contains(std::string_view key)
Definition: daw_json_value_state.h:257
constexpr basic_json_value< ParseState > at(std::string_view key)
Definition: daw_json_value_state.h:213
std::size_t size()
Definition: daw_json_value_state.h:228
constexpr basic_json_value< ParseState > operator[](json_member_name member)
Definition: daw_json_value_state.h:198
constexpr void reset(basic_json_value< ParseState > val)
Definition: daw_json_value_state.h:172
constexpr basic_stateful_json_value(basic_json_value< ParseState > val)
Definition: daw_json_value_state.h:150
constexpr basic_stateful_json_value(std::string_view json_data)
Definition: daw_json_value_state.h:165
constexpr basic_json_value< ParseState > operator[](Integer index)
Definition: daw_json_value_state.h:316
constexpr bool contains(std::size_t index)
Definition: daw_json_value_state.h:269
constexpr basic_json_value< ParseState > get_json_value() const
Definition: daw_json_value_state.h:367
std::size_t index_of(std::string_view key)
Definition: daw_json_value_state.h:246
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:189
Iterator & it
Definition: daw_json_traits.h:231
JsonBaseParseTypes
Definition: daw_json_enums.h:40
Definition: daw_from_json.h:22
Definition: daw_from_json.h:22
constexpr UInt32 name_hash(StringView const &key, std::uint32_t seed=0)
Definition: daw_murmur3.h:45
constexpr basic_stateful_json_value_state(daw::string_view Name, basic_json_value_iterator< ParseState > val)
Definition: daw_json_value_state.h:36
basic_json_value_iterator< ParseState > location
Definition: daw_json_value_state.h:34
constexpr bool is_match(daw::string_view Name) const
Definition: daw_json_value_state.h:42
daw::string_view name
Definition: daw_json_value_state.h:32
daw::UInt32 hash_value
Definition: daw_json_value_state.h:33
constexpr bool is_match(daw::string_view Name, daw::UInt32 hash) const
Definition: daw_json_value_state.h:46
Definition: daw_json_value_state.h:56
daw::string_view name
Definition: daw_json_value_state.h:57
daw::UInt32 hash_value
Definition: daw_json_value_state.h:58
constexpr json_member_name(std::string_view Name)
Definition: daw_json_value_state.h:60
#define DAW_JSON_VER
Definition: version.h:11