VirtualBox

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

Last change on this file since 16933 was 8245, checked in by vboxsync, 17 years ago

rebranding: IPRT files again.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1/* $Id: strspace.cpp 8245 2008-04-21 17:24:28Z vboxsync $ */
2/** @file
3 * IPRT - Unique String Spaces.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/string.h>
36#include <iprt/assert.h>
37
38
39/*******************************************************************************
40* Defined Constants And Macros *
41*******************************************************************************/
42/*
43 * AVL configuration.
44 */
45#define KAVL_FN(a) rtstrspace##a
46#define KAVL_MAX_STACK 27 /* Up to 2^24 nodes. */
47#define KAVL_EQUAL_ALLOWED 1
48#define KAVLNODECORE RTSTRSPACECORE
49#define PKAVLNODECORE PRTSTRSPACECORE
50#define PPKAVLNODECORE PPRTSTRSPACECORE
51#define KAVLKEY uint32_t
52#define PKAVLKEY uint32_t *
53
54#define PKAVLCALLBACK PFNRTSTRSPACECALLBACK
55
56/*
57 * AVL Compare macros
58 */
59#define KAVL_G(key1, key2) (key1 > key2)
60#define KAVL_E(key1, key2) (key1 == key2)
61#define KAVL_NE(key1, key2) (key1 != key2)
62
63
64/*
65 * Include the code.
66 */
67#define SSToDS(ptr) ptr
68#define KMAX RT_MAX
69#define kASSERT Assert
70#include "../table/avl_Base.cpp.h"
71#include "../table/avl_Get.cpp.h"
72#include "../table/avl_DoWithAll.cpp.h"
73#include "../table/avl_Destroy.cpp.h"
74
75
76
77/* sdbm:
78 This algorithm was created for sdbm (a public-domain reimplementation of
79 ndbm) database library. it was found to do well in scrambling bits,
80 causing better distribution of the keys and fewer splits. it also happens
81 to be a good general hashing function with good distribution. the actual
82 function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
83 is the faster version used in gawk. [there is even a faster, duff-device
84 version] the magic constant 65599 was picked out of thin air while
85 experimenting with different constants, and turns out to be a prime.
86 this is one of the algorithms used in berkeley db (see sleepycat) and
87 elsewhere. */
88inline uint32_t sdbm(const char *str, size_t *pcch)
89{
90 uint8_t *pu8 = (uint8_t *)str;
91 uint32_t hash = 0;
92 int c;
93
94 while ((c = *pu8++))
95 hash = c + (hash << 6) + (hash << 16) - hash;
96
97 *pcch = (uintptr_t)pu8 - (uintptr_t)str;
98 return hash;
99}
100
101
102/**
103 * Inserts a string into a unique string space.
104 *
105 * @returns true on success.
106 * @returns false if the string collieded with an existing string.
107 * @param pStrSpace The space to insert it into.
108 * @param pStr The string node.
109 */
110RTDECL(bool) RTStrSpaceInsert(PRTSTRSPACE pStrSpace, PRTSTRSPACECORE pStr)
111{
112 pStr->Key = sdbm(pStr->pszString, &pStr->cchString);
113 PRTSTRSPACECORE pMatch = KAVL_FN(Get)(pStrSpace, pStr->Key);
114 if (!pMatch)
115 return KAVL_FN(Insert)(pStrSpace, pStr);
116
117 /* Check for clashes. */
118 for (PRTSTRSPACECORE pCur = pMatch; pCur; pCur = pCur->pList)
119 if ( pCur->cchString == pStr->cchString
120 && !memcmp(pCur->pszString, pStr->pszString, pStr->cchString))
121 return false;
122 pStr->pList = pMatch->pList;
123 pMatch->pList = pStr;
124 return false;
125}
126
127
128/**
129 * Removes a string from a unique string space.
130 *
131 * @returns Pointer to the removed string node.
132 * @returns NULL if the string was not found in the string space.
133 * @param pStrSpace The space to insert it into.
134 * @param pszString The string to remove.
135 */
136RTDECL(PRTSTRSPACECORE) RTStrSpaceRemove(PRTSTRSPACE pStrSpace, const char *pszString)
137{
138 size_t cchString;
139 KAVLKEY Key = sdbm(pszString, &cchString);
140 PRTSTRSPACECORE pCur = KAVL_FN(Get)(pStrSpace, Key);
141 if (!pCur)
142 return NULL;
143
144 /* find the right one. */
145 PRTSTRSPACECORE pPrev = NULL;
146 for (; pCur; pPrev = pCur, pCur = pCur->pList)
147 if ( pCur->cchString == cchString
148 && !memcmp(pCur->pszString, pszString, cchString))
149 break;
150 if (pCur)
151 {
152 if (pPrev)
153 /* simple, it's in the linked list. */
154 pPrev->pList = pCur->pList;
155 else
156 {
157 /* in the tree. remove and reinsert list head. */
158 PRTSTRSPACECORE pInsert = pCur->pList;
159 pCur->pList = NULL;
160 pCur = KAVL_FN(Remove)(pStrSpace, Key);
161 Assert(pCur);
162 if (pInsert)
163 {
164 PRTSTRSPACECORE pList = pInsert->pList;
165 bool fRc = KAVL_FN(Insert)(pStrSpace, pInsert);
166 Assert(fRc); NOREF(fRc);
167 pInsert->pList = pList;
168 }
169 }
170 }
171
172 return pCur;
173}
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}
199
200
201
202/**
203 * Enumerates the string space.
204 * The caller supplies a callback which will be called for each of
205 * the string nodes.
206 *
207 * @returns 0 or what ever non-zero return value pfnCallback returned
208 * when aborting the destruction.
209 * @param pStrSpace The space to insert it into.
210 * @param pfnCallback The callback.
211 * @param pvUser The user argument.
212 */
213RTDECL(int) RTStrSpaceEnumerate(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
214{
215 return KAVL_FN(DoWithAll)(pStrSpace, true, pfnCallback, pvUser);
216}
217
218
219/**
220 * Destroys the string space.
221 * The caller supplies a callback which will be called for each of
222 * the string nodes in for freeing their memory and other resources.
223 *
224 * @returns 0 or what ever non-zero return value pfnCallback returned
225 * when aborting the destruction.
226 * @param pStrSpace The space to insert it into.
227 * @param pfnCallback The callback.
228 * @param pvUser The user argument.
229 */
230RTDECL(int) RTStrSpaceDestroy(PRTSTRSPACE pStrSpace, PFNRTSTRSPACECALLBACK pfnCallback, void *pvUser)
231{
232 return KAVL_FN(Destroy)(pStrSpace, pfnCallback, pvUser);
233}
234
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