First Commit
This commit is contained in:
200
3rdparty/rapidyaml/include/c4/yml/detail/checks.hpp
vendored
Normal file
200
3rdparty/rapidyaml/include/c4/yml/detail/checks.hpp
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
#ifndef C4_YML_DETAIL_CHECKS_HPP_
|
||||
#define C4_YML_DETAIL_CHECKS_HPP_
|
||||
|
||||
#include "c4/yml/tree.hpp"
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits" // error: comparison of unsigned expression >= 0 is always true
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4296/*expression is always 'boolean_value'*/)
|
||||
#endif
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
|
||||
void check_invariants(Tree const& t, size_t node=NONE);
|
||||
void check_free_list(Tree const& t);
|
||||
void check_arena(Tree const& t);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void check_invariants(Tree const& t, size_t node)
|
||||
{
|
||||
if(node == NONE)
|
||||
{
|
||||
if(t.size() == 0) return;
|
||||
node = t.root_id();
|
||||
}
|
||||
|
||||
auto const& n = *t._p(node);
|
||||
#ifdef RYML_DBG
|
||||
if(n.m_first_child != NONE || n.m_last_child != NONE)
|
||||
{
|
||||
printf("check(%zu): fc=%zu lc=%zu\n", node, n.m_first_child, n.m_last_child);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("check(%zu)\n", node);
|
||||
}
|
||||
#endif
|
||||
|
||||
C4_CHECK(n.m_parent != node);
|
||||
if(n.m_parent == NONE)
|
||||
{
|
||||
C4_CHECK(t.is_root(node));
|
||||
}
|
||||
else //if(n.m_parent != NONE)
|
||||
{
|
||||
C4_CHECK(t.has_child(n.m_parent, node));
|
||||
|
||||
auto const& p = *t._p(n.m_parent);
|
||||
if(n.m_prev_sibling == NONE)
|
||||
{
|
||||
C4_CHECK(p.m_first_child == node);
|
||||
C4_CHECK(t.first_sibling(node) == node);
|
||||
}
|
||||
else
|
||||
{
|
||||
C4_CHECK(p.m_first_child != node);
|
||||
C4_CHECK(t.first_sibling(node) != node);
|
||||
}
|
||||
|
||||
if(n.m_next_sibling == NONE)
|
||||
{
|
||||
C4_CHECK(p.m_last_child == node);
|
||||
C4_CHECK(t.last_sibling(node) == node);
|
||||
}
|
||||
else
|
||||
{
|
||||
C4_CHECK(p.m_last_child != node);
|
||||
C4_CHECK(t.last_sibling(node) != node);
|
||||
}
|
||||
}
|
||||
|
||||
C4_CHECK(n.m_first_child != node);
|
||||
C4_CHECK(n.m_last_child != node);
|
||||
if(n.m_first_child != NONE || n.m_last_child != NONE)
|
||||
{
|
||||
C4_CHECK(n.m_first_child != NONE);
|
||||
C4_CHECK(n.m_last_child != NONE);
|
||||
}
|
||||
|
||||
C4_CHECK(n.m_prev_sibling != node);
|
||||
C4_CHECK(n.m_next_sibling != node);
|
||||
if(n.m_prev_sibling != NONE)
|
||||
{
|
||||
C4_CHECK(t._p(n.m_prev_sibling)->m_next_sibling == node);
|
||||
C4_CHECK(t._p(n.m_prev_sibling)->m_prev_sibling != node);
|
||||
}
|
||||
if(n.m_next_sibling != NONE)
|
||||
{
|
||||
C4_CHECK(t._p(n.m_next_sibling)->m_prev_sibling == node);
|
||||
C4_CHECK(t._p(n.m_next_sibling)->m_next_sibling != node);
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
for(size_t i = n.m_first_child; i != NONE; i = t.next_sibling(i))
|
||||
{
|
||||
#ifdef RYML_DBG
|
||||
printf("check(%zu): descend to child[%zu]=%zu\n", node, count, i);
|
||||
#endif
|
||||
auto const& ch = *t._p(i);
|
||||
C4_CHECK(ch.m_parent == node);
|
||||
C4_CHECK(ch.m_next_sibling != i);
|
||||
++count;
|
||||
}
|
||||
C4_CHECK(count == t.num_children(node));
|
||||
|
||||
if(n.m_prev_sibling == NONE && n.m_next_sibling == NONE)
|
||||
{
|
||||
if(n.m_parent != NONE)
|
||||
{
|
||||
C4_CHECK(t.num_children(n.m_parent) == 1);
|
||||
C4_CHECK(t.num_siblings(node) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(node == t.root_id())
|
||||
{
|
||||
C4_CHECK(t.size() == t.m_size);
|
||||
C4_CHECK(t.capacity() == t.m_cap);
|
||||
C4_CHECK(t.m_cap == t.m_size + t.slack());
|
||||
check_free_list(t);
|
||||
check_arena(t);
|
||||
}
|
||||
|
||||
for(size_t i = t.first_child(node); i != NONE; i = t.next_sibling(i))
|
||||
{
|
||||
check_invariants(t, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void check_free_list(Tree const& t)
|
||||
{
|
||||
if(t.m_free_head == NONE)
|
||||
{
|
||||
C4_CHECK(t.m_free_tail == t.m_free_head);
|
||||
return;
|
||||
}
|
||||
|
||||
C4_CHECK(t.m_free_head >= 0 && t.m_free_head < t.m_cap);
|
||||
C4_CHECK(t.m_free_tail >= 0 && t.m_free_tail < t.m_cap);
|
||||
|
||||
auto const& head = *t._p(t.m_free_head);
|
||||
//auto const& tail = *t._p(t.m_free_tail);
|
||||
|
||||
//C4_CHECK(head.m_prev_sibling == NONE);
|
||||
//C4_CHECK(tail.m_next_sibling == NONE);
|
||||
|
||||
size_t count = 0;
|
||||
for(size_t i = t.m_free_head, prev = NONE; i != NONE; i = t._p(i)->m_next_sibling)
|
||||
{
|
||||
auto const& elm = *t._p(i);
|
||||
if(&elm != &head)
|
||||
{
|
||||
C4_CHECK(elm.m_prev_sibling == prev);
|
||||
}
|
||||
prev = i;
|
||||
++count;
|
||||
}
|
||||
C4_CHECK(count == t.slack());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void check_arena(Tree const& t)
|
||||
{
|
||||
C4_CHECK(t.m_arena.len == 0 || (t.m_arena_pos >= 0 && t.m_arena_pos <= t.m_arena.len));
|
||||
C4_CHECK(t.arena_size() == t.m_arena_pos);
|
||||
C4_CHECK(t.arena_slack() + t.m_arena_pos == t.m_arena.len);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace yml */
|
||||
} /* namespace c4 */
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif /* C4_YML_DETAIL_CHECKS_HPP_ */
|
||||
138
3rdparty/rapidyaml/include/c4/yml/detail/parser_dbg.hpp
vendored
Normal file
138
3rdparty/rapidyaml/include/c4/yml/detail/parser_dbg.hpp
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
#ifndef _C4_YML_DETAIL_PARSER_DBG_HPP_
|
||||
#define _C4_YML_DETAIL_PARSER_DBG_HPP_
|
||||
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#include "../common.hpp"
|
||||
#endif
|
||||
#include <cstdio>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// some debugging scaffolds
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4068/*unknown pragma*/)
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
//#pragma GCC diagnostic ignored "-Wpragma-system-header-outside-header"
|
||||
#pragma GCC system_header
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Werror"
|
||||
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
|
||||
// some debugging scaffolds
|
||||
#ifdef RYML_DBG
|
||||
#include <c4/dump.hpp>
|
||||
namespace c4 {
|
||||
inline void _dbg_dumper(csubstr s) { fwrite(s.str, 1, s.len, stdout); };
|
||||
template<class ...Args>
|
||||
void _dbg_printf(c4::csubstr fmt, Args&& ...args)
|
||||
{
|
||||
static char writebuf[256];
|
||||
auto results = c4::format_dump_resume<&_dbg_dumper>(writebuf, fmt, std::forward<Args>(args)...);
|
||||
// resume writing if the results failed to fit the buffer
|
||||
if(C4_UNLIKELY(results.bufsize > sizeof(writebuf))) // bufsize will be that of the largest element serialized. Eg int(1), will require 1 byte.
|
||||
{
|
||||
results = format_dump_resume<&_dbg_dumper>(results, writebuf, fmt, std::forward<Args>(args)...);
|
||||
if(C4_UNLIKELY(results.bufsize > sizeof(writebuf)))
|
||||
{
|
||||
results = format_dump_resume<&_dbg_dumper>(results, writebuf, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace c4
|
||||
|
||||
# define _c4dbgt(fmt, ...) this->_dbg ("{}:{}: " fmt , __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
# define _c4dbgpf(fmt, ...) _dbg_printf("{}:{}: " fmt "\n", __FILE__, __LINE__, ## __VA_ARGS__)
|
||||
# define _c4dbgp(msg) _dbg_printf("{}:{}: " msg "\n", __FILE__, __LINE__ )
|
||||
# define _c4dbgq(msg) _dbg_printf(msg "\n")
|
||||
# define _c4err(fmt, ...) \
|
||||
do { if(c4::is_debugger_attached()) { C4_DEBUG_BREAK(); } \
|
||||
this->_err("ERROR:\n" "{}:{}: " fmt, __FILE__, __LINE__, ## __VA_ARGS__); } while(0)
|
||||
#else
|
||||
# define _c4dbgt(fmt, ...)
|
||||
# define _c4dbgpf(fmt, ...)
|
||||
# define _c4dbgp(msg)
|
||||
# define _c4dbgq(msg)
|
||||
# define _c4err(fmt, ...) \
|
||||
do { if(c4::is_debugger_attached()) { C4_DEBUG_BREAK(); } \
|
||||
this->_err("ERROR: " fmt, ## __VA_ARGS__); } while(0)
|
||||
#endif
|
||||
|
||||
#define _c4prsp(sp) sp
|
||||
#define _c4presc(s) __c4presc(s.str, s.len)
|
||||
inline c4::csubstr _c4prc(const char &C4_RESTRICT c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\n': return c4::csubstr("\\n");
|
||||
case '\t': return c4::csubstr("\\t");
|
||||
case '\0': return c4::csubstr("\\0");
|
||||
case '\r': return c4::csubstr("\\r");
|
||||
case '\f': return c4::csubstr("\\f");
|
||||
case '\b': return c4::csubstr("\\b");
|
||||
case '\v': return c4::csubstr("\\v");
|
||||
case '\a': return c4::csubstr("\\a");
|
||||
default: return c4::csubstr(&c, 1);
|
||||
}
|
||||
}
|
||||
inline void __c4presc(const char *s, size_t len)
|
||||
{
|
||||
size_t prev = 0;
|
||||
for(size_t i = 0; i < len; ++i)
|
||||
{
|
||||
switch(s[i])
|
||||
{
|
||||
case '\n' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('n'); putchar('\n'); prev = i+1; break;
|
||||
case '\t' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('t'); prev = i+1; break;
|
||||
case '\0' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('0'); prev = i+1; break;
|
||||
case '\r' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('r'); prev = i+1; break;
|
||||
case '\f' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('f'); prev = i+1; break;
|
||||
case '\b' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('b'); prev = i+1; break;
|
||||
case '\v' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('v'); prev = i+1; break;
|
||||
case '\a' : if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('a'); prev = i+1; break;
|
||||
case '\x1b': if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('e'); prev = i+1; break;
|
||||
case -0x3e/*0xc2u*/:
|
||||
if(i+1 < len)
|
||||
{
|
||||
if(s[i+1] == -0x60/*0xa0u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('_'); prev = i+2; ++i;
|
||||
}
|
||||
else if(s[i+1] == -0x7b/*0x85u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('N'); prev = i+2; ++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case -0x1e/*0xe2u*/:
|
||||
if(i+2 < len && s[i+1] == -0x80/*0x80u*/)
|
||||
{
|
||||
if(s[i+2] == -0x58/*0xa8u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('L'); prev = i+3; i += 2;
|
||||
}
|
||||
else if(s[i+2] == -0x57/*0xa9u*/)
|
||||
{
|
||||
if(i > prev) { fwrite(s+prev, 1, i-prev, stdout); } putchar('\\'); putchar('P'); prev = i+3; i += 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(len > prev)
|
||||
fwrite(s + prev, 1, len - prev, stdout);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _C4_YML_DETAIL_PARSER_DBG_HPP_ */
|
||||
130
3rdparty/rapidyaml/include/c4/yml/detail/print.hpp
vendored
Normal file
130
3rdparty/rapidyaml/include/c4/yml/detail/print.hpp
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
#ifndef C4_YML_DETAIL_PRINT_HPP_
|
||||
#define C4_YML_DETAIL_PRINT_HPP_
|
||||
|
||||
#include "c4/yml/tree.hpp"
|
||||
#include "c4/yml/node.hpp"
|
||||
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
|
||||
inline size_t print_node(Tree const& p, size_t node, int level, size_t count, bool print_children)
|
||||
{
|
||||
printf("[%zd]%*s[%zd] %p", count, (2*level), "", node, (void const*)p.get(node));
|
||||
if(p.is_root(node))
|
||||
{
|
||||
printf(" [ROOT]");
|
||||
}
|
||||
printf(" %s:", p.type_str(node));
|
||||
if(p.has_key(node))
|
||||
{
|
||||
if(p.has_key_anchor(node))
|
||||
{
|
||||
csubstr ka = p.key_anchor(node);
|
||||
printf(" &%.*s", (int)ka.len, ka.str);
|
||||
}
|
||||
if(p.has_key_tag(node))
|
||||
{
|
||||
csubstr kt = p.key_tag(node);
|
||||
csubstr k = p.key(node);
|
||||
printf(" %.*s '%.*s'", (int)kt.len, kt.str, (int)k.len, k.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
csubstr k = p.key(node);
|
||||
printf(" '%.*s'", (int)k.len, k.str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT( ! p.has_key_tag(node));
|
||||
}
|
||||
if(p.has_val(node))
|
||||
{
|
||||
if(p.has_val_tag(node))
|
||||
{
|
||||
csubstr vt = p.val_tag(node);
|
||||
csubstr v = p.val(node);
|
||||
printf(" %.*s '%.*s'", (int)vt.len, vt.str, (int)v.len, v.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
csubstr v = p.val(node);
|
||||
printf(" '%.*s'", (int)v.len, v.str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p.has_val_tag(node))
|
||||
{
|
||||
csubstr vt = p.val_tag(node);
|
||||
printf(" %.*s", (int)vt.len, vt.str);
|
||||
}
|
||||
}
|
||||
if(p.has_val_anchor(node))
|
||||
{
|
||||
auto &a = p.val_anchor(node);
|
||||
printf(" valanchor='&%.*s'", (int)a.len, a.str);
|
||||
}
|
||||
printf(" (%zd sibs)", p.num_siblings(node));
|
||||
|
||||
++count;
|
||||
|
||||
if(p.is_container(node))
|
||||
{
|
||||
printf(" %zd children:\n", p.num_children(node));
|
||||
if(print_children)
|
||||
{
|
||||
for(size_t i = p.first_child(node); i != NONE; i = p.next_sibling(i))
|
||||
{
|
||||
count = print_node(p, i, level+1, count, print_children);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void print_node(ConstNodeRef const& p, int level=0)
|
||||
{
|
||||
print_node(*p.tree(), p.id(), level, 0, true);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline size_t print_tree(Tree const& p, size_t node=NONE)
|
||||
{
|
||||
printf("--------------------------------------\n");
|
||||
size_t ret = 0;
|
||||
if(!p.empty())
|
||||
{
|
||||
if(node == NONE)
|
||||
node = p.root_id();
|
||||
ret = print_node(p, node, 0, 0, true);
|
||||
}
|
||||
printf("#nodes=%zd vs #printed=%zd\n", p.size(), ret);
|
||||
printf("--------------------------------------\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
} /* namespace yml */
|
||||
} /* namespace c4 */
|
||||
|
||||
|
||||
#endif /* C4_YML_DETAIL_PRINT_HPP_ */
|
||||
280
3rdparty/rapidyaml/include/c4/yml/detail/stack.hpp
vendored
Normal file
280
3rdparty/rapidyaml/include/c4/yml/detail/stack.hpp
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
#ifndef _C4_YML_DETAIL_STACK_HPP_
|
||||
#define _C4_YML_DETAIL_STACK_HPP_
|
||||
|
||||
#ifndef _C4_YML_COMMON_HPP_
|
||||
#include "../common.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef RYML_DBG
|
||||
# include <type_traits>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace c4 {
|
||||
namespace yml {
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** A lightweight contiguous stack with SSO. This avoids a dependency on std. */
|
||||
template<class T, size_t N=16>
|
||||
class stack
|
||||
{
|
||||
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
|
||||
static_assert(std::is_trivially_destructible<T>::value, "T must be trivially destructible");
|
||||
|
||||
enum : size_t { sso_size = N };
|
||||
|
||||
public:
|
||||
|
||||
T m_buf[N];
|
||||
T * m_stack;
|
||||
size_t m_size;
|
||||
size_t m_capacity;
|
||||
Callbacks m_callbacks;
|
||||
|
||||
public:
|
||||
|
||||
constexpr static bool is_contiguous() { return true; }
|
||||
|
||||
stack(Callbacks const& cb)
|
||||
: m_buf()
|
||||
, m_stack(m_buf)
|
||||
, m_size(0)
|
||||
, m_capacity(N)
|
||||
, m_callbacks(cb) {}
|
||||
stack() : stack(get_callbacks()) {}
|
||||
~stack()
|
||||
{
|
||||
_free();
|
||||
}
|
||||
|
||||
stack(stack const& that) RYML_NOEXCEPT : stack(that.m_callbacks)
|
||||
{
|
||||
resize(that.m_size);
|
||||
_cp(&that);
|
||||
}
|
||||
|
||||
stack(stack &&that) noexcept : stack(that.m_callbacks)
|
||||
{
|
||||
_mv(&that);
|
||||
}
|
||||
|
||||
stack& operator= (stack const& that) RYML_NOEXCEPT
|
||||
{
|
||||
_cb(that.m_callbacks);
|
||||
resize(that.m_size);
|
||||
_cp(&that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
stack& operator= (stack &&that) noexcept
|
||||
{
|
||||
_cb(that.m_callbacks);
|
||||
_mv(&that);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
size_t empty() const { return m_size == 0; }
|
||||
size_t capacity() const { return m_capacity; }
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void resize(size_t sz)
|
||||
{
|
||||
reserve(sz);
|
||||
m_size = sz;
|
||||
}
|
||||
|
||||
void reserve(size_t sz);
|
||||
|
||||
void push(T const& C4_RESTRICT n)
|
||||
{
|
||||
RYML_ASSERT((const char*)&n + sizeof(T) < (const char*)m_stack || &n > m_stack + m_capacity);
|
||||
if(m_size == m_capacity)
|
||||
{
|
||||
size_t cap = m_capacity == 0 ? N : 2 * m_capacity;
|
||||
reserve(cap);
|
||||
}
|
||||
m_stack[m_size] = n;
|
||||
++m_size;
|
||||
}
|
||||
|
||||
void push_top()
|
||||
{
|
||||
RYML_ASSERT(m_size > 0);
|
||||
if(m_size == m_capacity)
|
||||
{
|
||||
size_t cap = m_capacity == 0 ? N : 2 * m_capacity;
|
||||
reserve(cap);
|
||||
}
|
||||
m_stack[m_size] = m_stack[m_size - 1];
|
||||
++m_size;
|
||||
}
|
||||
|
||||
T const& C4_RESTRICT pop()
|
||||
{
|
||||
RYML_ASSERT(m_size > 0);
|
||||
--m_size;
|
||||
return m_stack[m_size];
|
||||
}
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT top() const { RYML_ASSERT(m_size > 0); return m_stack[m_size - 1]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT top() { RYML_ASSERT(m_size > 0); return m_stack[m_size - 1]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT bottom() const { RYML_ASSERT(m_size > 0); return m_stack[0]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT bottom() { RYML_ASSERT(m_size > 0); return m_stack[0]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT top(size_t i) const { RYML_ASSERT(i < m_size); return m_stack[m_size - 1 - i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT top(size_t i) { RYML_ASSERT(i < m_size); return m_stack[m_size - 1 - i]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT bottom(size_t i) const { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT bottom(size_t i) { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
|
||||
C4_ALWAYS_INLINE T const& C4_RESTRICT operator[](size_t i) const { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
C4_ALWAYS_INLINE T & C4_RESTRICT operator[](size_t i) { RYML_ASSERT(i < m_size); return m_stack[i]; }
|
||||
|
||||
public:
|
||||
|
||||
using iterator = T *;
|
||||
using const_iterator = T const *;
|
||||
|
||||
iterator begin() { return m_stack; }
|
||||
iterator end () { return m_stack + m_size; }
|
||||
|
||||
const_iterator begin() const { return (const_iterator)m_stack; }
|
||||
const_iterator end () const { return (const_iterator)m_stack + m_size; }
|
||||
|
||||
public:
|
||||
void _free();
|
||||
void _cp(stack const* C4_RESTRICT that);
|
||||
void _mv(stack * that);
|
||||
void _cb(Callbacks const& cb);
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
void stack<T, N>::reserve(size_t sz)
|
||||
{
|
||||
if(sz <= m_size)
|
||||
return;
|
||||
if(sz <= N)
|
||||
{
|
||||
m_stack = m_buf;
|
||||
m_capacity = N;
|
||||
return;
|
||||
}
|
||||
T *buf = (T*) m_callbacks.m_allocate(sz * sizeof(T), m_stack, m_callbacks.m_user_data);
|
||||
memcpy(buf, m_stack, m_size * sizeof(T));
|
||||
if(m_stack != m_buf)
|
||||
{
|
||||
m_callbacks.m_free(m_stack, m_capacity * sizeof(T), m_callbacks.m_user_data);
|
||||
}
|
||||
m_stack = buf;
|
||||
m_capacity = sz;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
void stack<T, N>::_free()
|
||||
{
|
||||
RYML_ASSERT(m_stack != nullptr); // this structure cannot be memset() to zero
|
||||
if(m_stack != m_buf)
|
||||
{
|
||||
m_callbacks.m_free(m_stack, m_capacity * sizeof(T), m_callbacks.m_user_data);
|
||||
m_stack = m_buf;
|
||||
m_size = N;
|
||||
m_capacity = N;
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(m_capacity == N);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
void stack<T, N>::_cp(stack const* C4_RESTRICT that)
|
||||
{
|
||||
if(that->m_stack != that->m_buf)
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity > N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity <= N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
}
|
||||
memcpy(m_stack, that->m_stack, that->m_size * sizeof(T));
|
||||
m_size = that->m_size;
|
||||
m_capacity = that->m_size < N ? N : that->m_size;
|
||||
m_callbacks = that->m_callbacks;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
void stack<T, N>::_mv(stack * that)
|
||||
{
|
||||
if(that->m_stack != that->m_buf)
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity > N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
m_stack = that->m_stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
RYML_ASSERT(that->m_capacity <= N);
|
||||
RYML_ASSERT(that->m_size <= that->m_capacity);
|
||||
memcpy(m_buf, that->m_buf, that->m_size * sizeof(T));
|
||||
m_stack = m_buf;
|
||||
}
|
||||
m_size = that->m_size;
|
||||
m_capacity = that->m_capacity;
|
||||
m_callbacks = that->m_callbacks;
|
||||
// make sure no deallocation happens on destruction
|
||||
RYML_ASSERT(that->m_stack != m_buf);
|
||||
that->m_stack = that->m_buf;
|
||||
that->m_capacity = N;
|
||||
that->m_size = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template<class T, size_t N>
|
||||
void stack<T, N>::_cb(Callbacks const& cb)
|
||||
{
|
||||
if(cb != m_callbacks)
|
||||
{
|
||||
_free();
|
||||
m_callbacks = cb;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
C4_SUPPRESS_WARNING_GCC_CLANG_POP
|
||||
|
||||
} // namespace yml
|
||||
} // namespace c4
|
||||
|
||||
#endif /* _C4_YML_DETAIL_STACK_HPP_ */
|
||||
Reference in New Issue
Block a user