Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtmail / libDtMail / Common / Dictionary.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *
27  *      $TOG: Dictionary.C /main/5 1997/12/22 16:32:11 bill $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 #include <string.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <DtMail/Threads.hh>
48 #include <DtMail/Dictionary.hh>
49
50 DtMailDictionaryImpl::DtMailDictionaryImpl(int size)
51 {
52     _hash_size = size;
53
54     _hash_table = (HashTable_t *)malloc(sizeof(HashTable_t) * _hash_size);
55
56     for (int h = 0; h < _hash_size; h++) {
57         _hash_table[h] = NULL;
58     }
59
60     _obj_mutex = MutexInit();
61 }
62
63 DtMailDictionaryImpl::~DtMailDictionaryImpl(void)
64 {
65     MutexLock lock_scope(_obj_mutex);
66
67     if (_hash_table) {
68         for (int h = 0; h < _hash_size; h++) {
69             if (_hash_table[h]) {
70                 delete _hash_table[h];
71             }
72         }
73         free(_hash_table);
74         _hash_table = NULL;
75     }
76
77     lock_scope.unlock_and_destroy();
78 }
79
80 void
81 DtMailDictionaryImpl::set(const char * key, const void * value)
82 {
83     MutexLock lock_scope(_obj_mutex);
84
85     int hash = hashValue(key);
86
87     // See if this key is already there. If so, simply update the value.
88     //
89     Entry * ent;
90     locate(hash, key, &ent);
91
92     if (ent) {
93         ent->value = value;
94         return;
95     }
96
97     // New key/value. Add it to the appropriate slot.
98     //
99     if (_hash_table[hash] == NULL) {
100         _hash_table[hash] = new DtVirtArray<Entry *>(16);
101     }
102
103     DtVirtArray<Entry *> * slot = _hash_table[hash];
104
105     ent = new Entry;
106     ent->key = strdup(key);
107     ent->value = value;
108
109     slot->append(ent);
110     return;
111 }
112
113 const void *
114 DtMailDictionaryImpl::lookup(const char * key)
115 {
116     MutexLock lock_scope(_obj_mutex);
117
118     int hash = hashValue(key);
119
120     Entry * ent;
121     locate(hash, key, &ent);
122     const void * value = NULL;
123     if (ent) {
124         value = ent->value;
125     }
126
127     return(value);
128 }
129
130 void
131 DtMailDictionaryImpl::remove(const char * key)
132 {
133     MutexLock lock_scope(_obj_mutex);
134
135     int hash = hashValue(key);
136
137     // Locate the entry. This approach will cause us to search
138     // the hash list twice, but that should be cheap enough that
139     // we can afford to do it.
140     //
141     Entry * ent;
142     locate(hash, key, &ent);
143     if (ent == NULL) {
144         // Not here, just return.
145         return;
146     }
147
148     DtVirtArray<Entry *> * slot = _hash_table[hash];
149     int loc = slot->indexof(ent);
150     slot->remove(loc);
151
152     return;
153 }
154
155 int
156 DtMailDictionaryImpl::hashValue(const char * key)
157 {
158     int hash = 0;
159     for (const char * cur = key; *cur; cur++) {
160         hash ^= *cur;
161     }
162
163     hash %= _hash_size;
164
165     return(hash);
166 }
167
168 void
169 DtMailDictionaryImpl::locate(int hash, const char * key, Entry ** ent)
170 {
171     *ent = NULL;
172
173     DtVirtArray<Entry *> * slot = _hash_table[hash];
174
175     if (slot == NULL) {
176         return;
177     }
178
179     for (int col = 0; col < slot->length(); col++) {
180         Entry * t_ent = (*slot)[col];
181
182         if (strcmp(t_ent->key, key) == 0) {
183             *ent = t_ent;
184             break;
185         }
186     }
187
188     return;
189 }