rapidyaml  0.10.0
parse and emit YAML, and do it fast
c4::yml::TagDirective Struct Reference

#include <tag.hpp>

Public Member Functions

bool create_from_str (csubstr directive_)
 leaves next_node_id unfilled More...
 
size_t transform (csubstr tag, substr output, Callbacks const &callbacks, bool with_brackets=true) const
 

Public Attributes

csubstr handle
 Eg. More...
 
csubstr prefix
 Eg. More...
 
id_type next_node_id
 The next node to which this tag directive applies. More...
 

Detailed Description

Definition at line 57 of file tag.hpp.

Member Function Documentation

◆ create_from_str()

bool c4::yml::TagDirective::create_from_str ( csubstr  directive_)

leaves next_node_id unfilled

Definition at line 203 of file tag.cpp.

204 {
205  csubstr directive = directive_;
206  directive = directive.sub(4);
207  if(!directive.begins_with(' '))
208  return false;
209  directive = directive.triml(' ');
210  size_t pos = directive.find(' ');
211  if(pos == npos)
212  return false;
213  handle = directive.first(pos);
214  directive = directive.sub(handle.len).triml(' ');
215  pos = directive.find(' ');
216  if(pos != npos)
217  directive = directive.first(pos);
218  prefix = directive;
219  next_node_id = NONE;
220  _c4dbgpf("%TAG: handle={} prefix={}", handle, prefix);
221  return true;
222 }
@ npos
a null string position
Definition: common.hpp:267
@ NONE
an index to none
Definition: common.hpp:260
csubstr handle
Eg.
Definition: tag.hpp:60
id_type next_node_id
The next node to which this tag directive applies.
Definition: tag.hpp:64
csubstr prefix
Eg.
Definition: tag.hpp:62

References handle, next_node_id, c4::yml::NONE, c4::yml::npos, and prefix.

Referenced by c4::yml::extra::EventHandlerInts::add_directive().

◆ transform()

size_t c4::yml::TagDirective::transform ( csubstr  tag,
substr  output,
Callbacks const &  callbacks,
bool  with_brackets = true 
) const

Definition at line 224 of file tag.cpp.

225 {
226  _c4dbgpf("%TAG: handle={} prefix={} next_node={}. tag={}", handle, prefix, next_node_id, tag);
227  _RYML_CB_ASSERT(callbacks, tag.len >= handle.len);
228  csubstr rest = tag.sub(handle.len);
229  _c4dbgpf("%TAG: rest={}", rest);
230  if(rest.begins_with('<'))
231  {
232  _c4dbgpf("%TAG: begins with <. rest={}", rest);
233  if(C4_UNLIKELY(!rest.ends_with('>')))
234  _RYML_CB_ERR(callbacks, "malformed tag");
235  rest = rest.offs(1, 1);
236  if(rest.begins_with(prefix))
237  {
238  _c4dbgpf("%TAG: already transformed! actual={}", rest.sub(prefix.len));
239  return 0; // return 0 to signal that the tag is local and cannot be resolved
240  }
241  }
242  size_t len = prefix.len + rest.len;
243  if(with_brackets)
244  len += 2;
245  size_t numpc = rest.count('%');
246  if(numpc == 0)
247  {
248  if(len <= output.len)
249  {
250  if(with_brackets)
251  {
252  output.str[0] = '<';
253  memcpy(1u + output.str, prefix.str, prefix.len);
254  memcpy(1u + output.str + prefix.len, rest.str, rest.len);
255  output.str[1u + prefix.len + rest.len] = '>';
256  }
257  else
258  {
259  memcpy(output.str, prefix.str, prefix.len);
260  memcpy(output.str + prefix.len, rest.str, rest.len);
261  }
262  }
263  }
264  else
265  {
266  // need to decode URI % sequences
267  size_t pos = rest.find('%');
268  _RYML_CB_ASSERT(callbacks, pos != npos);
269  do {
270  size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1);
271  if(next == npos)
272  next = rest.len;
273  _RYML_CB_CHECK(callbacks, pos+1 < next);
274  _RYML_CB_CHECK(callbacks, pos+1 + 2 <= next);
275  size_t delta = next - (pos+1);
276  len -= delta;
277  pos = rest.find('%', pos+1);
278  } while(pos != npos);
279  if(len <= output.len)
280  {
281  size_t prev = 0, wpos = 0;
282  auto appendstr = [&](csubstr s) { memcpy(output.str + wpos, s.str, s.len); wpos += s.len; };
283  auto appendchar = [&](char c) { output.str[wpos++] = c; };
284  if(with_brackets)
285  appendchar('<');
286  appendstr(prefix);
287  pos = rest.find('%');
288  _RYML_CB_ASSERT(callbacks, pos != npos);
289  do {
290  size_t next = rest.first_not_of("0123456789abcdefABCDEF", pos+1);
291  if(next == npos)
292  next = rest.len;
293  _RYML_CB_CHECK(callbacks, pos+1 < next);
294  _RYML_CB_CHECK(callbacks, pos+1 + 2 <= next);
295  uint8_t val;
296  if(C4_UNLIKELY(!read_hex(rest.range(pos+1, next), &val) || val > 127))
297  _RYML_CB_ERR(callbacks, "invalid URI character");
298  appendstr(rest.range(prev, pos));
299  appendchar(static_cast<char>(val));
300  prev = next;
301  pos = rest.find('%', pos+1);
302  } while(pos != npos);
303  _RYML_CB_ASSERT(callbacks, pos == npos);
304  _RYML_CB_ASSERT(callbacks, prev > 0);
305  _RYML_CB_ASSERT(callbacks, rest.len >= prev);
306  appendstr(rest.sub(prev));
307  if(with_brackets)
308  appendchar('>');
309  _RYML_CB_ASSERT(callbacks, wpos == len);
310  }
311  }
312  return len;
313 }
bool read_hex(csubstr s, I *v) noexcept
read an hexadecimal integer from a string.
Definition: charconv.hpp:890

References handle, next_node_id, c4::yml::npos, prefix, and c4::read_hex().

Referenced by c4::yml::extra::EventHandlerInts::_transform_directive(), and c4::yml::Tree::resolve_tag().

Member Data Documentation

◆ handle

csubstr c4::yml::TagDirective::handle

◆ prefix

csubstr c4::yml::TagDirective::prefix

Eg.

tag:example.com,2000:app/

in

TAG !e! tag:example.com,2000:app/

Definition at line 62 of file tag.hpp.

Referenced by c4::yml::extra::EventHandlerInts::_transform_directive(), c4::yml::extra::EventHandlerInts::add_directive(), c4::yml::Tree::add_tag_directive(), create_from_str(), and transform().

◆ next_node_id

id_type c4::yml::TagDirective::next_node_id

The next node to which this tag directive applies.

Definition at line 64 of file tag.hpp.

Referenced by c4::yml::extra::EventHandlerInts::add_directive(), create_from_str(), c4::yml::Tree::resolve_tag(), and transform().


The documentation for this struct was generated from the following files: