Prepare emitter for comments

This commit is contained in:
Joao Paulo Magalhaes
2025-10-29 18:11:59 +00:00
parent 6e7b1c5da7
commit 2e19c005f6
13 changed files with 566 additions and 437 deletions

View File

@@ -38,8 +38,9 @@
- Added `ParserOptions::detect_flow_ml()` to control this behavior
- Added `EmitOptions::indent_flow_ml()` to control indentation of FLOW_ML containers
- The emit implementation logic was refactored, and is now significantly cleaner
- Emitted YAML will now have anchors emitted before tags, as is customary ([see example](https://play.yaml.io/main/parser?input=LSAhdGFnICZhbmNob3IgfAogIG5vdGUgaG93IHRoZSBhbmNob3IgY29tZXMKICBmaXJzdCBpbiB0aGUgZXZlbnRz)).
- Added `ParserOptions` defaulted argument to temp-parser overloads of `parse_{yaml,json}_in_{place,arena}()`
- [PR#503](https://github.com/biojppm/rapidyaml/pull/503) (fixes [#399](https://github.com/biojppm/rapidyaml/issues/399)): change error callbacks.
[PR#503](https://github.com/biojppm/rapidyaml/pull/503) (fixes [#399](https://github.com/biojppm/rapidyaml/issues/399)): change error callbacks.
- Errors in ryml now have one of these types:
- parse error: when parsing YAML/JSON. See: `pfn_error_parse`, `ErrorDataParse`, `ExceptionParse`, `err_parse_format()`, `sample_error_parse`.
- visit error: when visiting a tree (reading or writing). See: `pfn_error_visit`, `ErrorDataVisit`, `ExceptionVisit`, `err_visit_format()`, `sample_error_visit`.

View File

@@ -4305,7 +4305,7 @@ void sample_emit_nested_node()
* formatting of emitted YAML code. */
void sample_style()
{
// we will be using these helpers throughout this function
// we will be using this helper throughout this function
auto tostr = [](ryml::ConstNodeRef n) { return ryml::emitrs_yaml<std::string>(n); };
// let's parse this:
ryml::csubstr yaml = R"(block map:
@@ -4473,7 +4473,7 @@ block seq:
)");
// you can set the style based on type conditions:
// set a single key to single-quoted
tree["block map"].set_style_conditionally(ryml::KEY,
tree["block map"].set_style_conditionally(/*type_mask*/ryml::KEY,
/*remflags*/ryml::KEY_STYLE,
/*addflags*/ryml::KEY_SQUO,
/*recurse*/false);

View File

@@ -10,6 +10,8 @@
#include "c4/yml/detail/dbgprint.hpp"
#endif
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
namespace c4 {
namespace yml {
@@ -30,13 +32,9 @@ substr Emitter<Writer>::emit_as(EmitType_e type, Tree const& tree, id_type id, b
m_ilevel = 0;
m_pws = _PWS_NONE;
if(type == EMIT_YAML)
{
_emit_yaml(id);
}
else if(type == EMIT_JSON)
{
_emit_json(id);
}
else
_RYML_ERR_BASIC_(m_tree->callbacks(), "unknown emit type"); // LCOV_EXCL_LINE
m_tree = nullptr;
@@ -108,12 +106,12 @@ void Emitter<Writer>::_emit_yaml(id_type id)
if(emit_key)
{
--m_ilevel;
_blck_map_close_entry(id);
_blck_close_entry(id);
}
else if(emit_dash)
{
--m_ilevel;
_blck_seq_close_entry(id);
_blck_close_entry(id);
}
else
{
@@ -121,12 +119,16 @@ void Emitter<Writer>::_emit_yaml(id_type id)
}
if(ty.is_flow_ml())
{
_newl();
}
else if(m_tree->is_root(id)
|| emit_dash || emit_key
|| !ty.is_val()
|| ty.is_val_literal() || ty.is_val_folded())
|| !ty.is_val_plain())
{
_write_pws_and_pend(_PWS_NONE);
}
}
@@ -147,12 +149,12 @@ void Emitter<Writer>::_visit_stream(id_type id)
const id_type parent = m_tree->parent(next_node);
for( ; tagds.b != end; ++tagds.b)
{
_write_pws_and_pend(_PWS_NONE);
if(next_node != m_tree->first_child(parent))
{
_write_pws_and_pend(_PWS_NEWL);
_write("...");
_newl();
}
_write_pws_and_pend(_PWS_NONE);
_write("%TAG ");
_write(tagds.b->handle);
_write(' ');
@@ -171,10 +173,20 @@ void Emitter<Writer>::_visit_stream(id_type id)
_top_open_entry(child);
_visit_doc(child);
_top_close_entry(child);
if(m_pws == _PWS_NONE)
_pend_newl();
if(m_tree->is_val(child))
{
if(m_tree->type(child) & VALNIL)
_pend_newl();
}
else if(m_tree->is_container(child))
{
if(m_tree->is_flow(child))
_pend_newl();
}
if(m_tree->next_sibling(child) != NONE)
{
write_tag_directives(m_tree->next_sibling(child));
}
}
--m_depth;
}
@@ -220,8 +232,8 @@ void Emitter<Writer>::_visit_doc_val(id_type id)
// appear at 0-indentation
NodeType ty = m_tree->type(id);
const csubstr val = m_tree->val(id);
const type_bits has_style_marks = ty & VAL_STYLE;
const bool is_ambiguous = (ty.is_val_plain() || !has_style_marks)
const type_bits val_style = ty & VAL_STYLE;
const bool is_ambiguous = ((ty & VAL_PLAIN) || !val_style)
&& (val.begins_with("...") || val.begins_with("---"));
if(is_ambiguous)
{
@@ -238,13 +250,14 @@ void Emitter<Writer>::_visit_doc_val(id_type id)
}
else
{
_blck_write_scalar_val(id);
if(!val_style)
ty = scalar_style_choose(val);
_blck_write_scalar(val, val_style);
}
if(is_ambiguous)
{
--m_ilevel;
}
_pend_newl();
}
@@ -256,7 +269,6 @@ void Emitter<Writer>::_visit_doc(id_type id)
const NodeType ty = m_tree->type(id);
_RYML_ASSERT_VISIT_(m_tree->m_callbacks, ty.is_doc(), m_tree, id);
_RYML_ASSERT_VISIT_(m_tree->m_callbacks, !ty.has_key(), m_tree, id);
if(ty.is_container()) // this is more frequent
{
_visit_blck_container(id);
@@ -280,17 +292,17 @@ void Emitter<Writer>::_top_open_entry(id_type node)
_write("---");
_pend_space();
}
if(ty.has_val_tag())
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(ty.has_val_anchor())
{
_write_pws_and_pend(_PWS_SPACE);
_write('&');
_write(m_tree->val_anchor(node));
}
if(ty.has_val_tag())
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(m_pws == _PWS_SPACE)
{
if(ty.has_val())
@@ -313,27 +325,10 @@ void Emitter<Writer>::_top_open_entry(id_type node)
template<class Writer>
void Emitter<Writer>::_top_close_entry(id_type node)
{
(void)node;
}
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_flow_sl_write_comma(id_type node, id_type first_sibling)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), first_sibling == m_tree->first_sibling(node), m_tree, node);
if(node != first_sibling)
_write(',');
}
template<class Writer>
void Emitter<Writer>::_flow_ml_write_comma(id_type node, id_type last_sibling)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), last_sibling == m_tree->last_sibling(node), m_tree, node);
if(node != last_sibling)
_write(',');
_pend_newl();
if(m_tree->is_val(node) && !(m_tree->type(node) & VALNIL))
{
_pend_newl();
}
}
@@ -344,27 +339,17 @@ void Emitter<Writer>::_flow_seq_open_entry(id_type node)
{
NodeType ty = m_tree->type(node);
_write_pws_and_pend(_PWS_NONE);
if(ty.has_val_tag())
{
_write_tag(m_tree->val_tag(node));
_pend_space();
}
if(ty.has_val_anchor())
if(ty & VALANCH)
{
_write_pws_and_pend(_PWS_SPACE);
_write('&');
_write(m_tree->val_anchor(node));
}
}
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_flow_seq_close_entry(id_type node)
{
(void)node;
_write_pws_and_pend(_PWS_NONE);
if(ty & VALTAG)
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
}
@@ -376,18 +361,18 @@ void Emitter<Writer>::_flow_map_open_entry(id_type node)
NodeType ty = m_tree->type(node);
_write_pws_and_pend(_PWS_NONE);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.has_key(), m_tree, node);
if(ty.has_key_tag())
{
_write_tag(m_tree->key_tag(node));
_pend_space();
}
if(ty.has_key_anchor())
if(ty & KEYANCH)
{
_write_pws_and_pend(_PWS_SPACE);
_write("&");
_write(m_tree->key_anchor(node));
}
if(ty.is_key_ref())
if(ty & KEYTAG)
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->key_tag(node));
}
if(ty & KEYREF)
{
_write_pws_and_pend(_PWS_SPACE);
_write_ref(m_tree->key(node));
@@ -395,31 +380,48 @@ void Emitter<Writer>::_flow_map_open_entry(id_type node)
else
{
_write_pws_and_pend(_PWS_NONE);
_blck_write_scalar_key(node);
csubstr key = m_tree->key(node);
if(!(ty & (NodeType_e)_styles_flow_key))
ty |= scalar_style_choose(key) & (NodeType_e)_styles_flow_key;
_flow_write_scalar(key, ty & (NodeType_e)_styles_flow_key);
}
_write_pws_and_pend(_PWS_SPACE);
_write(':');
if(ty.has_val_tag())
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(ty.has_val_anchor())
if(ty & VALANCH)
{
_write_pws_and_pend(_PWS_SPACE);
_write('&');
_write(m_tree->val_anchor(node));
}
if(ty & VALTAG)
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
}
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_flow_map_close_entry(id_type node)
void Emitter<Writer>::_flow_close_entry_sl(id_type node, id_type last_sibling)
{
(void)node;
_write_pws_and_pend(_PWS_NONE);
if(node != last_sibling)
{
_write_pws_and_pend(_PWS_NONE);
_write(',');
}
}
template<class Writer>
void Emitter<Writer>::_flow_close_entry_ml(id_type node, id_type last_sibling)
{
if(node != last_sibling)
{
_write_pws_and_pend(_PWS_NONE);
_write(',');
}
_pend_newl();
}
@@ -433,24 +435,24 @@ void Emitter<Writer>::_blck_seq_open_entry(id_type node)
_write_pws_and_pend(_PWS_SPACE); // pend the space after the following dash
_write('-');
bool has_tag_or_anchor = false;
if(ty.has_val_tag())
{
has_tag_or_anchor = true;
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(ty.has_val_anchor())
if(ty & VALANCH)
{
has_tag_or_anchor = true;
_write_pws_and_pend(_PWS_SPACE);
_write('&');
_write(m_tree->val_anchor(node));
}
if(ty & VALTAG)
{
has_tag_or_anchor = true;
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(has_tag_or_anchor && ty.is_container())
{
if(!(ty & CONTAINER_STYLE))
ty |= BLOCK;
if(ty.is_block() && m_tree->has_children(node))
if((ty & BLOCK) && m_tree->has_children(node))
_pend_newl();
}
}
@@ -459,10 +461,12 @@ void Emitter<Writer>::_blck_seq_open_entry(id_type node)
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_blck_seq_close_entry(id_type node)
void Emitter<Writer>::_blck_write_qmrk(id_type node, csubstr key, type_bits ty, bool has_qmrk_comments)
{
(void)node;
_pend_newl();
(void)key;
(void)ty;
(void)has_qmrk_comments;
}
@@ -473,43 +477,54 @@ void Emitter<Writer>::_blck_map_open_entry(id_type node)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), m_tree->has_key(node), m_tree, node);
NodeType ty = m_tree->type(node);
csubstr key = m_tree->key(node);
if(!(ty & (KEY_STYLE|KEYREF)))
ty |= (scalar_style_choose(key) & KEY_STYLE);
_write_pws_and_pend(_PWS_NONE);
if(ty.has_key_tag())
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->key_tag(node));
}
if(ty.has_key_anchor())
if(ty & KEYANCH)
{
_write_pws_and_pend(_PWS_SPACE);
_write('&');
_write(m_tree->key_anchor(node));
}
if(ty.is_key_ref())
if(ty & KEYTAG)
{
_write_pws_and_pend(_PWS_SPACE);
_write_ref(m_tree->key(node));
_write_tag(m_tree->key_tag(node));
}
if(ty & KEYREF)
{
_write_pws_and_pend(_PWS_SPACE);
_write_ref(key);
}
else
{
_write_pws_and_pend(_PWS_NONE);
_blck_write_scalar_key(node);
if(ty & (KEY_LITERAL|KEY_FOLDED))
_indent(m_ilevel);
type_bits use_qmrk = ty & (NodeType_e)_styles_block_key;
if(!use_qmrk)
{
_blck_write_scalar(key, ty & KEY_STYLE);
}
else
{
_write("? ");
_blck_write_scalar(key, ty & KEY_STYLE);
_pend_newl();
}
}
_write_pws_and_pend(_PWS_SPACE); // pend the space after the colon
_write(':');
if(ty.has_val_tag())
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(ty.has_val_anchor())
if(ty & VALANCH)
{
_write_pws_and_pend(_PWS_SPACE);
_write('&');
_write(m_tree->val_anchor(node));
}
if(ty & VALTAG)
{
_write_pws_and_pend(_PWS_SPACE);
_write_tag(m_tree->val_tag(node));
}
if(ty.is_container() && m_tree->has_children(node))
{
if(!(ty & CONTAINER_STYLE))
@@ -523,7 +538,7 @@ void Emitter<Writer>::_blck_map_open_entry(id_type node)
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_blck_map_close_entry(id_type node)
void Emitter<Writer>::_blck_close_entry(id_type node)
{
(void)node;
_pend_newl();
@@ -540,16 +555,23 @@ void Emitter<Writer>::_visit_blck_seq(id_type node)
for(id_type child = m_tree->first_child(node); child != NONE; child = m_tree->next_sibling(child))
{
empty = false;
const NodeType ty = m_tree->type(child);
NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.is_val() || ty.is_container() || ty == NOTYPE, m_tree, node);
_blck_seq_open_entry(child);
if(ty.is_val())
{
_write_pws_and_pend(_PWS_NONE);
csubstr val = m_tree->val(child);
if(!ty.is_val_ref())
_blck_write_scalar_val(child);
{
if(!(ty & VAL_STYLE))
ty |= (scalar_style_choose(val) & VAL_STYLE);
_blck_write_scalar(val, ty & VAL_STYLE);
}
else
_write_ref(m_tree->val(child));
{
_write_ref(val);
}
}
else if(ty.is_container())
{
@@ -559,7 +581,7 @@ void Emitter<Writer>::_visit_blck_seq(id_type node)
--m_depth;
--m_ilevel;
}
_blck_seq_close_entry(child);
_blck_close_entry(child);
}
if(empty)
{
@@ -579,16 +601,23 @@ void Emitter<Writer>::_visit_blck_map(id_type node)
for(id_type child = m_tree->first_child(node); child != NONE; child = m_tree->next_sibling(child))
{
empty = false;
const NodeType ty = m_tree->type(child);
NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.is_keyval() || ty.is_container() || ty == NOTYPE, m_tree, node);
_blck_map_open_entry(child); // also writes the key
if(ty.is_keyval())
{
_write_pws_and_pend(_PWS_NONE);
csubstr val = m_tree->val(child);
if(!ty.is_val_ref())
_blck_write_scalar_val(child);
{
if(!(ty & VAL_STYLE))
ty |= (scalar_style_choose(val) & VAL_STYLE);
_blck_write_scalar(val, ty & VAL_STYLE);
}
else
_write_ref(m_tree->val(child));
{
_write_ref(val);
}
}
else if(ty.is_container())
{
@@ -598,7 +627,7 @@ void Emitter<Writer>::_visit_blck_map(id_type node)
--m_depth;
--m_ilevel;
}
_blck_map_close_entry(child);
_blck_close_entry(child);
}
if(empty)
{
@@ -615,19 +644,25 @@ void Emitter<Writer>::_visit_flow_sl_seq(id_type node)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), m_tree->is_seq(node), m_tree, node);
_write('[');
for(id_type first = m_tree->first_child(node), child = first; child != NONE; child = m_tree->next_sibling(child))
for(id_type child = m_tree->first_child(node), last = m_tree->last_child(node); child != NONE; child = m_tree->next_sibling(child))
{
_flow_sl_write_comma(child, first);
const NodeType ty = m_tree->type(child);
NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.is_val() || ty.is_container() || ty == NOTYPE, m_tree, node);
_flow_seq_open_entry(child);
if(ty.is_val())
{
_write_pws_and_pend(_PWS_NONE);
csubstr val = m_tree->val(child);
if(!ty.is_val_ref())
_flow_write_scalar_val(child);
{
if(!(ty & (NodeType_e)_styles_flow_val))
ty |= (scalar_style_choose(val) & (NodeType_e)_styles_flow_val);
_flow_write_scalar(val, ty & (NodeType_e)_styles_flow_val);
}
else
_write_ref(m_tree->val(child));
{
_write_ref(val);
}
}
else if(ty.is_container())
{
@@ -635,12 +670,55 @@ void Emitter<Writer>::_visit_flow_sl_seq(id_type node)
_visit_flow_container(child);
--m_depth;
}
_flow_seq_close_entry(child);
_flow_close_entry_sl(child, last);
}
_write(']');
}
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_visit_flow_ml_seq(id_type node)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), m_tree->is_seq(node), m_tree, node);
_write('[');
_pend_newl();
if(m_opts.indent_flow_ml()) ++m_ilevel;
for(id_type child = m_tree->first_child(node), last = m_tree->last_child(node); child != NONE; child = m_tree->next_sibling(child))
{
NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.is_val() || ty.is_container() || ty == NOTYPE, m_tree, node);
_flow_seq_open_entry(child);
if(ty.is_val())
{
_write_pws_and_pend(_PWS_NONE);
csubstr val = m_tree->val(child);
if(!ty.is_val_ref())
{
if(!(ty & (NodeType_e)_styles_flow_val))
ty |= (scalar_style_choose(val) & (NodeType_e)_styles_flow_val);
_flow_write_scalar(val, ty & (NodeType_e)_styles_flow_val);
}
else
{
_write_ref(val);
}
}
else if(ty.is_container())
{
++m_depth;
_visit_flow_container(child);
--m_depth;
}
_flow_close_entry_ml(child, last);
}
if(m_opts.indent_flow_ml()) --m_ilevel;
_write_pws_and_pend(_PWS_NONE);
_write(']');
}
//-----------------------------------------------------------------------------
template<class Writer>
@@ -648,19 +726,25 @@ void Emitter<Writer>::_visit_flow_sl_map(id_type node)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), m_tree->is_map(node), m_tree, node);
_write('{');
for(id_type first = m_tree->first_child(node), child = first; child != NONE; child = m_tree->next_sibling(child))
for(id_type child = m_tree->first_child(node), last = m_tree->last_child(node); child != NONE; child = m_tree->next_sibling(child))
{
_flow_sl_write_comma(child, first);
const NodeType ty = m_tree->type(child);
NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.has_key() && (ty.has_val() || ty.is_container() || ty == NOTYPE), m_tree, node);
_flow_map_open_entry(child);
if(ty.has_val())
{
_write_pws_and_pend(_PWS_NONE);
csubstr val = m_tree->val(child);
if(!ty.is_val_ref())
_flow_write_scalar_val(child);
{
if(!(ty & (NodeType_e)_styles_flow_val))
ty |= (scalar_style_choose(val) & (NodeType_e)_styles_flow_val);
_flow_write_scalar(val, ty & (NodeType_e)_styles_flow_val);
}
else
_write_ref(m_tree->val(child));
{
_write_ref(val);
}
}
else if(ty.is_container())
{
@@ -668,8 +752,9 @@ void Emitter<Writer>::_visit_flow_sl_map(id_type node)
_visit_flow_container(child);
--m_depth;
}
_flow_map_close_entry(child);
_flow_close_entry_sl(child, last);
}
_write_pws_and_pend(_PWS_NONE);
_write('}');
}
@@ -685,16 +770,23 @@ void Emitter<Writer>::_visit_flow_ml_map(id_type node)
if(m_opts.indent_flow_ml()) ++m_ilevel;
for(id_type child = m_tree->first_child(node), last = m_tree->last_child(node); child != NONE; child = m_tree->next_sibling(child))
{
const NodeType ty = m_tree->type(child);
NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.has_key() && (ty.has_val() || ty.is_container() || ty == NOTYPE), m_tree, node);
_flow_map_open_entry(child);
if(ty.has_val())
{
_write_pws_and_pend(_PWS_NONE);
csubstr val = m_tree->val(child);
if(!ty.is_val_ref())
_flow_write_scalar_val(child);
{
if(!(ty & (NodeType_e)_styles_flow_val))
ty |= (scalar_style_choose(val) & (NodeType_e)_styles_flow_val);
_flow_write_scalar(val, ty & (NodeType_e)_styles_flow_val);
}
else
_write_ref(m_tree->val(child));
{
_write_ref(val);
}
}
else if(ty.is_container())
{
@@ -702,8 +794,7 @@ void Emitter<Writer>::_visit_flow_ml_map(id_type node)
_visit_flow_container(child);
--m_depth;
}
_flow_map_close_entry(child);
_flow_ml_write_comma(child, last);
_flow_close_entry_ml(child, last);
}
if(m_opts.indent_flow_ml()) --m_ilevel;
_write_pws_and_pend(_PWS_NONE);
@@ -711,43 +802,6 @@ void Emitter<Writer>::_visit_flow_ml_map(id_type node)
}
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_visit_flow_ml_seq(id_type node)
{
_RYML_ASSERT_VISIT_(m_tree->callbacks(), m_tree->is_seq(node), m_tree, node);
_write('[');
_pend_newl();
if(m_opts.indent_flow_ml()) ++m_ilevel;
for(id_type child = m_tree->first_child(node), last = m_tree->last_child(node); child != NONE; child = m_tree->next_sibling(child))
{
const NodeType ty = m_tree->type(child);
_RYML_ASSERT_VISIT_(m_tree->callbacks(), ty.is_val() || ty.is_container() || ty == NOTYPE, m_tree, node);
_flow_seq_open_entry(child);
if(ty.is_val())
{
_write_pws_and_pend(_PWS_NONE);
if(!ty.is_val_ref())
_flow_write_scalar_val(child);
else
_write_ref(m_tree->val(child));
}
else if(ty.is_container())
{
++m_depth;
_visit_flow_container(child);
--m_depth;
}
_flow_seq_close_entry(child);
_flow_ml_write_comma(child, last);
}
if(m_opts.indent_flow_ml()) --m_ilevel;
_write_pws_and_pend(_PWS_NONE);
_write(']');
}
//-----------------------------------------------------------------------------
template<class Writer>
@@ -820,140 +874,45 @@ void Emitter<Writer>::_visit_flow_ml(id_type node)
//-----------------------------------------------------------------------------
template<class Writer>
void Emitter<Writer>::_flow_write_scalar_key(id_type id)
void Emitter<Writer>::_flow_write_scalar(csubstr str, type_bits ty)
{
enum : type_bits {
_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 & (KEY_LITERAL|KEY_FOLDED)), m_tree, id);
if(ty & KEY_PLAIN)
_RYML_ASSERT_BASIC_(m_tree->callbacks(), !(ty & _styles_block));
if((ty & _styles_plain) || !(ty & SCALAR_STYLE))
{
if(C4_LIKELY(!(str.begins_with(": ") || str.begins_with(":\t"))))
_write_scalar_plain(str, m_ilevel);
else
_write_scalar_squo(str, m_ilevel);
_write_scalar_plain(str, m_ilevel);
}
else if(ty & KEY_SQUO)
else if(ty & _styles_squo)
{
_write_scalar_squo(str, m_ilevel);
}
else if(ty & KEY_DQUO)
else // if(ty & _styles_dquo)
{
_write_scalar_dquo(str, m_ilevel);
}
else
{
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, id, "not implemented"); // LCOV_EXCL_LINE
}
}
template<class Writer>
void Emitter<Writer>::_flow_write_scalar_val(id_type id)
void Emitter<Writer>::_blck_write_scalar(csubstr str, type_bits ty)
{
enum : type_bits {
_block_styles = VAL_LITERAL|VAL_FOLDED,
_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 & (VAL_LITERAL|VAL_FOLDED)), m_tree, id);
if(ty & VAL_PLAIN)
if((ty & _styles_plain) || !(ty & SCALAR_STYLE))
{
if(C4_LIKELY(!(str.begins_with(": ") || str.begins_with(":\t"))))
_write_scalar_plain(str, m_ilevel);
else
_write_scalar_squo(str, m_ilevel);
_write_scalar_plain(str, m_ilevel);
}
else if(ty & VAL_SQUO)
else if(ty & _styles_squo)
{
_write_scalar_squo(str, m_ilevel);
}
else if(ty & VAL_DQUO)
else if(ty & _styles_dquo)
{
_write_scalar_dquo(str, m_ilevel);
}
else
else if(ty & _styles_literal)
{
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, id, "not implemented"); // LCOV_EXCL_LINE
_write_scalar_literal(str, m_ilevel);
}
}
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);
if(!(ty & KEY_STYLE))
ty |= scalar_style_choose(key);
if(ty & KEY_PLAIN)
else // if(ty & _styles_folded)
{
if(C4_LIKELY(!(key.begins_with(": ") || key.begins_with(":\t"))))
_write_scalar_plain(key, m_ilevel);
else
_write_scalar_squo(key, m_ilevel);
}
else if(ty & KEY_SQUO)
{
_write_scalar_squo(key, m_ilevel);
}
else if(ty & KEY_DQUO)
{
_write_scalar_dquo(key, m_ilevel);
}
else if(ty & KEY_LITERAL)
{
_write_scalar_literal(key, m_ilevel, /*explicit*/true);
}
else if(ty & KEY_FOLDED)
{
_write_scalar_folded(key, m_ilevel, /*explicit*/true);
}
else
{
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, NONE, "not implemented"); // LCOV_EXCL_LINE
}
}
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);
if(!(ty & VAL_STYLE))
ty |= scalar_style_choose(str);
if(ty & VAL_PLAIN)
{
if(C4_LIKELY(!(str.begins_with(": ") || str.begins_with(":\t"))))
_write_scalar_plain(str, m_ilevel);
else
_write_scalar_squo(str, m_ilevel);
}
else if(ty & VAL_SQUO)
{
_write_scalar_squo(str, m_ilevel);
}
else if(ty & VAL_DQUO)
{
_write_scalar_dquo(str, m_ilevel);
}
else if(ty & VAL_LITERAL)
{
_write_scalar_literal(str, m_ilevel, /*explicit*/false);
}
else if(ty & VAL_FOLDED)
{
_write_scalar_folded(str, m_ilevel, /*explicit*/false);
}
else
{
_RYML_ERR_VISIT_(m_tree->callbacks(), m_tree, NONE, "not implemented"); // LCOV_EXCL_LINE
_write_scalar_folded(str, m_ilevel);
}
}
@@ -1024,11 +983,9 @@ again:
}
template<class Writer>
void Emitter<Writer>::_write_scalar_literal(csubstr s, id_type ilevel, bool explicit_key)
void Emitter<Writer>::_write_scalar_literal(csubstr s, id_type ilevel)
{
_RYML_ASSERT_BASIC_(m_tree->callbacks(), s.find("\r") == csubstr::npos);
if(explicit_key)
_write("? ");
csubstr trimmed = s.trimr('\n');
const size_t numnewlines_at_end = s.len - trimmed.len;
const bool is_newline_only = (trimmed.len == 0 && (s.len > 0));
@@ -1065,15 +1022,11 @@ void Emitter<Writer>::_write_scalar_literal(csubstr s, id_type ilevel, bool expl
}
for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i)
_newl();
if(explicit_key)
_newl();
}
template<class Writer>
void Emitter<Writer>::_write_scalar_folded(csubstr s, id_type ilevel, bool explicit_key)
void Emitter<Writer>::_write_scalar_folded(csubstr s, id_type ilevel)
{
if(explicit_key)
_write("? ");
_RYML_ASSERT_BASIC_(m_tree->callbacks(), s.find("\r") == csubstr::npos);
csubstr trimmed = s.trimr('\n');
const size_t numnewlines_at_end = s.len - trimmed.len;
@@ -1143,8 +1096,6 @@ void Emitter<Writer>::_write_scalar_folded(csubstr s, id_type ilevel, bool expli
}
for(size_t i = !is_newline_only; i < numnewlines_at_end; ++i)
_newl();
if(explicit_key)
_newl();
}
template<class Writer>
@@ -1528,4 +1479,6 @@ void Emitter<Writer>::_write_scalar_json_dquo(csubstr s)
} // namespace yml
} // namespace c4
C4_SUPPRESS_WARNING_GCC_CLANG_POP
#endif /* _C4_YML_EMIT_DEF_HPP_ */

