jsoncons 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/jsoncons/extconf.rb +43 -0
- data/ext/jsoncons/jsoncons.cpp +161 -0
- data/ext/jsoncons/jsoncons.h +10 -0
- data/jsoncons.gemspec +44 -0
- data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
- data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
- data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
- data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
- data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
- data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
- data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
- data/lib/jsoncons/version.rb +5 -0
- data/lib/jsoncons.rb +33 -0
- data/test/jsoncons_test.rb +108 -0
- data/test/test_helper.rb +7 -0
- metadata +268 -0
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
// Copyright 2013 Daniel Parker
|
|
2
|
+
// Distributed under the Boost license, Version 1.0.
|
|
3
|
+
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
4
|
+
|
|
5
|
+
// See https://github.com/danielaparker/jsoncons for latest version
|
|
6
|
+
|
|
7
|
+
#ifndef JSONCONS_CSV_CSV_ENCODER_HPP
|
|
8
|
+
#define JSONCONS_CSV_CSV_ENCODER_HPP
|
|
9
|
+
|
|
10
|
+
#include <array> // std::array
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <vector>
|
|
13
|
+
#include <ostream>
|
|
14
|
+
#include <utility> // std::move
|
|
15
|
+
#include <unordered_map> // std::unordered_map
|
|
16
|
+
#include <memory> // std::allocator
|
|
17
|
+
#include <limits> // std::numeric_limits
|
|
18
|
+
#include <jsoncons/json_exception.hpp>
|
|
19
|
+
#include <jsoncons/json_visitor.hpp>
|
|
20
|
+
#include <jsoncons/detail/write_number.hpp>
|
|
21
|
+
#include <jsoncons_ext/csv/csv_options.hpp>
|
|
22
|
+
#include <jsoncons/sink.hpp>
|
|
23
|
+
|
|
24
|
+
namespace jsoncons { namespace csv {
|
|
25
|
+
|
|
26
|
+
template<class CharT,class Sink=jsoncons::stream_sink<CharT>,class Allocator=std::allocator<char>>
|
|
27
|
+
class basic_csv_encoder final : public basic_json_visitor<CharT>
|
|
28
|
+
{
|
|
29
|
+
public:
|
|
30
|
+
using char_type = CharT;
|
|
31
|
+
using typename basic_json_visitor<CharT>::string_view_type;
|
|
32
|
+
using sink_type = Sink;
|
|
33
|
+
|
|
34
|
+
using allocator_type = Allocator;
|
|
35
|
+
using char_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT>;
|
|
36
|
+
using string_type = std::basic_string<CharT, std::char_traits<CharT>, char_allocator_type>;
|
|
37
|
+
using string_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<string_type>;
|
|
38
|
+
using string_string_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<std::pair<const string_type,string_type>>;
|
|
39
|
+
|
|
40
|
+
private:
|
|
41
|
+
static jsoncons::basic_string_view<CharT> null_constant()
|
|
42
|
+
{
|
|
43
|
+
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"null");
|
|
44
|
+
return k;
|
|
45
|
+
}
|
|
46
|
+
static jsoncons::basic_string_view<CharT> true_constant()
|
|
47
|
+
{
|
|
48
|
+
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"true");
|
|
49
|
+
return k;
|
|
50
|
+
}
|
|
51
|
+
static jsoncons::basic_string_view<CharT> false_constant()
|
|
52
|
+
{
|
|
53
|
+
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"false");
|
|
54
|
+
return k;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
enum class stack_item_kind
|
|
58
|
+
{
|
|
59
|
+
row_mapping,
|
|
60
|
+
column_mapping,
|
|
61
|
+
object,
|
|
62
|
+
row,
|
|
63
|
+
column,
|
|
64
|
+
object_multi_valued_field,
|
|
65
|
+
row_multi_valued_field,
|
|
66
|
+
column_multi_valued_field
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
struct stack_item
|
|
70
|
+
{
|
|
71
|
+
stack_item_kind item_kind_;
|
|
72
|
+
std::size_t count_;
|
|
73
|
+
|
|
74
|
+
stack_item(stack_item_kind item_kind) noexcept
|
|
75
|
+
: item_kind_(item_kind), count_(0)
|
|
76
|
+
{
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
bool is_object() const
|
|
80
|
+
{
|
|
81
|
+
return item_kind_ == stack_item_kind::object;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
stack_item_kind item_kind() const
|
|
85
|
+
{
|
|
86
|
+
return item_kind_;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
Sink sink_;
|
|
91
|
+
const basic_csv_encode_options<CharT> options_;
|
|
92
|
+
allocator_type alloc_;
|
|
93
|
+
|
|
94
|
+
std::vector<stack_item> stack_;
|
|
95
|
+
jsoncons::detail::write_double fp_;
|
|
96
|
+
std::vector<string_type,string_allocator_type> strings_buffer_;
|
|
97
|
+
|
|
98
|
+
std::unordered_map<string_type,string_type, std::hash<string_type>,std::equal_to<string_type>,string_string_allocator_type> buffered_line_;
|
|
99
|
+
string_type name_;
|
|
100
|
+
std::size_t column_index_;
|
|
101
|
+
std::vector<std::size_t> row_counts_;
|
|
102
|
+
|
|
103
|
+
// Noncopyable and nonmoveable
|
|
104
|
+
basic_csv_encoder(const basic_csv_encoder&) = delete;
|
|
105
|
+
basic_csv_encoder& operator=(const basic_csv_encoder&) = delete;
|
|
106
|
+
public:
|
|
107
|
+
basic_csv_encoder(Sink&& sink,
|
|
108
|
+
const Allocator& alloc = Allocator())
|
|
109
|
+
: basic_csv_encoder(std::forward<Sink>(sink), basic_csv_encode_options<CharT>(), alloc)
|
|
110
|
+
{
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
basic_csv_encoder(Sink&& sink,
|
|
114
|
+
const basic_csv_encode_options<CharT>& options,
|
|
115
|
+
const Allocator& alloc = Allocator())
|
|
116
|
+
: sink_(std::forward<Sink>(sink)),
|
|
117
|
+
options_(options),
|
|
118
|
+
alloc_(alloc),
|
|
119
|
+
stack_(),
|
|
120
|
+
fp_(options.float_format(), options.precision()),
|
|
121
|
+
column_index_(0)
|
|
122
|
+
{
|
|
123
|
+
jsoncons::csv::detail::parse_column_names(options.column_names(), strings_buffer_);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
~basic_csv_encoder() noexcept
|
|
127
|
+
{
|
|
128
|
+
JSONCONS_TRY
|
|
129
|
+
{
|
|
130
|
+
sink_.flush();
|
|
131
|
+
}
|
|
132
|
+
JSONCONS_CATCH(...)
|
|
133
|
+
{
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
void reset()
|
|
138
|
+
{
|
|
139
|
+
stack_.clear();
|
|
140
|
+
strings_buffer_.clear();
|
|
141
|
+
buffered_line_.clear();
|
|
142
|
+
name_.clear();
|
|
143
|
+
column_index_ = 0;
|
|
144
|
+
row_counts_.clear();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
void reset(Sink&& sink)
|
|
148
|
+
{
|
|
149
|
+
sink_ = std::move(sink);
|
|
150
|
+
reset();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private:
|
|
154
|
+
|
|
155
|
+
template<class AnyWriter>
|
|
156
|
+
void escape_string(const CharT* s,
|
|
157
|
+
std::size_t length,
|
|
158
|
+
CharT quote_char, CharT quote_escape_char,
|
|
159
|
+
AnyWriter& sink)
|
|
160
|
+
{
|
|
161
|
+
const CharT* begin = s;
|
|
162
|
+
const CharT* end = s + length;
|
|
163
|
+
for (const CharT* it = begin; it != end; ++it)
|
|
164
|
+
{
|
|
165
|
+
CharT c = *it;
|
|
166
|
+
if (c == quote_char)
|
|
167
|
+
{
|
|
168
|
+
sink.push_back(quote_escape_char);
|
|
169
|
+
sink.push_back(quote_char);
|
|
170
|
+
}
|
|
171
|
+
else
|
|
172
|
+
{
|
|
173
|
+
sink.push_back(c);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
void visit_flush() override
|
|
179
|
+
{
|
|
180
|
+
sink_.flush();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override
|
|
184
|
+
{
|
|
185
|
+
if (stack_.empty())
|
|
186
|
+
{
|
|
187
|
+
stack_.emplace_back(stack_item_kind::column_mapping);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
switch (stack_.back().item_kind_)
|
|
191
|
+
{
|
|
192
|
+
case stack_item_kind::row_mapping:
|
|
193
|
+
stack_.emplace_back(stack_item_kind::object);
|
|
194
|
+
return true;
|
|
195
|
+
default: // error
|
|
196
|
+
ec = csv_errc::source_error;
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
bool visit_end_object(const ser_context&, std::error_code&) override
|
|
202
|
+
{
|
|
203
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
204
|
+
|
|
205
|
+
switch (stack_.back().item_kind_)
|
|
206
|
+
{
|
|
207
|
+
case stack_item_kind::object:
|
|
208
|
+
if (stack_[0].count_ == 0)
|
|
209
|
+
{
|
|
210
|
+
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
|
|
211
|
+
{
|
|
212
|
+
if (i > 0)
|
|
213
|
+
{
|
|
214
|
+
sink_.push_back(options_.field_delimiter());
|
|
215
|
+
}
|
|
216
|
+
sink_.append(strings_buffer_[i].data(),
|
|
217
|
+
strings_buffer_[i].length());
|
|
218
|
+
}
|
|
219
|
+
sink_.append(options_.line_delimiter().data(),
|
|
220
|
+
options_.line_delimiter().length());
|
|
221
|
+
}
|
|
222
|
+
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
|
|
223
|
+
{
|
|
224
|
+
if (i > 0)
|
|
225
|
+
{
|
|
226
|
+
sink_.push_back(options_.field_delimiter());
|
|
227
|
+
}
|
|
228
|
+
auto it = buffered_line_.find(strings_buffer_[i]);
|
|
229
|
+
if (it != buffered_line_.end())
|
|
230
|
+
{
|
|
231
|
+
sink_.append(it->second.data(),it->second.length());
|
|
232
|
+
it->second.clear();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
sink_.append(options_.line_delimiter().data(), options_.line_delimiter().length());
|
|
236
|
+
break;
|
|
237
|
+
case stack_item_kind::column_mapping:
|
|
238
|
+
{
|
|
239
|
+
for (const auto& item : strings_buffer_)
|
|
240
|
+
{
|
|
241
|
+
sink_.append(item.data(), item.size());
|
|
242
|
+
sink_.append(options_.line_delimiter().data(), options_.line_delimiter().length());
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
default:
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
stack_.pop_back();
|
|
250
|
+
if (!stack_.empty())
|
|
251
|
+
{
|
|
252
|
+
end_value();
|
|
253
|
+
}
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override
|
|
258
|
+
{
|
|
259
|
+
if (stack_.empty())
|
|
260
|
+
{
|
|
261
|
+
stack_.emplace_back(stack_item_kind::row_mapping);
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
switch (stack_.back().item_kind_)
|
|
265
|
+
{
|
|
266
|
+
case stack_item_kind::row_mapping:
|
|
267
|
+
stack_.emplace_back(stack_item_kind::row);
|
|
268
|
+
if (stack_[0].count_ == 0)
|
|
269
|
+
{
|
|
270
|
+
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
|
|
271
|
+
{
|
|
272
|
+
if (i > 0)
|
|
273
|
+
{
|
|
274
|
+
sink_.push_back(options_.field_delimiter());
|
|
275
|
+
}
|
|
276
|
+
sink_.append(strings_buffer_[i].data(),strings_buffer_[i].length());
|
|
277
|
+
}
|
|
278
|
+
if (strings_buffer_.size() > 0)
|
|
279
|
+
{
|
|
280
|
+
sink_.append(options_.line_delimiter().data(),
|
|
281
|
+
options_.line_delimiter().length());
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
case stack_item_kind::object:
|
|
286
|
+
stack_.emplace_back(stack_item_kind::object_multi_valued_field);
|
|
287
|
+
return true;
|
|
288
|
+
case stack_item_kind::column_mapping:
|
|
289
|
+
stack_.emplace_back(stack_item_kind::column);
|
|
290
|
+
row_counts_.push_back(1);
|
|
291
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
292
|
+
{
|
|
293
|
+
strings_buffer_.emplace_back();
|
|
294
|
+
}
|
|
295
|
+
return true;
|
|
296
|
+
case stack_item_kind::column:
|
|
297
|
+
{
|
|
298
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
299
|
+
{
|
|
300
|
+
strings_buffer_.emplace_back();
|
|
301
|
+
}
|
|
302
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
303
|
+
begin_value(bo);
|
|
304
|
+
stack_.emplace_back(stack_item_kind::column_multi_valued_field);
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
case stack_item_kind::row:
|
|
308
|
+
begin_value(sink_);
|
|
309
|
+
stack_.emplace_back(stack_item_kind::row_multi_valued_field);
|
|
310
|
+
return true;
|
|
311
|
+
default: // error
|
|
312
|
+
ec = csv_errc::source_error;
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
bool visit_end_array(const ser_context&, std::error_code&) override
|
|
318
|
+
{
|
|
319
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
320
|
+
switch (stack_.back().item_kind_)
|
|
321
|
+
{
|
|
322
|
+
case stack_item_kind::row:
|
|
323
|
+
sink_.append(options_.line_delimiter().data(),
|
|
324
|
+
options_.line_delimiter().length());
|
|
325
|
+
break;
|
|
326
|
+
case stack_item_kind::column:
|
|
327
|
+
++column_index_;
|
|
328
|
+
break;
|
|
329
|
+
default:
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
stack_.pop_back();
|
|
333
|
+
|
|
334
|
+
if (!stack_.empty())
|
|
335
|
+
{
|
|
336
|
+
end_value();
|
|
337
|
+
}
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
|
|
342
|
+
{
|
|
343
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
344
|
+
switch (stack_.back().item_kind_)
|
|
345
|
+
{
|
|
346
|
+
case stack_item_kind::object:
|
|
347
|
+
{
|
|
348
|
+
name_ = string_type(name);
|
|
349
|
+
buffered_line_[string_type(name)] = std::basic_string<CharT>();
|
|
350
|
+
if (stack_[0].count_ == 0 && options_.column_names().size() == 0)
|
|
351
|
+
{
|
|
352
|
+
strings_buffer_.emplace_back(name);
|
|
353
|
+
}
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
case stack_item_kind::column_mapping:
|
|
357
|
+
{
|
|
358
|
+
if (strings_buffer_.empty())
|
|
359
|
+
{
|
|
360
|
+
strings_buffer_.emplace_back(name);
|
|
361
|
+
}
|
|
362
|
+
else
|
|
363
|
+
{
|
|
364
|
+
strings_buffer_[0].push_back(options_.field_delimiter());
|
|
365
|
+
strings_buffer_[0].append(string_type(name));
|
|
366
|
+
}
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
default:
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
bool visit_null(semantic_tag, const ser_context&, std::error_code&) override
|
|
376
|
+
{
|
|
377
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
378
|
+
switch (stack_.back().item_kind_)
|
|
379
|
+
{
|
|
380
|
+
case stack_item_kind::object:
|
|
381
|
+
case stack_item_kind::object_multi_valued_field:
|
|
382
|
+
{
|
|
383
|
+
auto it = buffered_line_.find(name_);
|
|
384
|
+
if (it != buffered_line_.end())
|
|
385
|
+
{
|
|
386
|
+
std::basic_string<CharT> s;
|
|
387
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
|
388
|
+
write_null_value(bo);
|
|
389
|
+
bo.flush();
|
|
390
|
+
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
|
391
|
+
{
|
|
392
|
+
it->second.push_back(options_.subfield_delimiter());
|
|
393
|
+
}
|
|
394
|
+
it->second.append(s);
|
|
395
|
+
}
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
case stack_item_kind::row:
|
|
399
|
+
case stack_item_kind::row_multi_valued_field:
|
|
400
|
+
write_null_value(sink_);
|
|
401
|
+
break;
|
|
402
|
+
case stack_item_kind::column:
|
|
403
|
+
{
|
|
404
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
405
|
+
{
|
|
406
|
+
strings_buffer_.emplace_back();
|
|
407
|
+
}
|
|
408
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
409
|
+
write_null_value(bo);
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
case stack_item_kind::column_multi_valued_field:
|
|
413
|
+
{
|
|
414
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
415
|
+
write_null_value(bo);
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
default:
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
bool visit_string(const string_view_type& sv, semantic_tag, const ser_context&, std::error_code&) override
|
|
425
|
+
{
|
|
426
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
427
|
+
switch (stack_.back().item_kind_)
|
|
428
|
+
{
|
|
429
|
+
case stack_item_kind::object:
|
|
430
|
+
case stack_item_kind::object_multi_valued_field:
|
|
431
|
+
{
|
|
432
|
+
auto it = buffered_line_.find(name_);
|
|
433
|
+
if (it != buffered_line_.end())
|
|
434
|
+
{
|
|
435
|
+
std::basic_string<CharT> s;
|
|
436
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
|
437
|
+
write_string_value(sv,bo);
|
|
438
|
+
bo.flush();
|
|
439
|
+
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
|
440
|
+
{
|
|
441
|
+
it->second.push_back(options_.subfield_delimiter());
|
|
442
|
+
}
|
|
443
|
+
it->second.append(s);
|
|
444
|
+
}
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
case stack_item_kind::row:
|
|
448
|
+
case stack_item_kind::row_multi_valued_field:
|
|
449
|
+
write_string_value(sv,sink_);
|
|
450
|
+
break;
|
|
451
|
+
case stack_item_kind::column:
|
|
452
|
+
{
|
|
453
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
454
|
+
{
|
|
455
|
+
strings_buffer_.emplace_back();
|
|
456
|
+
}
|
|
457
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
458
|
+
write_string_value(sv,bo);
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
case stack_item_kind::column_multi_valued_field:
|
|
462
|
+
{
|
|
463
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
464
|
+
write_string_value(sv,bo);
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
default:
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
bool visit_byte_string(const byte_string_view& b,
|
|
474
|
+
semantic_tag tag,
|
|
475
|
+
const ser_context& context,
|
|
476
|
+
std::error_code& ec) override
|
|
477
|
+
{
|
|
478
|
+
byte_string_chars_format encoding_hint;
|
|
479
|
+
switch (tag)
|
|
480
|
+
{
|
|
481
|
+
case semantic_tag::base16:
|
|
482
|
+
encoding_hint = byte_string_chars_format::base16;
|
|
483
|
+
break;
|
|
484
|
+
case semantic_tag::base64:
|
|
485
|
+
encoding_hint = byte_string_chars_format::base64;
|
|
486
|
+
break;
|
|
487
|
+
case semantic_tag::base64url:
|
|
488
|
+
encoding_hint = byte_string_chars_format::base64url;
|
|
489
|
+
break;
|
|
490
|
+
default:
|
|
491
|
+
encoding_hint = byte_string_chars_format::none;
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
byte_string_chars_format format = jsoncons::detail::resolve_byte_string_chars_format(encoding_hint,byte_string_chars_format::none,byte_string_chars_format::base64url);
|
|
495
|
+
|
|
496
|
+
std::basic_string<CharT> s;
|
|
497
|
+
switch (format)
|
|
498
|
+
{
|
|
499
|
+
case byte_string_chars_format::base16:
|
|
500
|
+
{
|
|
501
|
+
encode_base16(b.begin(),b.end(),s);
|
|
502
|
+
visit_string(s, semantic_tag::none, context, ec);
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
case byte_string_chars_format::base64:
|
|
506
|
+
{
|
|
507
|
+
encode_base64(b.begin(),b.end(),s);
|
|
508
|
+
visit_string(s, semantic_tag::none, context, ec);
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case byte_string_chars_format::base64url:
|
|
512
|
+
{
|
|
513
|
+
encode_base64url(b.begin(),b.end(),s);
|
|
514
|
+
visit_string(s, semantic_tag::none, context, ec);
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
default:
|
|
518
|
+
{
|
|
519
|
+
JSONCONS_UNREACHABLE();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
bool visit_double(double val,
|
|
527
|
+
semantic_tag,
|
|
528
|
+
const ser_context& context,
|
|
529
|
+
std::error_code& ec) override
|
|
530
|
+
{
|
|
531
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
532
|
+
switch (stack_.back().item_kind_)
|
|
533
|
+
{
|
|
534
|
+
case stack_item_kind::object:
|
|
535
|
+
case stack_item_kind::object_multi_valued_field:
|
|
536
|
+
{
|
|
537
|
+
auto it = buffered_line_.find(name_);
|
|
538
|
+
if (it != buffered_line_.end())
|
|
539
|
+
{
|
|
540
|
+
std::basic_string<CharT> s;
|
|
541
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
|
542
|
+
write_double_value(val, context, bo, ec);
|
|
543
|
+
bo.flush();
|
|
544
|
+
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
|
545
|
+
{
|
|
546
|
+
it->second.push_back(options_.subfield_delimiter());
|
|
547
|
+
}
|
|
548
|
+
it->second.append(s);
|
|
549
|
+
}
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
case stack_item_kind::row:
|
|
553
|
+
case stack_item_kind::row_multi_valued_field:
|
|
554
|
+
write_double_value(val, context, sink_, ec);
|
|
555
|
+
break;
|
|
556
|
+
case stack_item_kind::column:
|
|
557
|
+
{
|
|
558
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
559
|
+
{
|
|
560
|
+
strings_buffer_.emplace_back();
|
|
561
|
+
}
|
|
562
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
563
|
+
write_double_value(val, context, bo, ec);
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
case stack_item_kind::column_multi_valued_field:
|
|
567
|
+
{
|
|
568
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
569
|
+
write_double_value(val, context, bo, ec);
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
default:
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
bool visit_int64(int64_t val,
|
|
579
|
+
semantic_tag,
|
|
580
|
+
const ser_context&,
|
|
581
|
+
std::error_code&) override
|
|
582
|
+
{
|
|
583
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
584
|
+
switch (stack_.back().item_kind_)
|
|
585
|
+
{
|
|
586
|
+
case stack_item_kind::object:
|
|
587
|
+
case stack_item_kind::object_multi_valued_field:
|
|
588
|
+
{
|
|
589
|
+
auto it = buffered_line_.find(name_);
|
|
590
|
+
if (it != buffered_line_.end())
|
|
591
|
+
{
|
|
592
|
+
std::basic_string<CharT> s;
|
|
593
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
|
594
|
+
write_int64_value(val,bo);
|
|
595
|
+
bo.flush();
|
|
596
|
+
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
|
597
|
+
{
|
|
598
|
+
it->second.push_back(options_.subfield_delimiter());
|
|
599
|
+
}
|
|
600
|
+
it->second.append(s);
|
|
601
|
+
}
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
case stack_item_kind::row:
|
|
605
|
+
case stack_item_kind::row_multi_valued_field:
|
|
606
|
+
write_int64_value(val,sink_);
|
|
607
|
+
break;
|
|
608
|
+
case stack_item_kind::column:
|
|
609
|
+
{
|
|
610
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
611
|
+
{
|
|
612
|
+
strings_buffer_.emplace_back();
|
|
613
|
+
}
|
|
614
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
615
|
+
write_int64_value(val, bo);
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
case stack_item_kind::column_multi_valued_field:
|
|
619
|
+
{
|
|
620
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
621
|
+
write_int64_value(val, bo);
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
624
|
+
default:
|
|
625
|
+
break;
|
|
626
|
+
}
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
bool visit_uint64(uint64_t val,
|
|
631
|
+
semantic_tag,
|
|
632
|
+
const ser_context&,
|
|
633
|
+
std::error_code&) override
|
|
634
|
+
{
|
|
635
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
636
|
+
switch (stack_.back().item_kind_)
|
|
637
|
+
{
|
|
638
|
+
case stack_item_kind::object:
|
|
639
|
+
case stack_item_kind::object_multi_valued_field:
|
|
640
|
+
{
|
|
641
|
+
auto it = buffered_line_.find(name_);
|
|
642
|
+
if (it != buffered_line_.end())
|
|
643
|
+
{
|
|
644
|
+
std::basic_string<CharT> s;
|
|
645
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
|
646
|
+
write_uint64_value(val, bo);
|
|
647
|
+
bo.flush();
|
|
648
|
+
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
|
649
|
+
{
|
|
650
|
+
it->second.push_back(options_.subfield_delimiter());
|
|
651
|
+
}
|
|
652
|
+
it->second.append(s);
|
|
653
|
+
}
|
|
654
|
+
break;
|
|
655
|
+
}
|
|
656
|
+
case stack_item_kind::row:
|
|
657
|
+
case stack_item_kind::row_multi_valued_field:
|
|
658
|
+
write_uint64_value(val,sink_);
|
|
659
|
+
break;
|
|
660
|
+
case stack_item_kind::column:
|
|
661
|
+
{
|
|
662
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
663
|
+
{
|
|
664
|
+
strings_buffer_.emplace_back();
|
|
665
|
+
}
|
|
666
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
667
|
+
write_uint64_value(val, bo);
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
case stack_item_kind::column_multi_valued_field:
|
|
671
|
+
{
|
|
672
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
673
|
+
write_uint64_value(val, bo);
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
default:
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
return true;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) override
|
|
683
|
+
{
|
|
684
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
685
|
+
switch (stack_.back().item_kind_)
|
|
686
|
+
{
|
|
687
|
+
case stack_item_kind::object:
|
|
688
|
+
case stack_item_kind::object_multi_valued_field:
|
|
689
|
+
{
|
|
690
|
+
auto it = buffered_line_.find(name_);
|
|
691
|
+
if (it != buffered_line_.end())
|
|
692
|
+
{
|
|
693
|
+
std::basic_string<CharT> s;
|
|
694
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
|
|
695
|
+
write_bool_value(val,bo);
|
|
696
|
+
bo.flush();
|
|
697
|
+
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
|
|
698
|
+
{
|
|
699
|
+
it->second.push_back(options_.subfield_delimiter());
|
|
700
|
+
}
|
|
701
|
+
it->second.append(s);
|
|
702
|
+
}
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
case stack_item_kind::row:
|
|
706
|
+
case stack_item_kind::row_multi_valued_field:
|
|
707
|
+
write_bool_value(val,sink_);
|
|
708
|
+
break;
|
|
709
|
+
case stack_item_kind::column:
|
|
710
|
+
{
|
|
711
|
+
if (strings_buffer_.size() <= row_counts_.back())
|
|
712
|
+
{
|
|
713
|
+
strings_buffer_.emplace_back();
|
|
714
|
+
}
|
|
715
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
716
|
+
write_bool_value(val, bo);
|
|
717
|
+
break;
|
|
718
|
+
}
|
|
719
|
+
case stack_item_kind::column_multi_valued_field:
|
|
720
|
+
{
|
|
721
|
+
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
|
|
722
|
+
write_bool_value(val, bo);
|
|
723
|
+
break;
|
|
724
|
+
}
|
|
725
|
+
default:
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
return true;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
template <class AnyWriter>
|
|
732
|
+
bool do_string_value(const CharT* s, std::size_t length, AnyWriter& sink)
|
|
733
|
+
{
|
|
734
|
+
bool quote = false;
|
|
735
|
+
if (options_.quote_style() == quote_style_kind::all || options_.quote_style() == quote_style_kind::nonnumeric ||
|
|
736
|
+
(options_.quote_style() == quote_style_kind::minimal &&
|
|
737
|
+
(std::char_traits<CharT>::find(s, length, options_.field_delimiter()) != nullptr || std::char_traits<CharT>::find(s, length, options_.quote_char()) != nullptr)))
|
|
738
|
+
{
|
|
739
|
+
quote = true;
|
|
740
|
+
sink.push_back(options_.quote_char());
|
|
741
|
+
}
|
|
742
|
+
escape_string(s, length, options_.quote_char(), options_.quote_escape_char(), sink);
|
|
743
|
+
if (quote)
|
|
744
|
+
{
|
|
745
|
+
sink.push_back(options_.quote_char());
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return true;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
template <class AnyWriter>
|
|
752
|
+
void write_string_value(const string_view_type& value, AnyWriter& sink)
|
|
753
|
+
{
|
|
754
|
+
begin_value(sink);
|
|
755
|
+
do_string_value(value.data(),value.length(),sink);
|
|
756
|
+
end_value();
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
template <class AnyWriter>
|
|
760
|
+
void write_double_value(double val, const ser_context& context, AnyWriter& sink, std::error_code& ec)
|
|
761
|
+
{
|
|
762
|
+
begin_value(sink);
|
|
763
|
+
|
|
764
|
+
if (!std::isfinite(val))
|
|
765
|
+
{
|
|
766
|
+
if ((std::isnan)(val))
|
|
767
|
+
{
|
|
768
|
+
if (options_.enable_nan_to_num())
|
|
769
|
+
{
|
|
770
|
+
sink.append(options_.nan_to_num().data(), options_.nan_to_num().length());
|
|
771
|
+
}
|
|
772
|
+
else if (options_.enable_nan_to_str())
|
|
773
|
+
{
|
|
774
|
+
visit_string(options_.nan_to_str(), semantic_tag::none, context, ec);
|
|
775
|
+
}
|
|
776
|
+
else
|
|
777
|
+
{
|
|
778
|
+
sink.append(null_constant().data(), null_constant().size());
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
else if (val == std::numeric_limits<double>::infinity())
|
|
782
|
+
{
|
|
783
|
+
if (options_.enable_inf_to_num())
|
|
784
|
+
{
|
|
785
|
+
sink.append(options_.inf_to_num().data(), options_.inf_to_num().length());
|
|
786
|
+
}
|
|
787
|
+
else if (options_.enable_inf_to_str())
|
|
788
|
+
{
|
|
789
|
+
visit_string(options_.inf_to_str(), semantic_tag::none, context, ec);
|
|
790
|
+
}
|
|
791
|
+
else
|
|
792
|
+
{
|
|
793
|
+
sink.append(null_constant().data(), null_constant().size());
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
else
|
|
797
|
+
{
|
|
798
|
+
if (options_.enable_neginf_to_num())
|
|
799
|
+
{
|
|
800
|
+
sink.append(options_.neginf_to_num().data(), options_.neginf_to_num().length());
|
|
801
|
+
}
|
|
802
|
+
else if (options_.enable_neginf_to_str())
|
|
803
|
+
{
|
|
804
|
+
visit_string(options_.neginf_to_str(), semantic_tag::none, context, ec);
|
|
805
|
+
}
|
|
806
|
+
else
|
|
807
|
+
{
|
|
808
|
+
sink.append(null_constant().data(), null_constant().size());
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
else
|
|
813
|
+
{
|
|
814
|
+
fp_(val, sink);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
end_value();
|
|
818
|
+
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
template <class AnyWriter>
|
|
822
|
+
void write_int64_value(int64_t val, AnyWriter& sink)
|
|
823
|
+
{
|
|
824
|
+
begin_value(sink);
|
|
825
|
+
|
|
826
|
+
jsoncons::detail::from_integer(val,sink);
|
|
827
|
+
|
|
828
|
+
end_value();
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
template <class AnyWriter>
|
|
832
|
+
void write_uint64_value(uint64_t val, AnyWriter& sink)
|
|
833
|
+
{
|
|
834
|
+
begin_value(sink);
|
|
835
|
+
|
|
836
|
+
jsoncons::detail::from_integer(val,sink);
|
|
837
|
+
|
|
838
|
+
end_value();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
template <class AnyWriter>
|
|
842
|
+
void write_bool_value(bool val, AnyWriter& sink)
|
|
843
|
+
{
|
|
844
|
+
begin_value(sink);
|
|
845
|
+
|
|
846
|
+
if (val)
|
|
847
|
+
{
|
|
848
|
+
sink.append(true_constant().data(), true_constant().size());
|
|
849
|
+
}
|
|
850
|
+
else
|
|
851
|
+
{
|
|
852
|
+
sink.append(false_constant().data(), false_constant().size());
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
end_value();
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
template <class AnyWriter>
|
|
859
|
+
bool write_null_value(AnyWriter& sink)
|
|
860
|
+
{
|
|
861
|
+
begin_value(sink);
|
|
862
|
+
sink.append(null_constant().data(), null_constant().size());
|
|
863
|
+
end_value();
|
|
864
|
+
return true;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
template <class AnyWriter>
|
|
868
|
+
void begin_value(AnyWriter& sink)
|
|
869
|
+
{
|
|
870
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
871
|
+
switch (stack_.back().item_kind_)
|
|
872
|
+
{
|
|
873
|
+
case stack_item_kind::row:
|
|
874
|
+
if (stack_.back().count_ > 0)
|
|
875
|
+
{
|
|
876
|
+
sink.push_back(options_.field_delimiter());
|
|
877
|
+
}
|
|
878
|
+
break;
|
|
879
|
+
case stack_item_kind::column:
|
|
880
|
+
{
|
|
881
|
+
if (row_counts_.size() >= 3)
|
|
882
|
+
{
|
|
883
|
+
for (std::size_t i = row_counts_.size()-2; i-- > 0;)
|
|
884
|
+
{
|
|
885
|
+
if (row_counts_[i] <= row_counts_.back())
|
|
886
|
+
{
|
|
887
|
+
sink.push_back(options_.field_delimiter());
|
|
888
|
+
}
|
|
889
|
+
else
|
|
890
|
+
{
|
|
891
|
+
break;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
if (column_index_ > 0)
|
|
896
|
+
{
|
|
897
|
+
sink.push_back(options_.field_delimiter());
|
|
898
|
+
}
|
|
899
|
+
break;
|
|
900
|
+
}
|
|
901
|
+
case stack_item_kind::row_multi_valued_field:
|
|
902
|
+
case stack_item_kind::column_multi_valued_field:
|
|
903
|
+
if (stack_.back().count_ > 0 && options_.subfield_delimiter() != char_type())
|
|
904
|
+
{
|
|
905
|
+
sink.push_back(options_.subfield_delimiter());
|
|
906
|
+
}
|
|
907
|
+
break;
|
|
908
|
+
default:
|
|
909
|
+
break;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
void end_value()
|
|
914
|
+
{
|
|
915
|
+
JSONCONS_ASSERT(!stack_.empty());
|
|
916
|
+
switch(stack_.back().item_kind_)
|
|
917
|
+
{
|
|
918
|
+
case stack_item_kind::row:
|
|
919
|
+
{
|
|
920
|
+
++stack_.back().count_;
|
|
921
|
+
break;
|
|
922
|
+
}
|
|
923
|
+
case stack_item_kind::column:
|
|
924
|
+
{
|
|
925
|
+
++row_counts_.back();
|
|
926
|
+
break;
|
|
927
|
+
}
|
|
928
|
+
default:
|
|
929
|
+
++stack_.back().count_;
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
using csv_stream_encoder = basic_csv_encoder<char>;
|
|
936
|
+
using csv_string_encoder = basic_csv_encoder<char,jsoncons::string_sink<std::string>>;
|
|
937
|
+
using csv_wstream_encoder = basic_csv_encoder<wchar_t>;
|
|
938
|
+
using wcsv_string_encoder = basic_csv_encoder<wchar_t,jsoncons::string_sink<std::wstring>>;
|
|
939
|
+
|
|
940
|
+
#if !defined(JSONCONS_NO_DEPRECATED)
|
|
941
|
+
template<class CharT, class Sink = jsoncons::stream_sink<CharT>, class Allocator = std::allocator<CharT>>
|
|
942
|
+
using basic_csv_serializer = basic_csv_encoder<CharT,Sink,Allocator>;
|
|
943
|
+
|
|
944
|
+
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_serializer;
|
|
945
|
+
JSONCONS_DEPRECATED_MSG("Instead, use csv_string_encoder") typedef csv_string_encoder csv_string_serializer;
|
|
946
|
+
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_serializer;
|
|
947
|
+
JSONCONS_DEPRECATED_MSG("Instead, use csv_string_encoder") typedef csv_string_encoder csv_string_serializer;
|
|
948
|
+
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_encoder;
|
|
949
|
+
JSONCONS_DEPRECATED_MSG("Instead, use wcsv_stream_encoder") typedef csv_stream_encoder wcsv_encoder;
|
|
950
|
+
#endif
|
|
951
|
+
|
|
952
|
+
}}
|
|
953
|
+
|
|
954
|
+
#endif
|