1 /*
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 % Cristy %
17 % March 2000 %
18 % %
19 % %
20 % Copyright 1999-2016 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 "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"
50 #include "MagickCore/registry-private.h"
51 #include "MagickCore/splay-tree.h"
52 #include "MagickCore/string_.h"
53 #include "MagickCore/utility.h"
54
55 /*
56 Typedef declarations.
57 */
58 typedef struct _RegistryInfo
59 {
60 RegistryType
61 type;
62
63 void
64 *value;
65
66 size_t
67 signature;
68 } RegistryInfo;
69
70 /*
71 Static declarations.
72 */
73 static SplayTreeInfo
74 *registry = (SplayTreeInfo *) NULL;
75
76 static SemaphoreInfo
77 *registry_semaphore = (SemaphoreInfo *) NULL;
78
79 /*
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 % %
82 % %
83 % %
84 % D e f i n e I m a g e R e g i s t r y %
85 % %
86 % %
87 % %
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 %
90 % DefineImageRegistry() associates a key/value pair with the image registry.
91 %
92 % The format of the DefineImageRegistry method is:
93 %
94 % MagickBooleanType DefineImageRegistry(const RegistryType type,
95 % const char *option,ExceptionInfo *exception)
96 %
97 % A description of each parameter follows:
98 %
99 % o type: the type.
100 %
101 % o option: the option.
102 %
103 % o exception: the exception.
104 %
105 */
DefineImageRegistry(const RegistryType type,const char * option,ExceptionInfo * exception)106 MagickExport MagickBooleanType DefineImageRegistry(const RegistryType type,
107 const char *option,ExceptionInfo *exception)
108 {
109 char
110 key[MagickPathExtent],
111 value[MagickPathExtent];
112
113 register char
114 *p;
115
116 assert(option != (const char *) NULL);
117 (void) CopyMagickString(key,option,MagickPathExtent);
118 for (p=key; *p != '\0'; p++)
119 if (*p == '=')
120 break;
121 *value='\0';
122 if (*p == '=')
123 (void) CopyMagickString(value,p+1,MagickPathExtent);
124 *p='\0';
125 return(SetImageRegistry(type,key,value,exception));
126 }
127
128 /*
129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130 % %
131 % %
132 % %
133 % D e l e t e I m a g e R e g i s t r y %
134 % %
135 % %
136 % %
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 %
139 % DeleteImageRegistry() deletes a key from the image registry.
140 %
141 % The format of the DeleteImageRegistry method is:
142 %
143 % MagickBooleanType DeleteImageRegistry(const char *key)
144 %
145 % A description of each parameter follows:
146 %
147 % o key: the registry.
148 %
149 */
DeleteImageRegistry(const char * key)150 MagickExport MagickBooleanType DeleteImageRegistry(const char *key)
151 {
152 if (IsEventLogging() != MagickFalse)
153 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
154 if (registry == (void *) NULL)
155 return(MagickFalse);
156 return(DeleteNodeFromSplayTree(registry,key));
157 }
158
159 /*
160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
161 % %
162 % %
163 % %
164 % G e t I m a g e R e g i s t r y %
165 % %
166 % %
167 % %
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 %
170 % GetImageRegistry() returns a value associated with an image registry key.
171 %
172 % The format of the GetImageRegistry method is:
173 %
174 % void *GetImageRegistry(const RegistryType type,const char *key,
175 % ExceptionInfo *exception)
176 %
177 % A description of each parameter follows:
178 %
179 % o type: the type.
180 %
181 % o key: the key.
182 %
183 % o exception: the exception.
184 %
185 */
GetImageRegistry(const RegistryType type,const char * key,ExceptionInfo * exception)186 MagickExport void *GetImageRegistry(const RegistryType type,const char *key,
187 ExceptionInfo *exception)
188 {
189 void
190 *value;
191
192 RegistryInfo
193 *registry_info;
194
195 if (IsEventLogging() != MagickFalse)
196 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
197 if (registry == (void *) NULL)
198 return((void *) NULL);
199 registry_info=(RegistryInfo *) GetValueFromSplayTree(registry,key);
200 if (registry_info == (void *) NULL)
201 {
202 (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
203 "UnableToGetRegistryID","`%s'",key);
204 return((void *) NULL);
205 }
206 value=(void *) NULL;
207 switch (type)
208 {
209 case ImageRegistryType:
210 {
211 if (type == registry_info->type)
212 value=(void *) CloneImageList((Image *) registry_info->value,exception);
213 break;
214 }
215 case ImageInfoRegistryType:
216 {
217 if (type == registry_info->type)
218 value=(void *) CloneImageInfo((ImageInfo *) registry_info->value);
219 break;
220 }
221 case StringRegistryType:
222 {
223 switch (registry_info->type)
224 {
225 case ImageRegistryType:
226 {
227 value=(Image *) ConstantString(((Image *)
228 registry_info->value)->filename);
229 break;
230 }
231 case ImageInfoRegistryType:
232 {
233 value=(Image *) ConstantString(((ImageInfo *)
234 registry_info->value)->filename);
235 break;
236 }
237 case StringRegistryType:
238 {
239 value=(void *) ConstantString((char *) registry_info->value);
240 break;
241 }
242 default:
243 break;
244 }
245 break;
246 }
247 default:
248 break;
249 }
250 return(value);
251 }
252
253 /*
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 % %
256 % %
257 % %
258 % G e t N e x t I m a g e R e g i s t r y %
259 % %
260 % %
261 % %
262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 %
264 % GetNextImageRegistry() gets the next image registry value.
265 %
266 % The format of the GetNextImageRegistry method is:
267 %
268 % char *GetNextImageRegistry(void)
269 %
270 */
GetNextImageRegistry(void)271 MagickExport char *GetNextImageRegistry(void)
272 {
273 if (IsEventLogging() != MagickFalse)
274 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
275 if (registry == (void *) NULL)
276 return((char *) NULL);
277 return((char *) GetNextKeyInSplayTree(registry));
278 }
279
280 /*
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282 % %
283 % %
284 % %
285 + R e g i s t r y C o m p o n e n t G e n e s i s %
286 % %
287 % %
288 % %
289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290 %
291 % RegistryComponentGenesis() instantiates the registry component.
292 %
293 % The format of the RegistryComponentGenesis method is:
294 %
295 % MagickBooleanType RegistryComponentGenesis(void)
296 %
297 */
RegistryComponentGenesis(void)298 MagickPrivate MagickBooleanType RegistryComponentGenesis(void)
299 {
300 if (registry_semaphore == (SemaphoreInfo *) NULL)
301 registry_semaphore=AcquireSemaphoreInfo();
302 return(MagickTrue);
303 }
304
305 /*
306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 % %
308 % %
309 % %
310 % 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 %
311 % %
312 % %
313 % %
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315 %
316 % RegistryComponentTerminus() destroys the registry component.
317 %
318 % The format of the DestroyDefines method is:
319 %
320 % void RegistryComponentTerminus(void)
321 %
322 */
RegistryComponentTerminus(void)323 MagickPrivate void RegistryComponentTerminus(void)
324 {
325 if (registry_semaphore == (SemaphoreInfo *) NULL)
326 ActivateSemaphoreInfo(®istry_semaphore);
327 LockSemaphoreInfo(registry_semaphore);
328 if (IsEventLogging() != MagickFalse)
329 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
330 if (registry != (void *) NULL)
331 registry=DestroySplayTree(registry);
332 UnlockSemaphoreInfo(registry_semaphore);
333 RelinquishSemaphoreInfo(®istry_semaphore);
334 }
335
336 /*
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
338 % %
339 % %
340 % %
341 % R e m o v e I m a g e R e g i s t r y %
342 % %
343 % %
344 % %
345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 %
347 % RemoveImageRegistry() removes a key from the image registry and returns its
348 % value.
349 %
350 % The format of the RemoveImageRegistry method is:
351 %
352 % void *RemoveImageRegistry(const char *key)
353 %
354 % A description of each parameter follows:
355 %
356 % o key: the registry.
357 %
358 */
RemoveImageRegistry(const char * key)359 MagickExport void *RemoveImageRegistry(const char *key)
360 {
361 if (IsEventLogging() != MagickFalse)
362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
363 if (registry == (void *) NULL)
364 return((void *) NULL);
365 return(RemoveNodeFromSplayTree(registry,key));
366 }
367
368 /*
369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
370 % %
371 % %
372 % %
373 % 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 %
374 % %
375 % %
376 % %
377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378 %
379 % ResetImageRegistryIterator() resets the registry iterator. Use it in
380 % conjunction with GetNextImageRegistry() to iterate over all the values
381 % in the image registry.
382 %
383 % The format of the ResetImageRegistryIterator method is:
384 %
385 % ResetImageRegistryIterator(void)
386 %
387 */
ResetImageRegistryIterator(void)388 MagickExport void ResetImageRegistryIterator(void)
389 {
390 if (IsEventLogging() != MagickFalse)
391 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
392 if (registry == (void *) NULL)
393 return;
394 ResetSplayTreeIterator(registry);
395 }
396
397 /*
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 % %
400 % %
401 % %
402 % S e t I m a g e R e g i s t r y %
403 % %
404 % %
405 % %
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 %
408 % SetImageRegistry() associates a value with an image registry key.
409 %
410 % The format of the SetImageRegistry method is:
411 %
412 % MagickBooleanType SetImageRegistry(const RegistryType type,
413 % const char *key,const void *value,ExceptionInfo *exception)
414 %
415 % A description of each parameter follows:
416 %
417 % o type: the type.
418 %
419 % o key: the key.
420 %
421 % o value: the value.
422 %
423 % o exception: the exception.
424 %
425 */
426
DestroyRegistryNode(void * registry_info)427 static void *DestroyRegistryNode(void *registry_info)
428 {
429 register RegistryInfo
430 *p;
431
432 p=(RegistryInfo *) registry_info;
433 switch (p->type)
434 {
435 case StringRegistryType:
436 default:
437 {
438 p->value=RelinquishMagickMemory(p->value);
439 break;
440 }
441 case ImageRegistryType:
442 {
443 p->value=(void *) DestroyImageList((Image *) p->value);
444 break;
445 }
446 case ImageInfoRegistryType:
447 {
448 p->value=(void *) DestroyImageInfo((ImageInfo *) p->value);
449 break;
450 }
451 }
452 return(RelinquishMagickMemory(p));
453 }
454
SetImageRegistry(const RegistryType type,const char * key,const void * value,ExceptionInfo * exception)455 MagickExport MagickBooleanType SetImageRegistry(const RegistryType type,
456 const char *key,const void *value,ExceptionInfo *exception)
457 {
458 MagickBooleanType
459 status;
460
461 RegistryInfo
462 *registry_info;
463
464 void
465 *clone_value;
466
467 if (IsEventLogging() != MagickFalse)
468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
469 if (value == (const void *) NULL)
470 return(MagickFalse);
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 != MagickCoreSignature)
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 != MagickCoreSignature)
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);
517 registry_info=(RegistryInfo *) AcquireMagickMemory(sizeof(*registry_info));
518 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=MagickCoreSignature;
524 if (registry == (SplayTreeInfo *) NULL)
525 {
526 if (registry_semaphore == (SemaphoreInfo *) NULL)
527 ActivateSemaphoreInfo(®istry_semaphore);
528 LockSemaphoreInfo(registry_semaphore);
529 if (registry == (SplayTreeInfo *) NULL)
530 registry=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
531 DestroyRegistryNode);
532 UnlockSemaphoreInfo(registry_semaphore);
533 }
534 status=AddValueToSplayTree(registry,ConstantString(key),registry_info);
535 return(status);
536 }
537