DAW JSON Link
Loading...
Searching...
No Matches
daw_json_lines_iterator.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
11#include "impl/version.h"
12
15#include "impl/daw_json_value.h"
16
17#include <daw/daw_cxmath.h>
18#include <daw/daw_move.h>
19#include <daw/daw_scope_guard.h>
20#include <daw/daw_traits.h>
21#include <daw/daw_utility.h>
22
23#include <array>
24#include <cstddef>
25#include <cstdlib>
26#include <iterator>
27#include <limits>
28#include <string>
29#include <string_view>
30#include <type_traits>
31
32namespace daw::json {
33 inline namespace DAW_JSON_VER {
37 template<typename JsonElement = json_value, auto... PolicyFlags>
40 options::details::make_parse_flags<PolicyFlags...>( ).value>>;
41 using CharT = typename ParseState::CharT;
42
43 public:
44 using element_type = json_details::json_deduced_type<JsonElement>;
45 static_assert( not std::is_same_v<element_type, void>,
46 "Unknown JsonElement type." );
47 using value_type = json_details::json_result_t<element_type>;
49 using pointer = json_details::arrow_proxy<value_type>;
50 using difference_type = std::ptrdiff_t;
51 // Can do forward iteration and be stored
52 using iterator_category = std::input_iterator_tag;
53
54 private:
55 ParseState m_state = ParseState( );
56 /***
57 * This lets us fastpath and just skip n characters as we have already
58 * parsed them
59 */
60 mutable CharT *m_can_skip = nullptr;
61
62 public:
63 explicit json_lines_iterator( ) = default;
64
65 explicit constexpr json_lines_iterator( daw::string_view json_lines_doc )
66 : m_state( ParseState( std::data( json_lines_doc ),
67 daw::data_end( json_lines_doc ) ) ) {
68
69 m_state.trim_left( );
70 }
71
75 [[nodiscard]] constexpr value_type operator*( ) const {
76 daw_json_assert_weak( m_state.has_more( ),
77 ErrorReason::UnexpectedEndOfData, m_state );
78
79 auto tmp = m_state;
80 auto const run_after_parse = daw::on_scope_exit( [&] {
81 m_can_skip = tmp.first;
82 } );
83 (void)run_after_parse;
84 return json_details::parse_value<element_type, false,
85 element_type::expected_type>( tmp );
86 }
87
93 [[nodiscard]] constexpr pointer operator->( ) const {
94 return pointer{ operator*( ) };
95 }
96
100 daw_json_assert_weak( m_state.has_more( ),
101 ErrorReason::UnexpectedEndOfData, m_state );
102 if( m_can_skip ) {
103 m_state.first = m_can_skip;
104 m_can_skip = nullptr;
105 } else {
106 (void)json_details::skip_known_value<element_type>( m_state );
107 }
108 m_state.move_next_member_or_end( );
109 return *this;
110 }
111
113 constexpr void operator++( int ) & {
114 (void)operator++( );
115 }
116
119 [[nodiscard]] constexpr bool good( ) const {
120 return not m_state.is_null( ) and m_state.has_more( );
121 }
122
125 [[nodiscard]] explicit constexpr operator bool( ) const {
126 return good( );
127 }
128
132 [[nodiscard]] constexpr bool
133 operator==( json_lines_iterator const &rhs ) const {
134 if( not( *this ) ) {
135 return not rhs;
136 }
137 if( not rhs ) {
138 return false;
139 }
140 return ( m_state.first == rhs.m_state.first );
141 }
142
146 [[nodiscard]] constexpr bool
147 operator!=( json_lines_iterator const &rhs ) const {
148 if( not( *this ) ) {
149 return static_cast<bool>( rhs );
150 }
151 if( not rhs ) {
152 return true;
153 }
154 return m_state.first != rhs.m_state.first;
155 }
156
157 constexpr std::string_view get_raw_json_document( ) const {
158 return std::string_view( m_state.first, m_state.size( ) );
159 }
160 };
162
166 template<typename JsonElement = json_value, auto... PolicyFlags>
169 options::details::make_parse_flags<PolicyFlags...>( ).value>>;
170 using iterator = json_lines_iterator<JsonElement, PolicyFlags...>;
171 using CharT = typename ParsePolicy::CharT;
172
173 private:
174 iterator m_first{ };
175 iterator m_last{ };
176
177 public:
178 explicit json_lines_range( ) = default;
179
180 explicit constexpr json_lines_range( iterator first,
181 iterator last = iterator( ) )
182 : m_first( first )
183 , m_last( last ) {}
184
185 explicit constexpr json_lines_range( daw::string_view json_lines_doc )
186 : m_first( json_lines_doc ) {}
187
189 [[nodiscard]] constexpr iterator begin( ) const {
190 return m_first;
191 }
192
194 [[nodiscard]] constexpr iterator end( ) const {
195 return m_last;
196 }
197
200 [[nodiscard]] constexpr bool empty( ) const {
201 return m_first == m_last;
202 }
203 };
204 json_lines_range( daw::string_view ) -> json_lines_range<>;
205
206 template<typename JsonElement, auto... PolicyFlags>
209 -> json_lines_range<JsonElement, PolicyFlags...>;
210
214 template<typename JsonElement = json_value, auto... ParsePolicies>
215 std::vector<json_lines_range<JsonElement, ParsePolicies...>>
216 partition_jsonl_document( std::size_t num_partitions,
217 daw::string_view jsonl_doc ) {
218 using result_t =
219 std::vector<json_lines_range<JsonElement, ParsePolicies...>>;
220 if( num_partitions <= 1 ) {
221 return result_t{
222 json_lines_range<JsonElement, ParsePolicies...>( jsonl_doc ) };
223 }
224 auto approx_segsize = jsonl_doc.size( ) / num_partitions;
225 auto result = result_t{ };
226 char const *const last = daw::data_end( jsonl_doc );
227 while( not jsonl_doc.empty( ) ) {
228 char const *tmp = std::data( jsonl_doc ) + approx_segsize;
229 if( tmp >= last ) {
230 result.emplace_back( jsonl_doc );
231 break;
232 }
233 while( tmp < last and *tmp != '\n' ) {
234 ++tmp;
235 }
236 if( tmp < last ) {
237 ++tmp;
238 }
239 auto sz = static_cast<std::size_t>( tmp - std::data( jsonl_doc ) );
240 auto doc = jsonl_doc.pop_front( sz );
241 doc.trim_suffix( );
242 if( not doc.empty( ) ) {
243 result.emplace_back( doc );
244 }
245 }
246 return result;
247 }
248 } // namespace DAW_JSON_VER
249} // namespace daw::json
constexpr void operator++(int) &
Move the parse state to the next element.
TryDefaultParsePolicy< BasicParsePolicy< options::details::make_parse_flags< PolicyFlags... >().value > > ParseState
constexpr bool operator==(json_lines_iterator const &rhs) const
Compare rhs for equivalence.
constexpr pointer operator->() const
A dereferencable value proxy holding the result of operator* . This is for compatibility with the Ite...
constexpr bool operator!=(json_lines_iterator const &rhs) const
Check if the other iterator is not equivalent.
constexpr json_lines_iterator & operator++()
Move the parse state to the next element.
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
std::vector< json_lines_range< JsonElement, ParsePolicies... > > partition_jsonl_document(std::size_t num_partitions, daw::string_view jsonl_doc)
parition the jsonl/nbjson document into num_partition non overlapping sub-ranges. This can be used to...
daw::conditional_t< ParsePolicy::is_default_parse_policy, DefaultParsePolicy, ParsePolicy > TryDefaultParsePolicy
Customization point traits.
TryDefaultParsePolicy< BasicParsePolicy< options::details::make_parse_flags< PolicyFlags... >().value > > ParsePolicy
Handles the bounds and policy items for parsing execution and comments.
A non-owning container for arbitrary JSON values that allows movement/iteration through.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20