1#ifndef _C4_YML_EMIT_HPP_
2#define _C4_YML_EMIT_HPP_
6#ifndef _C4_YML_WRITER_HPP_
10#ifndef _C4_YML_TREE_HPP_
14#ifndef _C4_YML_NODE_HPP_
19C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH(
"-Wold-style-cast")
36template<
class Writer>
class Emitter;
37template<
class OStream>
64 typedef enum : uint32_t {
65 EMIT_NONROOT_KEY = 1u << 0u,
66 EMIT_NONROOT_DASH = 1u << 1u,
67 EMIT_NONROOT_MARKUP = EMIT_NONROOT_KEY|EMIT_NONROOT_DASH,
68 INDENT_FLOW_ML = 1u << 2u,
69 JSON_ERR_ON_TAG = 1u << 3u,
70 JSON_ERR_ON_ANCHOR = 1u << 4u,
71 _JSON_ERR_MASK = JSON_ERR_ON_TAG|JSON_ERR_ON_ANCHOR,
72 DEFAULT_FLAGS = EMIT_NONROOT_KEY|INDENT_FLOW_ML,
82 C4_ALWAYS_INLINE
bool emit_nonroot_key() const noexcept {
return (m_option_flags & EMIT_NONROOT_KEY) != 0; }
83 EmitOptions&
emit_nonroot_key(
bool enabled)
noexcept { m_option_flags = (EmitOptionFlags_e)(enabled ? (m_option_flags | EMIT_NONROOT_KEY) : (m_option_flags & ~EMIT_NONROOT_KEY));
return *
this; }
85 C4_ALWAYS_INLINE
bool emit_nonroot_dash() const noexcept {
return (m_option_flags & EMIT_NONROOT_DASH) != 0; }
86 EmitOptions&
emit_nonroot_dash(
bool enabled)
noexcept { m_option_flags = (EmitOptionFlags_e)(enabled ? (m_option_flags | EMIT_NONROOT_DASH) : (m_option_flags & ~EMIT_NONROOT_DASH));
return *
this; }
88 C4_ALWAYS_INLINE
bool indent_flow_ml() const noexcept {
return (m_option_flags & INDENT_FLOW_ML) != 0; }
89 EmitOptions&
indent_flow_ml(
bool enabled)
noexcept { m_option_flags = (EmitOptionFlags_e)(enabled ? (m_option_flags | INDENT_FLOW_ML) : (m_option_flags & ~INDENT_FLOW_ML));
return *
this; }
91 C4_ALWAYS_INLINE EmitOptionFlags_e
json_error_flags() const noexcept {
return (EmitOptionFlags_e)(m_option_flags & _JSON_ERR_MASK); }
113 return m_max_depth == that.m_max_depth &&
114 m_option_flags == that.m_option_flags;
120 id_type m_max_depth{max_depth_default};
121 EmitOptionFlags_e m_option_flags{DEFAULT_FLAGS};
132template<
class Writer>
142 template<
class ...WriterArgs>
144 : Writer(std::forward<WriterArgs>(args)...)
156 template<
class ...WriterArgs>
158 : Writer(std::forward<WriterArgs>(args)...)
199 return this->
emit_as(type, *n.
tree(), n.
id(), error_on_excess);
220 void _visit_stream(
id_type id);
222 void _visit_doc_val(
id_type id);
223 void _visit_blck_container(
id_type id);
224 void _visit_flow_container(
id_type id);
226 void _visit_flow_sl(
id_type id);
227 void _visit_flow_sl_seq(
id_type id);
228 void _visit_flow_sl_map(
id_type id);
230 void _visit_flow_ml(
id_type id);
231 void _visit_flow_ml_seq(
id_type id);
232 void _visit_flow_ml_map(
id_type id);
235 void _visit_blck_seq(
id_type id);
236 void _visit_blck_map(
id_type id);
238 void _top_open_entry(
id_type id);
239 void _top_close_entry(
id_type id);
240 void _blck_seq_open_entry(
id_type id);
241 void _blck_map_open_entry(
id_type id);
242 void _blck_close_entry(
id_type id);
246 void _flow_seq_open_entry(
id_type id);
247 void _flow_map_open_entry(
id_type id);
261 size_t _write_escaped_newlines(
csubstr s,
size_t i);
268 bool _json_maybe_write_naninf(
csubstr s);
271 void _json_write_scalar_dquo(
csubstr s);
272 void _json_write_number(
csubstr s);
294 C4_ALWAYS_INLINE
void _indent(id_type level)
296 size_t num = (size_t)(2u * level);
297 this->Writer::_do_write(
' ', num);
302 C4_ALWAYS_INLINE
void _write(
const char (&a)[N])
304 this->Writer::_do_write(std::forward<
const char (&)[N]>(a));
307 C4_ALWAYS_INLINE
void _write(csubstr s)
309 this->Writer::_do_write(s);
312 C4_ALWAYS_INLINE
void _write(
char c)
314 this->Writer::_do_write(c);
317 C4_ALWAYS_INLINE
void _write(
char c,
size_t num)
319 this->Writer::_do_write(c, num);
324 C4_ALWAYS_INLINE
void _newl()
326 this->Writer::_do_write(
'\n');
333 typedef enum : uint32_t { _PWS_NONE, _PWS_SPACE, _PWS_NEWL } Pws_e;
336 C4_ALWAYS_INLINE
void _pend_none() noexcept
341 C4_ALWAYS_INLINE
void _pend_newl() noexcept
346 C4_ALWAYS_INLINE
void _pend_space() noexcept
351 C4_ALWAYS_INLINE
void _write_pws_and_pend(Pws_e next=_PWS_NONE)
noexcept
353 if(m_pws == _PWS_SPACE)
357 else if(m_pws == _PWS_NEWL)
367 Tree
const* C4_RESTRICT m_tree;
377 #if defined(__GNUC__) && (__GNUC__ < 5) && (!defined(__clang__))
378 #pragma GCC diagnostic push
379 #pragma GCC diagnostic ignored "-Wparentheses"
384 _styles_block = ((
type_bits)_styles_block_key) | ((type_bits)_styles_block_val),
386 _styles_flow_val = VAL_STYLE & (~((type_bits)_styles_block_val)),
387 _styles_flow = ((
type_bits)_styles_flow_key) | ((type_bits)_styles_flow_val),
394 #if defined(__GNUC__) && (__GNUC__ < 5) && (!defined(__clang__))
395 #pragma GCC diagnostic pop
520template<
class OStream>
521inline OStream& operator<< (OStream& s,
Tree const& t)
530template<
class OStream>
583template<
class OStream>
584inline OStream& operator<< (OStream& s,
as_json const& j)
594template<
class OStream>
595inline OStream& operator<< (OStream& s,
as_yaml const& y)
764template<
class CharOwningContainer>
767 size_t startpos = append ? cont->size() : 0u;
768 cont->resize(cont->capacity());
771 if(ret.
str ==
nullptr && ret.
len > 0)
773 cont->resize(startpos + ret.
len);
779 cont->resize(startpos + ret.
len);
784template<
class CharOwningContainer>
794template<
class CharOwningContainer>
797 const size_t startpos = append ? cont->size() : 0u;
798 cont->resize(cont->capacity());
802 if(ret.
str ==
nullptr && ret.
len > 0)
804 cont->resize(startpos + ret.
len);
810 cont->resize(startpos + ret.
len);
815template<
class CharOwningContainer>
823template<
class CharOwningContainer>
826 CharOwningContainer c;
827 emitrs_yaml(t,
id, opts, &c);
831template<
class CharOwningContainer>
834 CharOwningContainer c;
835 emitrs_json(t,
id, opts, &c);
845template<
class CharOwningContainer>
853template<
class CharOwningContainer>
863template<
class CharOwningContainer>
871template<
class CharOwningContainer>
881template<
class CharOwningContainer>
884 CharOwningContainer c;
887 emitrs_yaml(t, t.
root_id(), opts, &c);
891template<
class CharOwningContainer>
894 CharOwningContainer c;
897 emitrs_json(t, t.
root_id(), opts, &c);
908template<
class CharOwningContainer>
916template<
class CharOwningContainer>
926template<
class CharOwningContainer>
934template<
class CharOwningContainer>
944template<
class CharOwningContainer>
949 CharOwningContainer c;
950 emitrs_yaml(*n.
tree(), n.
id(), opts, &c);
954template<
class CharOwningContainer>
959 CharOwningContainer c;
960 emitrs_json(*n.
tree(), n.
id(), opts, &c);
972#define RYML_DEPRECATE_EMIT \
973 RYML_DEPRECATED("use emit_yaml() instead. " \
974 "See https://github.com/biojppm/rapidyaml/issues/120")
975#define RYML_DEPRECATE_EMITRS \
976 RYML_DEPRECATED("use emitrs_yaml() instead. " \
977 "See https://github.com/biojppm/rapidyaml/issues/120")
983#define RYML_TMP_EMIT_
987RYML_DEPRECATE_EMIT
inline size_t emit(Tree
const& t, id_type
id, FILE *f)
991RYML_DEPRECATE_EMIT
inline size_t emit(Tree
const& t, FILE *f=
nullptr)
995RYML_DEPRECATE_EMIT
inline size_t emit(ConstNodeRef
const& r, FILE *f=
nullptr)
1000RYML_DEPRECATE_EMIT
inline substr emit(Tree
const& t, id_type
id, substr buf,
bool error_on_excess=
true)
1002 return emit_yaml(t,
id, buf, error_on_excess);
1004RYML_DEPRECATE_EMIT
inline substr emit(Tree
const& t, substr buf,
bool error_on_excess=
true)
1006 return emit_yaml(t, buf, error_on_excess);
1008RYML_DEPRECATE_EMIT
inline substr emit(ConstNodeRef
const& r, substr buf,
bool error_on_excess=
true)
1010 return emit_yaml(r, buf, error_on_excess);
1013#ifdef RYML_TMP_EMIT_
1015#undef RYML_TMP_EMIT_
1018template<
class CharOwningContainer>
1019RYML_DEPRECATE_EMITRS
substr emitrs(Tree
const& t, id_type
id, CharOwningContainer * cont)
1023template<
class CharOwningContainer>
1024RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree
const& t, id_type
id)
1026 return emitrs_yaml<CharOwningContainer>(t,
id);
1028template<
class CharOwningContainer>
1029RYML_DEPRECATE_EMITRS
substr emitrs(Tree
const& t, CharOwningContainer * cont)
1033template<
class CharOwningContainer>
1034RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(Tree
const& t)
1036 return emitrs_yaml<CharOwningContainer>(t);
1038template<
class CharOwningContainer>
1039RYML_DEPRECATE_EMITRS
substr emitrs(ConstNodeRef
const& n, CharOwningContainer * cont)
1043template<
class CharOwningContainer>
1044RYML_DEPRECATE_EMITRS CharOwningContainer emitrs(ConstNodeRef
const& n)
1046 return emitrs_yaml<CharOwningContainer>(n);
1056C4_SUPPRESS_WARNING_GCC_CLANG_POP
1058#undef RYML_DEPRECATE_EMIT
1059#undef RYML_DEPRECATE_EMITRS
Holds a pointer to an existing tree, and a node id.
id_type id() const noexcept
Tree const * tree() const noexcept
bool readable() const noexcept
because a ConstNodeRef cannot be used to write to the tree, readable() has the same meaning as !...
A stateful emitter, for use with a writer such as WriterBuf, WriterFile, or WriterOStream.
id_type root_id() const
Get the id of the root node. The tree must not be empty.
Definitions for emit functions.
EmitOptionFlags_e json_error_flags() const noexcept
id_type max_depth() const noexcept
get the max depth for emitted trees (to prevent a stack overflow)
substr emit_as(EmitType_e type, ConstNodeRef const &n, bool error_on_excess=true)
emit starting at the given node
EmitOptions const & options() const noexcept
get the emit options for this object
bool emit_nonroot_key() const noexcept
void max_depth(id_type max_depth) noexcept
set the max depth for emitted trees (to prevent a stack overflow)
as_yaml(Tree const &t, EmitOptions const &opts={})
void options(EmitOptions opts) noexcept
set the emit options for this object
substr emit_as(EmitType_e type, Tree const &t, bool error_on_excess=true)
emit starting at the root node
id_type max_depth() const noexcept
as_yaml(Tree const &t, id_type id, EmitOptions const &opts={})
Emitter(WriterArgs &&...args)
Construct the emitter and its internal Writer state, using default emit options.
Emitter(EmitOptions const &opts, WriterArgs &&...args)
Construct the emitter and its internal Writer state.
substr emit_as(EmitType_e type, Tree const &t, id_type id, bool error_on_excess)
emit!
EmitOptions & max_depth(id_type d) noexcept
as_json(Tree const &t, EmitOptions const &opts={})
EmitOptions & indent_flow_ml(bool enabled) noexcept
as_yaml(ConstNodeRef const &n, EmitOptions const &opts={})
bool indent_flow_ml() const noexcept
EmitOptions & emit_nonroot_key(bool enabled) noexcept
bool emit_nonroot_dash() const noexcept
as_json(ConstNodeRef const &n, EmitOptions const &opts={})
EmitOptions & emit_nonroot_dash(bool enabled) noexcept
static constexpr const id_type max_depth_default
as_json(Tree const &t, id_type id, EmitOptions const &opts={})
EmitOptions & json_error_flags(EmitOptionFlags_e d) noexcept
substr emitrs_json(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit JSON to the given std::string/std::vector-like container, resizing it as needed...
substr emitrs_yaml(Tree const &t, id_type id, EmitOptions const &opts, CharOwningContainer *cont, bool append=false)
(1) emit+resize: emit YAML to the given std::string/std::vector-like container, resizing it as needed...
size_t emit_yaml(Tree const &t, id_type id, EmitOptions const &opts, FILE *f)
(1) emit YAML to the given file, starting at the given node.
size_t emit_json(Tree const &t, id_type id, EmitOptions const &opts, FILE *f)
(1) emit JSON to the given file, starting at the given node.
Emitter< WriterBuf > EmitterBuf
Emitter< WriterFile > EmitterFile
Emitter< WriterOStream< OStream > > EmitterOStream
EmitType_e
Specifies the type of content to emit.
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
@ KEY_DQUO
mark key scalar as double quoted "
@ VAL_FOLDED
mark val scalar as multiline, block folded >
@ VAL_SQUO
mark val scalar as single quoted '
@ KEY_STYLE
mask of all the scalar styles for key (not container styles!)
@ VAL_PLAIN
mark val scalar as plain scalar (unquoted, even when multiline)
@ VAL_DQUO
mark val scalar as double quoted "
@ KEY_SQUO
mark key scalar as single quoted '
@ VAL_LITERAL
mark val scalar as multiline, block literal |
@ KEY_LITERAL
mark key scalar as multiline, block literal |
@ KEY_PLAIN
mark key scalar as plain scalar (unquoted, even when multiline)
@ KEY_FOLDED
mark key scalar as multiline, block folded >
substr to_substr(char(&s)[N]) noexcept
basic_substring< char > substr
a mutable string view
basic_substring< const char > csubstr
an immutable string view
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
(Undefined by default) Use shorter error message from checks/asserts: do not show the check condition...
bool begins_with(const C c) const noexcept
true if the first character of the string is c
size_t len
the length of the substring
C * str
a restricted pointer to the first character of the substring
A lightweight object containing options to be used when emitting.
wraps a NodeType_e element with some syntactic sugar and predicates
mark a tree or node to be emitted as yaml when using operator<<, with options.
mark a tree or node to be emitted as yaml when using operator<< .