diff options
Diffstat (limited to 'vendor/jsoncons-0.99.2/jsoncons_ext/csv')
5 files changed, 1919 insertions, 0 deletions
diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp new file mode 100644 index 00000000..5056d380 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_error_category.hpp @@ -0,0 +1,55 @@ +/// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_CSV_CSV_TEXT_ERROR_CATEGORY_HPP +#define JSONCONS_CSV_CSV_TEXT_ERROR_CATEGORY_HPP + +#include "jsoncons/jsoncons.hpp" +#include <system_error> + +namespace jsoncons { namespace csv { + +namespace csv_parser_errc +{ + const int unexpected_eof = 1; + const int expected_quote = 2; + const int invalid_csv_text = 3; + const int invalid_state = 4; +} + +class csv_error_category_impl + : public std::error_category +{ +public: + virtual const char* name() const JSONCONS_NOEXCEPT + { + return "csv"; + } + virtual std::string message(int ev) const + { + switch (ev) + { + case csv_parser_errc::unexpected_eof: + return "Unexpected end of file"; + case csv_parser_errc::expected_quote: + return "Expected quote character"; + case csv_parser_errc::invalid_csv_text: + return "Invalid CSV text"; + default: + return "Unknown JSON parser error"; + } + } +}; + +inline +const std::error_category& csv_error_category() +{ + static csv_error_category_impl instance; + return instance; +} + +}} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp new file mode 100644 index 00000000..099a154f --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parameters.hpp @@ -0,0 +1,341 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_CSV_CSV_PARAMETERS_HPP +#define JSONCONS_CSV_CSV_PARAMETERS_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <ostream> +#include <cstdlib> +#include <limits> +#include <cwchar> + +namespace jsoncons { namespace csv { + +enum class quote_styles +{ + all,minimal,none,nonnumeric +}; + +template <typename CharT> +class basic_csv_parameters +{ +public: + static const size_t default_indent = 4; + +// Constructors + + basic_csv_parameters() + : + assume_header_(false), + ignore_empty_values_(false), + trim_leading_(false), + trim_trailing_(false), + trim_leading_inside_quotes_(false), + trim_trailing_inside_quotes_(false), + unquoted_empty_value_is_null_(false), + field_delimiter_(','), + quote_char_('\"'), + quote_escape_char_('\"'), + comment_starter_('\0'), + quote_style_(quote_styles::minimal), + max_lines_(std::numeric_limits<unsigned long>::max JSONCONS_NO_MACRO_EXP()), + header_lines_(0) + { + line_delimiter_.push_back('\n'); + } + +// Properties + + size_t header_lines() const + { + return (assume_header_ && header_lines_ <= 1) ? 1 : header_lines_; + } + + basic_csv_parameters<CharT>& header_lines(size_t value) + { + header_lines_ = value; + return *this; + } + + bool assume_header() const + { + return assume_header_; + } + + basic_csv_parameters<CharT>& assume_header(bool value) + { + assume_header_ = value; + return *this; + } + + bool ignore_empty_values() const + { + return ignore_empty_values_; + } + + basic_csv_parameters<CharT>& ignore_empty_values(bool value) + { + ignore_empty_values_ = value; + return *this; + } + + bool trim_leading() const + { + return trim_leading_; + } + + basic_csv_parameters<CharT>& trim_leading(bool value) + { + trim_leading_ = value; + return *this; + } + + bool trim_trailing() const + { + return trim_trailing_; + } + + basic_csv_parameters<CharT>& trim_trailing(bool value) + { + trim_trailing_ = value; + return *this; + } + + bool trim_leading_inside_quotes() const + { + return trim_leading_inside_quotes_; + } + + basic_csv_parameters<CharT>& trim_leading_inside_quotes(bool value) + { + trim_leading_inside_quotes_ = value; + return *this; + } + + bool trim_trailing_inside_quotes() const + { + return trim_trailing_inside_quotes_; + } + + basic_csv_parameters<CharT>& trim_trailing_inside_quotes(bool value) + { + trim_trailing_inside_quotes_ = value; + return *this; + } + + bool trim() const + { + return trim_leading_ && trim_trailing_; + } + + basic_csv_parameters<CharT>& trim(bool value) + { + trim_leading_ = value; + trim_trailing_ = value; + return *this; + } + + bool trim_inside_quotes() const + { + return trim_leading_inside_quotes_ && trim_trailing_inside_quotes_; + } + + basic_csv_parameters<CharT>& trim_inside_quotes(bool value) + { + trim_leading_inside_quotes_ = value; + trim_trailing_inside_quotes_ = value; + return *this; + } + + bool unquoted_empty_value_is_null() const + { + return unquoted_empty_value_is_null_; + } + + basic_csv_parameters<CharT>& unquoted_empty_value_is_null(bool value) + { + unquoted_empty_value_is_null_ = value; + return *this; + } + + std::vector<std::basic_string<CharT>> column_names() const + { + return column_names_; + } + + basic_csv_parameters<CharT>& column_names(const std::vector<std::basic_string<CharT>>& value) + { + column_names_ = value; + return *this; + } + + std::vector<std::basic_string<CharT>> column_types() const + { + return column_types_; + } + + basic_csv_parameters<CharT>& column_types(const std::vector<std::basic_string<CharT>>& value) + { + column_types_ = value; + return *this; + } + + std::vector<std::basic_string<CharT>> column_defaults() const + { + return column_defaults_; + } + + basic_csv_parameters<CharT>& column_defaults(const std::vector<std::basic_string<CharT>>& value) + { + column_defaults_ = value; + return *this; + } + + CharT field_delimiter() const + { + return field_delimiter_; + } + + basic_csv_parameters<CharT>& field_delimiter(CharT value) + { + field_delimiter_ = value; + return *this; + } + + std::basic_string<CharT> line_delimiter() const + { + return line_delimiter_; + } + + basic_csv_parameters<CharT>& line_delimiter(std::basic_string<CharT> value) + { + line_delimiter_ = value; + return *this; + } + + CharT quote_char() const + { + return quote_char_; + } + + basic_csv_parameters<CharT>& quote_char(CharT value) + { + quote_char_ = value; + return *this; + } + + CharT quote_escape_char() const + { + return quote_escape_char_; + } + + basic_csv_parameters<CharT>& quote_escape_char(CharT value) + { + quote_escape_char_ = value; + return *this; + } + + CharT comment_starter() const + { + return comment_starter_; + } + + basic_csv_parameters<CharT>& comment_starter(CharT value) + { + comment_starter_ = value; + return *this; + } + + quote_styles quote_style() const + { + return quote_style_; + } + + basic_csv_parameters<CharT>& assume_header(quote_styles value) + { + quote_style_ = value; + return *this; + } + + unsigned long max_lines() const + { + return max_lines_; + } + + basic_csv_parameters<CharT>& max_lines(unsigned long value) + { + max_lines_ = value; + return *this; + } + +#if !defined(JSONCONS_NO_DEPRECATED) + + std::basic_string<CharT> header() const + { + return header_; + } + + basic_csv_parameters<CharT>& header(const std::basic_string<CharT>& value) + { + header_ = value; + return *this; + } + + std::basic_string<CharT> data_types() const + { + return data_types_; + } + + basic_csv_parameters<CharT>& data_types(const std::basic_string<CharT>& value) + { + data_types_ = value; + return *this; + } + + std::basic_string<CharT> default_values() const + { + return default_values_; + } + + basic_csv_parameters<CharT>& default_values(const std::basic_string<CharT>& value) + { + default_values_ = value; + return *this; + } +#endif +private: + bool assume_header_; + bool ignore_empty_values_; + bool trim_leading_; + bool trim_trailing_; + bool trim_leading_inside_quotes_; + bool trim_trailing_inside_quotes_; + bool unquoted_empty_value_is_null_; + CharT field_delimiter_; + CharT quote_char_; + CharT quote_escape_char_; + CharT comment_starter_; + quote_styles quote_style_; + unsigned long max_lines_; + size_t header_lines_; + std::basic_string<CharT> line_delimiter_; + std::basic_string<CharT> header_; + std::basic_string<CharT> data_types_; + std::basic_string<CharT> default_values_; + std::vector<std::basic_string<CharT>> column_names_; + std::vector<std::basic_string<CharT>> column_types_; + std::vector<std::basic_string<CharT>> column_defaults_; +}; + +typedef basic_csv_parameters<char> csv_parameters; +typedef basic_csv_parameters<wchar_t> wcsv_parameters; + +}} +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp new file mode 100644 index 00000000..14323666 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_parser.hpp @@ -0,0 +1,903 @@ +// Copyright 2015 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_CSV_CSV_PARSER_HPP +#define JSONCONS_CSV_CSV_PARSER_HPP + +#include <memory> +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <cstdlib> +#include <stdexcept> +#include <system_error> +#include <cctype> +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons/json_parser.hpp" +#include "jsoncons/json_filter.hpp" +#include "jsoncons_ext/csv/csv_error_category.hpp" +#include "jsoncons_ext/csv/csv_parameters.hpp" + +namespace jsoncons { namespace csv { + +template <typename CharT> +struct json_csv_parser_traits +{ +}; + +template <> +struct json_csv_parser_traits<char> +{ + static const std::string string_literal() {return "string";}; + + static const std::string integer_literal() {return "integer";}; + + static const std::string float_literal() {return "float";}; + + static const std::string boolean_literal() {return "boolean";}; +}; + +template <> +struct json_csv_parser_traits<wchar_t> // assume utf16 +{ + static const std::wstring string_literal() {return L"string";}; + + static const std::wstring integer_literal() {return L"integer";}; + + static const std::wstring float_literal() {return L"float";}; + + static const std::wstring boolean_literal() {return L"boolean";}; +}; + +enum class csv_modes { + done, + header, + array, + object +}; + +enum class csv_states +{ + start, + comment, + expect_value, + between_fields, + quoted_string, + unquoted_string, + escaped_value, + minus, + zero, + integer, + fraction, + exp1, + exp2, + exp3, + done +}; + +enum class data_types +{ + string_t,integer_t,float_t,boolean_t +}; + +template<typename CharT> +class basic_csv_parser : private basic_parsing_context<CharT> +{ + static const int default_depth = 3; + + csv_states state_; + int top_; + std::vector<csv_modes> stack_; + basic_json_input_handler<CharT> *handler_; + basic_parse_error_handler<CharT> *err_handler_; + bool is_negative_; + uint32_t cp_; + size_t index_; + unsigned long column_; + unsigned long line_; + int curr_char_; + int prev_char_; + std::basic_string<CharT> string_buffer_; + csv_states saved_state_; + int depth_; + basic_csv_parameters<CharT> parameters_; + std::vector<std::basic_string<CharT>> column_names_; + std::vector<data_types> column_types_; + std::vector<std::basic_string<CharT>> column_defaults_; + size_t column_index_; + basic_begin_end_json_filter<CharT> filter_; + basic_json_parser<CharT> parser_; + +public: + basic_csv_parser(basic_json_input_handler<CharT>& handler) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())), + is_negative_(false), + cp_(0), + index_(0), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + basic_csv_parser(basic_json_input_handler<CharT>& handler, + basic_csv_parameters<CharT> params) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(basic_default_parse_error_handler<CharT>::instance())), + is_negative_(false), + cp_(0), + index_(0), + parameters_(params), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + basic_csv_parser(basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)), + is_negative_(false), + cp_(0), + index_(0), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + basic_csv_parser(basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler, + basic_csv_parameters<CharT> params) + : top_(-1), + stack_(default_depth), + handler_(std::addressof(handler)), + err_handler_(std::addressof(err_handler)), + is_negative_(false), + cp_(0), + index_(0), + parameters_(params), + filter_(handler), + parser_(filter_) + { + depth_ = default_depth; + state_ = csv_states::start; + top_ = -1; + line_ = 1; + column_ = 0; + column_index_ = 0; + } + + ~basic_csv_parser() + { + } + + const basic_parsing_context<CharT>& parsing_context() const + { + return *this; + } + + bool done() const + { + return state_ == csv_states::done; + } + + const std::vector<std::basic_string<CharT>>& column_labels() const + { + return column_names_; + } + + void after_field() + { + ++column_index_; + } + + void before_record() + { + if (column_index_ == 0) + { + switch (stack_[top_]) + { + case csv_modes::array: + handler_->begin_array(*this); + break; + case csv_modes::object: + handler_->begin_object(*this); + break; + default: + break; + } + } + } + + void after_record() + { + switch (stack_[top_]) + { + case csv_modes::array: + handler_->end_array(*this); + break; + case csv_modes::object: + handler_->end_object(*this); + break; + case csv_modes::header: + if (line_ >= parameters_.header_lines()) + { + if (column_names_.size() > 0) + { + flip(csv_modes::header, csv_modes::object); + } + else + { + flip(csv_modes::header, csv_modes::array); + } + } + break; + default: + break; + } + column_index_ = 0; + } + + void begin_parse() + { + push(csv_modes::done); + handler_->begin_json(); + + if (parameters_.column_names().size() > 0) + { + column_names_ = parameters_.column_names(); + } +#if !defined(JSONCONS_NO_DEPRECATED) + else if (parameters_.header().length() > 0) + { + basic_empty_json_input_handler<CharT> ih; + basic_csv_parameters<CharT> params; + params.field_delimiter(parameters_.field_delimiter()); + params.quote_char(parameters_.quote_char()); + params.quote_escape_char(parameters_.quote_escape_char()); + params.assume_header(true); + basic_csv_parser<CharT> p(ih,params); + p.begin_parse(); + p.parse(parameters_.header().data(),0,parameters_.header().length()); + p.end_parse(); + column_names_ = p.column_labels(); + } +#endif + if (parameters_.column_types().size() > 0) + { + column_types_.resize(parameters_.column_types().size()); + for (size_t i = 0; i < parameters_.column_types().size(); ++i) + { + if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::string_literal()) + { + column_types_[i] = data_types::string_t; + } + else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::integer_literal()) + { + column_types_[i] = data_types::integer_t; + } + else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::float_literal()) + { + column_types_[i] = data_types::float_t; + } + else if (parameters_.column_types()[i] == json_csv_parser_traits<CharT>::boolean_literal()) + { + column_types_[i] = data_types::boolean_t; + } + } + } +#if !defined(JSONCONS_NO_DEPRECATED) + else if (parameters_.data_types().length() > 0) + { + basic_empty_json_input_handler<CharT> ih; + basic_csv_parameters<CharT> params; + params.field_delimiter(parameters_.field_delimiter()); + params.assume_header(true); + basic_csv_parser<CharT> p(ih,params); + p.begin_parse(); + p.parse(parameters_.data_types().data(),0,parameters_.data_types().length()); + p.end_parse(); + column_types_.resize(p.column_labels().size()); + for (size_t i = 0; i < p.column_labels().size(); ++i) + { + if (p.column_labels()[i] == json_csv_parser_traits<CharT>::string_literal()) + { + column_types_[i] = data_types::string_t; + } + else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::integer_literal()) + { + column_types_[i] = data_types::integer_t; + } + else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::float_literal()) + { + column_types_[i] = data_types::float_t; + } + else if (p.column_labels()[i] == json_csv_parser_traits<CharT>::boolean_literal()) + { + column_types_[i] = data_types::boolean_t; + } + } + } +#endif + if (parameters_.column_defaults().size() > 0) + { + column_defaults_ = parameters_.column_defaults(); + } +#if !defined(JSONCONS_NO_DEPRECATED) + else if (parameters_.default_values().length() > 0) + { + basic_empty_json_input_handler<CharT> ih; + basic_csv_parameters<CharT> params; + params.field_delimiter(parameters_.field_delimiter()); + params.assume_header(true); + basic_csv_parser<CharT> p(ih,params); + p.begin_parse(); + p.parse(parameters_.default_values().data(),0,parameters_.default_values().length()); + p.end_parse(); + column_defaults_.resize(p.column_labels().size()); + for (size_t i = 0; i < p.column_labels().size(); ++i) + { + column_defaults_[i] = p.column_labels()[i]; + } + } +#endif + if (parameters_.header_lines() > 0) + { + push(csv_modes::header); + } + else + { + push(csv_modes::array); + } + handler_->begin_array(*this); + state_ = csv_states::expect_value; + column_index_ = 0; + prev_char_ = 0; + curr_char_ = 0; + column_ = 1; + } + + void parse(const CharT* p, size_t start, size_t length) + { + index_ = start; + for (; index_ < length && state_ != csv_states::done; ++index_) + { + curr_char_ = p[index_]; +all_csv_states: + switch (state_) + { + case csv_states::comment: + if (curr_char_ == '\n') + { + state_ = csv_states::expect_value; + } + else if (prev_char_ == '\r') + { + state_ = csv_states::expect_value; + goto all_csv_states; + } + break; + case csv_states::expect_value: + if (column_ == 1 && curr_char_ == parameters_.comment_starter()) + { + state_ = csv_states::comment; + } + else + { + state_ = csv_states::unquoted_string; + goto all_csv_states; + } + break; + case csv_states::between_fields: + if (curr_char_ == '\r' || (prev_char_ != '\r' && curr_char_ == '\n')) + { + after_record(); + state_ = csv_states::expect_value; + } + else if (curr_char_ == parameters_.field_delimiter()) + { + state_ = csv_states::expect_value; + } + break; + case csv_states::escaped_value: + { + if (curr_char_ == parameters_.quote_char()) + { + string_buffer_.push_back(curr_char_); + state_ = csv_states::quoted_string; + } + else if (parameters_.quote_escape_char() == parameters_.quote_char()) + { + before_record(); + end_quoted_string_value(); + after_field(); + state_ = csv_states::between_fields; + goto all_csv_states; + } + } + break; + case csv_states::quoted_string: + { + if (curr_char_ == parameters_.quote_escape_char()) + { + state_ = csv_states::escaped_value; + } + else if (curr_char_ == parameters_.quote_char()) + { + before_record(); + end_quoted_string_value(); + after_field(); + state_ = csv_states::between_fields; + } + else + { + string_buffer_.push_back(curr_char_); + } + } + break; + case csv_states::unquoted_string: + { + if (curr_char_ == '\r' || (prev_char_ != '\r' && curr_char_ == '\n')) + { + before_record(); + end_unquoted_string_value(); + after_field(); + after_record(); + state_ = csv_states::expect_value; + } + else if (curr_char_ == '\n') + { + if (prev_char_ != '\r') + { + before_record(); + end_unquoted_string_value(); + after_field(); + after_record(); + state_ = csv_states::expect_value; + } + } + else if (curr_char_ == parameters_.field_delimiter()) + { + before_record(); + end_unquoted_string_value(); + after_field(); + state_ = csv_states::expect_value; + } + else if (curr_char_ == parameters_.quote_char()) + { + string_buffer_.clear(); + state_ = csv_states::quoted_string; + } + else + { + string_buffer_.push_back(curr_char_); + } + } + break; + default: + err_handler_->error(std::error_code(csv_parser_errc::invalid_state, csv_error_category()), *this); + break; + } + if (line_ > parameters_.max_lines()) + { + state_ = csv_states::done; + } + switch (curr_char_) + { + case '\r': + ++line_; + column_ = 1; + break; + case '\n': + if (prev_char_ != '\r') + { + ++line_; + } + column_ = 1; + break; + default: + ++column_; + break; + } + prev_char_ = curr_char_; + } + } + + void end_parse() + { + switch (state_) + { + case csv_states::unquoted_string: + before_record(); + end_unquoted_string_value(); + after_field(); + break; + case csv_states::escaped_value: + if (parameters_.quote_escape_char() == parameters_.quote_char()) + { + before_record(); + end_quoted_string_value(); + after_field(); + } + break; + default: + break; + } + if (column_index_ > 0) + { + after_record(); + } + switch (stack_[top_]) + { + case csv_modes::array: + if (!pop(csv_modes::array)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + break; + case csv_modes::object: + if (!pop(csv_modes::object)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + break; + case csv_modes::header: + if (!pop(csv_modes::header)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + break; + default: + break; + } + handler_->end_array(*this); + if (!pop(csv_modes::done)) + { + err_handler_->error(std::error_code(csv_parser_errc::unexpected_eof, csv_error_category()), *this); + } + handler_->end_json(); + } + + csv_states state() const + { + return state_; + } + + size_t index() const + { + return index_; + } +private: + + void trim_string_buffer(bool trim_leading, bool trim_trailing) + { + size_t start = 0; + size_t length = string_buffer_.length(); + if (trim_leading) + { + bool done = false; + while (!done && start < string_buffer_.length()) + { + if ((string_buffer_[start] < 256) && std::isspace(string_buffer_[start])) + { + ++start; + } + else + { + done = true; + } + } + } + if (trim_trailing) + { + bool done = false; + while (!done && length > 0) + { + if ((string_buffer_[length-1] < 256) && std::isspace(string_buffer_[length-1])) + { + --length; + } + else + { + done = true; + } + } + } + if (start != 0 || length != string_buffer_.size()) + { + string_buffer_ = string_buffer_.substr(start,length-start); + } + } + + void end_unquoted_string_value() + { + if (parameters_.trim_leading() | parameters_.trim_trailing()) + { + trim_string_buffer(parameters_.trim_leading(),parameters_.trim_trailing()); + } + switch (stack_[top_]) + { + case csv_modes::header: + if (parameters_.assume_header() && line_ == 1) + { + column_names_.push_back(string_buffer_); + } + break; + case csv_modes::object: + if (!(parameters_.ignore_empty_values() && string_buffer_.size() == 0)) + { + if (column_index_ < column_names_.size()) + { + handler_->name(column_names_[column_index_].data(), column_names_[column_index_].length(), *this); + if (parameters_.unquoted_empty_value_is_null() && string_buffer_.length() == 0) + { + handler_->value(jsoncons::null_type(),*this); + } + else + { + end_value(); + } + } + } + break; + case csv_modes::array: + if (parameters_.unquoted_empty_value_is_null() && string_buffer_.length() == 0) + { + handler_->value(jsoncons::null_type(),*this); + } + else + { + end_value(); + } + break; + default: + err_handler_->error(std::error_code(csv_parser_errc::invalid_csv_text, csv_error_category()), *this); + break; + } + state_ = csv_states::expect_value; + string_buffer_.clear(); + } + + void end_quoted_string_value() + { + if (parameters_.trim_leading_inside_quotes() | parameters_.trim_trailing_inside_quotes()) + { + trim_string_buffer(parameters_.trim_leading_inside_quotes(),parameters_.trim_trailing_inside_quotes()); + } + switch (stack_[top_]) + { + case csv_modes::header: + if (parameters_.assume_header() && line_ == 1) + { + column_names_.push_back(string_buffer_); + } + break; + case csv_modes::object: + if (!(parameters_.ignore_empty_values() && string_buffer_.size() == 0)) + { + if (column_index_ < column_names_.size()) + { + handler_->name(column_names_[column_index_].data(), column_names_[column_index_].length(), *this); + end_value(); + } + } + break; + case csv_modes::array: + end_value(); + break; + default: + err_handler_->error(std::error_code(csv_parser_errc::invalid_csv_text, csv_error_category()), *this); + break; + } + state_ = csv_states::expect_value; + string_buffer_.clear(); + } + + void end_value() + { + if (column_index_ < column_types_.size()) + { + switch (column_types_[column_index_]) + { + case data_types::integer_t: + { + std::istringstream iss(string_buffer_); + long long val; + iss >> val; + if (!iss.fail()) + { + handler_->value(val, *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value(null_type(), *this); + } + } + } + break; + case data_types::float_t: + { + std::istringstream iss(string_buffer_); + double val; + iss >> val; + if (!iss.fail()) + { + handler_->value(val, 0, *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value(null_type(), *this); + } + } + } + break; + case data_types::boolean_t: + { + if (string_buffer_.length() == 1 && string_buffer_[0] == '0') + { + handler_->value(false, *this); + } + else if (string_buffer_.length() == 1 && string_buffer_[0] == '1') + { + handler_->value(true, *this); + } + else if (string_buffer_.length() == 5 && ((string_buffer_[0] == 'f' || string_buffer_[0] == 'F') && (string_buffer_[1] == 'a' || string_buffer_[1] == 'A') && (string_buffer_[2] == 'l' || string_buffer_[2] == 'L') && (string_buffer_[3] == 's' || string_buffer_[3] == 'S') && (string_buffer_[4] == 'e' || string_buffer_[4] == 'E'))) + { + handler_->value(false, *this); + } + else if (string_buffer_.length() == 4 && ((string_buffer_[0] == 't' || string_buffer_[0] == 'T') && (string_buffer_[1] == 'r' || string_buffer_[1] == 'R') && (string_buffer_[2] == 'u' || string_buffer_[2] == 'U') && (string_buffer_[3] == 'e' || string_buffer_[3] == 'E'))) + { + handler_->value(true, *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value(null_type(), *this); + } + } + } + break; + default: + if (string_buffer_.length() > 0) + { + handler_->value(string_buffer_.data(), string_buffer_.length(), *this); + } + else + { + if (column_index_ < column_defaults_.size() && column_defaults_[column_index_].length() > 0) + { + parser_.begin_parse(); + parser_.parse(column_defaults_[column_index_].data(),0,column_defaults_[column_index_].length()); + parser_.end_parse(); + } + else + { + handler_->value("", *this); + } + } + break; + } + } + else + { + handler_->value(string_buffer_.data(), string_buffer_.length(), *this); + } + } + + size_t do_line_number() const override + { + return line_; + } + + size_t do_column_number() const override + { + return column_; + } + + CharT do_current_char() const override + { + return (CharT)prev_char_; + } + + void push(csv_modes mode) + { + ++top_; + if (top_ >= depth_) + { + depth_ *= 2; + stack_.resize(depth_); + } + stack_[top_] = mode; + } + + int peek() + { + return stack_[top_]; + } + + bool peek(csv_modes mode) + { + return stack_[top_] == mode; + } + + bool flip(csv_modes mode1, csv_modes mode2) + { + if (top_ < 0 || stack_[top_] != mode1) + { + return false; + } + stack_[top_] = mode2; + return true; + } + + bool pop(csv_modes mode) + { + if (top_ < 0 || stack_[top_] != mode) + { + return false; + } + --top_; + return true; + } +}; + +typedef basic_csv_parser<char> csv_parser; +typedef basic_csv_parser<wchar_t> wcsv_parser; + +}} + +#endif + diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp new file mode 100644 index 00000000..38213e25 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_reader.hpp @@ -0,0 +1,175 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_CSV_CSV_READER_HPP +#define JSONCONS_CSV_CSV_READER_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <istream> +#include <cstdlib> +#include <stdexcept> +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/json_input_handler.hpp" +#include "jsoncons/parse_error_handler.hpp" +#include "jsoncons_ext/csv/csv_error_category.hpp" +#include "jsoncons_ext/csv/csv_parser.hpp" +#include "jsoncons/json.hpp" + +namespace jsoncons { namespace csv { + +template<typename CharT> +class basic_csv_reader +{ + struct stack_item + { + stack_item() + : array_begun_(false) + { + } + + bool array_begun_; + }; +public: + // Structural characters + static const size_t default_max_buffer_length = 16384; + //! Parse an input stream of CSV text into a json object + /*! + \param is The input stream to read from + */ + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler) + + : parser_(handler), + is_(std::addressof(is)), + buffer_(default_max_buffer_length), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + { + } + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler, + basic_csv_parameters<CharT> params) + + : parser_(handler,params), + is_(std::addressof(is)), + buffer_(default_max_buffer_length), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + { + } + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler) + : + parser_(handler,err_handler), + is_(std::addressof(is)), + buffer_(), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + + + { + } + + basic_csv_reader(std::basic_istream<CharT>& is, + basic_json_input_handler<CharT>& handler, + basic_parse_error_handler<CharT>& err_handler, + basic_csv_parameters<CharT> params) + : + parser_(handler,err_handler,params), + is_(std::addressof(is)), + buffer_(), + buffer_capacity_(default_max_buffer_length), + buffer_position_(0), + buffer_length_(0), + eof_(false), + index_(0) + { + } + + ~basic_csv_reader() + { + } + + void read() + { + parser_.begin_parse(); + while (!eof_ && !parser_.done()) + { + if (!(index_ < buffer_length_)) + { + if (!is_->eof()) + { + is_->read(buffer_.data(), buffer_capacity_); + buffer_length_ = static_cast<size_t>(is_->gcount()); + if (buffer_length_ == 0) + { + eof_ = true; + } + index_ = 0; + } + else + { + eof_ = true; + } + } + if (!eof_) + { + parser_.parse(buffer_.data(),index_,buffer_length_); + index_ = parser_.index(); + } + } + parser_.end_parse(); + } + + bool eof() const + { + return eof_; + } + + size_t buffer_capacity() const + { + return buffer_capacity_; + } + + void buffer_capacity(size_t buffer_capacity) + { + buffer_capacity_ = buffer_capacity; + } + +private: + basic_csv_reader(const basic_csv_reader&) = delete; + basic_csv_reader& operator = (const basic_csv_reader&) = delete; + + basic_csv_parser<CharT> parser_; + std::basic_istream<CharT>* is_; + std::vector<CharT> buffer_; + size_t buffer_capacity_; + size_t buffer_position_; + size_t buffer_length_; + bool eof_; + size_t index_; +}; + +typedef basic_csv_reader<char> csv_reader; + +}} + +#endif diff --git a/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp new file mode 100644 index 00000000..f331b629 --- /dev/null +++ b/vendor/jsoncons-0.99.2/jsoncons_ext/csv/csv_serializer.hpp @@ -0,0 +1,445 @@ +// Copyright 2013 Daniel Parker +// Distributed under the Boost license, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See https://github.com/danielaparker/jsoncons for latest version + +#ifndef JSONCONS_CSV_CSV_SERIALIZER_HPP +#define JSONCONS_CSV_CSV_SERIALIZER_HPP + +#include <string> +#include <sstream> +#include <vector> +#include <ostream> +#include <cstdlib> +#include <map> +#include "jsoncons/jsoncons.hpp" +#include "jsoncons/output_format.hpp" +#include "jsoncons/json_output_handler.hpp" +#include <limits> // std::numeric_limits + +namespace jsoncons { namespace csv { + +template <typename CharT> +struct csv_char_traits +{ +}; + +template <> +struct csv_char_traits<char> +{ + static const std::string all_literal() {return "all";}; + + static const std::string minimal_literal() {return "minimal";}; + + static const std::string none_literal() {return "none";}; + + static const std::string nonnumeric_literal() {return "nonumeric";}; +}; + +template <> +struct csv_char_traits<wchar_t> +{ + static const std::wstring all_literal() {return L"all";}; + + static const std::wstring minimal_literal() {return L"minimal";}; + + static const std::wstring none_literal() {return L"none";}; + + static const std::wstring nonnumeric_literal() {return L"nonumeric";}; +}; + +template <typename CharT> +void escape_string(const CharT* s, + size_t length, + CharT quote_char, CharT quote_escape_char, + buffered_ostream<CharT>& os) +{ + const CharT* begin = s; + const CharT* end = s + length; + for (const CharT* it = begin; it != end; ++it) + { + CharT c = *it; + if (c == quote_char) + { + os.put(quote_escape_char); + os.put(quote_char); + } + else + { + os.put(c); + } + } +} + +template<typename CharT> +class basic_csv_serializer : public basic_json_output_handler<CharT> +{ + struct stack_item + { + stack_item(bool is_object) + : is_object_(is_object), count_(0), skip_(false) + { + } + bool is_object() const + { + return is_object_; + } + + bool is_object_; + size_t count_; + bool skip_; + }; + buffered_ostream<CharT> os_; + basic_csv_parameters<CharT> parameters_; + basic_output_format<CharT> format_; + std::vector<stack_item> stack_; + std::streamsize original_precision_; + std::ios_base::fmtflags original_format_flags_; + std::basic_ostringstream<CharT> header_oss_; + buffered_ostream<CharT> header_os_; + std::map<std::basic_string<CharT>,size_t> header_; + float_printer<CharT> fp_; +public: + basic_csv_serializer(std::basic_ostream<CharT>& os) + : + os_(os), + format_(), + stack_(), + original_precision_(), + original_format_flags_(), + header_os_(header_oss_), + header_(), + fp_(format_.precision()) + { + } + + basic_csv_serializer(std::basic_ostream<CharT>& os, + basic_csv_parameters<CharT> params) + : + os_(os), + parameters_(params), + format_(), + stack_(), + original_precision_(), + original_format_flags_(), + header_os_(header_oss_), + header_(), + fp_(format_.precision()) + { + } + + ~basic_csv_serializer() + { + } + +private: + + void do_begin_json() override + { + } + + void do_end_json() override + { + } + + void do_begin_object() override + { + stack_.push_back(stack_item(true)); + } + + void do_end_object() override + { + if (stack_.size() == 2) + { + os_.write(parameters_.line_delimiter()); + if (stack_[0].count_ == 0) + { + os_.write(header_oss_.str()); + os_.write(parameters_.line_delimiter()); + } + } + stack_.pop_back(); + + end_value(); + } + + void do_begin_array() override + { + stack_.push_back(stack_item(false)); + } + + void do_end_array() override + { + if (stack_.size() == 2) + { + os_.write(parameters_.line_delimiter()); + } + stack_.pop_back(); + + end_value(); + } + + void do_name(const CharT* name, size_t length) override + { + if (stack_.size() == 2) + { + if (stack_[0].count_ == 0) + { + if (stack_.back().count_ > 0) + { + os_.put(parameters_.field_delimiter()); + } + bool quote = false; + if (parameters_.quote_style() == quote_styles::all || parameters_.quote_style() == quote_styles::nonnumeric || + (parameters_.quote_style() == quote_styles::minimal && std::char_traits<CharT>::find(name,length,parameters_.field_delimiter()) != nullptr)) + { + quote = true; + os_.put(parameters_.quote_char()); + } + jsoncons::csv::escape_string<CharT>(name, length, parameters_.quote_char(), parameters_.quote_escape_char(), os_); + if (quote) + { + os_.put(parameters_.quote_char()); + } + header_[name] = stack_.back().count_; + } + else + { + typename std::map<std::basic_string<CharT>,size_t>::iterator it = header_.find(std::basic_string<CharT>(name,length)); + if (it == header_.end()) + { + stack_.back().skip_ = true; + //std::cout << " Not found "; + } + else + { + stack_.back().skip_ = false; + while (stack_.back().count_ < it->second) + { + os_.put(parameters_.field_delimiter()); + ++stack_.back().count_; + } + // std::cout << " (" << it->value() << " " << stack_.back().count_ << ") "; + } + } + } + } + + void do_null_value() override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + do_null_value(header_os_); + } + else + { + do_null_value(os_); + } + } + } + + void do_string_value(const CharT* val, size_t length) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,length,header_os_); + } + else + { + value(val,length,os_); + } + } + } + + void do_double_value(double val, uint8_t precision) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void do_integer_value(int64_t val) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void do_uinteger_value(uint64_t val) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void do_bool_value(bool val) override + { + if (stack_.size() == 2 && !stack_.back().skip_) + { + if (stack_.back().is_object() && stack_[0].count_ == 0) + { + value(val,header_os_); + } + else + { + value(val,os_); + } + } + } + + void value(const CharT* val, size_t length, buffered_ostream<CharT>& os) + { + begin_value(os); + + bool quote = false; + if (parameters_.quote_style() == quote_styles::all || parameters_.quote_style() == quote_styles::nonnumeric || + (parameters_.quote_style() == quote_styles::minimal && std::char_traits<CharT>::find(val, length, parameters_.field_delimiter()) != nullptr)) + { + quote = true; + os.put(parameters_.quote_char()); + } + jsoncons::csv::escape_string<CharT>(val, length, parameters_.quote_char(), parameters_.quote_escape_char(), os); + if (quote) + { + os.put(parameters_.quote_char()); + } + + end_value(); + } + + void value(double val, buffered_ostream<CharT>& os) + { + begin_value(os); + + if (is_nan(val) && format_.replace_nan()) + { + os.write(format_.nan_replacement()); + } + else if (is_pos_inf(val) && format_.replace_pos_inf()) + { + os.write(format_.pos_inf_replacement()); + } + else if (is_neg_inf(val) && format_.replace_neg_inf()) + { + os.write(format_.neg_inf_replacement()); + } + //else if (format_.floatfield() != 0) + //{ + // std::basic_ostringstream<CharT> ss; + // ss.imbue(std::locale::classic()); + // ss.setf(format_.floatfield(), std::ios::floatfield); + // ss << std::showpoint << std::setprecision(format_.precision()) << val; + // os.write(ss.str()); + //} + else + { + fp_.print(val,format_.precision(),os); + } + + end_value(); + + } + + void value(int64_t val, buffered_ostream<CharT>& os) + { + begin_value(os); + + std::basic_ostringstream<CharT> ss; + ss << val; + os.write(ss.str()); + + end_value(); + } + + void value(uint64_t val, buffered_ostream<CharT>& os) + { + begin_value(os); + + std::basic_ostringstream<CharT> ss; + ss << val; + os.write(ss.str()); + + end_value(); + } + + void value(bool val, buffered_ostream<CharT>& os) + { + begin_value(os); + + if (val) + { + auto buf = json_literals<CharT>::true_literal(); + os.write(buf.first,buf.second); + } + else + { + auto buf = json_literals<CharT>::false_literal(); + os.write(buf.first,buf.second); + } + + end_value(); + } + + void do_null_value(buffered_ostream<CharT>& os) + { + begin_value(os); + auto buf = json_literals<CharT>::null_literal(); + os.write(buf.first,buf.second); + end_value(); + + } + + void begin_value(buffered_ostream<CharT>& os) + { + if (!stack_.empty()) + { + if (stack_.back().count_ > 0) + { + os.put(parameters_.field_delimiter()); + } + } + } + + void end_value() + { + if (!stack_.empty()) + { + ++stack_.back().count_; + } + } +}; + +typedef basic_csv_serializer<char> csv_serializer; + +}} + +#endif |