blob: 5971965d74b24750efde00380a560740c2cde2de [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% %
20% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
21% 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*/
43#include "magick/studio.h"
44#include "magick/exception.h"
45#include "magick/exception-private.h"
46#include "magick/image.h"
47#include "magick/list.h"
48#include "magick/memory_.h"
49#include "magick/registry.h"
50#include "magick/splay-tree.h"
51#include "magick/string_.h"
52#include "magick/utility.h"
53
54/*
55 Typedef declarations.
56*/
57typedef struct _RegistryInfo
58{
59 RegistryType
60 type;
61
62 void
63 *value;
64
65 unsigned long
66 signature;
67} RegistryInfo;
68
69/*
70 Static declarations.
71*/
72static SplayTreeInfo
73 *registry = (SplayTreeInfo *) NULL;
cristy41c3c772009-10-19 02:17:37 +000074
75static SemaphoreInfo
76 *registry_semaphore = (SemaphoreInfo *) NULL;
77
78static volatile MagickBooleanType
79 instantiate_registry = MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +000080
81/*
82%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83% %
84% %
85% %
86% D e f i n e I m a g e R e g i s t r y %
87% %
88% %
89% %
90%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91%
92% DefineImageRegistry() associates a key/value pair with the image registry.
93%
94% The format of the DefineImageRegistry method is:
95%
96% MagickBooleanType DefineImageRegistry(const RegistryType type,
97% const char *option,ExceptionInfo *exception)
98%
99% A description of each parameter follows:
100%
101% o type: the type.
102%
103% o option: the option.
104%
105% o exception: the exception.
106%
107*/
108MagickExport MagickBooleanType DefineImageRegistry(const RegistryType type,
109 const char *option,ExceptionInfo *exception)
110{
111 char
112 key[MaxTextExtent],
113 value[MaxTextExtent];
114
115 register char
116 *p;
117
118 assert(option != (const char *) NULL);
119 (void) CopyMagickString(key,option,MaxTextExtent);
120 for (p=key; *p != '\0'; p++)
121 if (*p == '=')
122 break;
123 *value='\0';
124 if (*p == '=')
125 (void) CopyMagickString(value,p+1,MaxTextExtent);
126 *p='\0';
127 return(SetImageRegistry(type,key,value,exception));
128}
129
130/*
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132% %
133% %
134% %
135% D e l e t e I m a g e R e g i s t r y %
136% %
137% %
138% %
139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140%
141% DeleteImageRegistry() deletes a key from the image registry.
142%
143% The format of the DeleteImageRegistry method is:
144%
145% MagickBooleanType DeleteImageRegistry(const char *key)
146%
147% A description of each parameter follows:
148%
149% o key: the registry.
150%
151*/
152MagickExport MagickBooleanType DeleteImageRegistry(const char *key)
153{
154 if (IsEventLogging() != MagickFalse)
155 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
156 if (registry == (void *) NULL)
157 return(MagickFalse);
158 return(DeleteNodeFromSplayTree(registry,key));
159}
160
161/*
162%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163% %
164% %
165% %
cristy3ed852e2009-09-05 21:47:34 +0000166% G e t I m a g e R e g i s t r y %
167% %
168% %
169% %
170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171%
172% GetImageRegistry() returns a value associated with an image registry key.
173%
174% The format of the GetImageRegistry method is:
175%
176% void *GetImageRegistry(const RegistryType type,const char *key,
177% ExceptionInfo *exception)
178%
179% A description of each parameter follows:
180%
181% o type: the type.
182%
183% o key: the key.
184%
185% o exception: the exception.
186%
187*/
188MagickExport void *GetImageRegistry(const RegistryType type,const char *key,
189 ExceptionInfo *exception)
190{
191 void
192 *value;
193
194 RegistryInfo
195 *registry_info;
196
197 if (IsEventLogging() != MagickFalse)
198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
199 if (registry == (void *) NULL)
200 return((void *) NULL);
201 registry_info=(RegistryInfo *) GetValueFromSplayTree(registry,key);
202 if (registry_info == (void *) NULL)
203 {
204 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
205 "UnableToGetRegistryID","`%s'",key);
206 return((void *) NULL);
207 }
208 value=(void *) NULL;
209 switch (type)
210 {
211 case ImageRegistryType:
212 {
213 if (type == registry_info->type)
214 value=(void *) CloneImageList((Image *) registry_info->value,exception);
215 break;
216 }
217 case ImageInfoRegistryType:
218 {
219 if (type == registry_info->type)
220 value=(void *) CloneImageInfo((ImageInfo *) registry_info->value);
221 break;
222 }
223 case StringRegistryType:
224 {
225 switch (registry_info->type)
226 {
227 case ImageRegistryType:
228 {
229 value=(Image *) ConstantString(((Image *)
230 registry_info->value)->filename);
231 break;
232 }
233 case ImageInfoRegistryType:
234 {
235 value=(Image *) ConstantString(((ImageInfo *)
236 registry_info->value)->filename);
237 break;
238 }
239 case StringRegistryType:
240 {
241 value=(void *) ConstantString((char *) registry_info->value);
242 break;
243 }
244 default:
245 break;
246 }
247 break;
248 }
249 default:
250 break;
251 }
252 return(value);
253}
254
255/*
256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257% %
258% %
259% %
260% G e t N e x t I m a g e R e g i s t r y %
261% %
262% %
263% %
264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265%
266% GetNextImageRegistry() gets the next image registry value.
267%
268% The format of the GetNextImageRegistry method is:
269%
270% char *GetNextImageRegistry(void)
271%
272*/
273MagickExport char *GetNextImageRegistry(void)
274{
275 if (IsEventLogging() != MagickFalse)
276 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
277 if (registry == (void *) NULL)
278 return((char *) NULL);
279 return((char *) GetNextKeyInSplayTree(registry));
280}
281
282/*
283%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284% %
285% %
286% %
cristyf34a1452009-10-24 22:29:27 +0000287+ 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 +0000288% %
289% %
290% %
291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292%
cristyf34a1452009-10-24 22:29:27 +0000293% RegistryComponentGenesis() instantiates the registry component.
cristy41c3c772009-10-19 02:17:37 +0000294%
cristyf34a1452009-10-24 22:29:27 +0000295% The format of the RegistryComponentGenesis method is:
cristy41c3c772009-10-19 02:17:37 +0000296%
cristyf34a1452009-10-24 22:29:27 +0000297% MagickBooleanType RegistryComponentGenesis(void)
cristy41c3c772009-10-19 02:17:37 +0000298%
299*/
cristyf34a1452009-10-24 22:29:27 +0000300MagickExport MagickBooleanType RegistryComponentGenesis(void)
cristy41c3c772009-10-19 02:17:37 +0000301{
cristy18b17442009-10-25 18:36:48 +0000302 assert(registry_semaphore == (SemaphoreInfo *) NULL);
303 registry_semaphore=AllocateSemaphoreInfo();
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*/
325MagickExport void RegistryComponentTerminus(void)
326{
cristy18b17442009-10-25 18:36:48 +0000327 if (registry_semaphore == (SemaphoreInfo *) NULL)
328 AcquireSemaphoreInfo(&registry_semaphore);
329 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;
cristy18b17442009-10-25 18:36:48 +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);
518 registry_info=(RegistryInfo *) AcquireMagickMemory(sizeof(*registry_info));
519 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);
cristy18b17442009-10-25 18:36:48 +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 }
cristy18b17442009-10-25 18:36:48 +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}