forked from maximuska/Freemap-waze
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroadmap_cyclic_array.c
400 lines (311 loc) · 10.9 KB
/
roadmap_cyclic_array.c
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
/* roadmap_cyclic_array.c
*
* LICENSE:
*
* Copyright 2008 PazO
*
* RoadMap is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License V2 as published by
* the Free Software Foundation.
*
* RoadMap is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RoadMap; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "roadmap_cyclic_array.h"
#define INVALID_INDEX (-1)
#define SHALLOW_COPY
//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
static int get_physical_index( cyclic_array_context_ptr this, int logical_index)
{
int physical_index;
if( (logical_index < 0) || (this->items_count <= logical_index))
return INVALID_INDEX;
physical_index = this->first_item + logical_index;
if( this->max_items_count <= physical_index)
physical_index -= this->max_items_count;
return physical_index;
}
static void* get_item_by_physical_index( cyclic_array_context_ptr this, int physical_index)
{
long pointer_base = (long)(this->items);
int pointer_offset = (physical_index * this->sizeof_item);
if( INVALID_INDEX == physical_index)
return NULL;
return (void*)(pointer_base + pointer_offset);
}
static void* get_item_by_logical_index( cyclic_array_context_ptr this, int logical_index)
{
int physical_index = get_physical_index( this, logical_index);
return get_item_by_physical_index( this, physical_index);
}
static BOOL insert_first_item( cyclic_array_context_ptr this, void* item)
{
if( !cyclic_array_is_empty(this))
return FALSE;
this->first_item = 0;
this->items_count = 1;
this->init_item( this->items);
this->copy_item( this->items, item);
return TRUE;
}
// ->>>>>
static void shift_one_item_up(cyclic_array_context_ptr this,
int range_begin,
int range_end)
{
int i;
assert(0 <= range_begin);
assert(range_end <= this->items_count);
assert(range_begin <= range_end);
// From: 6
// To: 9
// From: [8] [7] [6]
// To: [9] [8] [7]
for( i=range_end; range_begin<i; i--)
{
void* item_to = get_item_by_physical_index( this, i);
void* item_from = get_item_by_physical_index( this, i-1);
#ifdef SHALLOW_COPY
memcpy( item_to, item_from, this->sizeof_item);
#else
// Deep copy:
this->copy_item( item_to, item_from); // Alloc new
this->free_item( item_from); // Free old
#endif // SHALLOW_COPY
this->init_item( item_from);
}
}
// <<<<<-
static void shift_one_item_down( cyclic_array_context_ptr this,
int range_begin,
int range_end)
{
int i;
assert(0 <= range_begin);
assert(range_end <= this->items_count);
assert(range_begin <= range_end);
// From: 6
// To: 9
// From: [7] [8] [9]
// To: [6] [7] [8]
for( i=range_begin; i<range_end; i++)
{
void* item_to = get_item_by_physical_index( this, i);
void* item_from = get_item_by_physical_index( this, i+1);
#ifdef SHALLOW_COPY
memcpy( item_to, item_from, this->sizeof_item);
#else
// Deep copy:
this->copy_item( item_to, item_from); // Alloc new
this->free_item( item_from); // Free old
#endif // SHALLOW_COPY
this->init_item( item_from);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
void cyclic_array_init( cyclic_array_context_ptr this,
void* items_buffer,
int sizeof_item,
int max_items_count,
const char* module_name,
init_array_item init_item,
free_array_item free_item,
copy_array_item copy_item,
are_same_items items_are_same)
{
assert(this);
assert(items_buffer);
assert(sizeof_item);
assert(max_items_count);
assert(init_item);
assert(free_item);
assert(copy_item);
assert(items_are_same);
this->sizeof_item = sizeof_item;
this->max_items_count= max_items_count;
this->first_item = INVALID_INDEX;
this->items_count = 0;
this->init_item = init_item;
this->free_item = free_item;
this->copy_item = copy_item;
this->items_are_same = items_are_same;
this->items = items_buffer;
if( module_name)
this->module_name = module_name;
else
this->module_name = "";
}
void cyclic_array_free( cyclic_array_context_ptr this)
{
int logical_index;
for( logical_index=0; logical_index<cyclic_array_size(this); logical_index++)
{
void* item = get_item_by_logical_index( this, logical_index);
this->free_item( item);
this->init_item( item);
}
this->first_item = INVALID_INDEX;
this->items_count = 0;
}
BOOL cyclic_array_push_first( cyclic_array_context_ptr this, void* item)
{
void* array_item;
if( cyclic_array_is_full(this))
{
roadmap_log( ROADMAP_WARNING, "cyclic_array_push_first(%s) - Array is full", this->module_name);
return FALSE;
}
if( cyclic_array_is_empty(this))
return insert_first_item( this, item);
if(this->first_item)
this->first_item--;
else
this->first_item = (this->max_items_count - 1);
this->items_count++;
array_item = get_item_by_physical_index( this, this->first_item);
this->init_item( array_item);
this->copy_item( array_item, item);
return TRUE;
}
BOOL cyclic_array_push_last( cyclic_array_context_ptr this, void* item)
{
void* array_item;
if( cyclic_array_is_full(this))
{
roadmap_log( ROADMAP_WARNING, "cyclic_array_push_last(%s) - Array is full", this->module_name);
return FALSE;
}
if( cyclic_array_is_empty(this))
return insert_first_item( this, item);
array_item = get_item_by_logical_index( this, this->items_count++);
this->init_item( array_item);
this->copy_item( array_item, item);
return TRUE;
}
BOOL cyclic_array_pop_first( cyclic_array_context_ptr this, void* item)
{
void* array_item;
this->init_item( item);
if( cyclic_array_is_empty(this))
return FALSE;
array_item = get_item_by_physical_index( this, this->first_item);
#ifdef SHALLOW_COPY
memcpy( item, array_item, this->sizeof_item);
#else
// Deep copy:
this->copy_item( item, array_item);
this->free_item( array_item);
#endif // SHALLOW_COPY
this->init_item( array_item);
this->items_count--;
if( !this->items_count)
this->first_item = INVALID_INDEX;
else
{
this->first_item++;
if(this->first_item == this->max_items_count)
this->first_item = 0;
}
return TRUE;
}
BOOL cyclic_array_pop_last( cyclic_array_context_ptr this, void* item)
{
void* array_item;
this->init_item( item);
if( cyclic_array_is_empty(this))
return FALSE;
array_item = get_item_by_logical_index( this, (this->items_count - 1));
#ifdef SHALLOW_COPY
memcpy( item, array_item, this->sizeof_item);
#else
// Deep copy:
this->copy_item( item, array_item);
this->free_item( array_item);
#endif // SHALLOW_COPY
this->init_item( array_item);
this->items_count--;
if( !this->items_count)
this->first_item = INVALID_INDEX;
return TRUE;
}
int cyclic_array_size( cyclic_array_context_ptr this)
{ return this->items_count;}
BOOL cyclic_array_is_empty( cyclic_array_context_ptr this)
{ return (0 == this->items_count);}
BOOL cyclic_array_is_full( cyclic_array_context_ptr this)
{ return (this->max_items_count == this->items_count);}
void cyclic_array_clear( cyclic_array_context_ptr this)
{ cyclic_array_free( this);}
void* cyclic_array_get_item( cyclic_array_context_ptr this, int logical_index)
{ return get_item_by_logical_index( this, logical_index);}
void* cyclic_array_get_same_item( cyclic_array_context_ptr this, void* item)
{
int logical_index;
assert(item);
for( logical_index=0; logical_index<cyclic_array_size(this); logical_index++)
{
void* current = get_item_by_logical_index( this, logical_index);
assert(current);
if( this->items_are_same( item, current))
return cyclic_array_get_item( this, logical_index);
}
return NULL;
}
BOOL cyclic_array_remove_item( cyclic_array_context_ptr this, int logical_index)
{
int first_item;
int last_item;
int physical_index;
void* item_to_remove;
if( cyclic_array_is_empty(this))
return FALSE;
if( (logical_index < 0) || (this->items_count <= logical_index))
{
assert(0);
return FALSE;
}
first_item = this->first_item;
last_item = get_physical_index( this, (this->items_count - 1));
physical_index = get_physical_index( this, logical_index);
item_to_remove = get_item_by_physical_index( this, physical_index);
// Free item:
this->free_item( item_to_remove);
// Shift all other items:
if( (first_item < last_item) || (first_item <= physical_index))
{
shift_one_item_up( this, first_item, physical_index);
this->first_item++;
if( this->max_items_count == this->first_item)
this->first_item = 0;
}
else
shift_one_item_down( this, physical_index, last_item);
this->items_count--;
return TRUE;
}
BOOL cyclic_array_remove_same_item( cyclic_array_context_ptr this, void* item)
{
int logical_index;
assert(item);
for( logical_index=0; logical_index<cyclic_array_size(this); logical_index++)
{
void* current = get_item_by_logical_index( this, logical_index);
assert(current);
if( this->items_are_same( item, current))
return cyclic_array_remove_item( this, logical_index);
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////