LMMS
Loading...
Searching...
No Matches
assocarray.h
Go to the documentation of this file.
1#ifndef _WDL_ASSOCARRAY_H_
2#define _WDL_ASSOCARRAY_H_
3
4#include "heapbuf.h"
5#include "mergesort.h"
6
7// on all of these, if valdispose is set, the array will dispose of values as needed.
8// if keydup/keydispose are set, copies of (any) key data will be made/destroyed as necessary
9
10
11// WDL_AssocArrayImpl can be used on its own, and can contain structs for keys or values
12template <class KEY, class VAL> class WDL_AssocArrayImpl
13{
15
17
18public:
19
20 explicit WDL_AssocArrayImpl(int (*keycmp)(KEY *k1, KEY *k2), KEY (*keydup)(KEY)=0, void (*keydispose)(KEY)=0, void (*valdispose)(VAL)=0)
21 {
22 m_keycmp = keycmp;
23 m_keydup = keydup;
24 m_keydispose = keydispose;
25 m_valdispose = valdispose;
26 }
27
29 {
30 DeleteAll();
31 }
32
33 VAL* GetPtr(KEY key, KEY *keyPtrOut=NULL) const
34 {
35 bool ismatch = false;
36 int i = LowerBound(key, &ismatch);
37 if (ismatch)
38 {
39 KeyVal* kv = m_data.Get()+i;
40 if (keyPtrOut) *keyPtrOut = kv->key;
41 return &(kv->val);
42 }
43 return 0;
44 }
45
46 bool Exists(KEY key) const
47 {
48 bool ismatch = false;
49 LowerBound(key, &ismatch);
50 return ismatch;
51 }
52
53 int Insert(KEY key, VAL val)
54 {
55 bool ismatch = false;
56 int i = LowerBound(key, &ismatch);
57 if (ismatch)
58 {
59 KeyVal* kv = m_data.Get()+i;
61 kv->val = val;
62 }
63 else
64 {
65 KeyVal* kv = m_data.Resize(m_data.GetSize()+1)+i;
66 memmove(kv+1, kv, (m_data.GetSize()-i-1)*(unsigned int)sizeof(KeyVal));
67 if (m_keydup) key = m_keydup(key);
68 kv->key = key;
69 kv->val = val;
70 }
71 return i;
72 }
73
74 void Delete(KEY key)
75 {
76 bool ismatch = false;
77 int i = LowerBound(key, &ismatch);
78 if (ismatch)
79 {
80 KeyVal* kv = m_data.Get()+i;
83 m_data.Delete(i);
84 }
85 }
86
87 void DeleteByIndex(int idx)
88 {
89 if (idx >= 0 && idx < m_data.GetSize())
90 {
91 KeyVal* kv = m_data.Get()+idx;
94 m_data.Delete(idx);
95 }
96 }
97
98 void DeleteAll(bool resizedown=false)
99 {
101 {
102 int i;
103 for (i = 0; i < m_data.GetSize(); ++i)
104 {
105 KeyVal* kv = m_data.Get()+i;
106 if (m_keydispose) m_keydispose(kv->key);
107 if (m_valdispose) m_valdispose(kv->val);
108 }
109 }
110 m_data.Resize(0, resizedown);
111 }
112
113 int GetSize() const
114 {
115 return m_data.GetSize();
116 }
117
118 VAL* EnumeratePtr(int i, KEY* key=0) const
119 {
120 if (i >= 0 && i < m_data.GetSize())
121 {
122 KeyVal* kv = m_data.Get()+i;
123 if (key) *key = kv->key;
124 return &(kv->val);
125 }
126 return 0;
127 }
128
129 KEY* ReverseLookupPtr(VAL val) const
130 {
131 int i;
132 for (i = 0; i < m_data.GetSize(); ++i)
133 {
134 KeyVal* kv = m_data.Get()+i;
135 if (kv->val == val) return &kv->key;
136 }
137 return 0;
138 }
139
140 void ChangeKey(KEY oldkey, KEY newkey)
141 {
142 bool ismatch=false;
143 int i=LowerBound(oldkey, &ismatch);
144 if (ismatch) ChangeKeyByIndex(i, newkey, true);
145 }
146
147 void ChangeKeyByIndex(int idx, KEY newkey, bool needsort)
148 {
149 if (idx >= 0 && idx < m_data.GetSize())
150 {
151 KeyVal* kv=m_data.Get()+idx;
152 if (!needsort)
153 {
154 if (m_keydispose) m_keydispose(kv->key);
155 if (m_keydup) newkey=m_keydup(newkey);
156 kv->key=newkey;
157 }
158 else
159 {
160 VAL val=kv->val;
161 m_data.Delete(idx);
162 Insert(newkey, val);
163 }
164 }
165 }
166
167 // fast add-block mode
168 void AddUnsorted(KEY key, VAL val)
169 {
170 int i=m_data.GetSize();
171 KeyVal* kv = m_data.Resize(i+1)+i;
172 if (m_keydup) key = m_keydup(key);
173 kv->key = key;
174 kv->val = val;
175 }
176
177 void Resort(int (*new_keycmp)(KEY *k1, KEY *k2)=NULL)
178 {
179 if (new_keycmp) m_keycmp = new_keycmp;
180 if (m_data.GetSize() > 1 && m_keycmp)
181 {
182 qsort(m_data.Get(), m_data.GetSize(), sizeof(KeyVal),
183 (int(*)(const void*, const void*))m_keycmp);
184 if (!new_keycmp)
186 }
187 }
188
190 {
191 if (m_data.GetSize() > 1 && m_keycmp)
192 {
193 char *tmp=(char*)malloc(m_data.GetSize()*sizeof(KeyVal));
194 if (WDL_NORMALLY(tmp))
195 {
196 WDL_mergesort(m_data.Get(), m_data.GetSize(), sizeof(KeyVal),
197 (int(*)(const void*, const void*))m_keycmp, tmp);
198 free(tmp);
199 }
200 else
201 {
202 qsort(m_data.Get(), m_data.GetSize(), sizeof(KeyVal),
203 (int(*)(const void*, const void*))m_keycmp);
204 }
205
207 }
208 }
209
210 int LowerBound(KEY key, bool* ismatch) const
211 {
212 int a = 0;
213 int c = m_data.GetSize();
214 while (a != c)
215 {
216 int b = (a+c)/2;
217 KeyVal* kv=m_data.Get()+b;
218 int cmp = m_keycmp(&key, &kv->key);
219 if (cmp > 0) a = b+1;
220 else if (cmp < 0) c = b;
221 else
222 {
223 *ismatch = true;
224 return b;
225 }
226 }
227 *ismatch = false;
228 return a;
229 }
230
231 int GetIdx(KEY key) const
232 {
233 bool ismatch=false;
234 int i = LowerBound(key, &ismatch);
235 if (ismatch) return i;
236 return -1;
237 }
238
239 void SetGranul(int gran)
240 {
241 m_data.SetGranul(gran);
242 }
243
245 {
246 m_data=cp.m_data;
247 m_keycmp = cp.m_keycmp;
248 m_keydup = cp.m_keydup;
249 m_keydispose = m_keydup ? cp.m_keydispose : NULL;
250 m_valdispose = NULL; // avoid disposing of values twice, since we don't have a valdup, we can't have a fully valid copy
251 if (m_keydup)
252 {
253 int x;
254 const int n=m_data.GetSize();
255 for (x=0;x<n;x++)
256 {
257 KeyVal *kv=m_data.Get()+x;
258 if (kv->key) kv->key = m_keydup(kv->key);
259 }
260 }
261 }
262
264 {
265 DeleteAll(true);
266 m_keycmp = cp.m_keycmp;
267 m_keydup = NULL; // this no longer can own any data
270
271 m_data=cp.m_data;
272 }
273
274
275// private data, but exposed in case the caller wants to manipulate at its own risk
276 struct KeyVal
277 {
278 KEY key;
279 VAL val;
280 };
282
283protected:
284
285 int (*m_keycmp)(KEY *k1, KEY *k2);
286 KEY (*m_keydup)(KEY);
289
290private:
291
292 void RemoveDuplicateKeys() // after resorting
293 {
294 const int sz = m_data.GetSize();
295
296 int cnt = 1;
297 KeyVal *rd = m_data.Get() + 1, *wr = rd;
298 for (int x = 1; x < sz; x ++)
299 {
300 if (m_keycmp(&rd->key, &wr[-1].key))
301 {
302 if (rd != wr) *wr=*rd;
303 wr++;
304 cnt++;
305 }
306 else
307 {
308 if (m_keydispose) m_keydispose(rd->key);
309 if (m_valdispose) m_valdispose(rd->val);
310 }
311 rd++;
312 }
313 if (cnt < sz) m_data.Resize(cnt,false);
314 }
315};
316
317
318// WDL_AssocArray adds useful functions but cannot contain structs for keys or values
319template <class KEY, class VAL> class WDL_AssocArray : public WDL_AssocArrayImpl<KEY, VAL>
320{
321public:
322
323 explicit WDL_AssocArray(int (*keycmp)(KEY *k1, KEY *k2), KEY (*keydup)(KEY)=0, void (*keydispose)(KEY)=0, void (*valdispose)(VAL)=0)
324 : WDL_AssocArrayImpl<KEY, VAL>(keycmp, keydup, keydispose, valdispose)
325 {
326 }
327
328 VAL Get(KEY key, VAL notfound=0) const
329 {
330 VAL* p = this->GetPtr(key);
331 if (p) return *p;
332 return notfound;
333 }
334
335 VAL Enumerate(int i, KEY* key=0, VAL notfound=0) const
336 {
337 VAL* p = this->EnumeratePtr(i, key);
338 if (p) return *p;
339 return notfound;
340 }
341
342 KEY ReverseLookup(VAL val, KEY notfound=0) const
343 {
344 KEY* p=this->ReverseLookupPtr(val);
345 if (p) return *p;
346 return notfound;
347 }
348};
349
350
351template <class VAL> class WDL_IntKeyedArray : public WDL_AssocArray<int, VAL>
352{
353public:
354
355 explicit WDL_IntKeyedArray(void (*valdispose)(VAL)=0) : WDL_AssocArray<int, VAL>(cmpint, NULL, NULL, valdispose) {}
357
358private:
359
360 static int cmpint(int *i1, int *i2) { return *i1-*i2; }
361};
362
363template <class VAL> class WDL_IntKeyedArray2 : public WDL_AssocArrayImpl<int, VAL>
364{
365public:
366
367 explicit WDL_IntKeyedArray2(void (*valdispose)(VAL)=0) : WDL_AssocArrayImpl<int, VAL>(cmpint, NULL, NULL, valdispose) {}
369
370private:
371
372 static int cmpint(int *i1, int *i2) { return *i1-*i2; }
373};
374
375template <class VAL> class WDL_StringKeyedArray : public WDL_AssocArray<const char *, VAL>
376{
377public:
378
379 explicit WDL_StringKeyedArray(bool caseSensitive=true, void (*valdispose)(VAL)=0) : WDL_AssocArray<const char*, VAL>(caseSensitive?cmpstr:cmpistr, dupstr, freestr, valdispose) {}
380
382
383 static const char *dupstr(const char *s) { return strdup(s); } // these might not be necessary but depending on the libc maybe...
384 static int cmpstr(const char **s1, const char **s2) { return strcmp(*s1, *s2); }
385 static int cmpistr(const char **a, const char **b) { return stricmp(*a,*b); }
386 static void freestr(const char* s) { free((void*)s); }
387 static void freecharptr(char *p) { free(p); }
388};
389
390
391template <class VAL> class WDL_StringKeyedArray2 : public WDL_AssocArrayImpl<const char *, VAL>
392{
393public:
394
395 explicit WDL_StringKeyedArray2(bool caseSensitive=true, void (*valdispose)(VAL)=0) : WDL_AssocArrayImpl<const char*, VAL>(caseSensitive?cmpstr:cmpistr, dupstr, freestr, valdispose) {}
396
398
399 static const char *dupstr(const char *s) { return strdup(s); } // these might not be necessary but depending on the libc maybe...
400 static int cmpstr(const char **s1, const char **s2) { return strcmp(*s1, *s2); }
401 static int cmpistr(const char **a, const char **b) { return stricmp(*a,*b); }
402 static void freestr(const char* s) { free((void*)s); }
403 static void freecharptr(char *p) { free(p); }
404};
405
406// sorts text as text, sorts anything that looks like a number as a number
407template <class VAL> class WDL_LogicalSortStringKeyedArray : public WDL_StringKeyedArray<VAL>
408{
409public:
410
411 explicit WDL_LogicalSortStringKeyedArray(bool caseSensitive=true, void (*valdispose)(VAL)=0) : WDL_StringKeyedArray<VAL>(caseSensitive, valdispose)
412 {
413 WDL_StringKeyedArray<VAL>::m_keycmp = caseSensitive?cmpstr:cmpistr; // override
414 }
415
417
418 static int cmpstr(const char **a, const char **b) { return _cmpstr(*a, *b, true); }
419 static int cmpistr(const char **a, const char **b) { return _cmpstr(*a, *b, false); }
420
421private:
422
423 static int _cmpstr(const char *s1, const char *s2, bool case_sensitive)
424 {
425 // this also exists as WDL_strcmp_logical in wdlcstring.h
426
427 for (;;)
428 {
429 if (*s1 >= '0' && *s1 <= '9' && *s2 >= '0' && *s2 <= '9')
430 {
431 int lzdiff=0, len1=0, len2=0;
432
433 while (*s1 == '0') { s1++; lzdiff--; }
434 while (*s2 == '0') { s2++; lzdiff++; }
435
436 while (s1[len1] >= '0' && s1[len1] <= '9') len1++;
437 while (s2[len2] >= '0' && s2[len2] <= '9') len2++;
438
439 if (len1 != len2) return len1-len2;
440
441 while (len1--)
442 {
443 const int d = *s1++ - *s2++;
444 if (d) return d;
445 }
446
447 if (lzdiff) return lzdiff;
448 }
449 else
450 {
451 char c1 = *s1++, c2 = *s2++;
452 if (c1 != c2)
453 {
454 if (case_sensitive) return c1-c2;
455
456 if (c1>='a' && c1<='z') c1+='A'-'a';
457 if (c2>='a' && c2<='z') c2+='A'-'a';
458 if (c1 != c2) return c1-c2;
459 }
460 else if (!c1) return 0;
461 }
462 }
463 }
464};
465
466
467template <class VAL> class WDL_PtrKeyedArray : public WDL_AssocArray<INT_PTR, VAL>
468{
469public:
470
471 explicit WDL_PtrKeyedArray(void (*valdispose)(VAL)=0) : WDL_AssocArray<INT_PTR, VAL>(cmpptr, 0, 0, valdispose) {}
472
474
475private:
476
477 static int cmpptr(INT_PTR* a, INT_PTR* b) { const INT_PTR d = *a - *b; return d<0?-1:(d!=0); }
478};
479
480
481#endif
482
#define NULL
Definition CarlaBridgeFormat.cpp:30
uint8_t a
Definition Spc_Cpu.h:141
VAL Enumerate(int i, KEY *key=0, VAL notfound=0) const
Definition assocarray.h:335
VAL Get(KEY key, VAL notfound=0) const
Definition assocarray.h:328
WDL_AssocArray(int(*keycmp)(KEY *k1, KEY *k2), KEY(*keydup)(KEY)=0, void(*keydispose)(KEY)=0, void(*valdispose)(VAL)=0)
Definition assocarray.h:323
KEY ReverseLookup(VAL val, KEY notfound=0) const
Definition assocarray.h:342
~WDL_AssocArrayImpl()
Definition assocarray.h:28
KEY * ReverseLookupPtr(VAL val) const
Definition assocarray.h:129
void(* m_valdispose)(VAL)
Definition assocarray.h:288
void AddUnsorted(KEY key, VAL val)
Definition assocarray.h:168
void CopyContents(const WDL_AssocArrayImpl &cp)
Definition assocarray.h:244
int(* m_keycmp)(KEY *k1, KEY *k2)
Definition assocarray.h:285
void ChangeKeyByIndex(int idx, KEY newkey, bool needsort)
Definition assocarray.h:147
WDL_AssocArrayImpl(int(*keycmp)(KEY *k1, KEY *k2), KEY(*keydup)(KEY)=0, void(*keydispose)(KEY)=0, void(*valdispose)(VAL)=0)
Definition assocarray.h:20
int GetSize() const
Definition assocarray.h:113
VAL * GetPtr(KEY key, KEY *keyPtrOut=NULL) const
Definition assocarray.h:33
void ChangeKey(KEY oldkey, KEY newkey)
Definition assocarray.h:140
int GetIdx(KEY key) const
Definition assocarray.h:231
WDL_AssocArrayImpl(const WDL_AssocArrayImpl &cp)
Definition assocarray.h:14
void DeleteByIndex(int idx)
Definition assocarray.h:87
KEY(* m_keydup)(KEY)
Definition assocarray.h:286
void Resort(int(*new_keycmp)(KEY *k1, KEY *k2)=NULL)
Definition assocarray.h:177
WDL_TypedBuf< KeyVal > m_data
Definition assocarray.h:281
void(* m_keydispose)(KEY)
Definition assocarray.h:287
WDL_AssocArrayImpl & operator=(const WDL_AssocArrayImpl &cp)
Definition assocarray.h:16
void CopyContentsAsReference(const WDL_AssocArrayImpl &cp)
Definition assocarray.h:263
int LowerBound(KEY key, bool *ismatch) const
Definition assocarray.h:210
void ResortStable()
Definition assocarray.h:189
void RemoveDuplicateKeys()
Definition assocarray.h:292
bool Exists(KEY key) const
Definition assocarray.h:46
void DeleteAll(bool resizedown=false)
Definition assocarray.h:98
void Delete(KEY key)
Definition assocarray.h:74
int Insert(KEY key, VAL val)
Definition assocarray.h:53
VAL * EnumeratePtr(int i, KEY *key=0) const
Definition assocarray.h:118
void SetGranul(int gran)
Definition assocarray.h:239
static int cmpint(int *i1, int *i2)
Definition assocarray.h:372
WDL_IntKeyedArray2(void(*valdispose)(VAL)=0)
Definition assocarray.h:367
~WDL_IntKeyedArray2()
Definition assocarray.h:368
static int cmpint(int *i1, int *i2)
Definition assocarray.h:360
~WDL_IntKeyedArray()
Definition assocarray.h:356
WDL_IntKeyedArray(void(*valdispose)(VAL)=0)
Definition assocarray.h:355
static int _cmpstr(const char *s1, const char *s2, bool case_sensitive)
Definition assocarray.h:423
WDL_LogicalSortStringKeyedArray(bool caseSensitive=true, void(*valdispose)(VAL)=0)
Definition assocarray.h:411
static int cmpistr(const char **a, const char **b)
Definition assocarray.h:419
static int cmpstr(const char **a, const char **b)
Definition assocarray.h:418
~WDL_LogicalSortStringKeyedArray()
Definition assocarray.h:416
static int cmpptr(INT_PTR *a, INT_PTR *b)
Definition assocarray.h:477
WDL_PtrKeyedArray(void(*valdispose)(VAL)=0)
Definition assocarray.h:471
~WDL_PtrKeyedArray()
Definition assocarray.h:473
static int cmpstr(const char **s1, const char **s2)
Definition assocarray.h:400
static int cmpistr(const char **a, const char **b)
Definition assocarray.h:401
static const char * dupstr(const char *s)
Definition assocarray.h:399
~WDL_StringKeyedArray2()
Definition assocarray.h:397
WDL_StringKeyedArray2(bool caseSensitive=true, void(*valdispose)(VAL)=0)
Definition assocarray.h:395
static void freestr(const char *s)
Definition assocarray.h:402
static void freecharptr(char *p)
Definition assocarray.h:403
static void freecharptr(char *p)
Definition assocarray.h:387
~WDL_StringKeyedArray()
Definition assocarray.h:381
WDL_StringKeyedArray(bool caseSensitive=true, void(*valdispose)(VAL)=0)
Definition assocarray.h:379
static int cmpistr(const char **a, const char **b)
Definition assocarray.h:385
static int cmpstr(const char **s1, const char **s2)
Definition assocarray.h:384
static void freestr(const char *s)
Definition assocarray.h:386
static const char * dupstr(const char *s)
Definition assocarray.h:383
Definition heapbuf.h:259
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
static void c2(register WDL_FFT_COMPLEX *a)
Definition fft.c:270
int val
Definition jpeglib.h:956
static void WDL_STATICFUNC_UNUSED WDL_mergesort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *), char *tmpspace)
Definition mergesort.h:6
Definition assocarray.h:277
KEY key
Definition assocarray.h:278
VAL val
Definition assocarray.h:279
#define stricmp(x, y)
Definition swell-types.h:68
intptr_t INT_PTR
Definition swell-types.h:42
int n
Definition crypt.c:458
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
ZCONST char * key
Definition crypt.c:587
b
Definition crypt.c:628
char * cp
Definition unix.c:513
typedef int(UZ_EXP MsgFn)()
#define void
Definition unzip.h:396
char * malloc()
#define WDL_NORMALLY(x)
Definition wdltypes.h:165
#define const
Definition zconf.h:137