mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	
		
			
	
	
		
			201 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			201 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | #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_ */
 |