View File

@@ -136,9 +136,9 @@ public:
* @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)...)
template<class ...WriterArgs>
Emitter(EmitOptions const& opts, WriterArgs &&...args)
: Writer(std::forward<WriterArgs>(args)...)
, m_tree()
, m_opts(opts)
, m_col()
@@ -150,9 +150,9 @@ 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)...)
template<class ...WriterArgs>
Emitter(WriterArgs &&...args)
: Writer(std::forward<WriterArgs>(args)...)
, m_tree()
, m_opts()
, m_col()
@@ -208,10 +208,10 @@ public:
/** get the max depth for emitted trees (to prevent a stack overflow) */
id_type max_depth() const noexcept { return m_opts.max_depth(); }
/** @cond dev */
private:
/** @cond dev */
void _emit_yaml(id_type id);
void _visit_stream(id_type id);
@@ -235,30 +235,26 @@ private:
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 _blck_write_scalar_key(id_type id);
void _blck_write_scalar_val(id_type id);
void _blck_close_entry(id_type id);
void _blck_write_qmrk(id_type id, csubstr key, type_bits type, bool has_qmrk_comments);
void _blck_write_scalar(csubstr str, type_bits type);
void _flow_seq_open_entry(id_type id);
void _flow_seq_close_entry(id_type id);
void _flow_map_open_entry(id_type id);
void _flow_map_close_entry(id_type id);
void _flow_write_scalar_key(id_type id);
void _flow_write_scalar_val(id_type id);
void _flow_sl_write_comma(id_type id, id_type first_sibling);
void _flow_ml_write_comma(id_type id, id_type first_sibling);
void _flow_close_entry_sl(id_type id, id_type last_sibling);
void _flow_close_entry_ml(id_type id, id_type last_sibling);
void _flow_write_scalar(csubstr str, type_bits type);
private:
void _emit_json(id_type id);
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_literal(csubstr s, id_type level);
void _write_scalar_folded(csubstr s, id_type level);
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);
@@ -288,42 +284,48 @@ private:
}
}
void _indent(id_type level)
private:
C4_ALWAYS_INLINE void _indent(id_type level)
{
_write(' ', 2u * (size_t)level);
size_t num = (size_t)(2u * level);
this->Writer::_do_write(' ', num);
m_col += num;
}
template<size_t N>
C4_ALWAYS_INLINE void _write(const char (&a)[N])
{
this->Writer::_do_write(std::forward<const char (&)[N]>(a));
m_col += N-1;
}
C4_ALWAYS_INLINE void _write(csubstr s)
{
this->Writer::_do_write(s);
m_col += s.len;
}
C4_ALWAYS_INLINE void _write(char c)
{
this->Writer::_do_write(c);
++m_col;
}
C4_ALWAYS_INLINE void _write(char c, size_t num)
{
this->Writer::_do_write(c, num);
m_col += num;
}
/// write a newline and reset the column
C4_ALWAYS_INLINE void _newl()
{
m_col = 0;
this->Writer::_do_write('\n');
}
template<size_t N>
C4_ALWAYS_INLINE void _write(const char (&a)[N])
{
m_col += N-1;
this->Writer::_do_write(std::forward<const char (&)[N]>(a));
}
C4_ALWAYS_INLINE void _write(csubstr s)
{
m_col += s.len;
this->Writer::_do_write(s);
}
C4_ALWAYS_INLINE void _write(char c)
{
++m_col;
this->Writer::_do_write(c);
}
C4_ALWAYS_INLINE void _write(char c, size_t num)
{
m_col += num;
this->Writer::_do_write(c, num);
m_col = 0;
}
private: // pending whitespace
typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e; ///< pending whitespace
/// pending whitespace
typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e;
/// set pending whitespace, ignoring pending
C4_ALWAYS_INLINE void _pend_none() noexcept
@@ -359,10 +361,26 @@ 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;
size_t m_col;
id_type m_depth;
id_type m_ilevel;
Pws_e m_pws;
private:
enum : type_bits {
_styles_block_key = KEY_LITERAL|KEY_FOLDED,
_styles_block_val = VAL_LITERAL|VAL_FOLDED,
_styles_block = _styles_block_key|_styles_block_val,
_styles_flow_key = KEY_STYLE & ~_styles_block_key,
_styles_flow_val = VAL_STYLE & ~_styles_block_val,
_styles_flow = _styles_flow_key|_styles_flow_val,
_styles_squo = KEY_SQUO|VAL_SQUO,
_styles_dquo = KEY_DQUO|VAL_DQUO,
_styles_plain = KEY_PLAIN|VAL_PLAIN,
_styles_literal = KEY_LITERAL|VAL_LITERAL,
_styles_folded = KEY_FOLDED|VAL_FOLDED,
};
/** @endcond */
};

