rodecomp/Recovered/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp
ragnarok-clanker 9b9c369f0c Move exe-only code to Recovered/ and rebuild virtualised PakAuxiliary::Extract
Recovered/ holds the code linked only into the standalone exe (scripts/exe/build_exe.py), outside the Clank source dirs:
- jsoncons/ and nProtect/ moved from scripts/exe/; GameGuard stand-in follows main's renamed entry points.
- GPak/PakAuxiliary.cpp: Extract (virtualised in every build; 02-19 jumps out at 0x0065861E) rebuilt from the open GRF Editor decoder, after the visible 02-19 prologue; inline key and kRO keys 1-4. Apply traps (unreachable in 02-19).
- GGHash/GGHash.cpp: CGGHash::Load/Check/VerifyHash trap (RagHash.dat check unreachable in 02-19).
The whole client links: 984 units, 0 unresolved.
2026-11-06 19:33:10 +01:00

954 lines
32 KiB
C++

// Copyright 2013-2023 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_ENCODER_HPP
#define JSONCONS_CSV_CSV_ENCODER_HPP
#include <array> // std::array
#include <string>
#include <vector>
#include <ostream>
#include <utility> // std::move
#include <unordered_map> // std::unordered_map
#include <memory> // std::allocator
#include <limits> // std::numeric_limits
#include <jsoncons/json_exception.hpp>
#include <jsoncons/json_visitor.hpp>
#include <jsoncons/detail/write_number.hpp>
#include <jsoncons_ext/csv/csv_options.hpp>
#include <jsoncons/sink.hpp>
namespace jsoncons { namespace csv {
template<class CharT,class Sink=jsoncons::stream_sink<CharT>,class Allocator=std::allocator<char>>
class basic_csv_encoder final : public basic_json_visitor<CharT>
{
public:
using char_type = CharT;
using typename basic_json_visitor<CharT>::string_view_type;
using sink_type = Sink;
using allocator_type = Allocator;
using char_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<CharT>;
using string_type = std::basic_string<CharT, std::char_traits<CharT>, char_allocator_type>;
using string_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<string_type>;
using string_string_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<std::pair<const string_type,string_type>>;
private:
static jsoncons::basic_string_view<CharT> null_constant()
{
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"null");
return k;
}
static jsoncons::basic_string_view<CharT> true_constant()
{
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"true");
return k;
}
static jsoncons::basic_string_view<CharT> false_constant()
{
static jsoncons::basic_string_view<CharT> k = JSONCONS_STRING_VIEW_CONSTANT(CharT,"false");
return k;
}
enum class stack_item_kind
{
row_mapping,
column_mapping,
object,
row,
column,
object_multi_valued_field,
row_multi_valued_field,
column_multi_valued_field
};
struct stack_item
{
stack_item_kind item_kind_;
std::size_t count_;
stack_item(stack_item_kind item_kind) noexcept
: item_kind_(item_kind), count_(0)
{
}
bool is_object() const
{
return item_kind_ == stack_item_kind::object;
}
stack_item_kind item_kind() const
{
return item_kind_;
}
};
Sink sink_;
const basic_csv_encode_options<CharT> options_;
allocator_type alloc_;
std::vector<stack_item> stack_;
jsoncons::detail::write_double fp_;
std::vector<string_type,string_allocator_type> strings_buffer_;
std::unordered_map<string_type,string_type, std::hash<string_type>,std::equal_to<string_type>,string_string_allocator_type> buffered_line_;
string_type name_;
std::size_t column_index_;
std::vector<std::size_t> row_counts_;
// Noncopyable and nonmoveable
basic_csv_encoder(const basic_csv_encoder&) = delete;
basic_csv_encoder& operator=(const basic_csv_encoder&) = delete;
public:
basic_csv_encoder(Sink&& sink,
const Allocator& alloc = Allocator())
: basic_csv_encoder(std::forward<Sink>(sink), basic_csv_encode_options<CharT>(), alloc)
{
}
basic_csv_encoder(Sink&& sink,
const basic_csv_encode_options<CharT>& options,
const Allocator& alloc = Allocator())
: sink_(std::forward<Sink>(sink)),
options_(options),
alloc_(alloc),
stack_(),
fp_(options.float_format(), options.precision()),
column_index_(0)
{
jsoncons::csv::detail::parse_column_names(options.column_names(), strings_buffer_);
}
~basic_csv_encoder() noexcept
{
JSONCONS_TRY
{
sink_.flush();
}
JSONCONS_CATCH(...)
{
}
}
void reset()
{
stack_.clear();
strings_buffer_.clear();
buffered_line_.clear();
name_.clear();
column_index_ = 0;
row_counts_.clear();
}
void reset(Sink&& sink)
{
sink_ = std::move(sink);
reset();
}
private:
template<class AnyWriter>
void escape_string(const CharT* s,
std::size_t length,
CharT quote_char, CharT quote_escape_char,
AnyWriter& sink)
{
const CharT* begin = s;
const CharT* end = s + length;
for (const CharT* it = begin; it != end; ++it)
{
CharT c = *it;
if (c == quote_char)
{
sink.push_back(quote_escape_char);
sink.push_back(quote_char);
}
else
{
sink.push_back(c);
}
}
}
void visit_flush() override
{
sink_.flush();
}
bool visit_begin_object(semantic_tag, const ser_context&, std::error_code& ec) override
{
if (stack_.empty())
{
stack_.emplace_back(stack_item_kind::column_mapping);
return true;
}
switch (stack_.back().item_kind_)
{
case stack_item_kind::row_mapping:
stack_.emplace_back(stack_item_kind::object);
return true;
default: // error
ec = csv_errc::source_error;
return false;
}
}
bool visit_end_object(const ser_context&, std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
if (stack_[0].count_ == 0)
{
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
{
if (i > 0)
{
sink_.push_back(options_.field_delimiter());
}
sink_.append(strings_buffer_[i].data(),
strings_buffer_[i].length());
}
sink_.append(options_.line_delimiter().data(),
options_.line_delimiter().length());
}
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
{
if (i > 0)
{
sink_.push_back(options_.field_delimiter());
}
auto it = buffered_line_.find(strings_buffer_[i]);
if (it != buffered_line_.end())
{
sink_.append(it->second.data(),it->second.length());
it->second.clear();
}
}
sink_.append(options_.line_delimiter().data(), options_.line_delimiter().length());
break;
case stack_item_kind::column_mapping:
{
for (const auto& item : strings_buffer_)
{
sink_.append(item.data(), item.size());
sink_.append(options_.line_delimiter().data(), options_.line_delimiter().length());
}
break;
}
default:
break;
}
stack_.pop_back();
if (!stack_.empty())
{
end_value();
}
return true;
}
bool visit_begin_array(semantic_tag, const ser_context&, std::error_code& ec) override
{
if (stack_.empty())
{
stack_.emplace_back(stack_item_kind::row_mapping);
return true;
}
switch (stack_.back().item_kind_)
{
case stack_item_kind::row_mapping:
stack_.emplace_back(stack_item_kind::row);
if (stack_[0].count_ == 0)
{
for (std::size_t i = 0; i < strings_buffer_.size(); ++i)
{
if (i > 0)
{
sink_.push_back(options_.field_delimiter());
}
sink_.append(strings_buffer_[i].data(),strings_buffer_[i].length());
}
if (strings_buffer_.size() > 0)
{
sink_.append(options_.line_delimiter().data(),
options_.line_delimiter().length());
}
}
return true;
case stack_item_kind::object:
stack_.emplace_back(stack_item_kind::object_multi_valued_field);
return true;
case stack_item_kind::column_mapping:
stack_.emplace_back(stack_item_kind::column);
row_counts_.push_back(1);
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
return true;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
begin_value(bo);
stack_.emplace_back(stack_item_kind::column_multi_valued_field);
return true;
}
case stack_item_kind::row:
begin_value(sink_);
stack_.emplace_back(stack_item_kind::row_multi_valued_field);
return true;
default: // error
ec = csv_errc::source_error;
return false;
}
}
bool visit_end_array(const ser_context&, std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::row:
sink_.append(options_.line_delimiter().data(),
options_.line_delimiter().length());
break;
case stack_item_kind::column:
++column_index_;
break;
default:
break;
}
stack_.pop_back();
if (!stack_.empty())
{
end_value();
}
return true;
}
bool visit_key(const string_view_type& name, const ser_context&, std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
{
name_ = string_type(name);
buffered_line_[string_type(name)] = std::basic_string<CharT>();
if (stack_[0].count_ == 0 && options_.column_names().size() == 0)
{
strings_buffer_.emplace_back(name);
}
break;
}
case stack_item_kind::column_mapping:
{
if (strings_buffer_.empty())
{
strings_buffer_.emplace_back(name);
}
else
{
strings_buffer_[0].push_back(options_.field_delimiter());
strings_buffer_[0].append(string_type(name));
}
break;
}
default:
break;
}
return true;
}
bool visit_null(semantic_tag, const ser_context&, std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
case stack_item_kind::object_multi_valued_field:
{
auto it = buffered_line_.find(name_);
if (it != buffered_line_.end())
{
std::basic_string<CharT> s;
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
write_null_value(bo);
bo.flush();
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
{
it->second.push_back(options_.subfield_delimiter());
}
it->second.append(s);
}
break;
}
case stack_item_kind::row:
case stack_item_kind::row_multi_valued_field:
write_null_value(sink_);
break;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_null_value(bo);
break;
}
case stack_item_kind::column_multi_valued_field:
{
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_null_value(bo);
break;
}
default:
break;
}
return true;
}
bool visit_string(const string_view_type& sv, semantic_tag, const ser_context&, std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
case stack_item_kind::object_multi_valued_field:
{
auto it = buffered_line_.find(name_);
if (it != buffered_line_.end())
{
std::basic_string<CharT> s;
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
write_string_value(sv,bo);
bo.flush();
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
{
it->second.push_back(options_.subfield_delimiter());
}
it->second.append(s);
}
break;
}
case stack_item_kind::row:
case stack_item_kind::row_multi_valued_field:
write_string_value(sv,sink_);
break;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_string_value(sv,bo);
break;
}
case stack_item_kind::column_multi_valued_field:
{
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_string_value(sv,bo);
break;
}
default:
break;
}
return true;
}
bool visit_byte_string(const byte_string_view& b,
semantic_tag tag,
const ser_context& context,
std::error_code& ec) override
{
byte_string_chars_format encoding_hint;
switch (tag)
{
case semantic_tag::base16:
encoding_hint = byte_string_chars_format::base16;
break;
case semantic_tag::base64:
encoding_hint = byte_string_chars_format::base64;
break;
case semantic_tag::base64url:
encoding_hint = byte_string_chars_format::base64url;
break;
default:
encoding_hint = byte_string_chars_format::none;
break;
}
byte_string_chars_format format = jsoncons::detail::resolve_byte_string_chars_format(encoding_hint,byte_string_chars_format::none,byte_string_chars_format::base64url);
std::basic_string<CharT> s;
switch (format)
{
case byte_string_chars_format::base16:
{
encode_base16(b.begin(),b.end(),s);
visit_string(s, semantic_tag::none, context, ec);
break;
}
case byte_string_chars_format::base64:
{
encode_base64(b.begin(),b.end(),s);
visit_string(s, semantic_tag::none, context, ec);
break;
}
case byte_string_chars_format::base64url:
{
encode_base64url(b.begin(),b.end(),s);
visit_string(s, semantic_tag::none, context, ec);
break;
}
default:
{
JSONCONS_UNREACHABLE();
}
}
return true;
}
bool visit_double(double val,
semantic_tag,
const ser_context& context,
std::error_code& ec) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
case stack_item_kind::object_multi_valued_field:
{
auto it = buffered_line_.find(name_);
if (it != buffered_line_.end())
{
std::basic_string<CharT> s;
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
write_double_value(val, context, bo, ec);
bo.flush();
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
{
it->second.push_back(options_.subfield_delimiter());
}
it->second.append(s);
}
break;
}
case stack_item_kind::row:
case stack_item_kind::row_multi_valued_field:
write_double_value(val, context, sink_, ec);
break;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_double_value(val, context, bo, ec);
break;
}
case stack_item_kind::column_multi_valued_field:
{
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_double_value(val, context, bo, ec);
break;
}
default:
break;
}
return true;
}
bool visit_int64(int64_t val,
semantic_tag,
const ser_context&,
std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
case stack_item_kind::object_multi_valued_field:
{
auto it = buffered_line_.find(name_);
if (it != buffered_line_.end())
{
std::basic_string<CharT> s;
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
write_int64_value(val,bo);
bo.flush();
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
{
it->second.push_back(options_.subfield_delimiter());
}
it->second.append(s);
}
break;
}
case stack_item_kind::row:
case stack_item_kind::row_multi_valued_field:
write_int64_value(val,sink_);
break;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_int64_value(val, bo);
break;
}
case stack_item_kind::column_multi_valued_field:
{
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_int64_value(val, bo);
break;
}
default:
break;
}
return true;
}
bool visit_uint64(uint64_t val,
semantic_tag,
const ser_context&,
std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
case stack_item_kind::object_multi_valued_field:
{
auto it = buffered_line_.find(name_);
if (it != buffered_line_.end())
{
std::basic_string<CharT> s;
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
write_uint64_value(val, bo);
bo.flush();
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
{
it->second.push_back(options_.subfield_delimiter());
}
it->second.append(s);
}
break;
}
case stack_item_kind::row:
case stack_item_kind::row_multi_valued_field:
write_uint64_value(val,sink_);
break;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_uint64_value(val, bo);
break;
}
case stack_item_kind::column_multi_valued_field:
{
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_uint64_value(val, bo);
break;
}
default:
break;
}
return true;
}
bool visit_bool(bool val, semantic_tag, const ser_context&, std::error_code&) override
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::object:
case stack_item_kind::object_multi_valued_field:
{
auto it = buffered_line_.find(name_);
if (it != buffered_line_.end())
{
std::basic_string<CharT> s;
jsoncons::string_sink<std::basic_string<CharT>> bo(s);
write_bool_value(val,bo);
bo.flush();
if (!it->second.empty() && options_.subfield_delimiter() != char_type())
{
it->second.push_back(options_.subfield_delimiter());
}
it->second.append(s);
}
break;
}
case stack_item_kind::row:
case stack_item_kind::row_multi_valued_field:
write_bool_value(val,sink_);
break;
case stack_item_kind::column:
{
if (strings_buffer_.size() <= row_counts_.back())
{
strings_buffer_.emplace_back();
}
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_bool_value(val, bo);
break;
}
case stack_item_kind::column_multi_valued_field:
{
jsoncons::string_sink<std::basic_string<CharT>> bo(strings_buffer_[row_counts_.back()]);
write_bool_value(val, bo);
break;
}
default:
break;
}
return true;
}
template <class AnyWriter>
bool do_string_value(const CharT* s, std::size_t length, AnyWriter& sink)
{
bool quote = false;
if (options_.quote_style() == quote_style_kind::all || options_.quote_style() == quote_style_kind::nonnumeric ||
(options_.quote_style() == quote_style_kind::minimal &&
(std::char_traits<CharT>::find(s, length, options_.field_delimiter()) != nullptr || std::char_traits<CharT>::find(s, length, options_.quote_char()) != nullptr)))
{
quote = true;
sink.push_back(options_.quote_char());
}
escape_string(s, length, options_.quote_char(), options_.quote_escape_char(), sink);
if (quote)
{
sink.push_back(options_.quote_char());
}
return true;
}
template <class AnyWriter>
void write_string_value(const string_view_type& value, AnyWriter& sink)
{
begin_value(sink);
do_string_value(value.data(),value.length(),sink);
end_value();
}
template <class AnyWriter>
void write_double_value(double val, const ser_context& context, AnyWriter& sink, std::error_code& ec)
{
begin_value(sink);
if (!std::isfinite(val))
{
if ((std::isnan)(val))
{
if (options_.enable_nan_to_num())
{
sink.append(options_.nan_to_num().data(), options_.nan_to_num().length());
}
else if (options_.enable_nan_to_str())
{
visit_string(options_.nan_to_str(), semantic_tag::none, context, ec);
}
else
{
sink.append(null_constant().data(), null_constant().size());
}
}
else if (val == std::numeric_limits<double>::infinity())
{
if (options_.enable_inf_to_num())
{
sink.append(options_.inf_to_num().data(), options_.inf_to_num().length());
}
else if (options_.enable_inf_to_str())
{
visit_string(options_.inf_to_str(), semantic_tag::none, context, ec);
}
else
{
sink.append(null_constant().data(), null_constant().size());
}
}
else
{
if (options_.enable_neginf_to_num())
{
sink.append(options_.neginf_to_num().data(), options_.neginf_to_num().length());
}
else if (options_.enable_neginf_to_str())
{
visit_string(options_.neginf_to_str(), semantic_tag::none, context, ec);
}
else
{
sink.append(null_constant().data(), null_constant().size());
}
}
}
else
{
fp_(val, sink);
}
end_value();
}
template <class AnyWriter>
void write_int64_value(int64_t val, AnyWriter& sink)
{
begin_value(sink);
jsoncons::detail::from_integer(val,sink);
end_value();
}
template <class AnyWriter>
void write_uint64_value(uint64_t val, AnyWriter& sink)
{
begin_value(sink);
jsoncons::detail::from_integer(val,sink);
end_value();
}
template <class AnyWriter>
void write_bool_value(bool val, AnyWriter& sink)
{
begin_value(sink);
if (val)
{
sink.append(true_constant().data(), true_constant().size());
}
else
{
sink.append(false_constant().data(), false_constant().size());
}
end_value();
}
template <class AnyWriter>
bool write_null_value(AnyWriter& sink)
{
begin_value(sink);
sink.append(null_constant().data(), null_constant().size());
end_value();
return true;
}
template <class AnyWriter>
void begin_value(AnyWriter& sink)
{
JSONCONS_ASSERT(!stack_.empty());
switch (stack_.back().item_kind_)
{
case stack_item_kind::row:
if (stack_.back().count_ > 0)
{
sink.push_back(options_.field_delimiter());
}
break;
case stack_item_kind::column:
{
if (row_counts_.size() >= 3)
{
for (std::size_t i = row_counts_.size()-2; i-- > 0;)
{
if (row_counts_[i] <= row_counts_.back())
{
sink.push_back(options_.field_delimiter());
}
else
{
break;
}
}
}
if (column_index_ > 0)
{
sink.push_back(options_.field_delimiter());
}
break;
}
case stack_item_kind::row_multi_valued_field:
case stack_item_kind::column_multi_valued_field:
if (stack_.back().count_ > 0 && options_.subfield_delimiter() != char_type())
{
sink.push_back(options_.subfield_delimiter());
}
break;
default:
break;
}
}
void end_value()
{
JSONCONS_ASSERT(!stack_.empty());
switch(stack_.back().item_kind_)
{
case stack_item_kind::row:
{
++stack_.back().count_;
break;
}
case stack_item_kind::column:
{
++row_counts_.back();
break;
}
default:
++stack_.back().count_;
break;
}
}
};
using csv_stream_encoder = basic_csv_encoder<char>;
using csv_string_encoder = basic_csv_encoder<char,jsoncons::string_sink<std::string>>;
using csv_wstream_encoder = basic_csv_encoder<wchar_t>;
using wcsv_string_encoder = basic_csv_encoder<wchar_t,jsoncons::string_sink<std::wstring>>;
#if !defined(JSONCONS_NO_DEPRECATED)
template<class CharT, class Sink = jsoncons::stream_sink<CharT>, class Allocator = std::allocator<CharT>>
using basic_csv_serializer = basic_csv_encoder<CharT,Sink,Allocator>;
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_serializer;
JSONCONS_DEPRECATED_MSG("Instead, use csv_string_encoder") typedef csv_string_encoder csv_string_serializer;
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_serializer;
JSONCONS_DEPRECATED_MSG("Instead, use csv_string_encoder") typedef csv_string_encoder csv_string_serializer;
JSONCONS_DEPRECATED_MSG("Instead, use csv_stream_encoder") typedef csv_stream_encoder csv_encoder;
JSONCONS_DEPRECATED_MSG("Instead, use wcsv_stream_encoder") typedef csv_stream_encoder wcsv_encoder;
#endif
}}
#endif