VirtualBox

source: vbox/trunk/src/VBox/Runtime/strspace.cpp@ 3460

Last change on this file since 3460 was 2981, checked in by vboxsync, 18 years ago

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1/* $Id: strspace.cpp 2981 2007-06-01 16:01:28Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Unique String Spaces.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <iprt/string.h>
27#include <iprt/assert.h>
28
29
30/*******************************************************************************
31* Defined Constants And Macros *
32*******************************************************************************/
33/*
34 * AVL configuration.
35 */
36#define KAVL_FN(a) rtstrspace##a
37#define KAVL_MAX_STACK 27 /* Up to 2^24 nodes. */
38#define KAVL_EQUAL_ALLOWED 1
39#define KAVLNODECORE RTSTRSPACECORE
40#define PKAVLNODECORE PRTSTRSPACECORE
41#define PPKAVLNODECORE PPRTSTRSPACECORE
42#define KAVLKEY uint32_t
43#define PKAVLKEY uint32_t *
44
45#define PKAVLCALLBACK PFNRTSTRSPACECALLBACK
46
47/*
48 * AVL Compare macros
49 */
50#define KAVL_G(key1, key2) (key1 > key2)
51#define KAVL_E(key1, key2) (key1 == key2)
52#define KAVL_NE(key1, key2) (key1 != key2)
53
54
55/*
56 * Include the code.
57 */
58#define SSToDS(ptr) ptr
59#define KMAX RT_MAX
60#define kASSERT Assert
61#include "table/avl_Base.cpp.h"
62#include "table/avl_Get.cpp.h"
63#include "table/avl_DoWithAll.cpp.h"
64#include "table/avl_Destroy.cpp.h"
65
66
67
68/* sdbm:
69 This algorithm was created for sdbm (a public-domain reimplementation of
70 ndbm) database library. it was found to do well in scrambling bits,
71 causing better distribution of the keys and fewer splits. it also happens
72 to be a good general hashing function with good distribution. the actual
73 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
74 is the faster version used in gawk. [there is even a faster, duff-device
75 version] the magic constant 65599 was picked out of thin air while
76 experimenting with different constants, and turns out to be a prime.
77 this is one of the algorithms used in berkeley db (see sleepycat) and
78 elsewhere. */
79inline uint32_t sdbm(const char *str, size_t *pcch)
80{
81 uint8_t *pu8 = (uint8_t *)str;
82 uint32_t hash = 0;
83 int c;
84
85 while ((c = *pu8++))
86 hash = c + (hash << 6) + (hash << 16) - hash;
87
88 *pcch = (uintptr_t)pu8 - (uintptr_t)str;
89 return hash;
90}
91
92
93/**
94 * Inserts a string into a unique string space.
95 *
96 * @returns true on success.
97 * @returns false if the string collieded with an existing string.
98 * @param pStrSpace The space to insert it into.
99 * @param pStr The string node.
100 */
101RTDECL(bool) RTStrSpaceInsert(PRTSTRSPACE pStrSpace, PRTSTRSPACECORE pStr)
102{
103 pStr->Key = sdbm(pStr->pszString, &pStr->cchString);
104 PRTSTRSPACECORE pMatch = KAVL_FN(Get)(pStrSpace, pStr->Key);
105 if (!pMatch)
106 return KAVL_FN(Insert)(pStrSpace, pStr);
107
108 /* Check for clashes. */
109 for (PRTSTRSPACECORE pCur = pMatch; pCur; pCur = pCur->pList)
110 if ( pCur->cchString == pStr->cchString
111 && !memcmp(pCur->pszString, pStr->pszString, pStr->cchString))
112 return false;
113 pStr->pList = pMatch->pList;
114 pMatch->pList = pStr;
115 return false;
116}
117
118
119/**
120 * Removes a string from a unique string space.
121 *
122 * @returns Pointer to the removed string node.
123 * @returns NULL if the string was not found in the string space.
124 * @param pStrSpace The space to insert it into.
125 * @param pszString The string to remove.
126 */
127RTDECL(PRTSTRSPACECORE) RTStrSpaceRemove(PRTSTRSPACE pStrSpace, const char *pszString)
128{
129 size_t cchString;
130 KAVLKEY Key = sdbm(pszString, &cchString);
131 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
132 if (!pCur)
133 return NULL;
134
135 /* find the right one. */
136 PRTSTRSPACECORE pPrev = NULL;
137 for (; pCur; pPrev = pCur, pCur = pCur->pList)
138 if ( pCur->cchString == cchString
139 && !memcmp(pCur->pszString, pszString, cchString))
140 break;
141 if (pCur)
142 {
143 if (pPrev)
144 /* simple, it's in the linked list. */
145 pPrev->pList = pCur->pList;
146 else
147 {
148 /* in the tree. remove and reinsert list head. */
149 PRTSTRSPACECORE pInsert = pCur->pList;
150 pCur->pList = NULL;
151 pCur = KAVL_FN(Remove)(pStrSpace, Key);
152 Assert(pCur);
153 if (pInsert)
154 {
155 PRTSTRSPACECORE pList = pInsert->pList;
156 bool fRc = KAVL_FN(Insert)(pStrSpace, pInsert);
157 Assert(fRc); NOREF(fRc);
158 pInsert->pList = pList;
159 }
160 }
161 }
162
163 return pCur;
164}
165
166
167/**
168 * Gets a string from a unique string space.
169 *
170 * @returns Pointer to the string node.
171 * @returns NULL if the string was not found in the string space.
172 * @param pStrSpace The space to insert it into.
173 * @param pszString The string to get.
174 */
175RTDECL(PRTSTRSPACECORE) RTStrSpaceGet(PRTSTRSPACE pStrSpace, const char *pszString)
176{
177 size_t cchString;
178 KAVLKEY Key = sdbm(pszString, &cchString);
179 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
180 if (!pCur)
181 return NULL;
182
183 /* Linear search. */
184 for (; pCur; pCur = pCur->pList)
185 if ( pCur->cchString == cchString
186 && !memcmp(pCur->pszString, pszString, cchString))
187 return pCur;
188 return NULL;
189}
190
191
192
193/**
194 * Enumerates the string space.
195 * The caller supplies a callback which will be called for each of
196 * the string nodes.
197 *
198 * @returns 0 or what ever non-zero return value pfnCallback returned
199 * when aborting the destruction.
200 * @param pStrSpace The space to insert it into.
201 * @param pfnCallback The callback.
202 * @param pvUser The user argument.
203 */
204RTDECL(int) RTStrSpaceEnumerate(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
205{
206 return KAVL_FN(DoWithAll)(pStrSpace, true, pfnCallback, pvUser);
207}
208
209
210/**
211 * Destroys the string space.
212 * The caller supplies a callback which will be called for each of
213 * the string nodes in for freeing their memory and other resources.
214 *
215 * @returns 0 or what ever non-zero return value pfnCallback returned
216 * when aborting the destruction.
217 * @param pStrSpace The space to insert it into.
218 * @param pfnCallback The callback.
219 * @param pvUser The user argument.
220 */
221RTDECL(int) RTStrSpaceDestroy(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
222{
223 return KAVL_FN(Destroy)(pStrSpace, pfnCallback, pvUser);
224}
225
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette