VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strspace.cpp@ 36555

Last change on this file since 36555 was 36555, checked in by vboxsync, 14 years ago

Use DECLHIDDEN, especially in IPRT.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.0 KB
Line 
1/* $Id: strspace.cpp 36555 2011-04-05 12:34:09Z vboxsync $ */
2/** @file
3 * IPRT - Unique String Spaces.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
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 (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/string.h>
32#include "internal/iprt.h"
33
34#include <iprt/assert.h>
35
36
37/*******************************************************************************
38* Defined Constants And Macros *
39*******************************************************************************/
40/*
41 * AVL configuration.
42 */
43#define KAVL_DECL(a_Type) static a_Type
44#define KAVL_FN(a) rtstrspace##a
45#define KAVL_MAX_STACK 27 /* Up to 2^24 nodes. */
46#define KAVL_EQUAL_ALLOWED 1
47#define KAVLNODECORE RTSTRSPACECORE
48#define PKAVLNODECORE PRTSTRSPACECORE
49#define PPKAVLNODECORE PPRTSTRSPACECORE
50#define KAVLKEY uint32_t
51#define PKAVLKEY uint32_t *
52
53#define PKAVLCALLBACK PFNRTSTRSPACECALLBACK
54
55/*
56 * AVL Compare macros
57 */
58#define KAVL_G(key1, key2) (key1 > key2)
59#define KAVL_E(key1, key2) (key1 == key2)
60#define KAVL_NE(key1, key2) (key1 != key2)
61
62
63/*
64 * Include the code.
65 */
66#define SSToDS(ptr) ptr
67#define KMAX RT_MAX
68#define kASSERT Assert
69#include "../table/avl_Base.cpp.h"
70#include "../table/avl_Get.cpp.h"
71#include "../table/avl_DoWithAll.cpp.h"
72#include "../table/avl_Destroy.cpp.h"
73
74
75
76/* sdbm:
77 This algorithm was created for sdbm (a public-domain reimplementation of
78 ndbm) database library. it was found to do well in scrambling bits,
79 causing better distribution of the keys and fewer splits. it also happens
80 to be a good general hashing function with good distribution. the actual
81 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
82 is the faster version used in gawk. [there is even a faster, duff-device
83 version] the magic constant 65599 was picked out of thin air while
84 experimenting with different constants, and turns out to be a prime.
85 this is one of the algorithms used in berkeley db (see sleepycat) and
86 elsewhere. */
87DECLINLINE(uint32_t) sdbm(const char *str, size_t *pcch)
88{
89 uint8_t *pu8 = (uint8_t *)str;
90 uint32_t hash = 0;
91 int c;
92
93 while ((c = *pu8++))
94 hash = c + (hash << 6) + (hash << 16) - hash;
95
96 *pcch = (uintptr_t)pu8 - (uintptr_t)str - 1;
97 return hash;
98}
99
100DECLINLINE(uint32_t) sdbmN(const char *str, size_t cchMax, size_t *pcch)
101{
102 uint8_t *pu8 = (uint8_t *)str;
103 uint32_t hash = 0;
104 int c;
105
106 while ((c = *pu8++) && cchMax-- > 0)
107 hash = c + (hash << 6) + (hash << 16) - hash;
108
109 *pcch = (uintptr_t)pu8 - (uintptr_t)str - 1;
110 return hash;
111}
112
113
114/**
115 * Inserts a string into a unique string space.
116 *
117 * @returns true on success.
118 * @returns false if the string collided with an existing string.
119 * @param pStrSpace The space to insert it into.
120 * @param pStr The string node.
121 */
122RTDECL(bool) RTStrSpaceInsert(PRTSTRSPACE pStrSpace, PRTSTRSPACECORE pStr)
123{
124 pStr->Key = sdbm(pStr->pszString, &pStr->cchString);
125 PRTSTRSPACECORE pMatch = KAVL_FN(Get)(pStrSpace, pStr->Key);
126 if (!pMatch)
127 return KAVL_FN(Insert)(pStrSpace, pStr);
128
129 /* Check for clashes. */
130 for (PRTSTRSPACECORE pCur = pMatch; pCur; pCur = pCur->pList)
131 if ( pCur->cchString == pStr->cchString
132 && !memcmp(pCur->pszString, pStr->pszString, pStr->cchString))
133 return false;
134 pStr->pList = pMatch->pList;
135 pMatch->pList = pStr;
136 return true;
137}
138RT_EXPORT_SYMBOL(RTStrSpaceInsert);
139
140
141/**
142 * Removes a string from a unique string space.
143 *
144 * @returns Pointer to the removed string node.
145 * @returns NULL if the string was not found in the string space.
146 * @param pStrSpace The space to insert it into.
147 * @param pszString The string to remove.
148 */
149RTDECL(PRTSTRSPACECORE) RTStrSpaceRemove(PRTSTRSPACE pStrSpace, const char *pszString)
150{
151 size_t cchString;
152 KAVLKEY Key = sdbm(pszString, &cchString);
153 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
154 if (!pCur)
155 return NULL;
156
157 /* find the right one. */
158 PRTSTRSPACECORE pPrev = NULL;
159 for (; pCur; pPrev = pCur, pCur = pCur->pList)
160 if ( pCur->cchString == cchString
161 && !memcmp(pCur->pszString, pszString, cchString))
162 break;
163 if (pCur)
164 {
165 if (pPrev)
166 /* simple, it's in the linked list. */
167 pPrev->pList = pCur->pList;
168 else
169 {
170 /* in the tree. remove and reinsert list head. */
171 PRTSTRSPACECORE pInsert = pCur->pList;
172 pCur->pList = NULL;
173 pCur = KAVL_FN(Remove)(pStrSpace, Key);
174 Assert(pCur);
175 if (pInsert)
176 {
177 PRTSTRSPACECORE pList = pInsert->pList;
178 bool fRc = KAVL_FN(Insert)(pStrSpace, pInsert);
179 Assert(fRc); NOREF(fRc);
180 pInsert->pList = pList;
181 }
182 }
183 }
184
185 return pCur;
186}
187RT_EXPORT_SYMBOL(RTStrSpaceRemove);
188
189
190/**
191 * Gets a string from a unique string space.
192 *
193 * @returns Pointer to the string node.
194 * @returns NULL if the string was not found in the string space.
195 * @param pStrSpace The space to insert it into.
196 * @param pszString The string to get.
197 */
198RTDECL(PRTSTRSPACECORE) RTStrSpaceGet(PRTSTRSPACE pStrSpace, const char *pszString)
199{
200 size_t cchString;
201 KAVLKEY Key = sdbm(pszString, &cchString);
202 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
203 if (!pCur)
204 return NULL;
205
206 /* Linear search. */
207 for (; pCur; pCur = pCur->pList)
208 if ( pCur->cchString == cchString
209 && !memcmp(pCur->pszString, pszString, cchString))
210 return pCur;
211 return NULL;
212}
213RT_EXPORT_SYMBOL(RTStrSpaceGet);
214
215
216/**
217 * Gets a string from a unique string space.
218 *
219 * @returns Pointer to the string node.
220 * @returns NULL if the string was not found in the string space.
221 * @param pStrSpace The space to insert it into.
222 * @param pszString The string to get.
223 * @param cchMax The max string length to evaluate. Passing
224 * RTSTR_MAX is ok and makes it behave just like
225 * RTStrSpaceGet.
226 */
227RTDECL(PRTSTRSPACECORE) RTStrSpaceGetN(PRTSTRSPACE pStrSpace, const char *pszString, size_t cchMax)
228{
229 size_t cchString;
230 KAVLKEY Key = sdbmN(pszString, cchMax, &cchString);
231 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
232 if (!pCur)
233 return NULL;
234
235 /* Linear search. */
236 for (; pCur; pCur = pCur->pList)
237 if ( pCur->cchString == cchString
238 && !memcmp(pCur->pszString, pszString, cchString))
239 return pCur;
240 return NULL;
241}
242RT_EXPORT_SYMBOL(RTStrSpaceGetN);
243
244
245/**
246 * Enumerates the string space.
247 * The caller supplies a callback which will be called for each of
248 * the string nodes.
249 *
250 * @returns 0 or what ever non-zero return value pfnCallback returned
251 * when aborting the destruction.
252 * @param pStrSpace The space to insert it into.
253 * @param pfnCallback The callback.
254 * @param pvUser The user argument.
255 */
256RTDECL(int) RTStrSpaceEnumerate(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
257{
258 return KAVL_FN(DoWithAll)(pStrSpace, true, pfnCallback, pvUser);
259}
260RT_EXPORT_SYMBOL(RTStrSpaceEnumerate);
261
262
263/**
264 * Destroys the string space.
265 * The caller supplies a callback which will be called for each of
266 * the string nodes in for freeing their memory and other resources.
267 *
268 * @returns 0 or what ever non-zero return value pfnCallback returned
269 * when aborting the destruction.
270 * @param pStrSpace The space to insert it into.
271 * @param pfnCallback The callback.
272 * @param pvUser The user argument.
273 */
274RTDECL(int) RTStrSpaceDestroy(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
275{
276 return KAVL_FN(Destroy)(pStrSpace, pfnCallback, pvUser);
277}
278RT_EXPORT_SYMBOL(RTStrSpaceDestroy);
279
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