/src/jsoncons/include/jsoncons_ext/csv/csv_options.hpp
Line | Count | Source |
1 | | // Copyright 2013-2026 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_EXT_CSV_CSV_OPTIONS_HPP |
8 | | #define JSONCONS_EXT_CSV_CSV_OPTIONS_HPP |
9 | | |
10 | | #include <cstdint> |
11 | | #include <cwchar> |
12 | | #include <limits> // std::numeric_limits |
13 | | #include <map> |
14 | | #include <string> |
15 | | #include <unordered_map> // std::unordered_map |
16 | | #include <utility> // std::pair |
17 | | |
18 | | #include <jsoncons/json_options.hpp> |
19 | | #include <jsoncons/utility/string_utils.hpp> |
20 | | |
21 | | namespace jsoncons { |
22 | | namespace csv { |
23 | | |
24 | | enum class csv_column_type : uint8_t |
25 | | { |
26 | | string_t,integer_t,float_t,boolean_t,repeat_t |
27 | | }; |
28 | | |
29 | | enum class quote_style_kind : uint8_t |
30 | | { |
31 | | minimal,all,nonnumeric,none |
32 | | }; |
33 | | |
34 | | enum class csv_mapping_kind : uint8_t |
35 | | { |
36 | | n_rows = 1, |
37 | | n_objects, |
38 | | m_columns |
39 | | }; |
40 | | |
41 | | enum class column_state {sequence,label}; |
42 | | |
43 | | struct csv_type_info |
44 | | { |
45 | | csv_type_info() = default; |
46 | | csv_type_info(const csv_type_info&) = default; |
47 | | csv_type_info(csv_type_info&&) = default; |
48 | | |
49 | | csv_type_info(csv_column_type ctype, std::size_t lev, std::size_t repcount = 0) noexcept |
50 | 0 | { |
51 | 0 | col_type = ctype; |
52 | 0 | level = lev; |
53 | 0 | rep_count = repcount; |
54 | 0 | } |
55 | | |
56 | | csv_column_type col_type; |
57 | | std::size_t level; |
58 | | std::size_t rep_count; |
59 | | }; |
60 | | |
61 | | namespace detail { |
62 | | |
63 | | template <typename CharT,typename Container> |
64 | | void parse_column_names(const std::basic_string<CharT>& names, |
65 | | Container& cont) |
66 | 5.49k | { |
67 | 5.49k | column_state state = column_state::sequence; |
68 | 5.49k | typename Container::value_type buffer(cont.get_allocator()); |
69 | | |
70 | 5.49k | auto p = names.begin(); |
71 | 5.49k | while (p != names.end()) |
72 | 0 | { |
73 | 0 | switch (state) |
74 | 0 | { |
75 | 0 | case column_state::sequence: |
76 | 0 | { |
77 | 0 | switch (*p) |
78 | 0 | { |
79 | 0 | case ' ': case '\t':case '\r': case '\n': |
80 | 0 | ++p; |
81 | 0 | break; |
82 | 0 | default: |
83 | 0 | buffer.clear(); |
84 | 0 | state = column_state::label; |
85 | 0 | break; |
86 | 0 | } |
87 | 0 | break; |
88 | 0 | } |
89 | 0 | case column_state::label: |
90 | 0 | { |
91 | 0 | switch (*p) |
92 | 0 | { |
93 | 0 | case ',': |
94 | 0 | cont.push_back(buffer); |
95 | 0 | buffer.clear(); |
96 | 0 | ++p; |
97 | 0 | state = column_state::sequence; |
98 | 0 | break; |
99 | 0 | default: |
100 | 0 | buffer.push_back(*p); |
101 | 0 | ++p; |
102 | 0 | break; |
103 | 0 | } |
104 | 0 | break; |
105 | 0 | } |
106 | 0 | } |
107 | 0 | } |
108 | 5.49k | if (state == column_state::label) |
109 | 0 | { |
110 | 0 | cont.push_back(buffer); |
111 | 0 | buffer.clear(); |
112 | 0 | } |
113 | | |
114 | 5.49k | } // namespace detail |
115 | | |
116 | | template <typename CharT,typename Container> |
117 | | void parse_column_types(const std::basic_string<CharT>& types, |
118 | | Container& column_types) |
119 | 2.74k | { |
120 | 2.74k | const std::map<jsoncons::basic_string_view<CharT>,csv_column_type> type_dictionary = |
121 | 2.74k | { |
122 | | |
123 | 2.74k | {JSONCONS_STRING_VIEW_CONSTANT(CharT,"string"),csv_column_type::string_t}, |
124 | 2.74k | {JSONCONS_STRING_VIEW_CONSTANT(CharT,"integer"),csv_column_type::integer_t}, |
125 | 2.74k | {JSONCONS_STRING_VIEW_CONSTANT(CharT,"float"),csv_column_type::float_t}, |
126 | 2.74k | {JSONCONS_STRING_VIEW_CONSTANT(CharT,"boolean"),csv_column_type::boolean_t} |
127 | 2.74k | }; |
128 | | |
129 | 2.74k | column_state state = column_state::sequence; |
130 | 2.74k | int depth = 0; |
131 | 2.74k | std::basic_string<CharT> buffer; |
132 | | |
133 | 2.74k | auto p = types.begin(); |
134 | 2.74k | while (p != types.end()) |
135 | 0 | { |
136 | 0 | switch (state) |
137 | 0 | { |
138 | 0 | case column_state::sequence: |
139 | 0 | { |
140 | 0 | switch (*p) |
141 | 0 | { |
142 | 0 | case ' ': case '\t':case '\r': case '\n': |
143 | 0 | ++p; |
144 | 0 | break; |
145 | 0 | case '[': |
146 | 0 | ++depth; |
147 | 0 | ++p; |
148 | 0 | break; |
149 | 0 | case ']': |
150 | 0 | JSONCONS_ASSERT(depth > 0); |
151 | 0 | --depth; |
152 | 0 | ++p; |
153 | 0 | break; |
154 | 0 | case '*': |
155 | 0 | { |
156 | 0 | JSONCONS_ASSERT(column_types.size() != 0); |
157 | 0 | std::size_t offset = 0; |
158 | 0 | std::size_t level = column_types.size() > 0 ? column_types.back().level: 0; |
159 | 0 | if (level > 0) |
160 | 0 | { |
161 | 0 | for (auto it = column_types.rbegin(); |
162 | 0 | it != column_types.rend() && level == (*it).level; |
163 | 0 | ++it) |
164 | 0 | { |
165 | 0 | ++offset; |
166 | 0 | } |
167 | 0 | } |
168 | 0 | else |
169 | 0 | { |
170 | 0 | offset = 1; |
171 | 0 | } |
172 | 0 | column_types.emplace_back(csv_column_type::repeat_t,depth,offset); |
173 | 0 | ++p; |
174 | 0 | break; |
175 | 0 | } |
176 | 0 | default: |
177 | 0 | buffer.clear(); |
178 | 0 | state = column_state::label; |
179 | 0 | break; |
180 | 0 | } |
181 | 0 | break; |
182 | 0 | } |
183 | 0 | case column_state::label: |
184 | 0 | { |
185 | 0 | switch (*p) |
186 | 0 | { |
187 | 0 | case '*': |
188 | 0 | { |
189 | 0 | auto it = type_dictionary.find(buffer); |
190 | 0 | if (it != type_dictionary.end()) |
191 | 0 | { |
192 | 0 | column_types.emplace_back((*it).second,depth); |
193 | 0 | buffer.clear(); |
194 | 0 | } |
195 | 0 | else |
196 | 0 | { |
197 | 0 | JSONCONS_ASSERT(false); |
198 | 0 | } |
199 | 0 | state = column_state::sequence; |
200 | 0 | break; |
201 | 0 | } |
202 | 0 | case ',': |
203 | 0 | { |
204 | 0 | auto it = type_dictionary.find(buffer); |
205 | 0 | if (it != type_dictionary.end()) |
206 | 0 | { |
207 | 0 | column_types.emplace_back((*it).second,depth); |
208 | 0 | buffer.clear(); |
209 | 0 | } |
210 | 0 | else |
211 | 0 | { |
212 | 0 | JSONCONS_ASSERT(false); |
213 | 0 | } |
214 | 0 | ++p; |
215 | 0 | state = column_state::sequence; |
216 | 0 | break; |
217 | 0 | } |
218 | 0 | case ']': |
219 | 0 | { |
220 | 0 | JSONCONS_ASSERT(depth > 0); |
221 | 0 | auto it = type_dictionary.find(buffer); |
222 | 0 | if (it != type_dictionary.end()) |
223 | 0 | { |
224 | 0 | column_types.emplace_back((*it).second,depth); |
225 | 0 | buffer.clear(); |
226 | 0 | } |
227 | 0 | else |
228 | 0 | { |
229 | 0 | JSONCONS_ASSERT(false); |
230 | 0 | } |
231 | 0 | --depth; |
232 | 0 | ++p; |
233 | 0 | state = column_state::sequence; |
234 | 0 | break; |
235 | 0 | } |
236 | 0 | default: |
237 | 0 | { |
238 | 0 | buffer.push_back(*p); |
239 | 0 | ++p; |
240 | 0 | break; |
241 | 0 | } |
242 | 0 | } |
243 | 0 | break; |
244 | 0 | } |
245 | 0 | } |
246 | 0 | } |
247 | 2.74k | if (state == column_state::label) |
248 | 0 | { |
249 | 0 | auto it = type_dictionary.find(buffer); |
250 | 0 | if (it != type_dictionary.end()) |
251 | 0 | { |
252 | 0 | column_types.emplace_back((*it).second,depth); |
253 | 0 | buffer.clear(); |
254 | 0 | } |
255 | 0 | else |
256 | 0 | { |
257 | 0 | JSONCONS_ASSERT(false); |
258 | 0 | } |
259 | 0 | } |
260 | 2.74k | } |
261 | | |
262 | | } // namespace detail |
263 | | |
264 | | template <typename CharT> |
265 | | class basic_csv_options; |
266 | | |
267 | | template <typename CharT> |
268 | | class basic_csv_options_common |
269 | | { |
270 | | friend class basic_csv_options<CharT>; |
271 | | public: |
272 | | using char_type = CharT; |
273 | | using string_type = std::basic_string<CharT>; |
274 | | private: |
275 | | char_type field_delimiter_{','}; |
276 | | char_type quote_char_{'\"'}; |
277 | | char_type quote_escape_char_{'\"'}; |
278 | | char_type subfield_delimiter_{char_type{}}; |
279 | | |
280 | | bool flat_:1; |
281 | | bool enable_nan_to_num_:1; |
282 | | bool enable_inf_to_num_:1; |
283 | | bool enable_neginf_to_num_:1; |
284 | | bool enable_nan_to_str_:1; |
285 | | bool enable_inf_to_str_:1; |
286 | | bool enable_neginf_to_str_:1; |
287 | | bool enable_str_to_nan_:1; |
288 | | bool enable_str_to_inf_:1; |
289 | | bool enable_str_to_neginf_:1; |
290 | | |
291 | | string_type nan_to_num_; |
292 | | string_type inf_to_num_; |
293 | | string_type neginf_to_num_; |
294 | | string_type nan_to_str_; |
295 | | string_type inf_to_str_; |
296 | | string_type neginf_to_str_; |
297 | | string_type column_names_; |
298 | | std::vector<std::pair<std::string,std::string>> column_mapping_; |
299 | | std::size_t max_nesting_depth_{1024}; |
300 | | |
301 | | protected: |
302 | | basic_csv_options_common() |
303 | 2.74k | : flat_{true}, |
304 | 2.74k | enable_nan_to_num_{false}, |
305 | 2.74k | enable_inf_to_num_{false}, |
306 | 2.74k | enable_neginf_to_num_{false}, |
307 | 2.74k | enable_nan_to_str_{false}, |
308 | 2.74k | enable_inf_to_str_{false}, |
309 | 2.74k | enable_neginf_to_str_{false}, |
310 | 2.74k | enable_str_to_nan_{false}, |
311 | 2.74k | enable_str_to_inf_{false}, |
312 | 2.74k | enable_str_to_neginf_{false} |
313 | 2.74k | { |
314 | 2.74k | } |
315 | | |
316 | 2.74k | basic_csv_options_common(const basic_csv_options_common&) = default; |
317 | | basic_csv_options_common& operator=(const basic_csv_options_common&) = default; |
318 | | //basic_csv_options_common& operator=(basic_csv_options_common&&) = default; |
319 | | |
320 | 5.49k | virtual ~basic_csv_options_common() = default; |
321 | | public: |
322 | | |
323 | | bool flat() const |
324 | | { |
325 | | return flat_; |
326 | | } |
327 | | |
328 | | std::size_t max_nesting_depth() const |
329 | | { |
330 | | return max_nesting_depth_; |
331 | | } |
332 | | |
333 | | char_type field_delimiter() const |
334 | 2.74k | { |
335 | 2.74k | return field_delimiter_; |
336 | 2.74k | } |
337 | | |
338 | | const char_type subfield_delimiter() const |
339 | 2.74k | { |
340 | 2.74k | return subfield_delimiter_; |
341 | 2.74k | } |
342 | | |
343 | | char_type quote_char() const |
344 | 2.74k | { |
345 | 2.74k | return quote_char_; |
346 | 2.74k | } |
347 | | |
348 | | char_type quote_escape_char() const |
349 | 2.74k | { |
350 | 2.74k | return quote_escape_char_; |
351 | 2.74k | } |
352 | | |
353 | | const string_type& column_names() const |
354 | 2.74k | { |
355 | 2.74k | return column_names_; |
356 | 2.74k | } |
357 | | |
358 | | const std::vector<std::pair<std::string,std::string>>& column_mapping() const |
359 | | { |
360 | | return column_mapping_; |
361 | | } |
362 | | |
363 | | bool enable_nan_to_num() const |
364 | | { |
365 | | return enable_nan_to_num_; |
366 | | } |
367 | | |
368 | | bool enable_inf_to_num() const |
369 | | { |
370 | | return enable_inf_to_num_; |
371 | | } |
372 | | |
373 | | bool enable_neginf_to_num() const |
374 | | { |
375 | | return enable_neginf_to_num_ || enable_inf_to_num_; |
376 | | } |
377 | | |
378 | | bool enable_nan_to_str() const |
379 | | { |
380 | | return enable_nan_to_str_; |
381 | | } |
382 | | |
383 | | bool enable_str_to_nan() const |
384 | 2.74k | { |
385 | 2.74k | return enable_str_to_nan_; |
386 | 2.74k | } |
387 | | |
388 | | bool enable_inf_to_str() const |
389 | | { |
390 | | return enable_inf_to_str_; |
391 | | } |
392 | | |
393 | | bool enable_str_to_inf() const |
394 | 2.74k | { |
395 | 2.74k | return enable_str_to_inf_; |
396 | 2.74k | } |
397 | | |
398 | | bool enable_neginf_to_str() const |
399 | | { |
400 | | return enable_neginf_to_str_ || enable_inf_to_str_; |
401 | | } |
402 | | |
403 | | bool enable_str_to_neginf() const |
404 | 2.74k | { |
405 | 2.74k | return enable_str_to_neginf_ || enable_str_to_inf_; |
406 | 2.74k | } |
407 | | |
408 | | string_type nan_to_num() const |
409 | | { |
410 | | return nan_to_num_; |
411 | | } |
412 | | |
413 | | string_type inf_to_num() const |
414 | | { |
415 | | return inf_to_num_; |
416 | | } |
417 | | |
418 | | string_type neginf_to_num() const |
419 | | { |
420 | | if (enable_neginf_to_num_) |
421 | | { |
422 | | return neginf_to_num_; |
423 | | } |
424 | | else if (enable_inf_to_num_) |
425 | | { |
426 | | string_type s; |
427 | | s.push_back('-'); |
428 | | s.append(inf_to_num_); |
429 | | return s; |
430 | | } |
431 | | else |
432 | | { |
433 | | return neginf_to_num_; |
434 | | } |
435 | | } |
436 | | |
437 | | string_type nan_to_str() const |
438 | 0 | { |
439 | 0 | return nan_to_str_; |
440 | 0 | } |
441 | | |
442 | | string_type inf_to_str() const |
443 | 0 | { |
444 | 0 | return inf_to_str_; |
445 | 0 | } |
446 | | |
447 | | string_type neginf_to_str() const |
448 | 0 | { |
449 | 0 | if (enable_neginf_to_str_) |
450 | 0 | { |
451 | 0 | return neginf_to_str_; |
452 | 0 | } |
453 | 0 | else if (enable_inf_to_str_) |
454 | 0 | { |
455 | 0 | string_type s; |
456 | 0 | s.push_back('-'); |
457 | 0 | s.append(inf_to_str_); |
458 | 0 | return s; |
459 | 0 | } |
460 | 0 | else |
461 | 0 | { |
462 | 0 | return neginf_to_str_; // empty string |
463 | 0 | } |
464 | 0 | } |
465 | | }; |
466 | | |
467 | | template <typename CharT> |
468 | | class basic_csv_decode_options : public virtual basic_csv_options_common<CharT> |
469 | | { |
470 | | friend class basic_csv_options<CharT>; |
471 | | using super_type = basic_csv_options_common<CharT>; |
472 | | public: |
473 | | using typename super_type::char_type; |
474 | | using typename super_type::string_type; |
475 | | |
476 | | private: |
477 | | bool assume_header_:1; |
478 | | bool ignore_empty_values_:1; |
479 | | bool ignore_empty_lines_:1; |
480 | | bool trim_leading_:1; |
481 | | bool trim_trailing_:1; |
482 | | bool trim_leading_inside_quotes_:1; |
483 | | bool trim_trailing_inside_quotes_:1; |
484 | | bool unquoted_empty_value_is_null_:1; |
485 | | bool infer_types_:1; |
486 | | bool lossless_number_:1; |
487 | | char_type comment_starter_{'\0'}; |
488 | | csv_mapping_kind mapping_kind_{}; |
489 | | std::size_t header_lines_{0}; |
490 | | std::size_t max_lines_{(std::numeric_limits<std::size_t>::max)()}; |
491 | | string_type column_types_; |
492 | | string_type column_defaults_; |
493 | | public: |
494 | | basic_csv_decode_options() |
495 | 2.74k | : assume_header_(false), |
496 | 2.74k | ignore_empty_values_(false), |
497 | 2.74k | ignore_empty_lines_(true), |
498 | 2.74k | trim_leading_(false), |
499 | 2.74k | trim_trailing_(false), |
500 | 2.74k | trim_leading_inside_quotes_(false), |
501 | 2.74k | trim_trailing_inside_quotes_(false), |
502 | 2.74k | unquoted_empty_value_is_null_(false), |
503 | 2.74k | infer_types_(true), |
504 | 2.74k | lossless_number_(false) |
505 | 2.74k | {} |
506 | | |
507 | 2.74k | basic_csv_decode_options(const basic_csv_decode_options& other) = default; |
508 | | |
509 | | basic_csv_decode_options(basic_csv_decode_options&& other) noexcept |
510 | | : super_type(std::move(other)), |
511 | | assume_header_(other.assume_header_), |
512 | | ignore_empty_values_(other.ignore_empty_values_), |
513 | | ignore_empty_lines_(other.ignore_empty_lines_), |
514 | | trim_leading_(other.trim_leading_), |
515 | | trim_trailing_(other.trim_trailing_), |
516 | | trim_leading_inside_quotes_(other.trim_leading_inside_quotes_), |
517 | | trim_trailing_inside_quotes_(other.trim_trailing_inside_quotes_), |
518 | | unquoted_empty_value_is_null_(other.unquoted_empty_value_is_null_), |
519 | | infer_types_(other.infer_types_), |
520 | | lossless_number_(other.lossless_number_), |
521 | | comment_starter_(other.comment_starter_), |
522 | | mapping_kind_(other.mapping_kind_), |
523 | | header_lines_(other.header_lines_), |
524 | | max_lines_(other.max_lines_), |
525 | | column_types_(std::move(other.column_types_)), |
526 | | column_defaults_(std::move(other.column_defaults_)) |
527 | | {} |
528 | | |
529 | | protected: |
530 | | basic_csv_decode_options& operator=(const basic_csv_decode_options& other) = default; |
531 | | basic_csv_decode_options& operator=(basic_csv_decode_options&& other) = default; |
532 | | public: |
533 | | |
534 | | std::size_t header_lines() const |
535 | 2.74k | { |
536 | 2.74k | return (assume_header_ && header_lines_ <= 1) ? 1 : header_lines_; |
537 | 2.74k | } |
538 | | |
539 | | bool assume_header() const |
540 | 2.74k | { |
541 | 2.74k | return assume_header_; |
542 | 2.74k | } |
543 | | |
544 | | bool ignore_empty_values() const |
545 | 2.74k | { |
546 | 2.74k | return ignore_empty_values_; |
547 | 2.74k | } |
548 | | |
549 | | bool ignore_empty_lines() const |
550 | 2.74k | { |
551 | 2.74k | return ignore_empty_lines_; |
552 | 2.74k | } |
553 | | |
554 | | bool trim_leading() const |
555 | 2.74k | { |
556 | 2.74k | return trim_leading_; |
557 | 2.74k | } |
558 | | |
559 | | bool trim_trailing() const |
560 | 2.74k | { |
561 | 2.74k | return trim_trailing_; |
562 | 2.74k | } |
563 | | |
564 | | bool trim_leading_inside_quotes() const |
565 | 2.74k | { |
566 | 2.74k | return trim_leading_inside_quotes_; |
567 | 2.74k | } |
568 | | |
569 | | bool trim_trailing_inside_quotes() const |
570 | 2.74k | { |
571 | 2.74k | return trim_trailing_inside_quotes_; |
572 | 2.74k | } |
573 | | |
574 | | bool trim() const |
575 | | { |
576 | | return trim_leading_ && trim_trailing_; |
577 | | } |
578 | | |
579 | | bool trim_inside_quotes() const |
580 | | { |
581 | | return trim_leading_inside_quotes_ && trim_trailing_inside_quotes_; |
582 | | } |
583 | | |
584 | | bool unquoted_empty_value_is_null() const |
585 | 2.74k | { |
586 | 2.74k | return unquoted_empty_value_is_null_; |
587 | 2.74k | } |
588 | | |
589 | | bool infer_types() const |
590 | 2.74k | { |
591 | 2.74k | return infer_types_; |
592 | 2.74k | } |
593 | | |
594 | | bool lossless_number() const |
595 | 2.74k | { |
596 | 2.74k | return lossless_number_; |
597 | 2.74k | } |
598 | | |
599 | | char_type comment_starter() const |
600 | 2.74k | { |
601 | 2.74k | return comment_starter_; |
602 | 2.74k | } |
603 | | |
604 | | csv_mapping_kind mapping_kind() const |
605 | 2.74k | { |
606 | 2.74k | return mapping_kind_ != csv_mapping_kind() ? mapping_kind_ : (assume_header() || this->column_names().size() > 0 ? csv_mapping_kind::n_objects : csv_mapping_kind::n_rows); |
607 | 2.74k | } |
608 | | |
609 | | std::size_t max_lines() const |
610 | 2.74k | { |
611 | 2.74k | return max_lines_; |
612 | 2.74k | } |
613 | | |
614 | | string_type column_types() const |
615 | 2.74k | { |
616 | 2.74k | return column_types_; |
617 | 2.74k | } |
618 | | |
619 | | string_type column_defaults() const |
620 | 2.74k | { |
621 | 2.74k | return column_defaults_; |
622 | 2.74k | } |
623 | | }; |
624 | | |
625 | | template <typename CharT> |
626 | | class basic_csv_encode_options : public virtual basic_csv_options_common<CharT> |
627 | | { |
628 | | friend class basic_csv_options<CharT>; |
629 | | using super_type = basic_csv_options_common<CharT>; |
630 | | public: |
631 | | using typename super_type::char_type; |
632 | | using typename super_type::string_type; |
633 | | private: |
634 | | quote_style_kind quote_style_{quote_style_kind::minimal}; |
635 | | float_chars_format float_format_{float_chars_format::general}; |
636 | | int8_t precision_{0}; |
637 | | string_type line_delimiter_; |
638 | | public: |
639 | | basic_csv_encode_options() |
640 | 2.74k | { |
641 | 2.74k | line_delimiter_.push_back('\n'); |
642 | 2.74k | } |
643 | | |
644 | 2.74k | basic_csv_encode_options(const basic_csv_encode_options& other) = default; |
645 | | |
646 | | basic_csv_encode_options(basic_csv_encode_options&& other) noexcept |
647 | | : super_type(std::move(other)), |
648 | | quote_style_(other.quote_style_), |
649 | | float_format_(other.float_format_), |
650 | | precision_(other.precision_), |
651 | | line_delimiter_(std::move(other.line_delimiter_)) |
652 | | { |
653 | | } |
654 | | |
655 | | protected: |
656 | | basic_csv_encode_options& operator=(const basic_csv_encode_options& other) = default; |
657 | | basic_csv_encode_options& operator=(basic_csv_encode_options&& other) = default; |
658 | | public: |
659 | | |
660 | | quote_style_kind quote_style() const |
661 | | { |
662 | | return quote_style_; |
663 | | } |
664 | | |
665 | | float_chars_format float_format() const |
666 | | { |
667 | | return float_format_; |
668 | | } |
669 | | |
670 | | int8_t precision() const |
671 | | { |
672 | | return precision_; |
673 | | } |
674 | | |
675 | | string_type line_delimiter() const |
676 | | { |
677 | | return line_delimiter_; |
678 | | } |
679 | | }; |
680 | | |
681 | | template <typename CharT> |
682 | | class basic_csv_options final : public basic_csv_decode_options<CharT>, public basic_csv_encode_options<CharT> |
683 | | { |
684 | | using char_type = CharT; |
685 | | using string_type = std::basic_string<CharT>; |
686 | | |
687 | | public: |
688 | | using basic_csv_decode_options<CharT>::enable_str_to_nan; |
689 | | using basic_csv_decode_options<CharT>::enable_str_to_inf; |
690 | | using basic_csv_decode_options<CharT>::enable_str_to_neginf; |
691 | | using basic_csv_decode_options<CharT>::nan_to_str; |
692 | | using basic_csv_decode_options<CharT>::inf_to_str; |
693 | | using basic_csv_decode_options<CharT>::neginf_to_str; |
694 | | using basic_csv_decode_options<CharT>::nan_to_num; |
695 | | using basic_csv_decode_options<CharT>::inf_to_num; |
696 | | using basic_csv_decode_options<CharT>::neginf_to_num; |
697 | | using basic_csv_decode_options<CharT>::flat; |
698 | | using basic_csv_decode_options<CharT>::max_nesting_depth; |
699 | | using basic_csv_decode_options<CharT>::field_delimiter; |
700 | | using basic_csv_decode_options<CharT>::subfield_delimiter; |
701 | | using basic_csv_decode_options<CharT>::quote_char; |
702 | | using basic_csv_decode_options<CharT>::quote_escape_char; |
703 | | using basic_csv_decode_options<CharT>::column_names; |
704 | | using basic_csv_decode_options<CharT>::column_mapping; |
705 | | using basic_csv_decode_options<CharT>::header_lines; |
706 | | using basic_csv_decode_options<CharT>::assume_header; |
707 | | using basic_csv_decode_options<CharT>::ignore_empty_values; |
708 | | using basic_csv_decode_options<CharT>::ignore_empty_lines; |
709 | | using basic_csv_decode_options<CharT>::trim_leading; |
710 | | using basic_csv_decode_options<CharT>::trim_trailing; |
711 | | using basic_csv_decode_options<CharT>::trim_leading_inside_quotes; |
712 | | using basic_csv_decode_options<CharT>::trim_trailing_inside_quotes; |
713 | | using basic_csv_decode_options<CharT>::trim; |
714 | | using basic_csv_decode_options<CharT>::trim_inside_quotes; |
715 | | using basic_csv_decode_options<CharT>::unquoted_empty_value_is_null; |
716 | | using basic_csv_decode_options<CharT>::infer_types; |
717 | | using basic_csv_decode_options<CharT>::lossless_number; |
718 | | using basic_csv_decode_options<CharT>::comment_starter; |
719 | | using basic_csv_decode_options<CharT>::mapping_kind; |
720 | | using basic_csv_decode_options<CharT>::max_lines; |
721 | | using basic_csv_decode_options<CharT>::column_types; |
722 | | using basic_csv_decode_options<CharT>::column_defaults; |
723 | | using basic_csv_encode_options<CharT>::float_format; |
724 | | using basic_csv_encode_options<CharT>::precision; |
725 | | using basic_csv_encode_options<CharT>::line_delimiter; |
726 | | using basic_csv_encode_options<CharT>::quote_style; |
727 | | |
728 | | static constexpr size_t default_indent = 4; |
729 | | |
730 | | // Constructors |
731 | | |
732 | 2.74k | basic_csv_options() = default; |
733 | 2.74k | basic_csv_options(const basic_csv_options&) = default; |
734 | | basic_csv_options(basic_csv_options&&) = default; |
735 | | basic_csv_options& operator=(const basic_csv_options&) = default; |
736 | | basic_csv_options& operator=(basic_csv_options&&) = default; |
737 | | |
738 | | basic_csv_options& float_format(float_chars_format value) |
739 | | { |
740 | | this->float_format_ = value; |
741 | | return *this; |
742 | | } |
743 | | |
744 | | basic_csv_options& precision(int8_t value) |
745 | | { |
746 | | this->precision_ = value; |
747 | | return *this; |
748 | | } |
749 | | |
750 | | basic_csv_options& header_lines(std::size_t value) |
751 | | { |
752 | | this->header_lines_ = value; |
753 | | return *this; |
754 | | } |
755 | | |
756 | | basic_csv_options& assume_header(bool value) |
757 | 2.74k | { |
758 | 2.74k | this->assume_header_ = value; |
759 | 2.74k | return *this; |
760 | 2.74k | } |
761 | | |
762 | | basic_csv_options& ignore_empty_values(bool value) |
763 | | { |
764 | | this->ignore_empty_values_ = value; |
765 | | return *this; |
766 | | } |
767 | | |
768 | | basic_csv_options& ignore_empty_lines(bool value) |
769 | | { |
770 | | this->ignore_empty_lines_ = value; |
771 | | return *this; |
772 | | } |
773 | | |
774 | | basic_csv_options& trim_leading(bool value) |
775 | | { |
776 | | this->trim_leading_ = value; |
777 | | return *this; |
778 | | } |
779 | | |
780 | | basic_csv_options& trim_trailing(bool value) |
781 | | { |
782 | | this->trim_trailing_ = value; |
783 | | return *this; |
784 | | } |
785 | | |
786 | | basic_csv_options& trim_leading_inside_quotes(bool value) |
787 | | { |
788 | | this->trim_leading_inside_quotes_ = value; |
789 | | return *this; |
790 | | } |
791 | | |
792 | | basic_csv_options& trim_trailing_inside_quotes(bool value) |
793 | | { |
794 | | this->trim_trailing_inside_quotes_ = value; |
795 | | return *this; |
796 | | } |
797 | | |
798 | | basic_csv_options& trim(bool value) |
799 | | { |
800 | | this->trim_leading_ = value; |
801 | | this->trim_trailing_ = value; |
802 | | return *this; |
803 | | } |
804 | | |
805 | | basic_csv_options& trim_inside_quotes(bool value) |
806 | | { |
807 | | this->trim_leading_inside_quotes_ = value; |
808 | | this->trim_trailing_inside_quotes_ = value; |
809 | | return *this; |
810 | | } |
811 | | |
812 | | basic_csv_options& unquoted_empty_value_is_null(bool value) |
813 | | { |
814 | | this->unquoted_empty_value_is_null_ = value; |
815 | | return *this; |
816 | | } |
817 | | |
818 | | basic_csv_options& column_names(const string_type& value) |
819 | | { |
820 | | this->column_names_ = value; |
821 | | return *this; |
822 | | } |
823 | | |
824 | | basic_csv_options& column_mapping(const std::vector<std::pair<std::string,std::string>>& value) |
825 | | { |
826 | | this->column_mapping_ = value; |
827 | | return *this; |
828 | | } |
829 | | |
830 | | basic_csv_options& column_types(const string_type& value) |
831 | | { |
832 | | this->column_types_ = value; |
833 | | return *this; |
834 | | } |
835 | | |
836 | | basic_csv_options& column_defaults(const string_type& value) |
837 | | { |
838 | | this->column_defaults_ = value; |
839 | | return *this; |
840 | | } |
841 | | |
842 | | basic_csv_options& flat(bool value) |
843 | | { |
844 | | this->flat_ = value; |
845 | | return *this; |
846 | | } |
847 | | |
848 | | basic_csv_options& max_nesting_depth(std::size_t value) |
849 | | { |
850 | | this->max_nesting_depth_ = value; |
851 | | return *this; |
852 | | } |
853 | | |
854 | | basic_csv_options& field_delimiter(char_type value) |
855 | | { |
856 | | this->field_delimiter_ = value; |
857 | | return *this; |
858 | | } |
859 | | |
860 | | basic_csv_options& subfield_delimiter(char_type value) |
861 | | { |
862 | | this->subfield_delimiter_ = value; |
863 | | return *this; |
864 | | } |
865 | | |
866 | | basic_csv_options& line_delimiter(const string_type& value) |
867 | | { |
868 | | this->line_delimiter_ = value; |
869 | | return *this; |
870 | | } |
871 | | |
872 | | basic_csv_options& quote_char(char_type value) |
873 | | { |
874 | | this->quote_char_ = value; |
875 | | return *this; |
876 | | } |
877 | | |
878 | | basic_csv_options& infer_types(bool value) |
879 | | { |
880 | | this->infer_types_ = value; |
881 | | return *this; |
882 | | } |
883 | | |
884 | | basic_csv_options& lossless_number(bool value) |
885 | | { |
886 | | this->lossless_number_ = value; |
887 | | return *this; |
888 | | } |
889 | | |
890 | | basic_csv_options& quote_escape_char(char_type value) |
891 | | { |
892 | | this->quote_escape_char_ = value; |
893 | | return *this; |
894 | | } |
895 | | |
896 | | basic_csv_options& comment_starter(char_type value) |
897 | | { |
898 | | this->comment_starter_ = value; |
899 | | return *this; |
900 | | } |
901 | | |
902 | | basic_csv_options& quote_style(quote_style_kind value) |
903 | | { |
904 | | this->quote_style_ = value; |
905 | | return *this; |
906 | | } |
907 | | |
908 | | basic_csv_options& mapping_kind(csv_mapping_kind value) |
909 | 2.74k | { |
910 | 2.74k | this->mapping_kind_ = value; |
911 | 2.74k | return *this; |
912 | 2.74k | } |
913 | | |
914 | | basic_csv_options& max_lines(std::size_t value) |
915 | | { |
916 | | this->max_lines_ = value; |
917 | | return *this; |
918 | | } |
919 | | |
920 | | basic_csv_options& nan_to_num(const string_type& value) |
921 | | { |
922 | | this->enable_nan_to_num_ = true; |
923 | | this->nan_to_str_.clear(); |
924 | | this->nan_to_num_ = value; |
925 | | return *this; |
926 | | } |
927 | | |
928 | | basic_csv_options& inf_to_num(const string_type& value) |
929 | | { |
930 | | this->enable_inf_to_num_ = true; |
931 | | this->inf_to_str_.clear(); |
932 | | this->inf_to_num_ = value; |
933 | | return *this; |
934 | | } |
935 | | |
936 | | basic_csv_options& neginf_to_num(const string_type& value) |
937 | | { |
938 | | this->enable_neginf_to_num_ = true; |
939 | | this->neginf_to_str_.clear(); |
940 | | this->neginf_to_num_ = value; |
941 | | return *this; |
942 | | } |
943 | | |
944 | | basic_csv_options& nan_to_str(const string_type& value, bool enable_inverse = true) |
945 | | { |
946 | | this->enable_nan_to_str_ = true; |
947 | | this->enable_str_to_nan_ = enable_inverse; |
948 | | this->nan_to_num_.clear(); |
949 | | this->nan_to_str_ = value; |
950 | | return *this; |
951 | | } |
952 | | |
953 | | basic_csv_options& inf_to_str(const string_type& value, bool enable_inverse = true) |
954 | | { |
955 | | this->enable_inf_to_str_ = true; |
956 | | this->enable_inf_to_str_ = enable_inverse; |
957 | | this->inf_to_num_.clear(); |
958 | | this->inf_to_str_ = value; |
959 | | return *this; |
960 | | } |
961 | | |
962 | | basic_csv_options& neginf_to_str(const string_type& value, bool enable_inverse = true) |
963 | | { |
964 | | this->enable_neginf_to_str_ = true; |
965 | | this->enable_neginf_to_str_ = enable_inverse; |
966 | | this->neginf_to_num_.clear(); |
967 | | this->neginf_to_str_ = value; |
968 | | return *this; |
969 | | } |
970 | | |
971 | | }; |
972 | | |
973 | | using csv_options = basic_csv_options<char>; |
974 | | using wcsv_options = basic_csv_options<wchar_t>; |
975 | | |
976 | | } // namespace jsonpath |
977 | | } // namespace jsoncons |
978 | | |
979 | | #endif // JSONCONS_EXT_CSV_CSV_OPTIONS_HPP |