Coverage Report

Created: 2026-01-20 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}