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
12
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
42 public:
43 using element_type = json_details::json_deduced_type<JsonElement>;
44 static_assert( not std::is_same_v<element_type, void>,
45 "Unknown JsonElement type." );
46 using value_type = json_details::json_result_t<element_type>;
48 using pointer = json_details::arrow_proxy<value_type>;
49 using difference_type = std::ptrdiff_t;
50 // Can do forward iteration and be stored
51 using iterator_category = std::input_iterator_tag;
52
53 private:
54 ParseState m_state = ParseState( );
55 /***
56 * This lets us fastpath and just skip n characters as we have already
57 * parsed them
58 */
59 mutable char const *m_can_skip = nullptr;
60
61 public:
62 explicit json_lines_iterator( ) = default;
63
64 explicit constexpr json_lines_iterator( daw::string_view json_lines_doc )
65 : m_state( ParseState( std::data( json_lines_doc ),
66 daw::data_end( json_lines_doc ) ) ) {
67
68 m_state.trim_left( );
69 }
70
74 [[nodiscard]] constexpr value_type operator*( ) const {
76 m_state.has_more( ), ErrorReason::UnexpectedEndOfData, m_state );
77
78 auto tmp = m_state;
79 auto const run_after_parse = daw::on_scope_exit( [&] {
80 m_can_skip = tmp.first;
81 } );
82 (void)run_after_parse;
83 return json_details::
84 parse_value<element_type, false, element_type::expected_type>( tmp );
85 }
86
92 [[nodiscard]] constexpr pointer operator->( ) const {
93 return pointer{ operator*( ) };
94 }
95
100 m_state.has_more( ), ErrorReason::UnexpectedEndOfData, m_state );
101 if( m_can_skip ) {
102 m_state.first = m_can_skip;
103 m_can_skip = nullptr;
104 } else {
105 (void)json_details::skip_known_value<element_type>( m_state );
106 }
107 m_state.move_next_member_or_end( );
108 return *this;
109 }
110
112 constexpr void operator++( int ) & {
113 (void)operator++( );
114 }
115
118 [[nodiscard]] constexpr bool good( ) const {
119 return not m_state.is_null( ) and m_state.has_more( );
120 }
121
124 [[nodiscard]] explicit constexpr operator bool( ) const {
125 return good( );
126 }
127
131 [[nodiscard]] constexpr bool
132 operator==( json_lines_iterator const &rhs ) const {
133 if( not( *this ) ) {
134 return not rhs;
135 }
136 if( not rhs ) {
137 return false;
138 }
139 return ( m_state.first == rhs.m_state.first );
140 }
141
145 [[nodiscard]] constexpr bool
146 operator!=( json_lines_iterator const &rhs ) const {
147 if( not( *this ) ) {
148 return static_cast<bool>( rhs );
149 }
150 if( not rhs ) {
151 return true;
152 }
153 return m_state.first != rhs.m_state.first;
154 }
155
156 constexpr std::string_view get_raw_json_document( ) const {
157 return std::string_view( m_state.first, m_state.size( ) );
158 }
159 };
161
165 template<typename JsonElement = json_value, auto... PolicyFlags>
168 options::details::make_parse_flags<PolicyFlags...>( ).value>>;
169 using iterator = json_lines_iterator<JsonElement, PolicyFlags...>;
170
171 private:
172 iterator m_first{ };
173 iterator m_last{ };
174
175 public:
176 explicit json_lines_range( ) = default;
177
178 explicit constexpr json_lines_range( iterator first,
179 iterator last = iterator( ) )
180 : m_first( first )
181 , m_last( last ) {}
182
183 explicit constexpr json_lines_range( daw::string_view json_lines_doc )
184 : m_first( json_lines_doc ) {}
185
187 [[nodiscard]] constexpr iterator begin( ) const {
188 return m_first;
189 }
190
192 [[nodiscard]] constexpr iterator end( ) const {
193 return m_last;
194 }
195
198 [[nodiscard]] constexpr bool empty( ) const {
199 return m_first == m_last;
200 }
201 };
202 json_lines_range( daw::string_view ) -> json_lines_range<>;
203
204 template<typename JsonElement, auto... PolicyFlags>
207 -> json_lines_range<JsonElement, PolicyFlags...>;
208
212 template<typename JsonElement = json_value, auto... ParsePolicies>
213 std::vector<json_lines_range<JsonElement, ParsePolicies...>>
214 partition_jsonl_document( std::size_t num_partitions,
215 daw::string_view jsonl_doc ) {
216 using result_t =
217 std::vector<json_lines_range<JsonElement, ParsePolicies...>>;
218 if( num_partitions <= 1 ) {
219 return result_t{
220 json_lines_range<JsonElement, ParsePolicies...>( jsonl_doc ) };
221 }
222 auto approx_segsize = jsonl_doc.size( ) / num_partitions;
223 auto result = result_t{ };
224 char const *const last = daw::data_end( jsonl_doc );
225 while( not jsonl_doc.empty( ) ) {
226 char const *tmp = std::data( jsonl_doc ) + approx_segsize;
227 if( tmp >= last ) {
228 result.emplace_back( jsonl_doc );
229 break;
230 }
231 while( tmp < last and *tmp != '\n' ) {
232 ++tmp;
233 }
234 if( tmp < last ) {
235 ++tmp;
236 }
237 auto sz = static_cast<std::size_t>( tmp - std::data( jsonl_doc ) );
238 auto doc = jsonl_doc.pop_front( sz );
239 doc.trim_suffix( );
240 if( not doc.empty( ) ) {
241 result.emplace_back( doc );
242 }
243 }
244 return result;
245 }
246 } // namespace DAW_JSON_VER
247} // 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