VirtualBox

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

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

strspace.cpp: Fixed bug in sdbm() resulting in wrong cchString values (+1). Return true when inserting into the collision list, only return false for identical strings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/* $Id: strspace.cpp 30611 2010-07-05 12:53:59Z 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_FN(a) rtstrspace##a
44#define KAVL_MAX_STACK 27 /* Up to 2^24 nodes. */
45#define KAVL_EQUAL_ALLOWED 1
46#define KAVLNODECORE RTSTRSPACECORE
47#define PKAVLNODECORE PRTSTRSPACECORE
48#define PPKAVLNODECORE PPRTSTRSPACECORE
49#define KAVLKEY uint32_t
50#define PKAVLKEY uint32_t *
51
52#define PKAVLCALLBACK PFNRTSTRSPACECALLBACK
53
54/*
55 * AVL Compare macros
56 */
57#define KAVL_G(key1, key2) (key1 > key2)
58#define KAVL_E(key1, key2) (key1 == key2)
59#define KAVL_NE(key1, key2) (key1 != key2)
60
61
62/*
63 * Include the code.
64 */
65#define SSToDS(ptr) ptr
66#define KMAX RT_MAX
67#define kASSERT Assert
68#include "../table/avl_Base.cpp.h"
69#include "../table/avl_Get.cpp.h"
70#include "../table/avl_DoWithAll.cpp.h"
71#include "../table/avl_Destroy.cpp.h"
72
73
74
75/* sdbm:
76 This algorithm was created for sdbm (a public-domain reimplementation of
77 ndbm) database library. it was found to do well in scrambling bits,
78 causing better distribution of the keys and fewer splits. it also happens
79 to be a good general hashing function with good distribution. the actual
80 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
81 is the faster version used in gawk. [there is even a faster, duff-device
82 version] the magic constant 65599 was picked out of thin air while
83 experimenting with different constants, and turns out to be a prime.
84 this is one of the algorithms used in berkeley db (see sleepycat) and
85 elsewhere. */
86DECLINLINE(uint32_t) sdbm(const char *str, size_t *pcch)
87{
88 uint8_t *pu8 = (uint8_t *)str;
89 uint32_t hash = 0;
90 int c;
91
92 while ((c = *pu8++))
93 hash = c + (hash << 6) + (hash << 16) - hash;
94
95 *pcch = (uintptr_t)pu8 - (uintptr_t)str - 1;
96 return hash;
97}
98
99
100/**
101 * Inserts a string into a unique string space.
102 *
103 * @returns true on success.
104 * @returns false if the string collieded with an existing string.
105 * @param pStrSpace The space to insert it into.
106 * @param pStr The string node.
107 */
108RTDECL(bool) RTStrSpaceInsert(PRTSTRSPACE pStrSpace, PRTSTRSPACECORE pStr)
109{
110 pStr->Key = sdbm(pStr->pszString, &pStr->cchString);
111 PRTSTRSPACECORE pMatch = KAVL_FN(Get)(pStrSpace, pStr->Key);
112 if (!pMatch)
113 return KAVL_FN(Insert)(pStrSpace, pStr);
114
115 /* Check for clashes. */
116 for (PRTSTRSPACECORE pCur = pMatch; pCur; pCur = pCur->pList)
117 if ( pCur->cchString == pStr->cchString
118 && !memcmp(pCur->pszString, pStr->pszString, pStr->cchString))
119 return false;
120 pStr->pList = pMatch->pList;
121 pMatch->pList = pStr;
122 return true;
123}
124RT_EXPORT_SYMBOL(RTStrSpaceInsert);
125
126
127/**
128 * Removes a string from a unique string space.
129 *
130 * @returns Pointer to the removed string node.
131 * @returns NULL if the string was not found in the string space.
132 * @param pStrSpace The space to insert it into.
133 * @param pszString The string to remove.
134 */
135RTDECL(PRTSTRSPACECORE) RTStrSpaceRemove(PRTSTRSPACE pStrSpace, const char *pszString)
136{
137 size_t cchString;
138 KAVLKEY Key = sdbm(pszString, &cchString);
139 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
140 if (!pCur)
141 return NULL;
142
143 /* find the right one. */
144 PRTSTRSPACECORE pPrev = NULL;
145 for (; pCur; pPrev = pCur, pCur = pCur->pList)
146 if ( pCur->cchString == cchString
147 && !memcmp(pCur->pszString, pszString, cchString))
148 break;
149 if (pCur)
150 {
151 if (pPrev)
152 /* simple, it's in the linked list. */
153 pPrev->pList = pCur->pList;
154 else
155 {
156 /* in the tree. remove and reinsert list head. */
157 PRTSTRSPACECORE pInsert = pCur->pList;
158 pCur->pList = NULL;
159 pCur = KAVL_FN(Remove)(pStrSpace, Key);
160 Assert(pCur);
161 if (pInsert)
162 {
163 PRTSTRSPACECORE pList = pInsert->pList;
164 bool fRc = KAVL_FN(Insert)(pStrSpace, pInsert);
165 Assert(fRc); NOREF(fRc);
166 pInsert->pList = pList;
167 }
168 }
169 }
170
171 return pCur;
172}
173RT_EXPORT_SYMBOL(RTStrSpaceRemove);
174
175
176/**
177 * Gets a string from a unique string space.
178 *
179 * @returns Pointer to the string node.
180 * @returns NULL if the string was not found in the string space.
181 * @param pStrSpace The space to insert it into.
182 * @param pszString The string to get.
183 */
184RTDECL(PRTSTRSPACECORE) RTStrSpaceGet(PRTSTRSPACE pStrSpace, const char *pszString)
185{
186 size_t cchString;
187 KAVLKEY Key = sdbm(pszString, &cchString);
188 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
189 if (!pCur)
190 return NULL;
191
192 /* Linear search. */
193 for (; pCur; pCur = pCur->pList)
194 if ( pCur->cchString == cchString
195 && !memcmp(pCur->pszString, pszString, cchString))
196 return pCur;
197 return NULL;
198}
199RT_EXPORT_SYMBOL(RTStrSpaceGet);
200
201
202
203/**
204 * Enumerates the string space.
205 * The caller supplies a callback which will be called for each of
206 * the string nodes.
207 *
208 * @returns 0 or what ever non-zero return value pfnCallback returned
209 * when aborting the destruction.
210 * @param pStrSpace The space to insert it into.
211 * @param pfnCallback The callback.
212 * @param pvUser The user argument.
213 */
214RTDECL(int) RTStrSpaceEnumerate(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
215{
216 return KAVL_FN(DoWithAll)(pStrSpace, true, pfnCallback, pvUser);
217}
218RT_EXPORT_SYMBOL(RTStrSpaceEnumerate);
219
220
221/**
222 * Destroys the string space.
223 * The caller supplies a callback which will be called for each of
224 * the string nodes in for freeing their memory and other resources.
225 *
226 * @returns 0 or what ever non-zero return value pfnCallback returned
227 * when aborting the destruction.
228 * @param pStrSpace The space to insert it into.
229 * @param pfnCallback The callback.
230 * @param pvUser The user argument.
231 */
232RTDECL(int) RTStrSpaceDestroy(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
233{
234 return KAVL_FN(Destroy)(pStrSpace, pfnCallback, pvUser);
235}
236RT_EXPORT_SYMBOL(RTStrSpaceDestroy);
237
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