blob: dc97d71631d9bd7ed20f206e9e50f3f6766742ab [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% RRRR EEEEE GGG IIIII SSSSS TTTTT RRRR Y Y %
7% R R E G I SS T R R Y Y %
8% RRRR EEE G GGG I SSS T RRRR Y %
9% R R E G G I SS T R R Y %
10% R R EEEEE GGG IIIII SSSSS T R R Y %
11% %
12% %
13% MagickCore Registry Methods %
14% %
15% Software Design %
16% John Cristy %
17% March 2000 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
44#include "MagickCore/exception.h"
45#include "MagickCore/exception-private.h"
46#include "MagickCore/image.h"
47#include "MagickCore/list.h"
48#include "MagickCore/memory_.h"
49#include "MagickCore/registry.h"
cristy5ff4eaf2011-09-03 01:38:02 +000050#include "MagickCore/registry-private.h"
cristy4c08aed2011-07-01 19:47:50 +000051#include "MagickCore/splay-tree.h"
52#include "MagickCore/string_.h"
53#include "MagickCore/utility.h"
cristy3ed852e2009-09-05 21:47:34 +000054
55/*
56 Typedef declarations.
57*/
58typedef struct _RegistryInfo
59{
60 RegistryType
61 type;
62
63 void
64 *value;
65
cristybb503372010-05-27 20:51:26 +000066 size_t
cristy3ed852e2009-09-05 21:47:34 +000067 signature;
68} RegistryInfo;
69
70/*
71 Static declarations.
72*/
73static SplayTreeInfo
74 *registry = (SplayTreeInfo *) NULL;
cristy41c3c772009-10-19 02:17:37 +000075
76static SemaphoreInfo
77 *registry_semaphore = (SemaphoreInfo *) NULL;
78
79static volatile MagickBooleanType
80 instantiate_registry = MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +000081
82/*
83%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84% %
85% %
86% %
87% D e f i n e I m a g e R e g i s t r y %
88% %
89% %
90% %
91%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92%
93% DefineImageRegistry() associates a key/value pair with the image registry.
94%
95% The format of the DefineImageRegistry method is:
96%
97% MagickBooleanType DefineImageRegistry(const RegistryType type,
98% const char *option,ExceptionInfo *exception)
99%
100% A description of each parameter follows:
101%
102% o type: the type.
103%
104% o option: the option.
105%
106% o exception: the exception.
107%
108*/
109MagickExport MagickBooleanType DefineImageRegistry(const RegistryType type,
110 const char *option,ExceptionInfo *exception)
111{
112 char
113 key[MaxTextExtent],
114 value[MaxTextExtent];
115
116 register char
117 *p;
118
119 assert(option != (const char *) NULL);
120 (void) CopyMagickString(key,option,MaxTextExtent);
121 for (p=key; *p != '\0'; p++)
122 if (*p == '=')
123 break;
124 *value='\0';
125 if (*p == '=')
126 (void) CopyMagickString(value,p+1,MaxTextExtent);
127 *p='\0';
128 return(SetImageRegistry(type,key,value,exception));
129}
130
131/*
132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133% %
134% %
135% %
136% D e l e t e I m a g e R e g i s t r y %
137% %
138% %
139% %
140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141%
142% DeleteImageRegistry() deletes a key from the image registry.
143%
144% The format of the DeleteImageRegistry method is:
145%
146% MagickBooleanType DeleteImageRegistry(const char *key)
147%
148% A description of each parameter follows:
149%
150% o key: the registry.
151%
152*/
153MagickExport MagickBooleanType DeleteImageRegistry(const char *key)
154{
155 if (IsEventLogging() != MagickFalse)
156 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
157 if (registry == (void *) NULL)
158 return(MagickFalse);
159 return(DeleteNodeFromSplayTree(registry,key));
160}
161
162/*
163%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164% %
165% %
166% %
cristy3ed852e2009-09-05 21:47:34 +0000167% G e t I m a g e R e g i s t r y %
168% %
169% %
170% %
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%
173% GetImageRegistry() returns a value associated with an image registry key.
174%
175% The format of the GetImageRegistry method is:
176%
177% void *GetImageRegistry(const RegistryType type,const char *key,
178% ExceptionInfo *exception)
179%
180% A description of each parameter follows:
181%
182% o type: the type.
183%
184% o key: the key.
185%
186% o exception: the exception.
187%
188*/
189MagickExport void *GetImageRegistry(const RegistryType type,const char *key,
190 ExceptionInfo *exception)
191{
192 void
193 *value;
194
195 RegistryInfo
196 *registry_info;
197
198 if (IsEventLogging() != MagickFalse)
199 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
200 if (registry == (void *) NULL)
201 return((void *) NULL);
202 registry_info=(RegistryInfo *) GetValueFromSplayTree(registry,key);
203 if (registry_info == (void *) NULL)
204 {
205 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
anthonye5b39652012-04-21 05:37:29 +0000206 "UnableToGetRegistryID","'%s'",key);
cristy3ed852e2009-09-05 21:47:34 +0000207 return((void *) NULL);
208 }
209 value=(void *) NULL;
210 switch (type)
211 {
212 case ImageRegistryType:
213 {
214 if (type == registry_info->type)
215 value=(void *) CloneImageList((Image *) registry_info->value,exception);
216 break;
217 }
218 case ImageInfoRegistryType:
219 {
220 if (type == registry_info->type)
221 value=(void *) CloneImageInfo((ImageInfo *) registry_info->value);
222 break;
223 }
224 case StringRegistryType:
225 {
226 switch (registry_info->type)
227 {
228 case ImageRegistryType:
229 {
230 value=(Image *) ConstantString(((Image *)
231 registry_info->value)->filename);
232 break;
233 }
234 case ImageInfoRegistryType:
235 {
236 value=(Image *) ConstantString(((ImageInfo *)
237 registry_info->value)->filename);
238 break;
239 }
240 case StringRegistryType:
241 {
242 value=(void *) ConstantString((char *) registry_info->value);
243 break;
244 }
245 default:
246 break;
247 }
248 break;
249 }
250 default:
251 break;
252 }
253 return(value);
254}
255
256/*
257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258% %
259% %
260% %
261% G e t N e x t I m a g e R e g i s t r y %
262% %
263% %
264% %
265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266%
267% GetNextImageRegistry() gets the next image registry value.
268%
269% The format of the GetNextImageRegistry method is:
270%
271% char *GetNextImageRegistry(void)
272%
273*/
274MagickExport char *GetNextImageRegistry(void)
275{
276 if (IsEventLogging() != MagickFalse)
277 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
278 if (registry == (void *) NULL)
279 return((char *) NULL);
280 return((char *) GetNextKeyInSplayTree(registry));
281}
282
283/*
284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285% %
286% %
287% %
cristyf34a1452009-10-24 22:29:27 +0000288+ R e g i s t r y C o m p o n e n t G e n e s i s %
cristy41c3c772009-10-19 02:17:37 +0000289% %
290% %
291% %
292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293%
cristyf34a1452009-10-24 22:29:27 +0000294% RegistryComponentGenesis() instantiates the registry component.
cristy41c3c772009-10-19 02:17:37 +0000295%
cristyf34a1452009-10-24 22:29:27 +0000296% The format of the RegistryComponentGenesis method is:
cristy41c3c772009-10-19 02:17:37 +0000297%
cristyf34a1452009-10-24 22:29:27 +0000298% MagickBooleanType RegistryComponentGenesis(void)
cristy41c3c772009-10-19 02:17:37 +0000299%
300*/
cristy5ff4eaf2011-09-03 01:38:02 +0000301MagickPrivate MagickBooleanType RegistryComponentGenesis(void)
cristy41c3c772009-10-19 02:17:37 +0000302{
cristy165b6092009-10-26 13:52:10 +0000303 AcquireSemaphoreInfo(&registry_semaphore);
cristy41c3c772009-10-19 02:17:37 +0000304 return(MagickTrue);
305}
306
307/*
308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309% %
310% %
311% %
cristyf34a1452009-10-24 22:29:27 +0000312% R e g i s t r y C o m p o n e n t T e r m i n u s %
313% %
314% %
315% %
316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317%
318% RegistryComponentTerminus() destroys the registry component.
319%
320% The format of the DestroyDefines method is:
321%
322% void RegistryComponentTerminus(void)
323%
324*/
cristy5ff4eaf2011-09-03 01:38:02 +0000325MagickPrivate void RegistryComponentTerminus(void)
cristyf34a1452009-10-24 22:29:27 +0000326{
cristy18b17442009-10-25 18:36:48 +0000327 if (registry_semaphore == (SemaphoreInfo *) NULL)
328 AcquireSemaphoreInfo(&registry_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000329 LockSemaphoreInfo(registry_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000330 if (IsEventLogging() != MagickFalse)
331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
332 if (registry != (void *) NULL)
333 registry=DestroySplayTree(registry);
334 instantiate_registry=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000335 UnlockSemaphoreInfo(registry_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000336 DestroySemaphoreInfo(&registry_semaphore);
337}
338
339/*
340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341% %
342% %
343% %
cristy3ed852e2009-09-05 21:47:34 +0000344% R e m o v e I m a g e R e g i s t r y %
345% %
346% %
347% %
348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349%
350% RemoveImageRegistry() removes a key from the image registry and returns its
351% value.
352%
353% The format of the RemoveImageRegistry method is:
354%
355% void *RemoveImageRegistry(const char *key)
356%
357% A description of each parameter follows:
358%
359% o key: the registry.
360%
361*/
362MagickExport void *RemoveImageRegistry(const char *key)
363{
364 if (IsEventLogging() != MagickFalse)
365 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
366 if (registry == (void *) NULL)
367 return((void *) NULL);
368 return(RemoveNodeFromSplayTree(registry,key));
369}
370
371/*
372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373% %
374% %
375% %
376% R e s e t I m a g e R e g i s t r y I t e r a t o r %
377% %
378% %
379% %
380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381%
382% ResetImageRegistryIterator() resets the registry iterator. Use it in
383% conjunction with GetNextImageRegistry() to iterate over all the values
384% in the image registry.
385%
386% The format of the ResetImageRegistryIterator method is:
387%
388% ResetImageRegistryIterator(void)
389%
390*/
391MagickExport void ResetImageRegistryIterator(void)
392{
393 if (IsEventLogging() != MagickFalse)
394 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
395 if (registry == (void *) NULL)
396 return;
397 ResetSplayTreeIterator(registry);
398}
399
400/*
401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402% %
403% %
404% %
405% S e t I m a g e R e g i s t r y %
406% %
407% %
408% %
409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
410%
411% SetImageRegistry() associates a value with an image registry key.
412%
413% The format of the SetImageRegistry method is:
414%
415% MagickBooleanType SetImageRegistry(const RegistryType type,
416% const char *key,const void *value,ExceptionInfo *exception)
417%
418% A description of each parameter follows:
419%
420% o type: the type.
421%
422% o key: the key.
423%
424% o value: the value.
425%
426% o exception: the exception.
427%
428*/
429
430static void *DestroyRegistryNode(void *registry_info)
431{
432 register RegistryInfo
433 *p;
cristy82b15832009-10-06 19:17:37 +0000434
cristy3ed852e2009-09-05 21:47:34 +0000435 p=(RegistryInfo *) registry_info;
436 switch (p->type)
437 {
438 case StringRegistryType:
439 default:
440 {
441 p->value=RelinquishMagickMemory(p->value);
442 break;
443 }
444 case ImageRegistryType:
445 {
446 p->value=(void *) DestroyImageList((Image *) p->value);
447 break;
448 }
449 case ImageInfoRegistryType:
450 {
451 p->value=(void *) DestroyImageInfo((ImageInfo *) p->value);
452 break;
453 }
cristy82b15832009-10-06 19:17:37 +0000454 }
cristy3ed852e2009-09-05 21:47:34 +0000455 return(RelinquishMagickMemory(p));
456}
457
458MagickExport MagickBooleanType SetImageRegistry(const RegistryType type,
459 const char *key,const void *value,ExceptionInfo *exception)
460{
461 MagickBooleanType
462 status;
463
464 RegistryInfo
465 *registry_info;
466
467 void
468 *clone_value;
469
470 if (IsEventLogging() != MagickFalse)
471 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
472 clone_value=(void *) NULL;
473 switch (type)
474 {
475 case StringRegistryType:
476 default:
477 {
478 const char
479 *string;
480
481 string=(const char *) value;
482 clone_value=(void *) ConstantString(string);
483 break;
484 }
485 case ImageRegistryType:
486 {
487 const Image
488 *image;
489
490 image=(const Image *) value;
491 if (image->signature != MagickSignature)
492 {
493 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
494 "UnableToSetRegistry","%s",key);
495 return(MagickFalse);
496 }
497 clone_value=(void *) CloneImageList(image,exception);
498 break;
499 }
500 case ImageInfoRegistryType:
501 {
502 const ImageInfo
503 *image_info;
504
505 image_info=(const ImageInfo *) value;
506 if (image_info->signature != MagickSignature)
507 {
508 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
509 "UnableToSetRegistry","%s",key);
510 return(MagickFalse);
511 }
512 clone_value=(void *) CloneImageInfo(image_info);
513 break;
514 }
515 }
516 if (clone_value == (void *) NULL)
517 return(MagickFalse);
cristy73bd4a52010-10-05 11:24:23 +0000518 registry_info=(RegistryInfo *) AcquireMagickMemory(sizeof(*registry_info));
cristy3ed852e2009-09-05 21:47:34 +0000519 if (registry_info == (RegistryInfo *) NULL)
520 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
521 (void) ResetMagickMemory(registry_info,0,sizeof(*registry_info));
522 registry_info->type=type;
523 registry_info->value=clone_value;
524 registry_info->signature=MagickSignature;
cristy41c3c772009-10-19 02:17:37 +0000525 if ((registry == (SplayTreeInfo *) NULL) &&
526 (instantiate_registry == MagickFalse))
527 {
cristy4e1dff62009-10-25 20:36:03 +0000528 if (registry_semaphore == (SemaphoreInfo *) NULL)
529 AcquireSemaphoreInfo(&registry_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000530 LockSemaphoreInfo(registry_semaphore);
cristy41c3c772009-10-19 02:17:37 +0000531 if ((registry == (SplayTreeInfo *) NULL) &&
532 (instantiate_registry == MagickFalse))
533 {
534 registry=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
535 DestroyRegistryNode);
536 instantiate_registry=MagickTrue;
537 }
cristyf84a1932010-01-03 18:00:18 +0000538 UnlockSemaphoreInfo(registry_semaphore);
cristy41c3c772009-10-19 02:17:37 +0000539 }
cristy3ed852e2009-09-05 21:47:34 +0000540 status=AddValueToSplayTree(registry,ConstantString(key),registry_info);
541 return(status);
542}