Coverage Report

Created: 2026-07-16 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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