rapidyaml  0.16.0
parseandemitYAML,anddoitfast
vector.hpp
Go to the documentation of this file.
1 #ifndef C4_YML_STD_VECTOR_HPP_
2 #define C4_YML_STD_VECTOR_HPP_
3 
4 #include "c4/yml/node.hpp"
5 #include <c4/std/vector.hpp>
6 #include <vector>
7 
8 namespace c4 {
9 namespace yml {
10 
11 C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
12 
13 // vector<T> is a sequence-like type, and it requires child nodes
14 // in the data tree hierarchy (a SEQ node in ryml parlance).
15 // So it should be serialized via write()/read().
16 
17 /** serialize a vector to a node: implementation for @ref Tree */
18 template<class T, class Alloc>
19 void write(Tree *tree, id_type id, std::vector<T, Alloc> const& vec)
20 {
21  tree->set_seq(id);
22  for(T const& val : vec)
23  tree->set_serialized(tree->append_child(id), val);
24 }
25 
26 /** serialize a vector to a node: implementation for @ref NodeRef */
27 template<class T, class Alloc>
28 void write(NodeRef *n, std::vector<T, Alloc> const& vec)
29 {
30  // don't defer to the tree impl here (if that were the case, we
31  // wouldn't even need to implement this function, as ryml ends up
32  // calling the tree impl by default). It may be the case that the
33  // serialization of T uses a serialization of a nested type that
34  // is not available in the tree implementation, so we need to
35  // provide this as a hook for that. If that's not required, then
36  // the tree implementation will get called anyway.
37  n->set_seq();
38  for(T const& val : vec)
39  {
40  NodeRef ch = n->append_child();
41  // call write() directly. ch.set_serialized() would also work,
42  // but does an additional check (to create the node if it is a
43  // seed). That check is not needed here because we used
44  // .append_child() to create the node.
45  write(&ch, val);
46  }
47 }
48 
49 
50 /** deserialize from a @ref Tree node, overwriting existing vector entries. */
51 template<class T, class Alloc>
52 ReadResult read(Tree const *tree, id_type id, std::vector<T, Alloc> *vec)
53 {
54  if C4_UNLIKELY(!tree->is_seq(id))
55  return ReadResult(id);
56  vec->clear();
57  #if C4_CPP < 17 // prior to C++17, emplace_back() does not return a reference
58  size_t pos = 0;
59  #endif
60  for(id_type child = tree->first_child(id); child != NONE; child = tree->next_sibling(child))
61  {
62  #if C4_CPP >= 17
63  T &val = vec->emplace_back();
64  #else
65  vec->emplace_back();
66  T &val = (*vec)[pos++];
67  #endif
68  // do not call read(tree, child, &val) here. we do not know
69  // that the YAML is valid, so we need to do the checks in
70  // child.deserialize()
71  if(!tree->deserialize(child, &val))
72  return ReadResult(id);
73  }
74  return ReadResult{};
75 }
76 
77 /** deserialize from a @ref ConstNodeRef node, overwriting existing vector entries. */
78 template<class T, class Alloc>
79 ReadResult read(ConstNodeRef const& node, std::vector<T, Alloc> *vec)
80 {
81  // don't defer to the tree impl here (if that were the case, we
82  // wouldn't even need to implement this function, as ryml ends up
83  // calling the tree impl by default). It may be the case that the
84  // serialization of T uses a serialization of a nested type that
85  // is not available in the tree implementation, so we need to
86  // provide this as a hook for that. If that's not required, then
87  // the tree implementation will get called anyway.
88  if C4_UNLIKELY(!node.is_seq())
89  return ReadResult(node.id());
90  vec->clear();
91  #if C4_CPP < 17 // prior to C++17, emplace_back() does not return a reference
92  size_t pos = 0;
93  #endif
94  for(ConstNodeRef const& child : node.children())
95  {
96  #if C4_CPP >= 17
97  T &val = vec->emplace_back();
98  #else
99  vec->emplace_back();
100  T &val = (*vec)[pos++];
101  #endif
102  // do not call read(child, &val) here. we do not know that the
103  // YAML is valid, so we need to do the checks in
104  // child.deserialize()
105  if(!child.deserialize(&val))
106  return ReadResult(child.id());
107  }
108  return ReadResult();
109 }
110 
111 
112 
113 //-----------------------------------------------------
114 // specialization for std::vector<bool>. needed because the return
115 // type of its operator[] is not bool, but std::vector<bool>::reference
116 
117 /** deserialize from a @ref Tree node, overwriting existing vector entries. */
118 template<class Alloc>
119 ReadResult read(Tree const* tree, id_type id, std::vector<bool, Alloc> *vec)
120 {
121  if C4_UNLIKELY(!tree->is_seq(id))
122  return ReadResult(id);
123  vec->clear();
124  bool tmp = {};
125  for(id_type child = tree->first_child(id); child != NONE; child = tree->next_sibling(child))
126  {
127  if(!from_chars(tree->val(child), &tmp))
128  return ReadResult(child);
129  vec->push_back(tmp); // leave this. gcc4.8 does not have std::vector<bool>::emplace_back()
130  }
131  return ReadResult();
132 }
133 
134 /** deserialize from a @ref ConstNodeRef node, overwriting existing vector entries. */
135 template<class Alloc>
136 ReadResult read(ConstNodeRef const& n, std::vector<bool, Alloc> *vec)
137 {
138  // call the tree implementation, saving the node readability
139  // checks. we can do that here because bool (the value type) is a
140  // final type, so it can't be overrided.
141  return read(n.tree(), n.id(), vec);
142 }
143 
144 C4_SUPPRESS_WARNING_GCC_POP
145 
146 } // namespace yml
147 } // namespace c4
148 
149 #endif // C4_YML_STD_VECTOR_HPP_
csubstr const & val(id_type node) const
Definition: tree.hpp:460
an index to none
Definition: common.hpp:131
id_type first_child(id_type node) const
Definition: tree.hpp:577
A lightweight truthy type, used to enable reporting the offending node when a deserializing error hap...
Definition: common.hpp:161
bool is_seq() const RYML_NOEXCEPT
Forward to Tree::is_seq().
Definition: node.hpp:208
id_type id() const noexcept
Definition: node.hpp:822
bool from_chars(csubstr buf, uint8_t *v) noexcept
Definition: charconv.hpp:2383
A reference to a node in an existing yaml tree, offering a more convenient API than the index-based A...
Definition: node.hpp:1062
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...
Definition: common.hpp:124
void write(NodeRef *n, T const &v)
Definition: node.hpp:2114
bool is_seq(id_type node) const
Definition: tree.hpp:481
ReadResult deserialize(id_type node, T *v) const
(1) deserialize a node's contents to a variable
Definition: tree.hpp:954
Holds a pointer to an existing tree, and a node id.
Definition: node.hpp:736
Tree const * tree() const noexcept
Definition: node.hpp:821
id_type next_sibling(id_type node) const
Definition: tree.hpp:572
Node classes.
const_children_view children() const RYML_NOEXCEPT
get an iterable view over children
Definition: node.hpp:987
NodeRef append_child()
Definition: node.hpp:1715
ReadResult read(ConstNodeRef const &n, T *v)
Definition: node.hpp:2074
void set_seq()
Definition: node.hpp:1254