JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
parse_index.hpp
Go to the documentation of this file.
1/// \file jsonv/parse_index.hpp
2/// Parsed index of a JSON document.
3///
4/// Copyright (c) 2020 by Travis Gockel. All rights reserved.
5///
6/// This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
7/// as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
8/// version.
9///
10/// \author Travis Gockel (travis@gockelhut.com)
11#pragma once
12
13#include <jsonv/config.hpp>
14#include <jsonv/ast.hpp>
15
16#include <optional>
17
18namespace jsonv
19{
20
21class extract_options;
22class parse_options;
23
24/// \ingroup Value
25/// \{
26
27/// Represents the index of a parsed AST. When combined with the original text, can be used to create a \c value. See
28/// \c parse_index::parse to construct instances from JSON source text.
30{
31public:
33 {
34 public:
35 using value_type = ast_node;
36
37 public:
38 iterator() = default;
39
40 iterator& operator++();
41 iterator operator++(int)
42 {
43 iterator temp(*this);
44 ++*this;
45 return temp;
46 }
47
48 /// Move to the node after the structure this iterator is on, however much is inside it.
49 ///
50 /// This is a constant-time operation. The index records where each structure ends as it parses the matching
51 /// close token, so stepping over a subtree costs the same whether it holds one element or a million. Use it to
52 /// ignore a value without paying to walk it.
53 ///
54 /// \code
55 /// // `iter` is on the `[` of `"a": [ 1, 2, 3 ]`
56 /// iter.skip_subtree(); // now on the key which follows the array
57 /// \endcode
58 ///
59 /// If the structure was never closed -- only possible when \ref parse_index::success is \c false -- the
60 /// error which truncated the document stands in as its end, so this moves to the end of the index.
61 ///
62 /// \throws std::invalid_argument if this iterator is not on a \c ast_node_type::document_start,
63 /// \c ast_node_type::object_begin or \c ast_node_type::array_begin.
65
67 value_type operator*() const;
68
69 // Note the lack of comparison between `_prefix` -- valid `iterator`s will always have the same `_prefix`
71 bool operator==(const iterator& other) const { return _iter == other._iter; }
73 bool operator!=(const iterator& other) const { return _iter != other._iter; }
75 bool operator< (const iterator& other) const { return _iter < other._iter; }
77 bool operator<=(const iterator& other) const { return _iter <= other._iter; }
79 bool operator> (const iterator& other) const { return _iter > other._iter; }
81 bool operator>=(const iterator& other) const { return _iter >= other._iter; }
82
83 private:
84 explicit iterator(const std::uintptr_t prefix, const std::uint64_t* iter) :
85 _prefix(prefix),
86 _iter(iter)
87 { }
88
89 friend class parse_index;
90
91 private:
92 std::uintptr_t _prefix;
93 const std::uint64_t* _iter;
94 };
95
96 using const_iterator = iterator;
97
98public:
99 /// Creates an empty not-an-AST instance.
101
103 _impl(std::exchange(src._impl, nullptr))
104 { }
105
106 parse_index& operator=(parse_index&& src) noexcept
107 {
108 if (this == &src)
109 return *this;
110
111 using std::swap;
112 swap(_impl, src._impl);
113 src.reset();
114
115 return *this;
116 }
117
118 ~parse_index() noexcept;
119
120 /// \{
121 /// Create an \c parse_index from the given \a src JSON.
122 ///
123 /// \param options
124 /// The options used to control parsing. If unspecified, these will be \c parse_options::create_default().
125 /// \param initial_buffer_capacity
126 /// The initial capacity of the underlying buffer. By default (\c nullopt), this will size the buffer according
127 /// to the length of the \a src string.
129 static parse_index parse(std::string_view src,
130 const parse_options& options,
132 );
134 static parse_index parse(std::string_view src, std::optional<std::size_t> initial_buffer_capacity);
136 static parse_index parse(std::string_view src, const parse_options& options);
138 static parse_index parse(std::string_view src);
139 /// \}
140
141 /// Clear the contents of this instance.
142 void reset();
143
144 /// Check if this instance represents a valid AST. This will be \c false if the source JSON was not valid JSON text.
145 /// This will also be \c false if this instance was default-constructed or moved-from.
146 ///
147 /// \note
148 /// Even if this returns true, it is possible that conversion to a \c jsonv::value will throw an exception. For
149 /// example, if the value of a number exceeds the range of an \c int64_t. This is because JSON does not specify an
150 /// acceptable range for numbers, but the storage of \c jsonv::value does.
152 bool success() const noexcept;
153
154 /// See \ref success.
157
158 /// Validate that the parse was a \c success.
159 ///
160 /// \throws parse_error if the parse was not successful. This will contain additional details about why the parse
161 /// failed.
162 /// \throws std::invalid_argument if this instance was default-constructed or moved-from.
163 void validate() const;
164
166 iterator begin() const;
168 iterator cbegin() const { return begin(); }
169
171 iterator end() const;
172
174 iterator cend() const { return end(); }
175
176 /// \{
177 /// \param options
178 /// The options used to control how values are extracted from this source. If unspecified, these will be
179 /// \c extract_options::create_default().
181 value extract_tree(const extract_options& options) const;
183 value extract_tree() const;
184 /// \}
185
186 /// \{
187 /// Get a string representation of the AST.
188 ///
189 /// +--------------------+--------+
190 /// | `ast_node_type` | Output |
191 /// +--------------------+--------+
192 /// | `document_start` | `^` |
193 /// | `document_end` | `$` |
194 /// | `object_begin` | `{` |
195 /// | `object_end` | `}` |
196 /// | `array_begin` | `[` |
197 /// | `array_end` | `]` |
198 /// | `string_canonical` | `s` |
199 /// | `string_escaped` | `S` |
200 /// | `key_canonical` | `k` |
201 /// | `key_escaped` | `K` |
202 /// | `literal_true` | `t` |
203 /// | `literal_false` | `f` |
204 /// | `literal_null` | `n` |
205 /// | `integer` | `i` |
206 /// | `decimal` | `d` |
207 /// | `error` | `!` |
208 /// +--------------------+--------+
209 ///
210 /// This exists primarily for debugging purposes.
211 friend std::ostream& operator<<(std::ostream&, const parse_index&);
212 friend std::string to_string(const parse_index&);
213 /// \}
214
215private:
216 struct impl;
217
218 explicit parse_index(impl*) noexcept;
219
220private:
221 impl* _impl = nullptr;
222};
223
224/// \}
225
226}
Utilities for directly dealing with a JSON AST.
Represents an entry in a JSON AST.
Definition ast.hpp:165
An adapter for enumeration types.
Configuration for various extraction options. This becomes part of the extraction_context.
Definition extract.hpp:213
iterator & skip_subtree()
Move to the node after the structure this iterator is on, however much is inside it.
Represents the index of a parsed AST.
parse_index() noexcept=default
Creates an empty not-an-AST instance.
friend std::ostream & operator<<(std::ostream &, const parse_index &)
value extract_tree(const extract_options &options) const
Configuration for various parsing options.
Definition parse.hpp:64
Represents a single JSON value, which can be any one of a potential kind, each behaving slightly diff...
Definition value.hpp:113
Copyright (c) 2014-2020 by Travis Gockel.
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:121
#define JSONV_PUBLIC
This function or class is part of the public API for JSON Voorhees.
Definition config.hpp:102
JSONV_PUBLIC void swap(value &a, value &b) noexcept
Swap the values a and b.
STL namespace.