View File

@@ -188,20 +188,25 @@ public:
{
_c4dbgp("ensure stream");
_set_root_as_stream();
id_type first = m_tree->first_child(m_tree->root_id());
_RYML_ASSERT_VISIT_(m_stack.m_callbacks, m_tree->is_stream(m_tree->root_id()), m_tree, m_curr->node_id);
_RYML_ASSERT_VISIT_(m_stack.m_callbacks, m_tree->num_children(m_tree->root_id()) == 1u, m_tree, m_curr->node_id);
const id_type root = m_tree->root_id();
const id_type first = m_tree->first_child(root);
_RYML_ASSERT_VISIT_(m_stack.m_callbacks, m_tree->is_stream(root), m_tree, root);
_RYML_ASSERT_VISIT_(m_stack.m_callbacks, m_tree->num_children(root) == 1u, m_tree, root);
if(m_tree->is_container(first) || m_tree->is_val(first))
{
_c4dbgp("push!");
_push();
#ifdef RYML_WITH_COMMENTS
m_tree->_p(root)->m_first_comment = NONE;
m_tree->_p(root)->m_last_comment = NONE;
#endif
}
else
{
_c4dbgp("tweak");
_push();
_remove_speculative();
m_curr->node_id = m_tree->last_child(m_tree->root_id());
m_curr->node_id = m_tree->last_child(root);
m_curr->tr_data = m_tree->_p(m_curr->node_id);
}
}

