mirror of
https://github.com/biojppm/rapidyaml.git
synced 2026-01-18 21:41:18 +01:00
Emitter: internal cleanup
This commit is contained in:
@@ -38,7 +38,7 @@ substr Emitter<Writer>::emit_as(EmitType_e type, Tree const& tree, id_type id, b
|
||||
_emit_json(id);
|
||||
}
|
||||
else
|
||||
_RYML_ERR_BASIC_(m_tree->callbacks(), "unknown emit type");
|
||||
_RYML_ERR_BASIC_(m_tree->callbacks(), "unknown emit type"); // LCOV_EXCL_LINE
|
||||
m_tree = nullptr;
|
||||
return this->Writer::_get(error_on_excess);
|
||||
}
|
||||
@@ -823,14 +823,14 @@ template<class Writer>
|
||||
void Emitter<Writer>::_flow_write_scalar_key(id_type id)
|
||||
{
|
||||
enum : type_bits {
|
||||
_block_styles = KEY_LITERAL|KEY_FOLDED,
|
||||
_flow_styles = KEY_STYLE & ~_block_styles,
|
||||
_block_styles = (KEY_LITERAL|KEY_FOLDED),
|
||||
_flow_styles = KEY_STYLE & ~(KEY_LITERAL|KEY_FOLDED),
|
||||
};
|
||||
csubstr str = m_tree->key(id);
|
||||
NodeType ty = m_tree->type(id) & static_cast<NodeType_e>(_flow_styles);
|
||||
if(!(ty & KEY_STYLE))
|
||||
ty |= scalar_style_choose(str);
|
||||
_RYML_ASSERT_VISIT_(m_tree->callbacks(), !(ty & _block_styles), m_tree, id);
|
||||
_RYML_ASSERT_VISIT_(m_tree->callbacks(), !(ty & (KEY_LITERAL|KEY_FOLDED)), m_tree, id);
|
||||
if(ty & KEY_PLAIN)
|
||||
{
|
||||
if(C4_LIKELY(!(str.begins_with(": ") || str.begins_with(":\t"))))
|
||||
@@ -857,13 +857,13 @@ void Emitter<Writer>::_flow_write_scalar_val(id_type id)
|
||||
{
|
||||
enum : type_bits {
|
||||
_block_styles = VAL_LITERAL|VAL_FOLDED,
|
||||
_flow_styles = VAL_STYLE & ~_block_styles,
|
||||
_flow_styles = (VAL_STYLE) & (~(VAL_LITERAL|VAL_FOLDED)),
|
||||
};
|
||||
csubstr str = m_tree->val(id);
|
||||
NodeType ty = m_tree->type(id) & static_cast<NodeType_e>(_flow_styles);
|
||||
if(!(ty & VAL_STYLE))
|
||||
ty |= scalar_style_choose(str);
|
||||
_RYML_ASSERT_VISIT_(m_tree->callbacks(), !(ty & static_cast<NodeType_e>(_block_styles)), m_tree, id);
|
||||
_RYML_ASSERT_VISIT_(m_tree->callbacks(), !(ty & (VAL_LITERAL|VAL_FOLDED)), m_tree, id);
|
||||
if(ty & VAL_PLAIN)
|
||||
{
|
||||
if(C4_LIKELY(!(str.begins_with(": ") || str.begins_with(":\t"))))
|
||||
@@ -889,7 +889,7 @@ template<class Writer>
|
||||
void Emitter<Writer>::_blck_write_scalar_key(id_type id)
|
||||
{
|
||||
csubstr key = m_tree->key(id);
|
||||
NodeType ty = m_tree->type(id) & static_cast<NodeType_e>(_keysc);
|
||||
NodeType ty = m_tree->type(id);
|
||||
if(!(ty & KEY_STYLE))
|
||||
ty |= scalar_style_choose(key);
|
||||
if(ty & KEY_PLAIN)
|
||||
@@ -925,7 +925,7 @@ template<class Writer>
|
||||
void Emitter<Writer>::_blck_write_scalar_val(id_type id)
|
||||
{
|
||||
csubstr str = m_tree->val(id);
|
||||
NodeType ty = m_tree->type(id) & static_cast<NodeType_e>(_valsc);
|
||||
NodeType ty = m_tree->type(id);
|
||||
if(!(ty & VAL_STYLE))
|
||||
ty |= scalar_style_choose(str);
|
||||
if(ty & VAL_PLAIN)
|
||||
@@ -1305,8 +1305,8 @@ void Emitter<Writer>::_write_scalar_plain(csubstr s, id_type ilevel)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class Writer>
|
||||
void Emitter<Writer>::_emit_json(id_type id)
|
||||
{
|
||||
@@ -1331,19 +1331,19 @@ void Emitter<Writer>::_visit_json_sl(id_type id, id_type depth)
|
||||
NodeType ty = m_tree->type(id);
|
||||
if(ty.is_keyval())
|
||||
{
|
||||
_writek_json(id);
|
||||
_writek_json(id, ty);
|
||||
_write(": ");
|
||||
_writev_json(id);
|
||||
_writev_json(id, ty);
|
||||
}
|
||||
else if(ty.is_val())
|
||||
{
|
||||
_writev_json(id);
|
||||
_writev_json(id, ty);
|
||||
}
|
||||
else if(ty.is_container())
|
||||
{
|
||||
if(ty.has_key())
|
||||
{
|
||||
_writek_json(id);
|
||||
_writek_json(id, ty);
|
||||
_write(": ");
|
||||
}
|
||||
if(ty.is_seq())
|
||||
@@ -1374,19 +1374,19 @@ void Emitter<Writer>::_visit_json_ml(id_type id, id_type depth)
|
||||
NodeType ty = m_tree->type(id);
|
||||
if(ty.is_keyval())
|
||||
{
|
||||
_writek_json(id);
|
||||
_writek_json(id, ty);
|
||||
_write(": ");
|
||||
_writev_json(id);
|
||||
_writev_json(id, ty);
|
||||
}
|
||||
else if(ty.is_val())
|
||||
{
|
||||
_writev_json(id);
|
||||
_writev_json(id, ty);
|
||||
}
|
||||
else if(ty.is_container())
|
||||
{
|
||||
if(ty.has_key())
|
||||
{
|
||||
_writek_json(id);
|
||||
_writek_json(id, ty);
|
||||
_write(": ");
|
||||
}
|
||||
if(ty.is_seq())
|
||||
@@ -1426,29 +1426,44 @@ void Emitter<Writer>::_visit_json_ml(id_type id, id_type depth)
|
||||
}
|
||||
|
||||
template<class Writer>
|
||||
void Emitter<Writer>::_write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags)
|
||||
void Emitter<Writer>::_writek_json(id_type id, NodeType ty)
|
||||
{
|
||||
if(m_opts.json_error_flags() & EmitOptions::JSON_ERR_ON_TAG)
|
||||
if(C4_UNLIKELY(flags & (KEYTAG|VALTAG)))
|
||||
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, NONE, "JSON does not have tags");
|
||||
if(C4_UNLIKELY(ty.has_key_tag()))
|
||||
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, id, "JSON does not have tags");
|
||||
if(m_opts.json_error_flags() & EmitOptions::JSON_ERR_ON_ANCHOR)
|
||||
if(C4_UNLIKELY(flags.has_anchor()))
|
||||
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, NONE, "JSON does not have anchors");
|
||||
if(sc.scalar.len)
|
||||
if(C4_UNLIKELY(ty.has_key_anchor()))
|
||||
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, id, "JSON does not have anchors");
|
||||
csubstr key = m_tree->key(id);
|
||||
if(key.len)
|
||||
_write_scalar_json_dquo(key);
|
||||
else
|
||||
_write("\"\"");
|
||||
}
|
||||
|
||||
template<class Writer>
|
||||
void Emitter<Writer>::_writev_json(id_type id, NodeType ty)
|
||||
{
|
||||
if(m_opts.json_error_flags() & EmitOptions::JSON_ERR_ON_TAG)
|
||||
if(C4_UNLIKELY(ty.has_val_tag()))
|
||||
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, id, "JSON does not have tags");
|
||||
if(m_opts.json_error_flags() & EmitOptions::JSON_ERR_ON_ANCHOR)
|
||||
if(C4_UNLIKELY(ty.has_val_anchor()))
|
||||
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, id, "JSON does not have anchors");
|
||||
csubstr val = m_tree->val(id);
|
||||
if(val.len)
|
||||
{
|
||||
// use double quoted style...
|
||||
// if it is a key (mandatory in JSON)
|
||||
// if the style is marked quoted
|
||||
bool dquoted = ((flags & (KEY|VALQUO))
|
||||
|| (scalar_style_json_choose(sc.scalar) & SCALAR_DQUO)); // choose the style
|
||||
// use double quoted style if the style is marked quoted
|
||||
bool dquoted = ((ty & VALQUO)
|
||||
|| (scalar_style_json_choose(val) & SCALAR_DQUO)); // choose the style
|
||||
if(dquoted)
|
||||
_write_scalar_json_dquo(sc.scalar);
|
||||
_write_scalar_json_dquo(val);
|
||||
else
|
||||
_write(sc.scalar);
|
||||
_write(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sc.scalar.str || (flags & (KEY|VALQUO|KEYTAG|VALTAG)))
|
||||
if(val.str || (ty & (VALQUO|VALTAG)))
|
||||
_write("\"\"");
|
||||
else
|
||||
_write("null");
|
||||
|
||||
@@ -131,19 +131,35 @@ class Emitter : public Writer
|
||||
{
|
||||
public:
|
||||
|
||||
/** Construct the emitter and its internal Writer state, using default emit options.
|
||||
* @param args arguments to be forwarded to the constructor of the writer.
|
||||
*/
|
||||
template<class ...Args>
|
||||
Emitter(Args &&...args) : Writer(std::forward<Args>(args)...), m_tree(), m_opts() {}
|
||||
|
||||
/** Construct the emitter and its internal Writer state.
|
||||
*
|
||||
* @param opts @ref EmitOptions
|
||||
* @param args arguments to be forwarded to the constructor of the writer.
|
||||
*/
|
||||
template<class ...Args>
|
||||
Emitter(EmitOptions const& opts, Args &&...args) : Writer(std::forward<Args>(args)...), m_tree(), m_opts(opts) {}
|
||||
Emitter(EmitOptions const& opts, Args &&...args)
|
||||
: Writer(std::forward<Args>(args)...)
|
||||
, m_tree()
|
||||
, m_opts(opts)
|
||||
, m_col()
|
||||
, m_depth()
|
||||
, m_ilevel()
|
||||
, m_pws()
|
||||
{}
|
||||
|
||||
/** Construct the emitter and its internal Writer state, using default emit options.
|
||||
* @param args arguments to be forwarded to the constructor of the writer.
|
||||
*/
|
||||
template<class ...Args>
|
||||
Emitter(Args &&...args)
|
||||
: Writer(std::forward<Args>(args)...)
|
||||
, m_tree()
|
||||
, m_opts()
|
||||
, m_col()
|
||||
, m_depth()
|
||||
, m_ilevel()
|
||||
, m_pws()
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
@@ -158,7 +174,7 @@ public:
|
||||
* When writing to a file, the returned substr will be null, but its
|
||||
* length will be set to the number of bytes written.
|
||||
*
|
||||
* @param type specify what to emit
|
||||
* @param type specify what to emit (YAML or JSON)
|
||||
* @param t the tree to emit
|
||||
* @param id the id of the node to emit
|
||||
* @param error_on_excess when true, an error is raised when the
|
||||
@@ -192,21 +208,8 @@ public:
|
||||
/** get the max depth for emitted trees (to prevent a stack overflow) */
|
||||
id_type max_depth() const noexcept { return m_opts.max_depth(); }
|
||||
|
||||
private:
|
||||
|
||||
/** @cond dev */
|
||||
|
||||
typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e; ///< pending whitespace
|
||||
|
||||
private:
|
||||
|
||||
Tree const* C4_RESTRICT m_tree;
|
||||
EmitOptions m_opts;
|
||||
size_t m_col;
|
||||
id_type m_depth;
|
||||
id_type m_ilevel;
|
||||
Pws_e m_pws;
|
||||
|
||||
private:
|
||||
|
||||
void _emit_yaml(id_type id);
|
||||
@@ -229,12 +232,12 @@ private:
|
||||
void _visit_blck_seq(id_type id);
|
||||
void _visit_blck_map(id_type id);
|
||||
|
||||
void _top_open_entry(id_type id);
|
||||
void _top_close_entry(id_type id);
|
||||
void _blck_seq_open_entry(id_type id);
|
||||
void _blck_seq_close_entry(id_type id);
|
||||
void _blck_map_open_entry(id_type id);
|
||||
void _blck_map_close_entry(id_type id);
|
||||
void _top_open_entry(id_type id);
|
||||
void _top_close_entry(id_type id);
|
||||
void _blck_write_scalar_key(id_type id);
|
||||
void _blck_write_scalar_val(id_type id);
|
||||
|
||||
@@ -251,20 +254,24 @@ private:
|
||||
private:
|
||||
|
||||
void _emit_json(id_type id);
|
||||
void _visit_json_ml(id_type id, id_type depth);
|
||||
void _visit_json_sl(id_type id, id_type depth);
|
||||
void _write_json(NodeScalar const& C4_RESTRICT sc, NodeType flags);
|
||||
|
||||
void _write_scalar_json_dquo(csubstr s);
|
||||
void _write_scalar_literal(csubstr s, id_type level, bool as_key);
|
||||
void _write_scalar_folded(csubstr s, id_type level, bool as_key);
|
||||
void _write_scalar_squo(csubstr s, id_type level);
|
||||
void _write_scalar_dquo(csubstr s, id_type level);
|
||||
void _write_scalar_plain(csubstr s, id_type level);
|
||||
|
||||
size_t _write_escaped_newlines(csubstr s, size_t i);
|
||||
size_t _write_indented_block(csubstr s, size_t i, id_type level);
|
||||
|
||||
private:
|
||||
|
||||
void _visit_json_ml(id_type id, id_type depth);
|
||||
void _visit_json_sl(id_type id, id_type depth);
|
||||
void _writek_json(id_type id, NodeType ty);
|
||||
void _writev_json(id_type id, NodeType ty);
|
||||
void _write_scalar_json_dquo(csubstr s);
|
||||
|
||||
private:
|
||||
|
||||
void _write_tag(csubstr tag)
|
||||
{
|
||||
if(!tag.begins_with('!'))
|
||||
@@ -281,21 +288,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
enum : type_bits {
|
||||
_keysc = (KEY|KEYREF|KEYANCH|KEYQUO|KEY_STYLE) | ~(VAL|VALREF|VALANCH|VALQUO|VAL_STYLE) | CONTAINER_STYLE,
|
||||
_valsc = ~(KEY|KEYREF|KEYANCH|KEYQUO|KEY_STYLE) | (VAL|VALREF|VALANCH|VALQUO|VAL_STYLE) | CONTAINER_STYLE,
|
||||
_keysc_json = (KEY) | ~(VAL),
|
||||
_valsc_json = ~(KEY) | (VAL),
|
||||
};
|
||||
|
||||
C4_ALWAYS_INLINE void _writek_json(id_type id) { _write_json(m_tree->keysc(id), m_tree->_p(id)->m_type.type & ~(VAL)); }
|
||||
C4_ALWAYS_INLINE void _writev_json(id_type id) { _write_json(m_tree->valsc(id), m_tree->_p(id)->m_type.type & ~(KEY)); }
|
||||
|
||||
void _indent(id_type level, bool enabled)
|
||||
{
|
||||
if(enabled)
|
||||
_write(' ', 2u * (size_t)level);
|
||||
}
|
||||
void _indent(id_type level)
|
||||
{
|
||||
_write(' ', 2u * (size_t)level);
|
||||
@@ -329,7 +321,9 @@ private:
|
||||
this->Writer::_do_write(c, num);
|
||||
}
|
||||
|
||||
private:
|
||||
private: // pending whitespace
|
||||
|
||||
typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e; ///< pending whitespace
|
||||
|
||||
/// set pending whitespace, ignoring pending
|
||||
C4_ALWAYS_INLINE void _pend_none() noexcept
|
||||
@@ -361,6 +355,15 @@ private:
|
||||
m_pws = next;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Tree const* C4_RESTRICT m_tree;
|
||||
EmitOptions m_opts;
|
||||
size_t m_col;
|
||||
id_type m_depth;
|
||||
id_type m_ilevel;
|
||||
Pws_e m_pws;
|
||||
|
||||
/** @endcond */
|
||||
};
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ RYML_EXPORT Tree parse_json_in_place( substr json
|
||||
* substr mutable_buffer = ...;
|
||||
* parser.parse_in_arena(mutable_buffer); // linker error
|
||||
*
|
||||
* csubstr immutable_buffer = ...;
|
||||
* csubstr immutable_buffer = mutable_buffer; // convert first to csubstr
|
||||
* parser.parse_in_arena(immutable_buffer); // ok
|
||||
* ```
|
||||
*
|
||||
@@ -263,8 +263,8 @@ RYML_DEPRECATED(RYML_DONT_PARSE_SUBSTR_IN_ARENA) Tree parse_json_in_arena(Parser
|
||||
* substr mutable_buffer = ...;
|
||||
* parser.parse_in_arena(mutable_buffer); // linker error
|
||||
*
|
||||
* csubstr immutable_buffer = ...;
|
||||
* parser.parse_in_arena(immutable_buffer); // ok
|
||||
* csubstr immutable_buffer = mutable_buffer; // convert first to csubstr
|
||||
* parser.parse_in_arena(immutable_buffer); // ok now
|
||||
* ```
|
||||
*
|
||||
* @{
|
||||
|
||||
@@ -731,6 +731,13 @@ TEST(parse_json, seq_nested_on_seq_with_trailing_comma)
|
||||
}
|
||||
|
||||
|
||||
TEST(emit_json, empty_val)
|
||||
{
|
||||
Tree t = parse_in_arena("a: \nb: \"\"\nc: !!tag\nd: !!tag e");
|
||||
EXPECT_EQ(emitrs_json<std::string>(t), "{\n \"a\": null,\n \"b\": \"\",\n \"c\": \"\",\n \"d\": \"e\"\n}\n");
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------
|
||||
// this is needed to use the test case library
|
||||
Case const* get_case(csubstr /*name*/)
|
||||
|
||||
Reference in New Issue
Block a user