-
Notifications
You must be signed in to change notification settings - Fork 0
/
containers.h
562 lines (539 loc) · 21.3 KB
/
containers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
#ifndef CONTAINERS_H_INCLUDED
#define CONTAINERS_H_INCLUDED
/* set of generic and type safe containers written in ANSI C
* can be compiled in to modes:
* default: fast
* with -DDEBUG: includes lots of checkings for easing debug
* c 2014, Haroldo Gambini Santos - haroldo@iceb.ufop.br */
#include <limits.h>
#include "macros.h"
typedef struct
{
int a;
int b;
} IntPair;
#define NOT_FOUND INT_MAX
/* to be used in qsort */
int intcmp_func( const void *p1, const void *p2 );
/* set of integers */
typedef struct _ISet ISet;
ISet *iset_create( int hashSize );
void iset_ini( ISet *iset, int hashSize );
void iset_cpy( ISet *target, const ISet *source );
void iset_add( ISet *set, int value );
void iset_remove( ISet *set, int value );
void iset_remove_set( ISet *set, const ISet *toRemove );
void iset_clear( ISet *set );
char iset_has( const ISet *set, int value );
int iset_n_elements( const ISet *set );
int iset_element( const ISet *set, int idx );
char iset_equals( const ISet *set1, const ISet *set2 );
void iset_clear_mem( ISet *iset );
void iset_free( ISet **_iset );
/* one dimensional vector */
#define DECLARE_VECTOR_TYPE(type) \
typedef struct _##Vec_##type{ \
type *array; \
int size; \
int capacity; \
} Vec_##type; \
Vec_##type *vec_##type##_create( ); \
Vec_##type *vec_##type##_create_cap( const int iniCap ); \
Vec_##type *vec_##type##_create_fill( const int size, const type value ); \
int vec_##type##_size( const Vec_##type *vec ); \
char vec_##type##_equals( const Vec_##type *vec1, const Vec_##type *vec2 ); \
int vec_##type##_capacity( const Vec_##type *vec ); \
void vec_##type##_clear( Vec_##type *vec ); \
void vec_##type##_free( Vec_##type **vec ); \
void vec_##type##_push_back( Vec_##type *vec, const type value ); \
void vec_##type##_push_back_v( Vec_##type *vec, int n, const type v[] ); \
type vec_##type##_pop_back( Vec_##type *vec ); \
/* sets a value into an existing position */\
void vec_##type##_set( Vec_##type *vec, const int pos, const type value ); \
void vec_##type##_swap( Vec_##type *vec, const int pos1, const int pos2 ); \
/* sets a value into a position, if this position does not exists, creates */\
void vec_##type##_fset( Vec_##type *vec, const int pos, const type value ); \
type vec_##type##_first( const Vec_##type *vec ); \
type vec_##type##_last( const Vec_##type *vec ); \
type vec_##type##_get( const Vec_##type *vec, const int pos ); \
/* returns a pointer to a element */ \
type *vec_##type##_getp( Vec_##type *vec, const int pos ); \
/* returns a pointer to the vector */ \
type *vec_##type##_ptr( const Vec_##type *vec ); \
void vec_##type##_cpy( Vec_##type *vecTarget, const Vec_##type *vecSource ); \
void vec_##type##_resize( Vec_##type *vec, const int size, const type valueNewElements ); \
int vec_##type##_find( const Vec_##type *vec, const type value ); \
/* removes element with value, changes the order of the vector since the last element will go to the position of the removed element */ \
void vec_##type##_remove(Vec_##type *vec, const type value ); \
void vec_##type##_remove_positions( Vec_##type *vec, int nPos, const int positions[] ); \
void vec_##type##_insert_unique( Vec_##type *vec, const type value );
/* dictionary which maps strings to another type */
#define DECLARE_DICT_TYPE(type) \
typedef struct { \
char str[STR_SIZE]; \
type value; \
int keyPos; /* in keys vector */ \
} Dict_Bucket_##type; \
typedef struct { \
Dict_Bucket_##type **cont; \
int *rowSize; \
int *rowCap; \
type defValue; \
unsigned int hashSize; \
StrV *keys; \
} Dict_##type; \
Dict_##type *dict_##type##_create( unsigned int hashSize, type defaultValue ); \
void dict_##type##_set( Dict_##type *dict, const char *key, const type value ); \
void dict_##type##_iset( Dict_##type *dict, const int key, const type value ); \
void dict_##type##_remove( Dict_##type *dict, const char *key ); \
void dict_##type##_iremove( Dict_##type *dict, int key ); \
type dict_##type##_get( const Dict_##type *dict, const char *str ); \
int dict_##type##_size( const Dict_##type *dict ); \
const char *dict_##type##_key( const Dict_##type *dict, int pos ); \
int dict_##type##_ikey( const Dict_##type *dict, int pos ); \
type dict_##type##_iget( const Dict_##type *dict, const int key ); \
void dict_##type##_clear( Dict_##type *dict ); \
void dict_##type##_cpy( Dict_##type *target, const Dict_##type *source ); \
void dict_##type##_free( Dict_##type **dict );
/* string vector */
typedef struct _StrV StrV;
StrV *strv_create( int strSize );
void strv_resize( StrV *strv, int newSize );
void strv_push_back( StrV *strv, const char *str );
void strv_add_lines( StrV *strv, const StrV *lines );
const char *strv_get( const StrV *strv, int pos );
void strv_set( StrV *strv, int pos, const char *str );
char **strv_ptr( StrV *strv );
int strv_size( const StrV *strv );
void strv_clear( StrV *strv );
int strv_find( const StrV *strv, const char *str );
int strv_find_substr( const StrV *strv, const char *str );
void strv_read_from( StrV *strv, const char *fileName, const char ignoreEmptyLines );
void strv_write_to( StrV *strv, const char *fileName );
void strv_free( StrV **strv );
/* put here all types of vectors you will need */
DECLARE_DICT_TYPE(int)
DECLARE_VECTOR_TYPE(int)
DECLARE_VECTOR_TYPE(char)
DECLARE_VECTOR_TYPE(float)
DECLARE_VECTOR_TYPE(double)
DECLARE_VECTOR_TYPE(IntPair)
/* shuffles a vector of integers, using a vector of intpairs as auxiliary structure */
void vec_int_shuffle( Vec_int *vint, Vec_IntPair *vpair );
/* sorts a vector of int pair by its second field */
void vec_IntPair_sort( Vec_IntPair *vip );
/* two dimensional vector of integers */
typedef Vec_int* Vec_intp;
typedef Vec_IntPair *Vec_IntPairp;
DECLARE_VECTOR_TYPE(Vec_IntPairp)
DECLARE_VECTOR_TYPE(Vec_intp)
typedef Vec_Vec_intp V2D_int;
V2D_int *v2d_create( const int rows );
int v2d_size( const V2D_int *v2d );
void v2d_resize( V2D_int *v2d, const int rows );
void v2d_int_row_push_back( V2D_int *v2d, int row, int value );
void v2d_int_row_insert_unique( V2D_int *v2d, int row, int value );
void v2d_int_row_clear( V2D_int *v2d, int row );
int v2d_int_row_size( const V2D_int *v2d, int row );
int v2d_int_row_get( const V2D_int *v2d, int row, int col );
int *v2d_int_row_ptr( V2D_int *v2d, int row );
char v2d_int_equals( const V2D_int *v2d1, const V2D_int *v2d2 );
void v2d_cpy( V2D_int *target, const V2D_int *source );
void v2d_free( V2D_int **v2di );
DECLARE_DICT_TYPE( Vec_intp )
#define DEF_INI_CAP 64
#ifdef DEBUG
#define CHECK_NULL_VEC( v ) \
if ( v==NULL ) { \
fprintf( stderr, "ERROR: NULL passed as vector in %s:%d\n", __FILE__, __LINE__ ); \
abort(); \
}
#else
#define CHECK_NULL_VEC( v ) ;
#endif
#define IMPLEMENT_VECTOR_TYPE(type) \
Vec_##type *vec_##type##_create( ) { \
return vec_##type##_create_cap( DEF_INI_CAP ); \
} \
Vec_##type *vec_##type##_create_cap( const int iniCap ) { \
Vec_##type *vec = (Vec_##type *) malloc( sizeof(Vec_##type) ); \
if (!vec) { \
fprintf( stderr, "ERROR: out of memory.\n" ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); \
} \
vec->capacity = iniCap; \
vec->size = 0; \
vec->array = (type*) malloc( sizeof(type)*vec->capacity ); \
if (!vec->array) { \
fprintf( stderr, "ERROR: out of memory.\n" ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); \
} \
return vec; \
} \
Vec_##type *vec_##type##_create_fill( const int size, const type value ) { \
Vec_##type *vec = vec_##type##_create_cap( size ); \
int i; \
for ( i=0 ; (i<size) ; ++i ) \
vec->array[i] = value; \
vec->size = size; \
return vec; \
} \
void vec_##type##_clear( Vec_##type *vec ) { \
CHECK_NULL_VEC( vec ); \
vec->size = 0; \
} \
void vec_##type##_free(Vec_##type **vec) { \
free( (*vec)->array ); \
free( *vec ); \
*vec = NULL; \
} \
void vec_##type##_push_back( Vec_##type *vec, const type value ) { \
if ( vec->size == vec->capacity ) { \
vec->capacity *= 2; \
type *p =(type *) realloc( vec->array, sizeof(type)*vec->capacity ); \
if (!p) { \
fprintf( stderr, "ERROR: out of memory.\n" ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); \
} \
vec->array = p; \
} \
vec->array[vec->size] = value; \
vec->size++; \
} \
void vec_##type##_push_back_v( Vec_##type *vec, int n, const type v[] ) { \
if ( vec->size+n > vec->capacity ) { \
vec->capacity = MAX( vec->capacity*2, vec->size+n+8 ); \
type *p =(type *) realloc( vec->array, sizeof(type)*vec->capacity ); \
if (!p) { \
fprintf( stderr, "ERROR: out of memory.\n" ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); \
} \
vec->array = p; \
} \
memcpy( vec->array+vec->size, v, sizeof(type)*n ); \
vec->size += n; \
} \
type vec_##type##_pop_back( Vec_##type *vec ) { \
if (vec->size==0) { \
fprintf( stderr, "ERROR: vec_type_pop_back - trying to remove element from empty vector.\n" ); \
abort(); \
} \
vec->size--; \
return vec->array[vec->size]; \
} \
void vec_##type##_set( Vec_##type *vec, const int pos, const type value) { \
if ( (pos>=vec->size) || (pos<0) ) { \
fprintf(stderr, "ERROR: accessing array out of bounds at Vec_##type##_set.\n"); \
fprintf(stderr, "\tpos: %d array size: %d array capacity: %d\n", pos, vec->size, vec->capacity ); \
abort(); \
} \
vec->array[pos] = value; \
} \
void vec_##type##_swap( Vec_##type *vec, const int pos1, const int pos2 ) { \
if ( (pos1>=vec->size) || (pos1<0) ) { \
fprintf(stderr, "ERROR: accessing array out of bounds at Vec_##type##_swap.\n"); \
fprintf(stderr, "\tpos1: %d array size: %d array capacity: %d\n", pos1, vec->size, vec->capacity ); \
abort(); \
} \
if ( (pos2>=vec->size) || (pos2<0) ) { \
fprintf(stderr, "ERROR: accessing array out of bounds at Vec_##type##_swap.\n"); \
fprintf(stderr, "\tpos2: %d array size: %d array capacity: %d\n", pos2, vec->size, vec->capacity ); \
abort(); \
} \
type aux = vec->array[pos1]; \
vec->array[pos1] = vec->array[pos2]; \
vec->array[pos2] = aux; \
}; \
/* resizes without filling new elements */ \
void vec_##type##_resize_nf( Vec_##type *vec, const int size ) { \
if ( vec->capacity>=size ) { \
vec->size = size; \
return; \
} \
const int oldSize = vec->size; \
vec->size = vec->capacity = size; \
type *p = (type*) realloc( vec->array, sizeof(type)*vec->capacity ); \
if (!p) { \
fprintf( stderr, "ERROR: out of memory resizing vector from %d to %d elements.\n", oldSize, size ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); exit( EXIT_FAILURE ); \
} \
vec->array = p; \
}\
void vec_##type##_fset( Vec_##type *vec, const int pos, const type value ) { \
if ( pos<0 ) { \
fprintf(stderr, "ERROR: accessing array out of bounds at Vec_##type##_set.\n"); \
fprintf(stderr, "\tpos: %d array size: %d array capacity: %d\n", pos, vec->size, vec->capacity ); \
abort(); \
} \
if ( pos >= vec->capacity ) { \
vec->capacity = MAX( 2*vec->capacity, pos+1 ); \
type *p =(type *) realloc( vec->array, sizeof(type)*vec->capacity ); \
if (!p) { \
fprintf( stderr, "ERROR: out of memory.\n" ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); \
} \
vec->array = p; \
} \
vec->array[pos] = value; \
vec->size = MAX( vec->size, pos+1 ); \
} \
type vec_##type##_first( const Vec_##type *vec ) { \
assert( vec->size ); return vec->array[0]; \
} \
type vec_##type##_last( const Vec_##type *vec ) { \
assert( vec->size ); return vec->array[vec->size-1]; \
} \
type vec_##type##_get( const Vec_##type *vec, const int pos ) { \
if ( (pos>=vec->size) || (pos<0) ) { \
fprintf(stderr, "ERROR: accessing array out of bounds at Vec_##type##_get.\n"); \
fprintf(stderr, "\tpos: %d array size: %d array capacity: %d\n", pos, vec->size, vec->capacity ); \
abort(); \
} \
return vec->array[pos]; \
} \
type *vec_##type##_getp( Vec_##type *vec, const int pos ) { \
if ( (pos>=vec->size) || (pos<0) ) { \
fprintf(stderr, "ERROR: accessing array out of bounds at Vec_##type##_getp.\n"); \
fprintf(stderr, "\tpos: %d array size: %d array capacity: %d\n", pos, vec->size, vec->capacity ); \
abort(); \
} \
return &(vec->array[pos]); \
} \
void vec_##type##_cpy( Vec_##type *vecTarget, const Vec_##type *vecSource ) { \
if ( vecTarget->capacity < vecSource->size ) { \
vecTarget->capacity = vecSource->size; \
type *p = (type *)realloc( vecTarget->array, sizeof(type)*vecTarget->capacity ); \
if (!p) { \
fprintf( stderr, "ERROR: out of memory.\n" ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); \
} \
vecTarget->array = p; \
} \
vecTarget->size = vecSource->size; \
memcpy( vecTarget->array, vecSource->array, vecSource->size*sizeof(type) ); \
} \
int vec_##type##_size( const Vec_##type *vec ) { \
return vec->size; \
} \
char vec_##type##_equals( const Vec_##type *vec1, const Vec_##type *vec2 ) { \
if ( vec_##type##_size(vec1) != vec_##type##_size(vec2) ) return 0; \
int i; const int sz = vec_##type##_size(vec1); \
for ( i=0 ; (i<sz) ; ++i ) \
if ( !EQUAL_##type( vec_##type##_get(vec1,i), vec_##type##_get(vec2,i) ) ) \
return 0; \
return 1; \
}\
int vec_##type##_capacity( const Vec_##type *vec ) { \
return vec->capacity; \
} \
type *vec_##type##_ptr( const Vec_##type *vec ) { \
return vec->array; \
}\
void vec_##type##_resize( Vec_##type *vec, const int size, const type valueNewElements ) { \
if ( vec->capacity>=size ) { \
int i; \
for ( i=vec->size ; (i<size) ; ++i ) \
vec->array[i] = valueNewElements; \
vec->size = size; \
return; \
} \
const int oldSize = vec->size; \
vec->size = vec->capacity = size; \
type *p = (type *) realloc( vec->array, sizeof(type)*vec->capacity ); \
if (!p) { \
fprintf( stderr, "ERROR: out of memory resizing vector from %d to %d elements.\n", oldSize, size ); \
fprintf( stderr, "\t%s:%d\n", __FILE__, __LINE__ ); \
abort(); exit( EXIT_FAILURE ); \
} \
vec->array = p; \
int i; \
for ( i=oldSize ; (i<vec->size) ; i++ ) \
vec_##type##_set( vec, i, valueNewElements ); \
}\
int vec_##type##_find( const Vec_##type *vec, const type value ) { \
int i; \
for ( i=0 ; (i<vec_##type##_size(vec)) ; ++i ) \
if (EQUAL_##type( vec->array[i], value )) return i; \
return NOT_FOUND; \
} \
void vec_##type##_remove(Vec_##type *vec, const type value ) { \
int pos = vec_##type##_find( vec, value ); \
if ( pos == NOT_FOUND ) return; \
if ( pos == vec_##type##_size(vec)-1 ) { vec->size--; return; } \
vec_##type##_swap( vec, pos, vec_##type##_size(vec)-1 ); \
vec->size--; \
} \
void vec_##type##_remove_positions( Vec_##type *vec, int nPos, const int positions[] ) { \
assert( nPos <= vec->size && nPos >= 1 ); \
assert( vec!=NULL && positions!=NULL ); \
while ( (--nPos) >=0 ) { \
int p = positions[nPos]; \
assert( p>=0 && p<vec->size ); \
if ( nPos && p<=positions[nPos-1] ) { \
fprintf( stderr, "Positions should be informed in ascending order.\n" ); \
abort(); \
} \
if ( p == vec->size-1 ) \
vec->size--; \
else { \
vec_##type##_swap( vec, p, vec->size-1 ); \
vec->size--; \
} \
} \
} \
void vec_##type##_insert_unique( Vec_##type *vec, const type value ) { \
if (vec_##type##_find( vec, value )==NOT_FOUND) \
vec_##type##_push_back( vec, value ); \
}
#define IMPLEMENT_DICT_TYPE(type) \
Dict_##type *dict_##type##_create( unsigned int hashSize, type defaultValue ) \
{ \
Dict_##type *res; \
ALLOCATE( res, Dict_##type ); \
ALLOCATE_VECTOR_INI( res->cont, Dict_Bucket_##type *, hashSize ); \
ALLOCATE_VECTOR_INI( res->rowSize, int, hashSize ); \
ALLOCATE_VECTOR_INI( res->rowCap, int, hashSize ); \
res->defValue = defaultValue; \
res->keys = strv_create( STR_SIZE ); \
res->hashSize = hashSize; \
return res; \
} \
void dict_##type##_set( Dict_##type *dict, const char *key, const type value ) \
{ \
unsigned int hashPos = str_hash( key, dict->hashSize ); \
int i; \
char found = False; \
for ( i=0 ; (i<dict->rowSize[hashPos]) ; i++ ) { \
if ( strcmp( key, dict->cont[hashPos][i].str) == 0 ) { \
found = True; \
break; \
} \
} \
if (found) { \
dict->cont[hashPos][i].value = value; \
return; \
} \
if ( dict->rowSize[hashPos]+1 > dict->rowCap[hashPos] ) \
{ \
if (dict->rowSize[hashPos]==0) { \
ALLOCATE_VECTOR( dict->cont[hashPos], Dict_Bucket_##type, DEF_INI_CAP ); \
dict->rowCap[hashPos] = DEF_INI_CAP; \
} else { \
dict->rowCap[hashPos]*=2; \
Dict_Bucket_##type *bigger =(Dict_Bucket_##type *) realloc( dict->cont[hashPos], sizeof(Dict_Bucket_##type)*dict->rowCap[hashPos] ); \
if (!bigger) { \
fprintf( stderr, "ERROR: no more memory available" ); abort(); exit(EXIT_FAILURE); \
} \
dict->cont[hashPos] = bigger; \
} \
} \
strncpy( dict->cont[hashPos][dict->rowSize[hashPos]].str, key, STR_SIZE ); \
dict->cont[hashPos][dict->rowSize[hashPos]].value = value; \
dict->cont[hashPos][dict->rowSize[hashPos]].keyPos = strv_size( dict->keys ); \
dict->rowSize[hashPos]++; \
strv_push_back( dict->keys, key ); \
}\
void dict_##type##_remove( Dict_##type *dict, const char *key ) { \
/* finding bucket for key */ \
unsigned int hashPos = str_hash( key, dict->hashSize ); \
int i, pBucket = -1; \
Dict_Bucket_##type *bucket = NULL; \
for ( i=0 ; (i<dict->rowSize[hashPos]) ; i++ ) { \
if ( strcmp( key, dict->cont[hashPos][i].str) == 0 ) { \
pBucket = i; \
bucket = &dict->cont[hashPos][i]; \
break; \
} \
} \
/* if not found getting out */ \
if ( pBucket == -1 ) return; \
/* removing key from keys vector */ \
if ( bucket->keyPos != (strv_size(dict->keys)-1) ) { \
/* moving last key in str vector to pos */ \
const char *keyToUpdate = strv_get(dict->keys, strv_size(dict->keys)-1); \
strv_set( dict->keys, bucket->keyPos, keyToUpdate ); \
{ \
unsigned int hashPosK = str_hash( keyToUpdate, dict->hashSize ); \
Dict_Bucket_##type *bucketK = NULL; \
int ik; \
for ( ik=0 ; (ik<dict->rowSize[hashPosK]) ; ik++ ) { \
if ( strcmp( keyToUpdate, dict->cont[hashPosK][ik].str) == 0 ) { \
bucketK = dict->cont[hashPosK] + ik; \
break; \
} \
} \
assert( bucketK!=NULL ); \
bucketK->keyPos = bucket->keyPos; \
} \
} \
strv_resize( dict->keys, strv_size(dict->keys)-1 ); \
/* now updating row in hash matrix */ \
if ( pBucket != dict->rowSize[hashPos]-1 ) { \
dict->cont[hashPos][pBucket] = dict->cont[hashPos][dict->rowSize[hashPos]-1]; \
} \
dict->rowSize[hashPos]--; \
} \
void dict_##type##_iset( Dict_##type *dict, const int key, const type value ) { \
char str[32]; sprintf( str, "%d", key ); \
dict_##type##_set( dict, str, value ); \
} \
type dict_##type##_iget( const Dict_##type *dict, const int key ) { \
char str[32]; sprintf( str, "%d", key ); \
return dict_##type##_get( dict, str); \
} \
type dict_##type##_get( const Dict_##type *dict, const char *str ) \
{ \
unsigned int hashPos = str_hash( str, dict->hashSize ); \
int i; \
for ( i=0 ; (i<dict->rowSize[hashPos]) ; i++ ) { \
if ( strcmp( str, dict->cont[hashPos][i].str) == 0 ) { \
return dict->cont[hashPos][i].value; \
break; \
} \
} \
return dict->defValue; \
} \
void dict_##type##_iremove( Dict_##type *dict, int key ) { \
char strKey[STR_SIZE]; sprintf( strKey, "%d", key ); dict_##type##_remove(dict, strKey); \
} \
int dict_##type##_size( const Dict_##type *dict ) { \
return strv_size( dict->keys ); \
} \
const char *dict_##type##_key( const Dict_##type *dict, int pos ) { \
return strv_get( dict->keys, pos ); \
} \
int dict_##type##_ikey( const Dict_##type *dict, int pos ) { \
return atoi(strv_get(dict->keys, pos)); \
}\
void dict_##type##_clear( Dict_##type *dict ) { \
memset( dict->rowSize, 0, dict->hashSize*sizeof(int) ); \
strv_resize( dict->keys, 0 ); \
} \
void dict_##type##_cpy( Dict_##type *target, const Dict_##type *source ) { \
dict_##type##_clear( target ); \
int i; \
for ( i=0 ; (i<dict_##type##_size(source)) ; ++i ) \
dict_##type##_set( target, dict_##type##_key(source,i), dict_##type##_get(source, dict_##type##_key(source,i)) ); \
} \
void dict_##type##_free( Dict_##type **dict ) \
{ \
Dict_##type *d = *dict; \
unsigned int i; \
for (i=0;(i<d->hashSize);++i) \
if (d->rowCap[i]) \
free( d->cont[i] ); \
free( (*dict)->cont ); \
free( (*dict)->rowSize ); \
free( (*dict)->rowCap ); \
strv_free( &(*dict)->keys ); \
free( *dict ); \
}
void strv_sort( StrV *strv );
#endif