View File

@@ -159,8 +159,7 @@ bool scalar_style_query_plain(csubstr s) noexcept
{
return true;
}
return s != ':'
&& ( ! s.begins_with_any("-:?*&,'\"{}[]|>%#@`\r")) // @ and ` are reserved characters
return ( ! s.begins_with_any("-:?*&,'\"{}[]|>%#@`\r")) // @ and ` are reserved characters
&& ( ! s.ends_with_any(":#"))
// make this check in the last place, as it has linear
// complexity, while the previous ones are

View File

@@ -934,7 +934,7 @@ bool Tree::change_type(id_type node, NodeType type)
return false;
else if(type.is_val() && is_val(node))
return false;
d->m_type = (d->m_type & (~(MAP|SEQ|VAL))) | type;
d->m_type = (d->m_type & (~(MAP|SEQ|VAL|CONTAINER_STYLE|KEY_STYLE|VAL_STYLE))) | type;
remove_children(node);
return true;
}

View File

@@ -61,6 +61,40 @@ int32_t estimate_events_ints_size(csubstr src)
return count;
}
// ensure the ievt flags work despite being signed
namespace ievt {
static_assert((MASK & BSTR) == BSTR, "overflow?");
static_assert((MASK & ESTR) == ESTR, "overflow?");
static_assert((MASK & BDOC) == BDOC, "overflow?");
static_assert((MASK & EDOC) == EDOC, "overflow?");
static_assert((MASK & BMAP) == BMAP, "overflow?");
static_assert((MASK & EMAP) == EMAP, "overflow?");
static_assert((MASK & BSEQ) == BSEQ, "overflow?");
static_assert((MASK & ESEQ) == ESEQ, "overflow?");
static_assert((MASK & ANCH) == ANCH, "overflow?");
static_assert((MASK & ALIA) == ALIA, "overflow?");
static_assert((MASK & TAG_) == TAG_, "overflow?");
static_assert((MASK & PLAI) == PLAI, "overflow?");
static_assert((MASK & SQUO) == SQUO, "overflow?");
static_assert((MASK & DQUO) == DQUO, "overflow?");
static_assert((MASK & LITL) == LITL, "overflow?");
static_assert((MASK & FOLD) == FOLD, "overflow?");
static_assert((MASK & FLOW) == FLOW, "overflow?");
static_assert((MASK & BLCK) == BLCK, "overflow?");
static_assert((MASK & KEY_) == KEY_, "overflow?");
static_assert((MASK & VAL_) == VAL_, "overflow?");
static_assert((MASK & EXPL) == EXPL, "overflow?");
static_assert((MASK & YAML) == YAML, "overflow?");
static_assert((MASK & TAGD) == TAGD, "overflow?");
static_assert((MASK & TAGV) == TAGV, "overflow?");
static_assert((MASK & AREN) == AREN, "overflow?");
static_assert((MASK & PSTR) == PSTR, "overflow?");
static_assert((MASK & UNFILT) == UNFILT, "overflow?");
static_assert((MASK & LAST) == LAST, "overflow?");
static_assert((MASK & MASK) == MASK, "overflow?");
static_assert((MASK & WSTR) == WSTR, "overflow?");
} // namespace ievt
} // namespace extra
} // namespace yml
} // namespace c4

