blob: 6222cdef6f8ce8e45b1d8cd386d2bb30ac065369 [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% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 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*/
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{
cristy165b6092009-10-26 13:52:10 +0000302 AcquireSemaphoreInfo(&registry_semaphore);
cristy41c3c772009-10-19 02:17:37 +0000303 return(MagickTrue);
304}
305
306/*
307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308% %
309% %
310% %
cristyf34a1452009-10-24 22:29:27 +0000311% 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 %
312% %
313% %
314% %
315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316%
317% RegistryComponentTerminus() destroys the registry component.
318%
319% The format of the DestroyDefines method is:
320%
321% void RegistryComponentTerminus(void)
322%
323*/
324MagickExport void RegistryComponentTerminus(void)
325{
cristy18b17442009-10-25 18:36:48 +0000326 if (registry_semaphore == (SemaphoreInfo *) NULL)
327 AcquireSemaphoreInfo(&registry_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000328 LockSemaphoreInfo(registry_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000329 if (IsEventLogging() != MagickFalse)
330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
331 if (registry != (void *) NULL)
332 registry=DestroySplayTree(registry);
333 instantiate_registry=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000334 UnlockSemaphoreInfo(registry_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000335 DestroySemaphoreInfo(&registry_semaphore);
336}
337
338/*
339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340% %
341% %
342% %
cristy3ed852e2009-09-05 21:47:34 +0000343% R e m o v e I m a g e R e g i s t r y %
344% %
345% %
346% %
347%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348%
349% RemoveImageRegistry() removes a key from the image registry and returns its
350% value.
351%
352% The format of the RemoveImageRegistry method is:
353%
354% void *RemoveImageRegistry(const char *key)
355%
356% A description of each parameter follows:
357%
358% o key: the registry.
359%
360*/
361MagickExport void *RemoveImageRegistry(const char *key)
362{
363 if (IsEventLogging() != MagickFalse)
364 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
365 if (registry == (void *) NULL)
366 return((void *) NULL);
367 return(RemoveNodeFromSplayTree(registry,key));
368}
369
370/*
371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372% %
373% %
374% %
375% 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 %
376% %
377% %
378% %
379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380%
381% ResetImageRegistryIterator() resets the registry iterator. Use it in
382% conjunction with GetNextImageRegistry() to iterate over all the values
383% in the image registry.
384%
385% The format of the ResetImageRegistryIterator method is:
386%
387% ResetImageRegistryIterator(void)
388%
389*/
390MagickExport void ResetImageRegistryIterator(void)
391{
392 if (IsEventLogging() != MagickFalse)
393 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
394 if (registry == (void *) NULL)
395 return;
396 ResetSplayTreeIterator(registry);
397}
398
399/*
400%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401% %
402% %
403% %
404% S e t I m a g e R e g i s t r y %
405% %
406% %
407% %
408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409%
410% SetImageRegistry() associates a value with an image registry key.
411%
412% The format of the SetImageRegistry method is:
413%
414% MagickBooleanType SetImageRegistry(const RegistryType type,
415% const char *key,const void *value,ExceptionInfo *exception)
416%
417% A description of each parameter follows:
418%
419% o type: the type.
420%
421% o key: the key.
422%
423% o value: the value.
424%
425% o exception: the exception.
426%
427*/
428
429static void *DestroyRegistryNode(void *registry_info)
430{
431 register RegistryInfo
432 *p;
cristy82b15832009-10-06 19:17:37 +0000433
cristy3ed852e2009-09-05 21:47:34 +0000434 p=(RegistryInfo *) registry_info;
435 switch (p->type)
436 {
437 case StringRegistryType:
438 default:
439 {
440 p->value=RelinquishMagickMemory(p->value);
441 break;
442 }
443 case ImageRegistryType:
444 {
445 p->value=(void *) DestroyImageList((Image *) p->value);
446 break;
447 }
448 case ImageInfoRegistryType:
449 {
450 p->value=(void *) DestroyImageInfo((ImageInfo *) p->value);
451 break;
452 }
cristy82b15832009-10-06 19:17:37 +0000453 }
cristy3ed852e2009-09-05 21:47:34 +0000454 return(RelinquishMagickMemory(p));
455}
456
457MagickExport MagickBooleanType SetImageRegistry(const RegistryType type,
458 const char *key,const void *value,ExceptionInfo *exception)
459{
460 MagickBooleanType
461 status;
462
463 RegistryInfo
464 *registry_info;
465
466 void
467 *clone_value;
468
469 if (IsEventLogging() != MagickFalse)
470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
471 clone_value=(void *) NULL;
472 switch (type)
473 {
474 case StringRegistryType:
475 default:
476 {
477 const char
478 *string;
479
480 string=(const char *) value;
481 clone_value=(void *) ConstantString(string);
482 break;
483 }
484 case ImageRegistryType:
485 {
486 const Image
487 *image;
488
489 image=(const Image *) value;
490 if (image->signature != MagickSignature)
491 {
492 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
493 "UnableToSetRegistry","%s",key);
494 return(MagickFalse);
495 }
496 clone_value=(void *) CloneImageList(image,exception);
497 break;
498 }
499 case ImageInfoRegistryType:
500 {
501 const ImageInfo
502 *image_info;
503
504 image_info=(const ImageInfo *) value;
505 if (image_info->signature != MagickSignature)
506 {
507 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
508 "UnableToSetRegistry","%s",key);
509 return(MagickFalse);
510 }
511 clone_value=(void *) CloneImageInfo(image_info);
512 break;
513 }
514 }
515 if (clone_value == (void *) NULL)
516 return(MagickFalse);
cristy90823212009-12-12 20:48:33 +0000517 registry_info=(RegistryInfo *) AcquireAlignedMemory(1,sizeof(*registry_info));
cristy3ed852e2009-09-05 21:47:34 +0000518 if (registry_info == (RegistryInfo *) NULL)
519 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
520 (void) ResetMagickMemory(registry_info,0,sizeof(*registry_info));
521 registry_info->type=type;
522 registry_info->value=clone_value;
523 registry_info->signature=MagickSignature;
cristy41c3c772009-10-19 02:17:37 +0000524 if ((registry == (SplayTreeInfo *) NULL) &&
525 (instantiate_registry == MagickFalse))
526 {
cristy4e1dff62009-10-25 20:36:03 +0000527 if (registry_semaphore == (SemaphoreInfo *) NULL)
528 AcquireSemaphoreInfo(&registry_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000529 LockSemaphoreInfo(registry_semaphore);
cristy41c3c772009-10-19 02:17:37 +0000530 if ((registry == (SplayTreeInfo *) NULL) &&
531 (instantiate_registry == MagickFalse))
532 {
533 registry=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
534 DestroyRegistryNode);
535 instantiate_registry=MagickTrue;
536 }
cristyf84a1932010-01-03 18:00:18 +0000537 UnlockSemaphoreInfo(registry_semaphore);
cristy41c3c772009-10-19 02:17:37 +0000538 }
cristy3ed852e2009-09-05 21:47:34 +0000539 status=AddValueToSplayTree(registry,ConstantString(key),registry_info);
540 return(status);
541}