fixed Solaris build
[public/netxms.git] / src / libnetxms / strmapbase.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003-2014 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: strmapbase.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include "strmap-internal.h"
26
27 #if HAVE_ALLOCA_H
28 #include <alloca.h>
29 #endif
30
31 /**
32 * Standard object destructor
33 */
34 static void ObjectDestructor(void *object)
35 {
36 free(object);
37 }
38
39 /**
40 * Constructors
41 */
42 StringMapBase::StringMapBase(bool objectOwner)
43 {
44 m_size = 0;
45 m_data = NULL;
46 m_objectOwner = objectOwner;
47 m_ignoreCase = true;
48 m_objectDestructor = ObjectDestructor;
49 }
50
51 /**
52 * Destructor
53 */
54 StringMapBase::~StringMapBase()
55 {
56 clear();
57 }
58
59 /**
60 * Clear map
61 */
62 void StringMapBase::clear()
63 {
64 StringMapEntry *entry, *tmp;
65 HASH_ITER(hh, m_data, entry, tmp)
66 {
67 HASH_DEL(m_data, entry);
68 free(entry->key);
69 destroyObject(entry->value);
70 free(entry);
71 }
72 m_size = 0;
73 }
74
75 /**
76 * Find entry index by key
77 */
78 StringMapEntry *StringMapBase::find(const TCHAR *key)
79 {
80 if (key == NULL)
81 return NULL;
82
83 StringMapEntry *entry;
84 int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
85 if (m_ignoreCase)
86 {
87 TCHAR *ukey = (TCHAR *)alloca(keyLen + sizeof(TCHAR));
88 memcpy(ukey, key, keyLen + sizeof(TCHAR));
89 _tcsupr(ukey);
90 HASH_FIND(hh, m_data, ukey, keyLen, entry);
91 }
92 else
93 {
94 HASH_FIND(hh, m_data, key, keyLen, entry);
95 }
96 return entry;
97 }
98
99 /**
100 * Set value
101 */
102 void StringMapBase::setObject(TCHAR *key, void *value, bool keyPreAllocated)
103 {
104 if (key == NULL)
105 return;
106
107 StringMapEntry *entry = find(key);
108 if (entry != NULL)
109 {
110 if (keyPreAllocated)
111 free(key);
112 if (m_objectOwner)
113 destroyObject(entry->value);
114 entry->value = value;
115 }
116 else
117 {
118 entry = (StringMapEntry *)malloc(sizeof(StringMapEntry));
119 entry->key = keyPreAllocated ? key : _tcsdup(key);
120 if (m_ignoreCase)
121 _tcsupr(entry->key);
122 int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
123 entry->value = value;
124 HASH_ADD_KEYPTR(hh, m_data, entry->key, keyLen, entry);
125 m_size++;
126 }
127 }
128
129 /**
130 * Get value by key
131 */
132 void *StringMapBase::getObject(const TCHAR *key)
133 {
134 StringMapEntry *entry = find(key);
135 return (entry != NULL) ? entry->value : NULL;
136 }
137
138 /**
139 * Delete value
140 */
141 void StringMapBase::remove(const TCHAR *key)
142 {
143 StringMapEntry *entry = find(key);
144 if (entry != NULL)
145 {
146 free(entry->key);
147 if (m_objectOwner)
148 destroyObject(entry->value);
149 free(entry);
150 m_size--;
151 }
152 }
153
154 /**
155 * Enumerate entries
156 * Returns true if whole map was enumerated and false if enumeration was aborted by callback.
157 */
158 bool StringMapBase::forEach(bool (*cb)(const TCHAR *, const void *, void *), void *userData)
159 {
160 bool result = true;
161 StringMapEntry *entry, *tmp;
162 HASH_ITER(hh, m_data, entry, tmp)
163 {
164 if (!cb(entry->key, entry->value, userData))
165 {
166 result = false;
167 break;
168 }
169 }
170 return result;
171 }