View File

@@ -43,13 +43,32 @@ using DataType = int32_t;
/** enumeration of integer event bits. */
typedef enum : DataType {
// Structure flags
KEY_ = (1 << 0), ///< as key
VAL_ = (1 << 1), ///< as value
/// special flag to enable look-back in the event array. it
/// signifies that the previous event has a string, meaning that
/// the jump back to that event is 3 positions. without this flag it
/// would be impossible to jump to the previous event.
/// see also @ref WSTR
PSTR = (1 << 2),
/// IMPORTANT. Marks events whose string was placed in the
/// arena. This happens when the filtered string is larger than the
/// original string in the YAML code (eg from tags that resolve to
/// a larger string, or from "\L" or "\P" in double quotes, which
/// expand from two to three bytes). Because of this size
/// expansion, the filtered string cannot be placed in the original
/// source and needs to be placed in the arena.
AREN = (1 << 3),
// Event scopes
BEG_ = (1 << 0), ///< scope: begin
END_ = (1 << 1), ///< scope: end
SEQ_ = (1 << 2), ///< scope: seq
MAP_ = (1 << 3), ///< scope: map
DOC_ = (1 << 4), ///< scope: doc
STRM = (1 << 5), ///< scope: stream
BEG_ = (1 << 5), ///< scope: begin
END_ = (1 << 6), ///< scope: end
SEQ_ = (1 << 7), ///< scope: seq
MAP_ = (1 << 8), ///< scope: map
DOC_ = (1 << 9), ///< scope: doc
EXPL = (1 << 10), ///< `---` (with BDOC) or `...` (with EDOC)
STRM = (1 << 11), ///< scope: stream
BSEQ = BEG_|SEQ_, ///< begin seq (+SEQ in test suite events)
ESEQ = END_|SEQ_, ///< end seq (-SEQ in test suite events)
BMAP = BEG_|MAP_, ///< begin map (+MAP in test suite events)
@@ -60,58 +79,41 @@ typedef enum : DataType {
EDOC = END_|DOC_, ///< end doc (-DOC in test suite events)
// Single events
SCLR = (1 << 6), ///< scalar (=VAL in test suite events)
ALIA = (1 << 7), ///< *ref (reference)
ANCH = (1 << 8), ///< &anchor
TAG_ = (1 << 9), ///< !tag
// Structure flags
KEY_ = (1 << 10), ///< as key
VAL_ = (1 << 11), ///< as value
EXPL = (1 << 12), ///< `---` (with BDOC) or `...` (with EDOC)
SCLR = (1 << 12), ///< scalar (=VAL in test suite events)
ALIA = (1 << 13), ///< *ref (reference)
ANCH = (1 << 14), ///< &anchor
TAG_ = (1 << 15), ///< !tag
// Style flags
PLAI = (1 << 13), ///< scalar: plain
SQUO = (1 << 14), ///< scalar: single-quoted (')
DQUO = (1 << 15), ///< scalar: double-quoted ("")
LITL = (1 << 16), ///< scalar: block literal (|)
FOLD = (1 << 17), ///< scalar: block folded (>)
FLOW = (1 << 18), ///< container: flow: [] for seqs or {} for maps
BLCK = (1 << 19), ///< container: block
PLAI = (1 << 16), ///< scalar: plain
SQUO = (1 << 17), ///< scalar: single-quoted (')
DQUO = (1 << 18), ///< scalar: double-quoted ("")
LITL = (1 << 19), ///< scalar: block literal (|)
FOLD = (1 << 20), ///< scalar: block folded (>)
FLOW = (1 << 21), ///< container: flow: [] for seqs or {} for maps
BLCK = (1 << 22), ///< container: block
// Directive flags
YAML = (1 << 20), ///< yaml directive: `\%YAML <version>`
TAGD = (1 << 21), ///< tag directive, name : `\%TAG <name> .......`
TAGV = (1 << 22), ///< tag directive, value: `\%TAG ...... <value>`
YAML = (1 << 23), ///< yaml directive: `\%YAML <version>`
TAGD = (1 << 24), ///< tag directive, name : `\%TAG <name> .......`
TAGV = (1 << 25), ///< tag directive, value: `\%TAG ...... <value>`
// Buffer flags
/// IMPORTANT. Marks events whose string was placed in the
/// arena. This happens when the filtered string is larger than the
/// original string in the YAML code (eg from tags that resolve to
/// a larger string, or from "\L" or "\P" in double quotes, which
/// expand from two to three bytes). Because of this size
/// expansion, the filtered string cannot be placed in the original
/// source and needs to be placed in the arena.
AREN = (1 << 23),
/// special flag to enable look-back in the event array. it
/// signifies that the previous event has a string, meaning that
/// the jump back to that event is 3 positions. without this flag it
/// would be impossible to jump to the previous event.
PSTR = (1 << 24),
/// special flag to mark a scalar as unfiltered (when the parser
/// is set not to filter).
UNFILT = (1 << 25),
UNFILT = (1 << 26),
// Utility flags/masks
/// the last flag defined above
LAST = UNFILT,
/// a mask of all bits in this enumeration
MASK = (LAST << 1) - 1,
/// with string: mask of all the events that encode a string
/// following the event. in the event has a string. the next two
/// integers will provide respectively the string's offset and
/// length. See also @ref PSTR.
/// WithSTRing: mask of all the events that encode a string
/// following the event. For such events, the next two integers
/// will provide respectively the string's offset and length. See
/// also @ref PSTR.
WSTR = SCLR|ALIA|ANCH|TAG_|TAGD|TAGV|YAML,
} EventFlags;
} // namespace ievt

