checks.hpp (5501B)
1 #ifndef C4_YML_DETAIL_CHECKS_HPP_ 2 #define C4_YML_DETAIL_CHECKS_HPP_ 3 4 #include "c4/yml/tree.hpp" 5 6 #ifdef __clang__ 7 # pragma clang diagnostic push 8 #elif defined(__GNUC__) 9 # pragma GCC diagnostic push 10 # pragma GCC diagnostic ignored "-Wtype-limits" // error: comparison of unsigned expression >= 0 is always true 11 #elif defined(_MSC_VER) 12 # pragma warning(push) 13 # pragma warning(disable: 4296/*expression is always 'boolean_value'*/) 14 #endif 15 16 namespace c4 { 17 namespace yml { 18 19 20 void check_invariants(Tree const& t, size_t node=NONE); 21 void check_free_list(Tree const& t); 22 void check_arena(Tree const& t); 23 24 25 //----------------------------------------------------------------------------- 26 //----------------------------------------------------------------------------- 27 //----------------------------------------------------------------------------- 28 29 inline void check_invariants(Tree const& t, size_t node) 30 { 31 if(node == NONE) 32 { 33 if(t.size() == 0) return; 34 node = t.root_id(); 35 } 36 37 auto const& n = *t._p(node); 38 #ifdef RYML_DBG 39 if(n.m_first_child != NONE || n.m_last_child != NONE) 40 { 41 printf("check(%zu): fc=%zu lc=%zu\n", node, n.m_first_child, n.m_last_child); 42 } 43 else 44 { 45 printf("check(%zu)\n", node); 46 } 47 #endif 48 49 C4_CHECK(n.m_parent != node); 50 if(n.m_parent == NONE) 51 { 52 C4_CHECK(t.is_root(node)); 53 } 54 else //if(n.m_parent != NONE) 55 { 56 C4_CHECK(t.has_child(n.m_parent, node)); 57 58 auto const& p = *t._p(n.m_parent); 59 if(n.m_prev_sibling == NONE) 60 { 61 C4_CHECK(p.m_first_child == node); 62 C4_CHECK(t.first_sibling(node) == node); 63 } 64 else 65 { 66 C4_CHECK(p.m_first_child != node); 67 C4_CHECK(t.first_sibling(node) != node); 68 } 69 70 if(n.m_next_sibling == NONE) 71 { 72 C4_CHECK(p.m_last_child == node); 73 C4_CHECK(t.last_sibling(node) == node); 74 } 75 else 76 { 77 C4_CHECK(p.m_last_child != node); 78 C4_CHECK(t.last_sibling(node) != node); 79 } 80 } 81 82 C4_CHECK(n.m_first_child != node); 83 C4_CHECK(n.m_last_child != node); 84 if(n.m_first_child != NONE || n.m_last_child != NONE) 85 { 86 C4_CHECK(n.m_first_child != NONE); 87 C4_CHECK(n.m_last_child != NONE); 88 } 89 90 C4_CHECK(n.m_prev_sibling != node); 91 C4_CHECK(n.m_next_sibling != node); 92 if(n.m_prev_sibling != NONE) 93 { 94 C4_CHECK(t._p(n.m_prev_sibling)->m_next_sibling == node); 95 C4_CHECK(t._p(n.m_prev_sibling)->m_prev_sibling != node); 96 } 97 if(n.m_next_sibling != NONE) 98 { 99 C4_CHECK(t._p(n.m_next_sibling)->m_prev_sibling == node); 100 C4_CHECK(t._p(n.m_next_sibling)->m_next_sibling != node); 101 } 102 103 size_t count = 0; 104 for(size_t i = n.m_first_child; i != NONE; i = t.next_sibling(i)) 105 { 106 #ifdef RYML_DBG 107 printf("check(%zu): descend to child[%zu]=%zu\n", node, count, i); 108 #endif 109 auto const& ch = *t._p(i); 110 C4_CHECK(ch.m_parent == node); 111 C4_CHECK(ch.m_next_sibling != i); 112 ++count; 113 } 114 C4_CHECK(count == t.num_children(node)); 115 116 if(n.m_prev_sibling == NONE && n.m_next_sibling == NONE) 117 { 118 if(n.m_parent != NONE) 119 { 120 C4_CHECK(t.num_children(n.m_parent) == 1); 121 C4_CHECK(t.num_siblings(node) == 1); 122 } 123 } 124 125 if(node == t.root_id()) 126 { 127 C4_CHECK(t.size() == t.m_size); 128 C4_CHECK(t.capacity() == t.m_cap); 129 C4_CHECK(t.m_cap == t.m_size + t.slack()); 130 check_free_list(t); 131 check_arena(t); 132 } 133 134 for(size_t i = t.first_child(node); i != NONE; i = t.next_sibling(i)) 135 { 136 check_invariants(t, i); 137 } 138 } 139 140 141 //----------------------------------------------------------------------------- 142 //----------------------------------------------------------------------------- 143 //----------------------------------------------------------------------------- 144 145 inline void check_free_list(Tree const& t) 146 { 147 if(t.m_free_head == NONE) 148 { 149 C4_CHECK(t.m_free_tail == t.m_free_head); 150 return; 151 } 152 153 C4_CHECK(t.m_free_head >= 0 && t.m_free_head < t.m_cap); 154 C4_CHECK(t.m_free_tail >= 0 && t.m_free_tail < t.m_cap); 155 156 auto const& head = *t._p(t.m_free_head); 157 //auto const& tail = *t._p(t.m_free_tail); 158 159 //C4_CHECK(head.m_prev_sibling == NONE); 160 //C4_CHECK(tail.m_next_sibling == NONE); 161 162 size_t count = 0; 163 for(size_t i = t.m_free_head, prev = NONE; i != NONE; i = t._p(i)->m_next_sibling) 164 { 165 auto const& elm = *t._p(i); 166 if(&elm != &head) 167 { 168 C4_CHECK(elm.m_prev_sibling == prev); 169 } 170 prev = i; 171 ++count; 172 } 173 C4_CHECK(count == t.slack()); 174 } 175 176 177 //----------------------------------------------------------------------------- 178 //----------------------------------------------------------------------------- 179 //----------------------------------------------------------------------------- 180 181 inline void check_arena(Tree const& t) 182 { 183 C4_CHECK(t.m_arena.len == 0 || (t.m_arena_pos >= 0 && t.m_arena_pos <= t.m_arena.len)); 184 C4_CHECK(t.arena_size() == t.m_arena_pos); 185 C4_CHECK(t.arena_slack() + t.m_arena_pos == t.m_arena.len); 186 } 187 188 189 } /* namespace yml */ 190 } /* namespace c4 */ 191 192 #ifdef __clang__ 193 # pragma clang diagnostic pop 194 #elif defined(__GNUC__) 195 # pragma GCC diagnostic pop 196 #elif defined(_MSC_VER) 197 # pragma warning(pop) 198 #endif 199 200 #endif /* C4_YML_DETAIL_CHECKS_HPP_ */