/src/graphicsmagick/magick/map.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2003-2025 GraphicsMagick Group |
3 | | % |
4 | | % This program is covered by multiple licenses, which are described in |
5 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
6 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
7 | | % |
8 | | % Key,value associative map interface |
9 | | % Written by Bob Friesenhahn, September 2003 |
10 | | % |
11 | | */ |
12 | | |
13 | | #include "magick/studio.h" |
14 | | #include "magick/map.h" |
15 | | #include "magick/utility.h" |
16 | | #include "magick/semaphore.h" |
17 | | |
18 | | /* |
19 | | Structure to represent a contained object |
20 | | */ |
21 | | typedef struct _MagickMapObject |
22 | | { |
23 | | /* Object key value */ |
24 | | char |
25 | | *key; |
26 | | |
27 | | /* Pointer to stored object */ |
28 | | void |
29 | | *object; |
30 | | |
31 | | /* Object size. Optional. May be set to zero depending on needs of |
32 | | object type */ |
33 | | size_t |
34 | | object_size; |
35 | | |
36 | | /* Function which clones (copies) contained objects */ |
37 | | MagickMapObjectClone |
38 | | clone_function; |
39 | | |
40 | | /* Function which deallocates contained object */ |
41 | | MagickMapObjectDeallocator |
42 | | deallocate_function; |
43 | | |
44 | | /* Number of references to this object. */ |
45 | | long |
46 | | reference_count; |
47 | | |
48 | | struct _MagickMapObject |
49 | | *previous, |
50 | | *next; |
51 | | |
52 | | unsigned long |
53 | | signature; |
54 | | |
55 | | } MagickMapObject; |
56 | | |
57 | | /* |
58 | | Structure to act as the user handle to a key,value map |
59 | | */ |
60 | | typedef struct _MagickMapHandle |
61 | | { |
62 | | /* Function which clones (copies) contained objects */ |
63 | | MagickMapObjectClone |
64 | | clone_function; |
65 | | |
66 | | /* Function which deallocates contained object */ |
67 | | MagickMapObjectDeallocator |
68 | | deallocate_function; |
69 | | |
70 | | /* Global semaphore for all operations pertaining to this map */ |
71 | | SemaphoreInfo |
72 | | *semaphore; |
73 | | |
74 | | /* Number of references to this object. */ |
75 | | long |
76 | | reference_count; |
77 | | |
78 | | MagickMapObject |
79 | | *list; |
80 | | |
81 | | unsigned long |
82 | | signature; |
83 | | |
84 | | } MagickMapHandle; |
85 | | |
86 | | /* |
87 | | Iterator position. Used to manage iterator state. |
88 | | */ |
89 | | typedef enum |
90 | | { |
91 | | InListPosition, |
92 | | FrontPosition, |
93 | | BackPosition |
94 | | } MagickMapIteratorPosition; |
95 | | |
96 | | /* |
97 | | Structure to act as a map iterator |
98 | | */ |
99 | | typedef struct _MagickMapIteratorHandle |
100 | | { |
101 | | /* Pointer to base map */ |
102 | | MagickMap |
103 | | map; |
104 | | |
105 | | /* Pointer to member of map */ |
106 | | const MagickMapObject |
107 | | *member; |
108 | | |
109 | | /* Iterator position */ |
110 | | MagickMapIteratorPosition |
111 | | position; |
112 | | |
113 | | unsigned long |
114 | | signature; |
115 | | } MagickMapIteratorHandle; |
116 | | |
117 | | /* |
118 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
119 | | % % |
120 | | % % |
121 | | % % |
122 | | + M a g i c k M a p A l l o c a t e O b j e c t % |
123 | | % % |
124 | | % % |
125 | | % % |
126 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
127 | | % |
128 | | % MagickMapAllocateObject() allocates a new object for inclusion in |
129 | | % the map. |
130 | | % |
131 | | % The format of the MagickMapAllocateObject method is: |
132 | | % |
133 | | % MagickMapObject *MagickMapAllocateObject(const char *key, |
134 | | % const void *object, const size_t object_size, |
135 | | % MagickMapObjectClone clone, MagickMapObjectDeallocator deallocate) |
136 | | % |
137 | | % A description of each parameter follows: |
138 | | % |
139 | | % o key: object unique key. |
140 | | % |
141 | | % o object: Object value |
142 | | % |
143 | | % o object_size: Object size. Optional. May be set to zero if the |
144 | | % object size is known through some other means. |
145 | | % |
146 | | % o clone: function to create a copy of this object type. |
147 | | % |
148 | | % o deallocate: function to deallocate this object type. |
149 | | % |
150 | | */ |
151 | | static MagickMapObject * |
152 | | MagickMapAllocateObject(const char *key, const void *object, |
153 | | const size_t object_size, MagickMapObjectClone clone, |
154 | | MagickMapObjectDeallocator deallocate) |
155 | 12.1M | { |
156 | 12.1M | MagickMapObject * |
157 | 12.1M | map_object; |
158 | | |
159 | 12.1M | assert(key != 0); |
160 | 12.1M | assert(object != 0); |
161 | 12.1M | assert(clone != 0); |
162 | 12.1M | assert(deallocate != 0); |
163 | | |
164 | 12.1M | map_object=MagickAllocateMemory(MagickMapObject *,sizeof(MagickMapObject)); |
165 | 12.1M | if (map_object) |
166 | 12.1M | { |
167 | 12.1M | map_object->key=AcquireString(key); |
168 | 12.1M | map_object->object=(clone)(object,object_size); |
169 | 12.1M | map_object->object_size=object_size; |
170 | 12.1M | map_object->clone_function=clone; |
171 | 12.1M | map_object->deallocate_function=deallocate; |
172 | 12.1M | map_object->reference_count=1; |
173 | 12.1M | map_object->previous=0; |
174 | 12.1M | map_object->next=0; |
175 | 12.1M | map_object->signature=MagickSignature; |
176 | 12.1M | } |
177 | | |
178 | 12.1M | return map_object; |
179 | 12.1M | } |
180 | | |
181 | | /* |
182 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
183 | | % % |
184 | | % % |
185 | | % % |
186 | | + M a g i c k M a p D e s t r o y O b j e c t % |
187 | | % % |
188 | | % % |
189 | | % % |
190 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
191 | | % |
192 | | % MagickMapDestroyObject deallocates a map object by invoking the |
193 | | % object's embedded deallocation function. |
194 | | % |
195 | | % The format of the MagickMapDestroyObject method is: |
196 | | % |
197 | | % void MagickMapDestroyObject(MagickMapObject *object) |
198 | | % |
199 | | % A description of each parameter follows: |
200 | | % |
201 | | % o object: Pointer to object to destroy. |
202 | | % |
203 | | */ |
204 | | static void |
205 | | MagickMapDestroyObject(MagickMapObject *object) |
206 | 12.1M | { |
207 | 12.1M | assert(object != 0); |
208 | 12.1M | assert(object->signature == MagickSignature); |
209 | | |
210 | 12.1M | object->reference_count--; |
211 | 12.1M | assert(object->reference_count == 0); |
212 | | |
213 | 12.1M | MagickFreeMemory(object->key); |
214 | 12.1M | (object->deallocate_function)(object->object); |
215 | | |
216 | 12.1M | (void) memset((void *)object,0xbf,sizeof(MagickMapObject)); |
217 | 12.1M | MagickFreeMemory(object); |
218 | 12.1M | } |
219 | | |
220 | | /* |
221 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
222 | | % % |
223 | | % % |
224 | | % % |
225 | | + M a g i c k M a p A c c e s s E n t r y % |
226 | | % % |
227 | | % % |
228 | | % % |
229 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
230 | | % |
231 | | % MagickMapAccessEntry() searches for an object in the map identified |
232 | | % by the specified key. If a matching object is found, then a const |
233 | | % pointer to the object data is returned, and the object_size |
234 | | % argument is updated with the object size. Null is returned if no |
235 | | % matching object is found. |
236 | | % |
237 | | % An object is not required to contain a size so object_size may be |
238 | | % updated to zero. If the object size is known to not be required by |
239 | | % this object type, then a null object_size pointer may be passed. |
240 | | % |
241 | | % The format of the MagickMapAccessEntry method is: |
242 | | % |
243 | | % const void *MagickMapAccessEntry(MagickMap map,const char *key, |
244 | | % size_t *object_size) |
245 | | % |
246 | | % A description of each parameter follows: |
247 | | % |
248 | | % o map: map context |
249 | | % |
250 | | % o key: unique key to match |
251 | | % |
252 | | % o object_size: Pointer to where object size is to be saved. |
253 | | % |
254 | | */ |
255 | | MagickExport const void * |
256 | | MagickMapAccessEntry(MagickMap map,const char *key, size_t *object_size) |
257 | 6.19M | { |
258 | 6.19M | MagickMapObject |
259 | 6.19M | *p; |
260 | | |
261 | 6.19M | assert(map != 0); |
262 | 6.19M | assert(map->signature == MagickSignature); |
263 | 6.19M | assert(key != 0); |
264 | | |
265 | 6.19M | if (object_size) |
266 | 43.0k | *object_size=0; |
267 | | |
268 | 6.19M | (void) LockSemaphoreInfo(map->semaphore); |
269 | | |
270 | 12.1M | for (p=map->list; p != 0; p=p->next) |
271 | 6.21M | if (LocaleCompare(key,p->key) == 0) |
272 | 265k | { |
273 | 265k | if (object_size) |
274 | 18.2k | *object_size=p->object_size; |
275 | 265k | (void) UnlockSemaphoreInfo(map->semaphore); |
276 | 265k | return(p->object); |
277 | 265k | } |
278 | | |
279 | 5.92M | (void) UnlockSemaphoreInfo(map->semaphore); |
280 | | |
281 | 5.92M | return 0; |
282 | 6.19M | } |
283 | | |
284 | | /* |
285 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
286 | | % % |
287 | | % % |
288 | | % % |
289 | | + M a g i c k M a p A d d E n t r y % |
290 | | % % |
291 | | % % |
292 | | % % |
293 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
294 | | % |
295 | | % MagickMapAddEntry() adds a new entry to a map, or replaces an existing |
296 | | % matching entry. True is returned on success. If False is returned, then |
297 | | % the exception argument describes the reason for failure. |
298 | | % |
299 | | % The format of the MagickMapAddEntry method is: |
300 | | % |
301 | | % void MagickMapAddEntry(MagickMap map,const char *key, |
302 | | % const void *object, const size_t object_size) |
303 | | % |
304 | | % A description of each parameter follows: |
305 | | % |
306 | | % o map: map context |
307 | | % |
308 | | % o key: unique key |
309 | | % |
310 | | % o object: pointer to object data to copy. |
311 | | % |
312 | | % o object_size: size of object data. If the copy function does not |
313 | | % require the object size, then the value zero may be used. |
314 | | % |
315 | | % o exception: check this argument for error information if False is |
316 | | % returned. |
317 | | % |
318 | | */ |
319 | | MagickExport unsigned int |
320 | | MagickMapAddEntry(MagickMap map,const char *key, const void *object, |
321 | | const size_t object_size, ExceptionInfo *exception) |
322 | 12.1M | { |
323 | 12.1M | MagickMapObject |
324 | 12.1M | *new_object; |
325 | | |
326 | 12.1M | assert(map != 0); |
327 | 12.1M | assert(map->signature == MagickSignature); |
328 | 12.1M | assert(key != 0); |
329 | 12.1M | assert(object != 0); |
330 | | |
331 | 12.1M | new_object=MagickMapAllocateObject(key, object, object_size, |
332 | 12.1M | map->clone_function, |
333 | 12.1M | map->deallocate_function); |
334 | | |
335 | 12.1M | if (!new_object) |
336 | 0 | { |
337 | 0 | if (exception) |
338 | 0 | ThrowException(exception,ResourceLimitError,MemoryAllocationFailed, |
339 | 0 | NULL); |
340 | 0 | return (False); |
341 | 0 | } |
342 | | |
343 | 12.1M | (void) LockSemaphoreInfo(map->semaphore); |
344 | | |
345 | 12.1M | if (!map->list) |
346 | 12.0M | { |
347 | | /* |
348 | | If list is empty, object becomes new list. |
349 | | */ |
350 | 12.0M | map->list=new_object; |
351 | 12.0M | } |
352 | 113k | else |
353 | 113k | { |
354 | 113k | MagickMapObject |
355 | 113k | *last_object=0, |
356 | 113k | *p; |
357 | | |
358 | 113k | MagickBool |
359 | 113k | spliced_in=MagickFalse; |
360 | | |
361 | | /* |
362 | | Search for, and replace any existing object with |
363 | | same key. |
364 | | */ |
365 | | |
366 | 191k | for (p=map->list; p != 0; p=p->next) |
367 | 163k | { |
368 | 163k | last_object=p; |
369 | 163k | if (LocaleCompare(key,p->key) == 0) |
370 | 85.9k | { |
371 | | /* |
372 | | Splice in new object |
373 | | */ |
374 | 85.9k | new_object->previous=p->previous; |
375 | 85.9k | new_object->next=p->next; |
376 | 85.9k | if (new_object->previous) |
377 | 27.0k | new_object->previous->next=new_object; |
378 | 85.9k | if (new_object->next) |
379 | 10.0k | new_object->next->previous=new_object; |
380 | 85.9k | if (map->list == p) |
381 | 58.8k | map->list=new_object; |
382 | 85.9k | p->previous=0; |
383 | 85.9k | p->next=0; |
384 | 85.9k | spliced_in=MagickTrue; |
385 | | |
386 | | /* |
387 | | Remove old object |
388 | | */ |
389 | 85.9k | MagickMapDestroyObject(p); |
390 | 85.9k | break; |
391 | 85.9k | } |
392 | 163k | } |
393 | | |
394 | 113k | if (!spliced_in) |
395 | 27.2k | { |
396 | | /* |
397 | | No existing matching object was found. The last_object |
398 | | pointer points to the last object in the list. Append new |
399 | | object to end of list. |
400 | | */ |
401 | 27.2k | new_object->previous=last_object; |
402 | 27.2k | last_object->next=new_object; |
403 | 27.2k | } |
404 | 113k | } |
405 | | |
406 | 12.1M | (void) UnlockSemaphoreInfo(map->semaphore); |
407 | | |
408 | 12.1M | return (True); |
409 | 12.1M | } |
410 | | |
411 | | /* |
412 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
413 | | % % |
414 | | % % |
415 | | % % |
416 | | + M a g i c k M a p A l l o c a t e M a p % |
417 | | % % |
418 | | % % |
419 | | % % |
420 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
421 | | % |
422 | | % MagickMapAllocateMap() allocates a new map context. The address of |
423 | | % the functions required to copy and deallocate contained object data |
424 | | % are provided when the map context is constructed. Objects contained |
425 | | % in a map are all of the same type. A null map context is returned if |
426 | | % the map construction fails. |
427 | | % |
428 | | % The format of the MagickMapAllocateMap method is: |
429 | | % |
430 | | % MagickMap MagickMapAllocateMap(MagickMapObjectClone clone, |
431 | | % MagickMapObjectDeallocator deallocate) |
432 | | % |
433 | | % A description of each parameter follows: |
434 | | % |
435 | | % o clone: Pointer to function which copies contained object data. |
436 | | % |
437 | | % o deallocate: Pointer to function which deallocates contained object |
438 | | % data. |
439 | | % |
440 | | */ |
441 | | MagickExport MagickMap |
442 | | MagickMapAllocateMap(MagickMapObjectClone clone, |
443 | | MagickMapObjectDeallocator deallocate) |
444 | 12.0M | { |
445 | 12.0M | MagickMap |
446 | 12.0M | map; |
447 | | |
448 | 12.0M | assert(clone != 0); |
449 | 12.0M | assert(deallocate != 0); |
450 | | |
451 | 12.0M | map=MagickAllocateMemory(MagickMap,sizeof(MagickMapHandle)); |
452 | 12.0M | if (map) |
453 | 12.0M | { |
454 | 12.0M | map->clone_function=clone; |
455 | 12.0M | map->deallocate_function=deallocate; |
456 | 12.0M | map->semaphore=AllocateSemaphoreInfo(); |
457 | 12.0M | (void) LockSemaphoreInfo(map->semaphore); |
458 | 12.0M | map->reference_count=1; |
459 | 12.0M | map->list=0; |
460 | 12.0M | (void) UnlockSemaphoreInfo(map->semaphore); |
461 | 12.0M | map->signature=MagickSignature; |
462 | 12.0M | } |
463 | | |
464 | 12.0M | return map; |
465 | 12.0M | } |
466 | | |
467 | | /* |
468 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
469 | | % % |
470 | | % % |
471 | | % % |
472 | | + M a g i c k M a p C l o n e M a p % |
473 | | % % |
474 | | % % |
475 | | % % |
476 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
477 | | % |
478 | | % MagickMapCloneMap() duplicates an existing map. If the duplication fails, |
479 | | % zero is returned and the error argument is updated. |
480 | | % |
481 | | % The format of the MagickMapCloneMap method is: |
482 | | % |
483 | | % MagickMap MagickMapCloneMap(MagickMap map) |
484 | | % |
485 | | % A description of each parameter follows: |
486 | | % |
487 | | % o map: map context to duplicate |
488 | | % |
489 | | % o exception: check this structure for error details if null is returned. |
490 | | % |
491 | | */ |
492 | | MagickExport MagickMap |
493 | | MagickMapCloneMap(MagickMap map,ExceptionInfo *exception) |
494 | 11.2M | { |
495 | 11.2M | MagickMap map_clone; |
496 | 11.2M | MagickMapIterator iterator; |
497 | 11.2M | size_t size; |
498 | 11.2M | const char *key; |
499 | | |
500 | 11.2M | assert(map != 0); |
501 | 11.2M | assert(map->signature == MagickSignature); |
502 | | |
503 | | /* |
504 | | Don't lock. Iterator locks the map. PTHREADS doesn't |
505 | | allow one thread multiple locks on one semaphore. |
506 | | */ |
507 | | /* LockSemaphoreInfo(map->semaphore); */ |
508 | | |
509 | 11.2M | map_clone=MagickMapAllocateMap(map->clone_function,map->deallocate_function); |
510 | 11.2M | if (map_clone == (MagickMap) NULL) |
511 | 0 | { |
512 | 0 | ThrowException(exception,ResourceLimitError,MemoryAllocationFailed, |
513 | 0 | "MagickMapAllocateMap"); |
514 | 0 | return (MagickMap) NULL; |
515 | 0 | } |
516 | 11.2M | iterator=MagickMapAllocateIterator(map); |
517 | 11.2M | if (iterator == (MagickMapIterator) NULL) |
518 | 0 | { |
519 | 0 | MagickMapDeallocateMap(map_clone); |
520 | 0 | ThrowException(exception,ResourceLimitError,MemoryAllocationFailed, |
521 | 0 | "MagickMapAllocateIterator"); |
522 | 0 | return (MagickMap) NULL; |
523 | 0 | } |
524 | 22.5M | while(MagickMapIterateNext(iterator,&key)) |
525 | 11.2M | { |
526 | 11.2M | const void *object=MagickMapDereferenceIterator(iterator,&size); |
527 | | /* Add clones key and object on insertion */ |
528 | 11.2M | if (MagickMapAddEntry(map_clone,key,object,size,exception) == False) |
529 | 0 | { |
530 | 0 | MagickMapDeallocateIterator(iterator); |
531 | 0 | MagickMapDeallocateMap(map_clone); |
532 | 0 | return 0; |
533 | 0 | } |
534 | 11.2M | } |
535 | 11.2M | MagickMapDeallocateIterator(iterator); |
536 | | |
537 | 11.2M | return map_clone; |
538 | 11.2M | } |
539 | | |
540 | | /* |
541 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
542 | | % % |
543 | | % % |
544 | | % % |
545 | | + M a g i c k M a p C l e a r M a p % |
546 | | % % |
547 | | % % |
548 | | % % |
549 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
550 | | % |
551 | | % MagickMapClearMap() removes all entries from a map. The deallocator |
552 | | % function for each contained object is invoked when it is removed. |
553 | | % |
554 | | % The format of the MagickMapClearMap method is: |
555 | | % |
556 | | % void MagickMapClearMap(MagickMap map) |
557 | | % |
558 | | % A description of each parameter follows: |
559 | | % |
560 | | % o map: map context to clear |
561 | | % |
562 | | */ |
563 | | MagickExport void |
564 | | MagickMapClearMap(MagickMap map) |
565 | 0 | { |
566 | 0 | assert(map != 0); |
567 | 0 | assert(map->signature == MagickSignature); |
568 | |
|
569 | 0 | (void) LockSemaphoreInfo(map->semaphore); |
570 | 0 | if (map->list) |
571 | 0 | { |
572 | 0 | register MagickMapObject |
573 | 0 | *current, |
574 | 0 | *p; |
575 | |
|
576 | 0 | for (p=map->list; p != 0; ) |
577 | 0 | { |
578 | 0 | current=p; |
579 | 0 | p=p->next; |
580 | 0 | MagickMapDestroyObject(current); |
581 | 0 | } |
582 | 0 | map->list=0; |
583 | 0 | } |
584 | 0 | (void) UnlockSemaphoreInfo(map->semaphore); |
585 | 0 | } |
586 | | |
587 | | /* |
588 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
589 | | % % |
590 | | % % |
591 | | % % |
592 | | + M a g i c k M a p A l l o c a t e I t e r a t o r % |
593 | | % % |
594 | | % % |
595 | | % % |
596 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
597 | | % |
598 | | % MagickMapAllocateIterator allocates an iterator which may be used to |
599 | | % traverse all the entries in the map. The iterator initially points to |
600 | | % the front of the map. |
601 | | % |
602 | | % The format of the MagickMapAllocateIterator method is: |
603 | | % |
604 | | % MagickMapIterator MagickMapAllocateIterator(MagickMap map) |
605 | | % |
606 | | % A description of each parameter follows: |
607 | | % |
608 | | % o map: map context |
609 | | % |
610 | | */ |
611 | | MagickExport MagickMapIterator |
612 | | MagickMapAllocateIterator(MagickMap map) |
613 | 11.2M | { |
614 | 11.2M | MagickMapIterator |
615 | 11.2M | iterator; |
616 | | |
617 | 11.2M | assert(map != 0); |
618 | 11.2M | assert(map->signature == MagickSignature); |
619 | | |
620 | 11.2M | LockSemaphoreInfo(map->semaphore); |
621 | | |
622 | 11.2M | iterator=MagickAllocateMemory(MagickMapIterator, |
623 | 11.2M | sizeof(MagickMapIteratorHandle)); |
624 | 11.2M | if (iterator) |
625 | 11.2M | { |
626 | 11.2M | iterator->map=map; |
627 | 11.2M | iterator->member=0; |
628 | 11.2M | iterator->position=FrontPosition; |
629 | 11.2M | iterator->map->reference_count++; |
630 | 11.2M | iterator->signature=MagickSignature; |
631 | 11.2M | } |
632 | | |
633 | 11.2M | UnlockSemaphoreInfo(map->semaphore); |
634 | | |
635 | 11.2M | return iterator; |
636 | 11.2M | } |
637 | | |
638 | | /* |
639 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
640 | | % % |
641 | | % % |
642 | | % % |
643 | | + M a g i c k M a p D e a l l o c a t e M a p % |
644 | | % % |
645 | | % % |
646 | | % % |
647 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
648 | | % |
649 | | % MagickMapDeallocateMap() deallocates a map, invoking the map deallocation |
650 | | % function on each entry contained in the map. |
651 | | % |
652 | | % The format of the MagickMapDeallocateMap method is: |
653 | | % |
654 | | % void MagickMapDeallocateMap(MagickMap map) |
655 | | % |
656 | | % A description of each parameter follows: |
657 | | % |
658 | | % o map: map context to destroy |
659 | | % |
660 | | */ |
661 | | MagickExport void |
662 | | MagickMapDeallocateMap(MagickMap map) |
663 | 12.0M | { |
664 | 12.0M | assert(map != 0); |
665 | 12.0M | assert(map->signature == MagickSignature); |
666 | | |
667 | 12.0M | (void) LockSemaphoreInfo(map->semaphore); |
668 | | |
669 | 12.0M | map->reference_count--; |
670 | | |
671 | | /* For the moment, do not allow outstanding references */ |
672 | 12.0M | assert(map->reference_count == 0); |
673 | | |
674 | 12.0M | if (map->list) |
675 | 12.0M | { |
676 | 12.0M | register MagickMapObject |
677 | 12.0M | *current, |
678 | 12.0M | *p; |
679 | | |
680 | 24.0M | for (p=map->list; p != 0; ) |
681 | 12.0M | { |
682 | 12.0M | current=p; |
683 | 12.0M | p=p->next; |
684 | 12.0M | MagickMapDestroyObject(current); |
685 | 12.0M | } |
686 | 12.0M | } |
687 | | |
688 | 12.0M | (void) UnlockSemaphoreInfo(map->semaphore); |
689 | 12.0M | DestroySemaphoreInfo(&map->semaphore); |
690 | | |
691 | 12.0M | (void) memset((void *)map,0xbf,sizeof(MagickMapHandle)); |
692 | 12.0M | MagickFreeMemory(map); |
693 | 12.0M | } |
694 | | |
695 | | /* |
696 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
697 | | % % |
698 | | % % |
699 | | % % |
700 | | + M a g i c k M a p D e a l l o c a t e I t e r a t o r % |
701 | | % % |
702 | | % % |
703 | | % % |
704 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
705 | | % |
706 | | % MagickMapDeallocateIterator() deallocates a map iterator |
707 | | % |
708 | | % The format of the MagickMapDeallocateIterator method is: |
709 | | % |
710 | | % void MagickMapDeallocateIterator(MagickMapIterator iterator) |
711 | | % |
712 | | % A description of each parameter follows: |
713 | | % |
714 | | % o iterator: iterator context to destroy |
715 | | % |
716 | | */ |
717 | | MagickExport void |
718 | | MagickMapDeallocateIterator(MagickMapIterator iterator) |
719 | 11.2M | { |
720 | 11.2M | assert(iterator != 0); |
721 | 11.2M | assert(iterator->signature == MagickSignature); |
722 | | |
723 | 11.2M | (void) LockSemaphoreInfo(iterator->map->semaphore); |
724 | | |
725 | 11.2M | iterator->map->reference_count--; |
726 | | |
727 | 11.2M | (void) UnlockSemaphoreInfo(iterator->map->semaphore); |
728 | | |
729 | 11.2M | (void) memset((void *)iterator,0xbf,sizeof(MagickMapIteratorHandle)); |
730 | 11.2M | MagickFreeMemory(iterator); |
731 | 11.2M | } |
732 | | |
733 | | /* |
734 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
735 | | % % |
736 | | % % |
737 | | % % |
738 | | + M a g i c k M a p D e r e f e r e n c e I t e r a t o r % |
739 | | % % |
740 | | % % |
741 | | % % |
742 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
743 | | % |
744 | | % MagickMapDereferenceIterator() dereferences a map iterator, providing |
745 | | % access to the contained data and its size. The object_size parameter may |
746 | | % be passed a null pointer if the object size is not required. |
747 | | % |
748 | | % The format of the MagickMapDereferenceIterator method is: |
749 | | % |
750 | | % const void *MagickMapDereferenceIterator( |
751 | | % const MagickMapIterator iterator, size_t *object_size) |
752 | | % |
753 | | % A description of each parameter follows: |
754 | | % |
755 | | % o iterator: iterator context |
756 | | % |
757 | | % o object_size: contained object size (if provided) |
758 | | % |
759 | | */ |
760 | | MagickExport const void * |
761 | | MagickMapDereferenceIterator(const MagickMapIterator iterator, |
762 | | size_t *object_size) |
763 | 11.2M | { |
764 | 11.2M | const void |
765 | 11.2M | *value=0; |
766 | | |
767 | 11.2M | assert(iterator != 0); |
768 | 11.2M | assert(iterator->signature == MagickSignature); |
769 | 11.2M | assert(iterator->member != 0); |
770 | | |
771 | 11.2M | if (object_size) |
772 | 11.2M | *object_size=0; |
773 | | |
774 | 11.2M | if (iterator->member) |
775 | 11.2M | { |
776 | 11.2M | value=iterator->member->object; |
777 | 11.2M | if (object_size) |
778 | 11.2M | *object_size=iterator->member->object_size; |
779 | 11.2M | } |
780 | | |
781 | 11.2M | return value; |
782 | 11.2M | } |
783 | | |
784 | | /* |
785 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
786 | | % % |
787 | | % % |
788 | | % % |
789 | | + M a g i c k M a p I t e r a t e T o B a c k % |
790 | | % % |
791 | | % % |
792 | | % % |
793 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
794 | | % |
795 | | % MagickMapIterateToBack() sets the iterator to one position beyond the |
796 | | % last element in the map. The MagickMapIteratePrevious() function must |
797 | | % be executed once to access the last element in the map. |
798 | | % |
799 | | % The format of the MagickMapIterateToBack method is: |
800 | | % |
801 | | % void MagickMapIterateToBack(MagickMapIterator iterator) |
802 | | % |
803 | | % A description of each parameter follows: |
804 | | % |
805 | | % o iterator: iterator context |
806 | | % |
807 | | */ |
808 | | MagickExport void |
809 | | MagickMapIterateToBack(MagickMapIterator iterator) |
810 | 0 | { |
811 | 0 | assert(iterator != 0); |
812 | 0 | assert(iterator->signature == MagickSignature); |
813 | |
|
814 | 0 | iterator->member=0; |
815 | 0 | iterator->position=BackPosition; |
816 | 0 | } |
817 | | |
818 | | /* |
819 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
820 | | % % |
821 | | % % |
822 | | % % |
823 | | + M a g i c k M a p I t e r a t e T o F r o n t % |
824 | | % % |
825 | | % % |
826 | | % % |
827 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
828 | | % |
829 | | % MagickMapIterateToFront() sets the iterator to one position before the |
830 | | % first element in the map. The MagickMapIterateNext() function must |
831 | | % be executed once to access the first element in the map. |
832 | | % |
833 | | % The format of the MagickMapIterateToFront method is: |
834 | | % |
835 | | % void MagickMapIterateToFront(MagickMapIterator iterator) |
836 | | % |
837 | | % A description of each parameter follows: |
838 | | % |
839 | | % o iterator: iterator context |
840 | | % |
841 | | */ |
842 | | MagickExport void |
843 | | MagickMapIterateToFront(MagickMapIterator iterator) |
844 | 0 | { |
845 | 0 | assert(iterator != 0); |
846 | 0 | assert(iterator->signature == MagickSignature); |
847 | |
|
848 | 0 | iterator->member=0; |
849 | 0 | iterator->position=FrontPosition; |
850 | 0 | } |
851 | | |
852 | | /* |
853 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
854 | | % % |
855 | | % % |
856 | | % % |
857 | | + M a g i c k M a p I t e r a t e N e x t % |
858 | | % % |
859 | | % % |
860 | | % % |
861 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
862 | | % |
863 | | % MagickMapIterateNext() advances the iterator by one element. True is |
864 | | % returned if there are remaining entries in the map. The key argument |
865 | | % is updated to point to the element key. |
866 | | % |
867 | | % The format of the MagickMapIterateNext method is: |
868 | | % |
869 | | % void MagickMapIterateToFront(MagickMapIterator iterator) |
870 | | % |
871 | | % A description of each parameter follows: |
872 | | % |
873 | | % o iterator: iterator context |
874 | | % |
875 | | % o key: pointer to location to store a pointer to the key |
876 | | % |
877 | | */ |
878 | | MagickExport unsigned int |
879 | | MagickMapIterateNext(MagickMapIterator iterator,const char **key) |
880 | 22.5M | { |
881 | 22.5M | assert(iterator != 0); |
882 | 22.5M | assert(iterator->signature == MagickSignature); |
883 | 22.5M | assert(key != 0); |
884 | | |
885 | 22.5M | LockSemaphoreInfo(iterator->map->semaphore); |
886 | | |
887 | 22.5M | *key=(const char *) NULL; |
888 | 22.5M | switch (iterator->position) |
889 | 22.5M | { |
890 | 11.2M | case FrontPosition: |
891 | 11.2M | iterator->member=iterator->map->list; |
892 | 11.2M | if (iterator->member) |
893 | 11.2M | iterator->position=InListPosition; |
894 | 11.2M | break; |
895 | 11.2M | case InListPosition: |
896 | 11.2M | assert(iterator->member != 0); |
897 | 11.2M | iterator->member=iterator->member->next; |
898 | 11.2M | if (!iterator->member) |
899 | 11.2M | iterator->position=BackPosition; |
900 | 11.2M | break; |
901 | 0 | case BackPosition: |
902 | 0 | break; |
903 | 22.5M | } |
904 | | |
905 | 22.5M | if (iterator->member) |
906 | 11.2M | *key=iterator->member->key; |
907 | | |
908 | 22.5M | UnlockSemaphoreInfo(iterator->map->semaphore); |
909 | | |
910 | 22.5M | return (iterator->member != 0); |
911 | 22.5M | } |
912 | | |
913 | | /* |
914 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
915 | | % % |
916 | | % % |
917 | | % % |
918 | | + M a g i c k M a p I t e r a t e P r e v i o u s % |
919 | | % % |
920 | | % % |
921 | | % % |
922 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
923 | | % |
924 | | % MagickMapIteratePrevious() moves the iterator by one element in the |
925 | | % reverse direction. True is returned if there are remaining entries |
926 | | % in the map prior to the entry. The key argument is updated to point |
927 | | % to the element key. |
928 | | % |
929 | | % The format of the MagickMapIteratePrevious method is: |
930 | | % |
931 | | % void MagickMapIterateToPrevious(MagickMapIterator iterator) |
932 | | % |
933 | | % A description of each parameter follows: |
934 | | % |
935 | | % o iterator: iterator context |
936 | | % |
937 | | % o key: pointer to location to store a pointer to the key |
938 | | % |
939 | | */ |
940 | | MagickExport unsigned int |
941 | | MagickMapIteratePrevious(MagickMapIterator iterator,const char **key) |
942 | 0 | { |
943 | 0 | assert(iterator != 0); |
944 | 0 | assert(iterator->signature == MagickSignature); |
945 | 0 | assert(key != 0); |
946 | |
|
947 | 0 | LockSemaphoreInfo(iterator->map->semaphore); |
948 | |
|
949 | 0 | switch (iterator->position) |
950 | 0 | { |
951 | 0 | case FrontPosition: |
952 | 0 | break; |
953 | 0 | case InListPosition: |
954 | 0 | assert(iterator->member != 0); |
955 | 0 | iterator->member=iterator->member->previous; |
956 | 0 | if (!iterator->member) |
957 | 0 | iterator->position=FrontPosition; |
958 | 0 | break; |
959 | 0 | case BackPosition: |
960 | 0 | { |
961 | 0 | for (iterator->member=iterator->map->list; |
962 | 0 | (iterator->member != 0) && (iterator->member->next != 0); |
963 | 0 | iterator->member=iterator->member->next); |
964 | 0 | if (iterator->member) |
965 | 0 | iterator->position=InListPosition; |
966 | 0 | } |
967 | 0 | break; |
968 | 0 | } |
969 | | |
970 | 0 | if (iterator->member) |
971 | 0 | *key=iterator->member->key; |
972 | |
|
973 | 0 | UnlockSemaphoreInfo(iterator->map->semaphore); |
974 | |
|
975 | 0 | return (iterator->member != 0); |
976 | 0 | } |
977 | | |
978 | | /* |
979 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
980 | | % % |
981 | | % % |
982 | | % % |
983 | | + M a g i c k M a p R e m o v e E n t r y % |
984 | | % % |
985 | | % % |
986 | | % % |
987 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
988 | | % |
989 | | % MagickMapRemoveEntry() removes (destroys) an entry from the map. The |
990 | | % deallocate function is invoked on the entry data. False is returned if |
991 | | % a matching key doesn't exist. |
992 | | % |
993 | | % The format of the MagickMapRemoveEntry method is: |
994 | | % |
995 | | % unsigned int MagickMapRemoveEntry(MagickMap map,const char *key) |
996 | | % |
997 | | % A description of each parameter follows: |
998 | | % |
999 | | % o map: map context |
1000 | | % |
1001 | | % o key: key corresponding to the entry to remove |
1002 | | % |
1003 | | */ |
1004 | | MagickExport unsigned int |
1005 | | MagickMapRemoveEntry(MagickMap map,const char *key) |
1006 | 3 | { |
1007 | 3 | unsigned int |
1008 | 3 | status = False; |
1009 | | |
1010 | 3 | assert(map != 0); |
1011 | 3 | assert(map->signature == MagickSignature); |
1012 | 3 | assert(key != 0); |
1013 | | |
1014 | 3 | LockSemaphoreInfo(map->semaphore); |
1015 | | |
1016 | 3 | if (map->list) |
1017 | 2 | { |
1018 | 2 | MagickMapObject |
1019 | 2 | *p; |
1020 | | |
1021 | 4 | for (p=map->list; p != 0; p=p->next) |
1022 | 2 | { |
1023 | 2 | if (LocaleCompare(key,p->key) == 0) |
1024 | 0 | { |
1025 | 0 | if (p == map->list) |
1026 | 0 | { |
1027 | 0 | if (!p->next) |
1028 | 0 | { |
1029 | 0 | map->list=0; |
1030 | 0 | } |
1031 | 0 | else |
1032 | 0 | { |
1033 | 0 | map->list=p->next; |
1034 | 0 | p->next->previous=0; |
1035 | 0 | } |
1036 | 0 | } |
1037 | 0 | else |
1038 | 0 | { |
1039 | 0 | if (p->previous) |
1040 | 0 | p->previous->next=p->next; |
1041 | |
|
1042 | 0 | if (p->next) |
1043 | 0 | p->next->previous=p->previous; |
1044 | 0 | } |
1045 | |
|
1046 | 0 | MagickMapDestroyObject(p); |
1047 | 0 | status=True; |
1048 | 0 | break; |
1049 | 0 | } |
1050 | 2 | } |
1051 | 2 | } |
1052 | | |
1053 | 3 | UnlockSemaphoreInfo(map->semaphore); |
1054 | | |
1055 | 3 | return status; |
1056 | 3 | } |
1057 | | |
1058 | | /* |
1059 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1060 | | % % |
1061 | | % % |
1062 | | % % |
1063 | | + M a g i c k M a p C o p y S t r i n g % |
1064 | | % % |
1065 | | % % |
1066 | | % % |
1067 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1068 | | % |
1069 | | % MagickMapCopyString() copies a string. It is intended for use as the |
1070 | | % clone function for strings so that C strings may easily be stored in |
1071 | | % a map. |
1072 | | % |
1073 | | % The format of the MagickMapCopyString method is: |
1074 | | % |
1075 | | % void *MagickMapCopyString(const void *string, const size_t size) |
1076 | | % |
1077 | | % A description of each parameter follows: |
1078 | | % |
1079 | | % o string: pointer to string data |
1080 | | % |
1081 | | % o size: ignored by this method. |
1082 | | % |
1083 | | */ |
1084 | | MagickExport void * |
1085 | | MagickMapCopyString(const void *string, const size_t size) |
1086 | 11.7M | { |
1087 | 11.7M | ARG_NOT_USED(size); |
1088 | 11.7M | if (string) |
1089 | 11.7M | { |
1090 | 11.7M | size_t length = strlen((const char *) string); |
1091 | 11.7M | char *dstring=MagickAllocateMemory(char *,length+1); |
1092 | 11.7M | if (dstring != (char *) NULL) |
1093 | 11.7M | { |
1094 | 11.7M | if (length != 0) |
1095 | 11.7M | (void) memcpy(dstring,string,length); |
1096 | 11.7M | dstring[length]='\0'; |
1097 | 11.7M | } |
1098 | 11.7M | return dstring; |
1099 | 11.7M | } |
1100 | 0 | return 0; |
1101 | 11.7M | } |
1102 | | |
1103 | | /* |
1104 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1105 | | % % |
1106 | | % % |
1107 | | % % |
1108 | | + M a g i c k M a p D e a l l o c a t e S t r i n g % |
1109 | | % % |
1110 | | % % |
1111 | | % % |
1112 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1113 | | % |
1114 | | % MagickMapDeallocateString() deallocates a string. It is intended for |
1115 | | % use as the deallocate function for strings so that C strings may easily |
1116 | | % be stored in a map. |
1117 | | % |
1118 | | % The format of the MagickMapDeallocateString method is: |
1119 | | % |
1120 | | % void MagickMapDeallocateString(void *string) |
1121 | | % |
1122 | | % A description of each parameter follows: |
1123 | | % |
1124 | | % o string: pointer to string data to deallocate |
1125 | | % |
1126 | | */ |
1127 | | MagickExport void |
1128 | | MagickMapDeallocateString(void *string) |
1129 | 11.7M | { |
1130 | 11.7M | MagickFreeMemory(string); |
1131 | 11.7M | } |
1132 | | |
1133 | | /* |
1134 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1135 | | % % |
1136 | | % % |
1137 | | % % |
1138 | | + M a g i c k M a p C o p y B l o b % |
1139 | | % % |
1140 | | % % |
1141 | | % % |
1142 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1143 | | % |
1144 | | % MagickMapCopyBlob() copies a BLOB. It is intended for use as the |
1145 | | % clone function for BLOBs so that BLOB may easily be stored in |
1146 | | % a map. |
1147 | | % |
1148 | | % The format of the MagickMapCopyBlob method is: |
1149 | | % |
1150 | | % void *MagickMapCopyBlob(const void *blob, const size_t size) |
1151 | | % |
1152 | | % A description of each parameter follows: |
1153 | | % |
1154 | | % o blob: pointer to BLOB data |
1155 | | % |
1156 | | % o size: BLOB size |
1157 | | % |
1158 | | */ |
1159 | | MagickExport void * |
1160 | | MagickMapCopyBlob(const void *blob, const size_t size) |
1161 | 0 | { |
1162 | 0 | if (blob) |
1163 | 0 | { |
1164 | 0 | void |
1165 | 0 | *memory; |
1166 | |
|
1167 | 0 | memory=MagickAllocateMemory(void *,size); |
1168 | 0 | if (memory) |
1169 | 0 | (void) memcpy(memory,blob,size); |
1170 | 0 | return (memory); |
1171 | 0 | } |
1172 | 0 | return 0; |
1173 | 0 | } |
1174 | | |
1175 | | /* |
1176 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1177 | | % % |
1178 | | % % |
1179 | | % % |
1180 | | + M a g i c k M a p D e a l l o c a t e B l o b % |
1181 | | % % |
1182 | | % % |
1183 | | % % |
1184 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1185 | | % |
1186 | | % MagickMapDeallocateBlob() deallocates a BLOB. It is intended for |
1187 | | % use as the deallocate function for BLOBs so that BLOBs may easily |
1188 | | % be stored in a map. |
1189 | | % |
1190 | | % The format of the MagickMapDeallocateBlob method is: |
1191 | | % |
1192 | | % void MagickMapDeallocateBlob(void *blob) |
1193 | | % |
1194 | | % A description of each parameter follows: |
1195 | | % |
1196 | | % o blob: pointer to BLOB data to deallocate |
1197 | | % |
1198 | | */ |
1199 | | MagickExport void |
1200 | | MagickMapDeallocateBlob(void *blob) |
1201 | 0 | { |
1202 | 0 | MagickFreeMemory(blob); |
1203 | 0 | } |
1204 | | |
1205 | | /* |
1206 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1207 | | % % |
1208 | | % % |
1209 | | % % |
1210 | | + M a g i c k M a p C o p y R e s o u r c e L i m i t e d S t r i n g % |
1211 | | % % |
1212 | | % % |
1213 | | % % |
1214 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1215 | | % |
1216 | | % MagickMapCopyResourceLimitedString() copies a string using the |
1217 | | % resource-limited memory allocator. It is intended for use as the clone |
1218 | | % function for strings so that C strings may easily be stored in a map. |
1219 | | % |
1220 | | % The format of the MagickMapCopyResourceLimitedString method is: |
1221 | | % |
1222 | | % void *MagickMapCopyResourceLimitedString(const void *string, const size_t size) |
1223 | | % |
1224 | | % A description of each parameter follows: |
1225 | | % |
1226 | | % o string: pointer to string data |
1227 | | % |
1228 | | % o size: ignored by this method. |
1229 | | % |
1230 | | */ |
1231 | | MagickExport void * |
1232 | | MagickMapCopyResourceLimitedString(const void *string, const size_t size) |
1233 | 0 | { |
1234 | 0 | ARG_NOT_USED(size); |
1235 | 0 | if (string) |
1236 | 0 | { |
1237 | 0 | size_t length = strlen((const char *) string); |
1238 | 0 | char *dstring=MagickAllocateResourceLimitedMemory(char *,length+1); |
1239 | 0 | if (dstring != (char *) NULL) |
1240 | 0 | { |
1241 | 0 | if (length != 0) |
1242 | 0 | (void) memcpy(dstring,string,length); |
1243 | 0 | dstring[length]='\0'; |
1244 | 0 | } |
1245 | 0 | return dstring; |
1246 | 0 | } |
1247 | 0 | return 0; |
1248 | 0 | } |
1249 | | |
1250 | | /* |
1251 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1252 | | % % |
1253 | | % % |
1254 | | % % |
1255 | | + M a g i c k M a p D e a l l o c a t e R e s o u r c e L i m i t e d S t r i n g % |
1256 | | % % |
1257 | | % % |
1258 | | % % |
1259 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1260 | | % |
1261 | | % MagickMapDeallocateResourceLimitedString() deallocates a string allocated |
1262 | | % using the resource-limited memory allocator. It is intended for |
1263 | | % use as the deallocate function for strings so that C strings may easily |
1264 | | % be stored in a map. |
1265 | | % |
1266 | | % The format of the MagickMapDeallocateResourceLimitedString method is: |
1267 | | % |
1268 | | % void MagickMapDeallocateResourceLimitedString(void *string) |
1269 | | % |
1270 | | % A description of each parameter follows: |
1271 | | % |
1272 | | % o string: pointer to string data to deallocate |
1273 | | % |
1274 | | */ |
1275 | | MagickExport void |
1276 | | MagickMapDeallocateResourceLimitedString(void *string) |
1277 | 0 | { |
1278 | 0 | MagickFreeResourceLimitedMemory(void *,string); |
1279 | 0 | } |
1280 | | |
1281 | | /* |
1282 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1283 | | % % |
1284 | | % % |
1285 | | % % |
1286 | | + M a g i c k M a p C o p y R e s o u r c e L i m i t e d B l o b % |
1287 | | % % |
1288 | | % % |
1289 | | % % |
1290 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1291 | | % |
1292 | | % MagickMapCopyResourceLimitedBlob() copies a BLOB using the |
1293 | | % resource-limited memory allocator. It is intended for use as the |
1294 | | % clone function for BLOBs so that BLOB may easily be stored in |
1295 | | % a map. |
1296 | | % |
1297 | | % The format of the MagickMapCopyResourceLimitedBlob method is: |
1298 | | % |
1299 | | % void *MagickMapCopyResourceLimitedBlob(const void *blob, const size_t size) |
1300 | | % |
1301 | | % A description of each parameter follows: |
1302 | | % |
1303 | | % o blob: pointer to BLOB data |
1304 | | % |
1305 | | % o size: BLOB size |
1306 | | % |
1307 | | */ |
1308 | | MagickExport void * |
1309 | | MagickMapCopyResourceLimitedBlob(const void *blob, const size_t size) |
1310 | 401k | { |
1311 | 401k | if (blob) |
1312 | 401k | { |
1313 | 401k | void |
1314 | 401k | *memory; |
1315 | | |
1316 | 401k | memory=MagickAllocateResourceLimitedMemory(void *,size); |
1317 | 401k | if (memory) |
1318 | 401k | (void) memcpy(memory,blob,size); |
1319 | 401k | return (memory); |
1320 | 401k | } |
1321 | 0 | return 0; |
1322 | 401k | } |
1323 | | |
1324 | | /* |
1325 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1326 | | % % |
1327 | | % % |
1328 | | % % |
1329 | | + M a g i c k M a p D e a l l o c a t e R e s o u r c e L i m i t e d B l o b % |
1330 | | % % |
1331 | | % % |
1332 | | % % |
1333 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
1334 | | % |
1335 | | % MagickMapDeallocateResourceLimitedBlob() deallocates a BLOB allocated |
1336 | | % using the resource-limited memory allocator. It is intended for |
1337 | | % use as the deallocate function for BLOBs so that BLOBs may easily |
1338 | | % be stored in a map. |
1339 | | % |
1340 | | % The format of the MagickMapDeallocateResourceLimitedBlob method is: |
1341 | | % |
1342 | | % void MagickMapDeallocateResourceLimitedBlob(void *blob) |
1343 | | % |
1344 | | % A description of each parameter follows: |
1345 | | % |
1346 | | % o blob: pointer to BLOB data to deallocate |
1347 | | % |
1348 | | */ |
1349 | | MagickExport void |
1350 | | MagickMapDeallocateResourceLimitedBlob(void *blob) |
1351 | 401k | { |
1352 | 401k | MagickFreeResourceLimitedMemory(void *,blob); |
1353 | 401k | } |