View File

@@ -17,7 +17,7 @@
#ifndef _C4_YML_EXTRA_SCALAR_HPP_
#include "c4/yml/extra/scalar.hpp"
#endif
#ifndef _C4_YML_EXTRA_SCALAR_HPP_
#ifndef _C4_YML_EXTRA_STRING_HPP_
#include "c4/yml/extra/string.hpp"
#endif

View File

@@ -234,28 +234,56 @@ TEST(emit_nested, basic)
TEST(emit_block_seq, ambiguous_plain_emitted_as_squo)
{
Tree t;
NodeRef r = t.rootref();
r |= SEQ|BLOCK;
r[0] = ": odd";
r[0] |= VAL_PLAIN;
r[1] = ":\todd";
r[1] |= VAL_PLAIN;
EXPECT_EQ(emitrs_yaml<std::string>(t), "- ': odd'\n- ':\todd'\n");
EXPECT_EQ(scalar_style_query_plain(": odd"), false);
EXPECT_EQ(scalar_style_query_plain(":\todd"), false);
EXPECT_EQ(scalar_style_choose(": odd"), SCALAR_SQUO);
EXPECT_EQ(scalar_style_choose(":\todd"), SCALAR_SQUO);
{
Tree t;
NodeRef r = t.rootref();
r |= SEQ|BLOCK;
r[0] = ": odd";
r[0] |= VAL_PLAIN;
r[1] = ":\todd";
r[1] |= VAL_PLAIN;
EXPECT_EQ(emitrs_yaml<std::string>(t), "- : odd\n- :\todd\n");
}
{
Tree t;
NodeRef r = t.rootref();
r |= SEQ|BLOCK;
r[0] = ": odd";
r[1] = ":\todd";
EXPECT_FALSE(r[0].is_val_plain());
EXPECT_FALSE(r[1].is_val_plain());
EXPECT_EQ(emitrs_yaml<std::string>(t), "- ': odd'\n- ':\todd'\n");
}
}
TEST(emit_block_map, ambiguous_plain_emitted_as_squo)
{
Tree t;
NodeRef r = t.rootref();
r |= MAP|BLOCK;
r[0].set_key(": odd");
r[0] = ": odd";
r[0] |= KEY_PLAIN|VAL_PLAIN;
r[1].set_key(":\todd");
r[1] = ":\todd";
r[1] |= KEY_PLAIN|VAL_PLAIN;
EXPECT_EQ(emitrs_yaml<std::string>(t), "': odd': ': odd'\n':\todd': ':\todd'\n");
{
Tree t;
NodeRef r = t.rootref();
r |= MAP|BLOCK;
r[0].set_key(": odd");
r[0] = ": odd";
r[1].set_key(":\todd");
r[1] = ":\todd";
EXPECT_EQ(emitrs_yaml<std::string>(t), "': odd': ': odd'\n':\todd': ':\todd'\n");
}
{
Tree t;
NodeRef r = t.rootref();
r |= MAP|BLOCK;
r[0].set_key(": odd");
r[0] = ": odd";
r[0] |= KEY_PLAIN|VAL_PLAIN;
r[1].set_key(":\todd");
r[1] = ":\todd";
r[1] |= KEY_PLAIN|VAL_PLAIN;
EXPECT_EQ(emitrs_yaml<std::string>(t), ": odd: : odd\n:\todd: :\todd\n");
}
}
@@ -755,12 +783,8 @@ TEST(emit, empty_key_literal)
test_emits(t, t.root_id(), expected, expected_json);
}
{
SCOPED_TRACE("nested");
const Tree t = parse_in_arena(R"(
level1:
? |-
: literal
)");
SCOPED_TRACE("nested1");
const Tree t = parse_in_arena("level1:\n ? |-\n : literal\n");
std::string expected = "level1:\n ? |-\n : literal\n";
std::string expected_json = "{\n \"level1\": {\n \"\": \"literal\"\n }\n}\n";
test_emits(t, t.root_id(), expected, expected_json);

View File

@@ -561,7 +561,7 @@ ENGINE_TEST(AnchorMapMapFlow,
//-----------------------------------------------------------------------------
ENGINE_TEST(AnchorTagPlacement,
ENGINE_TEST(AnchorTagPlacement1,
"- &a0 !b0 foo0: bar0\n"
"- &a1 !b1\n"
" foo1: bar1\n"
@@ -576,14 +576,14 @@ ENGINE_TEST(AnchorTagPlacement,
"\n"
" foo4: bar4\n"
,
"- !b0 &a0 foo0: bar0\n"
"- !b1 &a1\n"
"- &a0 !b0 foo0: bar0\n"
"- &a1 !b1\n"
" foo1: bar1\n"
"- &a2\n"
" !b2 foo2: bar2\n"
"- !b3 &a3\n"
"- &a3 !b3\n"
" foo3: bar3\n"
"- !b4 &a4\n"
"- &a4 !b4\n"
" foo4: bar4\n"
,
"+STR\n"
@@ -655,6 +655,100 @@ ENGINE_TEST(AnchorTagPlacement,
___(ps.end_stream());
}
ENGINE_TEST(AnchorTagPlacement2,
"- !b0 &a0 foo0: bar0\n"
"- !b1 &a1\n"
" foo1: bar1\n"
"- !b2\n"
" &a2 foo2: bar2\n"
"- !b3\n"
" &a3\n"
" foo3: bar3\n"
"- !b4\n"
"\n"
" &a4\n"
"\n"
" foo4: bar4\n"
,
"- &a0 !b0 foo0: bar0\n"
"- &a1 !b1\n"
" foo1: bar1\n"
"- !b2\n"
" &a2 foo2: bar2\n"
"- &a3 !b3\n"
" foo3: bar3\n"
"- &a4 !b4\n"
" foo4: bar4\n"
,
"+STR\n"
"+DOC\n"
"+SEQ\n"
"+MAP\n"
"=VAL &a0 <!b0> :foo0\n"
"=VAL :bar0\n"
"-MAP\n"
"+MAP &a1 <!b1>\n"
"=VAL :foo1\n"
"=VAL :bar1\n"
"-MAP\n"
"+MAP <!b2>\n"
"=VAL &a2 :foo2\n"
"=VAL :bar2\n"
"-MAP\n"
"+MAP &a3 <!b3>\n"
"=VAL :foo3\n"
"=VAL :bar3\n"
"-MAP\n"
"+MAP &a4 <!b4>\n"
"=VAL :foo4\n"
"=VAL :bar4\n"
"-MAP\n"
"-SEQ\n"
"-DOC\n"
"-STR\n")
{
___(ps.begin_stream());
___(ps.begin_doc());
___(ps.begin_seq_val_block());
___(ps.begin_map_val_block());
___(ps.set_key_anchor("a0"));
___(ps.set_key_tag("!b0"));
___(ps.set_key_scalar_plain("foo0"));
___(ps.set_val_scalar_plain("bar0"));
___(ps.end_map_block());
___(ps.add_sibling());
___(ps.set_val_anchor("a1"));
___(ps.set_val_tag("!b1"));
___(ps.begin_map_val_block());
___(ps.set_key_scalar_plain("foo1"));
___(ps.set_val_scalar_plain("bar1"));
___(ps.end_map_block());
___(ps.add_sibling());
___(ps.set_val_tag("!b2"));
___(ps.begin_map_val_block());
___(ps.set_key_anchor("a2"));
___(ps.set_key_scalar_plain("foo2"));
___(ps.set_val_scalar_plain("bar2"));
___(ps.end_map_block());
___(ps.add_sibling());
___(ps.set_val_anchor("a3"));
___(ps.set_val_tag("!b3"));
___(ps.begin_map_val_block());
___(ps.set_key_scalar_plain("foo3"));
___(ps.set_val_scalar_plain("bar3"));
___(ps.end_map_block());
___(ps.add_sibling());
___(ps.set_val_anchor("a4"));
___(ps.set_val_tag("!b4"));
___(ps.begin_map_val_block());
___(ps.set_key_scalar_plain("foo4"));
___(ps.set_val_scalar_plain("bar4"));
___(ps.end_map_block());
___(ps.end_seq_block());
___(ps.end_doc());
___(ps.end_stream());
}
ENGINE_TEST(AnchorMapMapSuckerPunch,
"!mymap &mymap\n"
@@ -684,23 +778,23 @@ ENGINE_TEST(AnchorMapMapSuckerPunch,
"bru: &wtf\n"
" foo\n"
,
"!mymap &mymap\n"
"!footag &fooanch foo: &seq\n"
"&mymap !mymap\n"
"&fooanch !footag foo: &seq\n"
" &key1 key1: &val1 val1\n"
" &key2 key2: &val2 val2\n"
"!bartag &baranch bar: !a &map2\n"
" !b &key10 key10: !c &val10 val10\n"
" !b &key20 key20: !c &val20 val20\n"
"&baranch !bartag bar: &map2 !a\n"
" &key10 !b key10: &val10 !c val10\n"
" &key20 !b key20: &val20 !c val20\n"
" key10: 20\n"
"!baztag &bazanch baz: !a &map2\n"
" !b &key10 key10: !c &val10 val10\n"
" !b &key20 key20: !c &val20 val20\n"
"&bazanch !baztag baz: &map2 !a\n"
" &key10 !b key10: &val10 !c val10\n"
" &key20 !b key20: &val20 !c val20\n"
" key10: 20\n"
"brr: &map2\n"
" !a foo: bar\n"
"bra: &map2\n"
" !a foo: bar\n"
"bre: !a &map2\n"
"bre: &map2 !a\n"
" foo: bar\n"
"bru: &wtf foo\n"
,
@@ -880,23 +974,24 @@ ENGINE_TEST(AnchorSeqMapSuckerPunch,
" foo: bar\n"
"- &wtf\n"
" foo\n"
" ",
" "
,
"&seq\n"
"- &key1 key1: &val1 val1\n"
" &key2 key2: &val2 val2\n"
"- !a &map2a\n"
" !b &key10 key10: &val10 val10\n"
"- &map2a !a\n"
" &key10 !b key10: &val10 val10\n"
" &key20 key20: &val20 val20\n"
" key10: 20\n"
"- !a &map2x\n"
" !b &key10 key10: &val10 val10\n"
"- &map2x !a\n"
" &key10 !b key10: &val10 val10\n"
" &key20 key20: &val20 val20\n"
" key10: 20\n"
"- &map2y\n"
" !a foo: bar\n"
"- &map2z\n"
" !a foo: bar\n"
"- !a &map2u\n"
"- &map2u !a\n"
" foo: bar\n"
"- &wtf foo\n"
,

View File

@@ -1131,8 +1131,6 @@ ENGINE_TEST(TagTestSuiteUGM3,
ENGINE_TEST(TagTestSuiteUKK6_02_0,
"!"
,
"!\n"
,
"+STR\n"
"+DOC\n"
"=VAL <!> :\n"
@@ -1142,7 +1140,7 @@ ENGINE_TEST(TagTestSuiteUKK6_02_0,
___(ps.begin_stream());
___(ps.begin_doc());
___(ps.set_val_tag("!"));
___(ps.set_val_scalar_plain({}));
___(ps.set_val_scalar_plain_empty());
___(ps.end_doc());
___(ps.end_stream());
}