Coverage Report

Created: 2025-07-11 07:05

/src/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2013-2025 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_READER_HPP
8
#define JSONCONS_CSV_CSV_READER_HPP
9
10
#include <cstddef>
11
#include <functional>
12
#include <memory> // std::allocator
13
#include <system_error>
14
#include <utility> // std::move
15
16
#include <jsoncons/config/compiler_support.hpp>
17
#include <jsoncons/json_decoder.hpp>
18
#include <jsoncons/json_exception.hpp>
19
#include <jsoncons/json_reader.hpp>
20
#include <jsoncons/json_visitor.hpp>
21
#include <jsoncons/ser_context.hpp>
22
#include <jsoncons/source.hpp>
23
#include <jsoncons/source_adaptor.hpp>
24
25
#include <jsoncons_ext/csv/csv_error.hpp>
26
#include <jsoncons_ext/csv/csv_options.hpp>
27
#include <jsoncons_ext/csv/csv_parser.hpp>
28
29
namespace jsoncons { 
30
namespace csv {
31
32
    template <typename CharT,typename Source=jsoncons::stream_source<CharT>,typename Allocator=std::allocator<char>>
33
    class basic_csv_reader 
34
    {
35
        struct stack_item
36
        {
37
            stack_item() noexcept
38
               : array_begun_(false)
39
            {
40
            }
41
42
            bool array_begun_;
43
        };
44
        using char_type = CharT;
45
        using temp_allocator_type = Allocator;
46
        using char_allocator_type = typename std::allocator_traits<temp_allocator_type>:: template rebind_alloc<CharT>;
47
48
        basic_csv_reader(const basic_csv_reader&) = delete; 
49
        basic_csv_reader& operator = (const basic_csv_reader&) = delete; 
50
51
        basic_default_json_visitor<CharT> default_visitor_;
52
        text_source_adaptor<Source> source_;
53
        basic_json_visitor<CharT>& visitor_;
54
        basic_csv_parser<CharT,Allocator> parser_;
55
56
    public:
57
        // Structural characters
58
        static constexpr size_t default_max_buffer_size = 16384;
59
        //!  Parse an input stream of CSV text into a json object
60
        /*!
61
          \param is The input stream to read from
62
        */
63
64
        template <typename Sourceable>
65
        basic_csv_reader(Sourceable&& source,
66
                         basic_json_visitor<CharT>& visitor, 
67
                         const Allocator& alloc = Allocator())
68
69
3.44k
           : basic_csv_reader(std::forward<Sourceable>(source), 
70
3.44k
                              visitor, 
71
3.44k
                              basic_csv_decode_options<CharT>(), 
72
3.44k
                              default_csv_parsing(), 
73
3.44k
                              alloc)
74
3.44k
        {
75
3.44k
        }
76
77
        template <typename Sourceable>
78
        basic_csv_reader(Sourceable&& source,
79
                         basic_json_visitor<CharT>& visitor,
80
                         const basic_csv_decode_options<CharT>& options, 
81
                         const Allocator& alloc = Allocator())
82
83
2.36k
            : basic_csv_reader(std::forward<Sourceable>(source), 
84
2.36k
                               visitor, 
85
2.36k
                               options, 
86
2.36k
                               default_csv_parsing(),
87
2.36k
                               alloc)
88
2.36k
        {
89
2.36k
        }
90
91
        template <typename Sourceable>
92
        basic_csv_reader(Sourceable&& source,
93
                         basic_json_visitor<CharT>& visitor,
94
                         std::function<bool(csv_errc,const ser_context&)> err_handler, 
95
                         const Allocator& alloc = Allocator())
96
            : basic_csv_reader(std::forward<Sourceable>(source), 
97
                               visitor, 
98
                               basic_csv_decode_options<CharT>(), 
99
                               err_handler,
100
                               alloc)
101
        {
102
        }
103
104
        template <typename Sourceable>
105
        basic_csv_reader(Sourceable&& source,
106
                         basic_json_visitor<CharT>& visitor,
107
                         const basic_csv_decode_options<CharT>& options,
108
                         std::function<bool(csv_errc,const ser_context&)> err_handler, 
109
                         const Allocator& alloc = Allocator())
110
5.81k
           : source_(std::forward<Sourceable>(source)),
111
5.81k
             visitor_(visitor),
112
5.81k
             parser_(options, err_handler, alloc)
113
             
114
5.81k
        {
115
5.81k
        }
jsoncons::csv::basic_csv_reader<char, jsoncons::stream_source<char>, std::__1::allocator<char> >::basic_csv_reader<std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, jsoncons::basic_json_visitor<char>&, jsoncons::csv::basic_csv_decode_options<char> const&, std::__1::function<bool (jsoncons::csv::csv_errc, jsoncons::ser_context const&)>, std::__1::allocator<char> const&)
Line
Count
Source
110
3.44k
           : source_(std::forward<Sourceable>(source)),
111
3.44k
             visitor_(visitor),
112
3.44k
             parser_(options, err_handler, alloc)
113
             
114
3.44k
        {
115
3.44k
        }
jsoncons::csv::basic_csv_reader<char, jsoncons::string_source<char>, std::__1::allocator<char> >::basic_csv_reader<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, jsoncons::basic_json_visitor<char>&, jsoncons::csv::basic_csv_decode_options<char> const&, std::__1::function<bool (jsoncons::csv::csv_errc, jsoncons::ser_context const&)>, std::__1::allocator<char> const&)
Line
Count
Source
110
2.36k
           : source_(std::forward<Sourceable>(source)),
111
2.36k
             visitor_(visitor),
112
2.36k
             parser_(options, err_handler, alloc)
113
             
114
2.36k
        {
115
2.36k
        }
116
117
5.81k
        ~basic_csv_reader() noexcept = default;
jsoncons::csv::basic_csv_reader<char, jsoncons::stream_source<char>, std::__1::allocator<char> >::~basic_csv_reader()
Line
Count
Source
117
3.44k
        ~basic_csv_reader() noexcept = default;
jsoncons::csv::basic_csv_reader<char, jsoncons::string_source<char>, std::__1::allocator<char> >::~basic_csv_reader()
Line
Count
Source
117
2.36k
        ~basic_csv_reader() noexcept = default;
118
119
        void read()
120
2.36k
        {
121
2.36k
            std::error_code ec;
122
2.36k
            read(ec);
123
2.36k
            if (JSONCONS_UNLIKELY(ec))
124
85
            {
125
85
                JSONCONS_THROW(ser_error(ec,parser_.line(),parser_.column()));
126
85
            }
127
2.36k
        }
128
129
        void read(std::error_code& ec)
130
5.81k
        {
131
5.81k
            read_internal(ec);
132
5.81k
        }
jsoncons::csv::basic_csv_reader<char, jsoncons::stream_source<char>, std::__1::allocator<char> >::read(std::__1::error_code&)
Line
Count
Source
130
3.44k
        {
131
3.44k
            read_internal(ec);
132
3.44k
        }
jsoncons::csv::basic_csv_reader<char, jsoncons::string_source<char>, std::__1::allocator<char> >::read(std::__1::error_code&)
Line
Count
Source
130
2.36k
        {
131
2.36k
            read_internal(ec);
132
2.36k
        }
133
134
        std::size_t line() const
135
        {
136
            return parser_.line();
137
        }
138
139
        std::size_t column() const
140
        {
141
            return parser_.column();
142
        }
143
144
        bool eof() const
145
        {
146
            return parser_.source_exhausted() && source_.eof();
147
        }
148
149
    private:
150
151
        void read_internal(std::error_code& ec)
152
5.81k
        {
153
5.81k
            if (source_.is_error())
154
0
            {
155
0
                ec = csv_errc::source_error;
156
0
                return;
157
0
            }   
158
47.2k
            while (!parser_.stopped())
159
41.5k
            {
160
41.5k
                if (parser_.source_exhausted())
161
41.5k
                {
162
41.5k
                    auto s = source_.read_buffer(ec);
163
41.5k
                    if (JSONCONS_UNLIKELY(ec)) return;
164
41.5k
                    if (s.size() > 0)
165
8.60k
                    {
166
8.60k
                        parser_.update(s.data(),s.size());
167
8.60k
                    }
168
41.5k
                }
169
41.5k
                parser_.parse_some(visitor_, ec);
170
41.5k
                if (JSONCONS_UNLIKELY(ec)) return;
171
41.5k
            }
172
5.81k
        }
jsoncons::csv::basic_csv_reader<char, jsoncons::stream_source<char>, std::__1::allocator<char> >::read_internal(std::__1::error_code&)
Line
Count
Source
152
3.44k
        {
153
3.44k
            if (source_.is_error())
154
0
            {
155
0
                ec = csv_errc::source_error;
156
0
                return;
157
0
            }   
158
29.5k
            while (!parser_.stopped())
159
26.1k
            {
160
26.1k
                if (parser_.source_exhausted())
161
26.1k
                {
162
26.1k
                    auto s = source_.read_buffer(ec);
163
26.1k
                    if (JSONCONS_UNLIKELY(ec)) return;
164
26.1k
                    if (s.size() > 0)
165
6.24k
                    {
166
6.24k
                        parser_.update(s.data(),s.size());
167
6.24k
                    }
168
26.1k
                }
169
26.1k
                parser_.parse_some(visitor_, ec);
170
26.1k
                if (JSONCONS_UNLIKELY(ec)) return;
171
26.1k
            }
172
3.44k
        }
jsoncons::csv::basic_csv_reader<char, jsoncons::string_source<char>, std::__1::allocator<char> >::read_internal(std::__1::error_code&)
Line
Count
Source
152
2.36k
        {
153
2.36k
            if (source_.is_error())
154
0
            {
155
0
                ec = csv_errc::source_error;
156
0
                return;
157
0
            }   
158
17.6k
            while (!parser_.stopped())
159
15.3k
            {
160
15.3k
                if (parser_.source_exhausted())
161
15.3k
                {
162
15.3k
                    auto s = source_.read_buffer(ec);
163
15.3k
                    if (JSONCONS_UNLIKELY(ec)) return;
164
15.3k
                    if (s.size() > 0)
165
2.35k
                    {
166
2.35k
                        parser_.update(s.data(),s.size());
167
2.35k
                    }
168
15.3k
                }
169
15.3k
                parser_.parse_some(visitor_, ec);
170
15.3k
                if (JSONCONS_UNLIKELY(ec)) return;
171
15.3k
            }
172
2.36k
        }
173
    };
174
175
    using csv_string_reader = basic_csv_reader<char,string_source<char>>;
176
    using wcsv_string_reader = basic_csv_reader<wchar_t,string_source<wchar_t>>;
177
    using csv_stream_reader = basic_csv_reader<char,stream_source<char>>;
178
    using wcsv_stream_reader = basic_csv_reader<wchar_t,stream_source<wchar_t>>;
179
180
}}
181
182
#endif