rapidyaml  0.11.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 209 of file tag.cpp.

210 {
211  _RYML_CHECK_BASIC(directive.begins_with("%TAG "));
212  directive = directive.sub(4);
213  if(!directive.begins_with(' '))
214  return false;
215  directive = directive.triml(' ');
216  size_t pos = directive.find(' ');
217  if(pos == npos)
218  return false;
219  handle = directive.first(pos);
220  directive = directive.sub(handle.len).triml(' ');
221  pos = directive.find(' ');
222  if(pos != npos)
223  directive = directive.first(pos);
224  prefix = directive;
225  next_node_id = NONE;
226  _c4dbgpf("%TAG: handle={} prefix={}", handle, prefix);
227  return true;
228 }
@ npos
a null string position
Definition: common.hpp:258
@ NONE
an index to none
Definition: common.hpp:251
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.

◆ transform()

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

Definition at line 230 of file tag.cpp.

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

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

Member Data Documentation

◆ handle

csubstr c4::yml::TagDirective::handle

Eg.

!e!

in

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

Definition at line 60 of file tag.hpp.

◆ 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.

◆ 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.


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