35dfa54d0b0b63549f47e6906a1f1b40744c5f9d
[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 /**
28 * Standard object destructor
29 */
30 static void ObjectDestructor(void *object)
31 {
32 free(object);
33 }
34
35 /**
36 * Constructors
37 */
38 StringMapBase::StringMapBase(bool objectOwner)
39 {
40 m_size = 0;
41 m_data = NULL;
42 m_objectOwner = objectOwner;
43 m_ignoreCase = true;
44 m_objectDestructor = ObjectDestructor;
45 }
46
47 /**
48 * Destructor
49 */
50 StringMapBase::~StringMapBase()
51 {
52 clear();
53 }
54
55 /**
56 * Clear map
57 */
58 void StringMapBase::clear()
59 {
60 StringMapEntry *entry, *tmp;
61 HASH_ITER(hh, m_data, entry, tmp)
62 {
63 HASH_DEL(m_data, entry);
64 free(entry->key);
65 destroyObject(entry->value);
66 free(entry);
67 }
68 m_size = 0;
69 }
70
71 /**
72 * Find entry index by key
73 */
74 StringMapEntry *StringMapBase::find(const TCHAR *key)
75 {
76 if (key == NULL)
77 return NULL;
78
79 StringMapEntry *entry;
80 int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
81 if (m_ignoreCase)
82 {
83 TCHAR *ukey = (TCHAR *)alloca(keyLen + sizeof(TCHAR));
84 memcpy(ukey, key, keyLen + sizeof(TCHAR));
85 _tcsupr(ukey);
86 HASH_FIND(hh, m_data, ukey, keyLen, entry);
87 }
88 else
89 {
90 HASH_FIND(hh, m_data, key, keyLen, entry);
91 }
92 return entry;
93 }
94
95 /**
96 * Set value
97 */
98 void StringMapBase::setObject(TCHAR *key, void *value, bool keyPreAllocated)
99 {
100 if (key == NULL)
101 return;
102
103 StringMapEntry *entry = find(key);
104 if (entry != NULL)
105 {
106 if (keyPreAllocated)
107 free(key);
108 if (m_objectOwner)
109 destroyObject(entry->value);
110 entry->value = value;
111 }
112 else
113 {
114 entry = (StringMapEntry *)malloc(sizeof(StringMapEntry));
115 entry->key = keyPreAllocated ? key : _tcsdup(key);
116 if (m_ignoreCase)
117 _tcsupr(entry->key);
118 int keyLen = (int)(_tcslen(key) * sizeof(TCHAR));
119 entry->value = value;
120 HASH_ADD_KEYPTR(hh, m_data, entry->key, keyLen, entry);
121 m_size++;
122 }
123 }
124
125 /**
126 * Get value by key
127 */
128 void *StringMapBase::getObject(const TCHAR *key)
129 {
130 StringMapEntry *entry = find(key);
131 return (entry != NULL) ? entry->value : NULL;
132 }
133
134 /**
135 * Delete value
136 */
137 void StringMapBase::remove(const TCHAR *key)
138 {
139 StringMapEntry *entry = find(key);
140 if (entry != NULL)
141 {
142 free(entry->key);
143 if (m_objectOwner)
144 destroyObject(entry->value);
145 free(entry);
146 m_size--;
147 }
148 }
149
150 /**
151 * Enumerate entries
152 * Returns true if whole map was enumerated and false if enumeration was aborted by callback.
153 */
154 bool StringMapBase::forEach(bool (*cb)(const TCHAR *, const void *, void *), void *userData)
155 {
156 bool result = true;
157 StringMapEntry *entry, *tmp;
158 HASH_ITER(hh, m_data, entry, tmp)
159 {
160 if (!cb(entry->key, entry->value, userData))
161 {
162 result = false;
163 break;
164 }
165 }
166 return result;
167 }