VirtualBox

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

Last change on this file since 4968 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

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