source: trunk/include/k/kRbTmpl/kRbAssert.h@ 63

Last change on this file since 63 was 38, checked in by bird, 16 years ago

kRbTmpl: Some more code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 4.5 KB
Line 
1/* $Id: kRbAssert.h 38 2009-11-10 00:01:38Z bird $ */
2/** @file
3 * kRbTmpl - Templated Red-Black Trees, Assert Valid Tree.
4 */
5
6/*
7 * Copyright (c) 2009 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/**
33 * Internal helper for KRB_FN(Assert)
34 *
35 * @returns The number of black nodes. -1 is return if the tree is invalid.
36 * @param pRoot The root of the (sub-)tree to assert.
37 */
38K_DECL_INLINE(int) KRB_FN(AssertRecurse)(KRBNODE *pRoot)
39{
40 int cLeft;
41 int cRight;
42
43 if (!pRoot)
44 /* leafs are black. */
45 return 1;
46
47#ifdef KRB_EQUAL_ALLOWED
48 /* equal nodes are equal :) */
49 if (pNode->mpList != KRB_NULL)
50 {
51 KRBROOT *pEqual;
52 for (pEqual = KRB_GET_POINTER(&pNode->mpList); pEqual; pEqual = KRB_GET_POINTER_NULL(&pEqual->mpList))
53 kHlpAssertReturn(K_CMP_E(pEqual->mKey, pNode->mKey), -1);
54 }
55#endif
56
57 /* binary tree. */
58 kHlpAssertReturn(pRoot->mpLeft != KRB_NULL && KRB_CMP_G(KRB_GET_POINTER(&pRoot->mpLeft)->mpKey, pRoot->mKey), -1);
59 kHlpAssertReturn(pRoot->mpRight != KRB_NULL && KRB_CMP_G(pRoot->mKey, KRB_GET_POINTER(&pRoot->mpRigth)->mpKey), -1);
60
61 /* both children of red nodes are black. */
62 kHlpAssertReturn(!KRB_IS_RED(pRoot) || (!KRB_IS_RED(pRoot->mpLeft) && !KRB_IS_RED(pRoot->mpRight)), -1);
63
64 /* all paths to leafs contains the same number of black nodes. */
65 cLeft = KRB_FN(AssertRecurse)(KRB_GET_POINTER_NULL(&pRoot->mpLeft));
66 cRight = KRB_FN(AssertRecurse)(KRB_GET_POINTER_NULL(&pRoot->mpRight));
67 kHlpAssertMsgReturn(cLeft == cRight || cLeft == -1 || cRight == -1, ("%d vs. %d\n", cLeft, cRight), -1);
68
69 return cLeft + !KRB_IS_RED(pRoot);
70}
71
72
73/**
74 * Asserts the validity of the Red-Black tree.
75 *
76 * This method is using recursion and may therefore consume quite a bit of stack
77 * on a large tree.
78 *
79 * @returns K_TRUE if valid.
80 * @returns K_FALSE if invalid, assertion raised on each violation.
81 * @param pRoot Pointer to the Red-Back tree's root structure.
82 */
83KRB_DECL(KBOOL) KRB_FN(Assert)(KRBROOT *pRoot)
84{
85 KBOOL fRc = K_TRUE;
86#ifdef KRB_CACHE_SIZE
87 unsigned i;
88#endif
89 KRBNODE *pNode;
90
91 KRB_READ_LOCK(pRoot);
92 if (pRoot->mpRoot == KRB_NULL)
93 {
94 KRB_READ_UNLOCK(pRoot);
95 return 0;
96 }
97
98#ifdef KRB_CACHE_SIZE
99 /*
100 * Validate the cache.
101 */
102 for (i = 0; i < (KRB_CACHE_SIZE); i++)
103 if (pRoot->maLookthru[i] != KRB_NULL)
104 {
105 KRBNODE pCache = KRB_GET_POINTER(&pRoot->maLookthru[i]);
106
107 /** @todo ranges */
108 kHlpAssertMsgStmt(i == KRB_CACHE_HASH(pCache->Key), ("Invalid cache entry %u, hashed to %u\n", i, KRB_CACHE_HASH(pCache->Key)), fRc = K_FALSE);
109
110 pNode = KRB_GET_POINTER(&pRoot->mpRoot);
111 while (pNode)
112 {
113 if (KRB_CMP_E(pCache->mKey, pNode->mKey))
114 {
115 kHlpAssertMsgStmt(pNode == pCache, ("Invalid cache entry %u=%p, found %p\n", i, pCache, pNode), fRc = K_FALSE);
116 break;
117 }
118 if (KRB_CMP_G(pCache->mKey, pNode->mKey))
119 pNode = KRB_GET_POINTER_NULL(&pNode->mRight);
120 else
121 pNode = KRB_GET_POINTER_NULL(&pNode->mLeft);
122 }
123 kHlpAssertMsgStmt(pNode, ("Invalid cache entry %u/%p - not found\n", i, pCache), fRc = K_FALSE);
124 }
125#endif
126
127 /*
128 * Recurse thru the tree.
129 */
130 if (KRB_FN(AssertRecurse)(KRB_GET_POINTER(&pRoot->mpRoot)) == -1)
131 fRc = K_FALSE;
132
133 KRB_READ_UNLOCK(pRoot);
134 return fRc;
135}
136
Note: See TracBrowser for help on using the repository browser.