blob: c5479f1e29ffae44ae90f5a84c2d3b3564b1d006 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
cristy670aa3c2011-11-03 00:54:00 +00006% SSSSS TTTTT RRRR IIIII N N GGGG %
7% SS T R R I NN N G %
8% SSS T RRRR I N N N G GGG %
9% SS T R R I N NN G G %
10% SSSSS T R R IIIII N N GGGG %
cristy3ed852e2009-09-05 21:47:34 +000011% %
12% %
cristy670aa3c2011-11-03 00:54:00 +000013% MagickCore String Methods %
cristy3ed852e2009-09-05 21:47:34 +000014% %
cristy670aa3c2011-11-03 00:54:00 +000015% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy670aa3c2011-11-03 00:54:00 +000017% August 2003 %
cristy3ed852e2009-09-05 21:47:34 +000018% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
cristy670aa3c2011-11-03 00:54:00 +000023% You may not use this file except in compliance with the license. You may %
cristy99bbf2c2011-09-26 18:27:50 +000024% obtain a copy of the license at %
cristy3ed852e2009-09-05 21:47:34 +000025% %
26% http://www.imagemagick.org/script/license.php %
27% %
cristy99bbf2c2011-09-26 18:27:50 +000028% 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. %
cristy670aa3c2011-11-03 00:54:00 +000031% See the license for the specific language governing permissions and %
cristy99bbf2c2011-09-26 18:27:50 +000032% limitations under the license. %
cristy3ed852e2009-09-05 21:47:34 +000033% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
cristy99bbf2c2011-09-26 18:27:50 +000040 include declarations.
cristy3ed852e2009-09-05 21:47:34 +000041*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/blob-private.h"
45#include "MagickCore/exception.h"
46#include "MagickCore/exception-private.h"
47#include "MagickCore/list.h"
48#include "MagickCore/locale_.h"
49#include "MagickCore/log.h"
50#include "MagickCore/memory_.h"
cristyd2d11ec2012-03-28 13:53:49 +000051#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000052#include "MagickCore/property.h"
53#include "MagickCore/resource_.h"
54#include "MagickCore/signature-private.h"
55#include "MagickCore/string_.h"
anthonyb1d483a2012-04-14 12:53:56 +000056#include "MagickCore/string-private.h"
cristy18c6c272011-09-23 14:40:37 +000057#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000058
59/*
cristy99bbf2c2011-09-26 18:27:50 +000060 static declarations.
cristy3ed852e2009-09-05 21:47:34 +000061*/
62#if !defined(MAGICKCORE_HAVE_STRCASECMP) || !defined(MAGICKCORE_HAVE_STRNCASECMP)
63static const unsigned char
cristy8e7a4612013-09-16 22:10:27 +000064 AsciiMap[] =
cristy3ed852e2009-09-05 21:47:34 +000065 {
66 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
67 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
68 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
69 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
70 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
71 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
72 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
73 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
74 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
75 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
76 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
77 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
78 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
79 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
80 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
81 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
82 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
83 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
84 0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
85 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
86 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
87 0xfc, 0xfd, 0xfe, 0xff,
88 };
89#endif
90
91/*
92%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93% %
94% %
95% %
96% A c q u i r e S t r i n g %
97% %
98% %
99% %
100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101%
anthony104f8932012-05-13 01:54:53 +0000102% AcquireString() returns an new extented string, containing a clone of the
103% given string.
cristy3ed852e2009-09-05 21:47:34 +0000104%
anthony104f8932012-05-13 01:54:53 +0000105% An extended string is the string length, plus an extra MaxTextExtent space
cristy5364f9c2013-12-28 23:29:28 +0000106% to allow for the string to be actively worked on.
anthony104f8932012-05-13 01:54:53 +0000107%
108% The returned string shoud be freed using DestoryString().
anthonyb1d483a2012-04-14 12:53:56 +0000109%
cristy3ed852e2009-09-05 21:47:34 +0000110% The format of the AcquireString method is:
111%
112% char *AcquireString(const char *source)
113%
114% A description of each parameter follows:
115%
116% o source: A character string.
117%
118*/
119MagickExport char *AcquireString(const char *source)
120{
121 char
122 *destination;
123
124 size_t
125 length;
126
127 length=0;
128 if (source != (char *) NULL)
129 length+=strlen(source);
cristy54aad5e2010-09-03 16:02:04 +0000130 if (~length < MaxTextExtent)
131 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
132 destination=(char *) AcquireQuantumMemory(length+MaxTextExtent,
133 sizeof(*destination));
cristy3ed852e2009-09-05 21:47:34 +0000134 if (destination == (char *) NULL)
135 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
136 *destination='\0';
137 if (source != (char *) NULL)
cristy54aad5e2010-09-03 16:02:04 +0000138 (void) memcpy(destination,source,length*sizeof(*destination));
139 destination[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000140 return(destination);
141}
142
143/*
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145% %
146% %
147% %
148% A c q u i r e S t r i n g I n f o %
149% %
150% %
151% %
152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153%
154% AcquireStringInfo() allocates the StringInfo structure.
155%
156% The format of the AcquireStringInfo method is:
157%
158% StringInfo *AcquireStringInfo(const size_t length)
159%
160% A description of each parameter follows:
161%
162% o length: the string length.
163%
164*/
165MagickExport StringInfo *AcquireStringInfo(const size_t length)
166{
167 StringInfo
168 *string_info;
169
cristy73bd4a52010-10-05 11:24:23 +0000170 string_info=(StringInfo *) AcquireMagickMemory(sizeof(*string_info));
cristy3ed852e2009-09-05 21:47:34 +0000171 if (string_info == (StringInfo *) NULL)
172 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
173 (void) ResetMagickMemory(string_info,0,sizeof(*string_info));
174 string_info->signature=MagickSignature;
175 string_info->length=length;
cristy8a68c242014-04-07 20:43:37 +0000176 string_info->datum=(unsigned char *) NULL;
177 if (~string_info->length >= (MaxTextExtent-1))
178 string_info->datum=(unsigned char *) AcquireQuantumMemory(
179 string_info->length+MaxTextExtent,sizeof(*string_info->datum));
180 if (string_info->datum == (unsigned char *) NULL)
181 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000182 return(string_info);
183}
184
185/*
186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187% %
188% %
189% %
cristy8723e4b2011-09-01 13:11:19 +0000190% B l o b T o S t r i n g I n f o %
191% %
192% %
193% %
194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195%
anthony104f8932012-05-13 01:54:53 +0000196% BlobToStringInfo() returns the contents of a blob as a StringInfo structure
197% with MaxTextExtent extra space.
cristy8723e4b2011-09-01 13:11:19 +0000198%
199% The format of the BlobToStringInfo method is:
200%
201% StringInfo *BlobToStringInfo(const void *blob,const size_t length)
202%
203% A description of each parameter follows:
204%
205% o blob: the blob.
206%
207% o length: the length of the blob.
208%
209*/
210MagickExport StringInfo *BlobToStringInfo(const void *blob,const size_t length)
211{
212 StringInfo
213 *string_info;
214
215 string_info=AcquireStringInfo(0);
cristy5ce7dac2014-05-28 12:22:17 +0000216 if (~length < MaxTextExtent)
217 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristyf8316342011-09-01 13:55:00 +0000218 string_info->length=length;
cristy5ce7dac2014-05-28 12:22:17 +0000219 if (string_info->datum == (unsigned char *) NULL)
220 string_info->datum=(unsigned char *) AcquireQuantumMemory(length+
221 MaxTextExtent,sizeof(*string_info->datum));
222 else
223 string_info->datum=(unsigned char *) ResizeQuantumMemory(string_info->datum,
224 length+MaxTextExtent,sizeof(*string_info->datum));
cristy8723e4b2011-09-01 13:11:19 +0000225 if (string_info->datum == (unsigned char *) NULL)
226 {
227 string_info=DestroyStringInfo(string_info);
228 return((StringInfo *) NULL);
229 }
230 if (blob != (const void *) NULL)
231 (void) memcpy(string_info->datum,blob,length);
232 return(string_info);
233}
234
235/*
236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237% %
238% %
239% %
cristy3ed852e2009-09-05 21:47:34 +0000240% C l o n e S t r i n g %
241% %
242% %
243% %
244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245%
anthony104f8932012-05-13 01:54:53 +0000246% CloneString() replaces or frees the destination string to make it
247% a clone of the input string plus MaxTextExtent more space so the string may
248% be worked on on.
cristy3ed852e2009-09-05 21:47:34 +0000249%
anthony104f8932012-05-13 01:54:53 +0000250% If source is a NULL pointer the destination string will be freed and set to
251% a NULL pointer. A pointer to the stored in the destination is also returned.
anthony72feaa62012-01-17 06:46:23 +0000252%
anthony104f8932012-05-13 01:54:53 +0000253% When finished the non-NULL string should be freed using DestoryString()
254% or using CloneString() with a NULL pointed for the source.
anthony06762232012-04-29 11:45:40 +0000255%
cristy3ed852e2009-09-05 21:47:34 +0000256% The format of the CloneString method is:
257%
258% char *CloneString(char **destination,const char *source)
259%
260% A description of each parameter follows:
261%
262% o destination: A pointer to a character string.
263%
264% o source: A character string.
265%
266*/
267MagickExport char *CloneString(char **destination,const char *source)
268{
269 size_t
270 length;
271
cristy3ed852e2009-09-05 21:47:34 +0000272 assert(destination != (char **) NULL);
273 if (source == (const char *) NULL)
274 {
275 if (*destination != (char *) NULL)
276 *destination=DestroyString(*destination);
277 return(*destination);
278 }
279 if (*destination == (char *) NULL)
280 {
281 *destination=AcquireString(source);
282 return(*destination);
283 }
284 length=strlen(source);
285 if (~length < MaxTextExtent)
286 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
287 *destination=(char *) ResizeQuantumMemory(*destination,length+MaxTextExtent,
cristyb936f702011-03-25 15:33:43 +0000288 sizeof(**destination));
cristy3ed852e2009-09-05 21:47:34 +0000289 if (*destination == (char *) NULL)
290 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristy54aad5e2010-09-03 16:02:04 +0000291 if (length != 0)
cristyf7e6ab42011-03-25 12:32:09 +0000292 (void) memcpy(*destination,source,length*sizeof(**destination));
cristy208cacf2010-09-03 02:24:42 +0000293 (*destination)[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000294 return(*destination);
295}
296
297/*
298%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299% %
300% %
301% %
302% C l o n e S t r i n g I n f o %
303% %
304% %
305% %
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307%
308% CloneStringInfo() clones a copy of the StringInfo structure.
309%
310% The format of the CloneStringInfo method is:
311%
312% StringInfo *CloneStringInfo(const StringInfo *string_info)
313%
314% A description of each parameter follows:
315%
316% o string_info: the string info.
317%
318*/
319MagickExport StringInfo *CloneStringInfo(const StringInfo *string_info)
320{
321 StringInfo
322 *clone_info;
323
cristy3ed852e2009-09-05 21:47:34 +0000324 assert(string_info != (StringInfo *) NULL);
325 assert(string_info->signature == MagickSignature);
326 clone_info=AcquireStringInfo(string_info->length);
327 if (string_info->length != 0)
cristy54aad5e2010-09-03 16:02:04 +0000328 (void) memcpy(clone_info->datum,string_info->datum,string_info->length+1);
cristy3ed852e2009-09-05 21:47:34 +0000329 return(clone_info);
330}
331
332/*
333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334% %
335% %
336% %
337% C o m p a r e S t r i n g I n f o %
338% %
339% %
340% %
341%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342%
343% CompareStringInfo() compares the two datums target and source. It returns
344% an integer less than, equal to, or greater than zero if target is found,
345% respectively, to be less than, to match, or be greater than source.
346%
347% The format of the CompareStringInfo method is:
348%
349% int CompareStringInfo(const StringInfo *target,const StringInfo *source)
350%
351% A description of each parameter follows:
352%
353% o target: the target string.
354%
355% o source: the source string.
356%
357*/
358
359static inline size_t MagickMin(const size_t x,const size_t y)
360{
361 if (x < y)
362 return(x);
363 return(y);
364}
365
366MagickExport int CompareStringInfo(const StringInfo *target,
367 const StringInfo *source)
368{
369 int
370 status;
371
cristy3ed852e2009-09-05 21:47:34 +0000372 assert(target != (StringInfo *) NULL);
373 assert(target->signature == MagickSignature);
374 assert(source != (StringInfo *) NULL);
375 assert(source->signature == MagickSignature);
376 status=memcmp(target->datum,source->datum,MagickMin(target->length,
377 source->length));
378 if (status != 0)
379 return(status);
380 if (target->length == source->length)
381 return(0);
382 return(target->length < source->length ? -1 : 1);
383}
384
385/*
386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387% %
388% %
389% %
390% C o n c a t e n a t e M a g i c k S t r i n g %
391% %
392% %
393% %
394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395%
396% ConcatenateMagickString() concatenates the source string to the destination
397% string. The destination buffer is always null-terminated even if the
398% string must be truncated.
399%
400% The format of the ConcatenateMagickString method is:
401%
402% size_t ConcatenateMagickString(char *destination,const char *source,
403% const size_t length)
404%
405% A description of each parameter follows:
406%
407% o destination: the destination string.
408%
409% o source: the source string.
410%
411% o length: the length of the destination string.
412%
413*/
414MagickExport size_t ConcatenateMagickString(char *destination,
415 const char *source,const size_t length)
416{
417 register char
418 *q;
419
420 register const char
421 *p;
422
423 register size_t
424 i;
425
426 size_t
427 count;
428
429 assert(destination != (char *) NULL);
430 assert(source != (const char *) NULL);
431 assert(length >= 1);
432 p=source;
433 q=destination;
434 i=length;
435 while ((i-- != 0) && (*q != '\0'))
436 q++;
437 count=(size_t) (q-destination);
438 i=length-count;
439 if (i == 0)
440 return(count+strlen(p));
441 while (*p != '\0')
442 {
443 if (i != 1)
444 {
445 *q++=(*p);
446 i--;
447 }
448 p++;
449 }
450 *q='\0';
451 return(count+(p-source));
452}
453
454/*
455%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456% %
457% %
458% %
459% C o n c a t e n a t e S t r i n g %
460% %
461% %
462% %
463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464%
465% ConcatenateString() appends a copy of string source, including the
466% terminating null character, to the end of string destination.
467%
468% The format of the ConcatenateString method is:
469%
470% MagickBooleanType ConcatenateString(char **destination,
471% const char *source)
472%
473% A description of each parameter follows:
474%
475% o destination: A pointer to a character string.
476%
477% o source: A character string.
478%
479*/
480MagickExport MagickBooleanType ConcatenateString(char **destination,
481 const char *source)
482{
483 size_t
cristy54aad5e2010-09-03 16:02:04 +0000484 destination_length,
cristy3ed852e2009-09-05 21:47:34 +0000485 length,
486 source_length;
487
488 assert(destination != (char **) NULL);
489 if (source == (const char *) NULL)
490 return(MagickTrue);
491 if (*destination == (char *) NULL)
492 {
493 *destination=AcquireString(source);
494 return(MagickTrue);
495 }
cristy54aad5e2010-09-03 16:02:04 +0000496 destination_length=strlen(*destination);
cristy3ed852e2009-09-05 21:47:34 +0000497 source_length=strlen(source);
cristy54aad5e2010-09-03 16:02:04 +0000498 length=destination_length;
cristy3ed852e2009-09-05 21:47:34 +0000499 if (~length < source_length)
500 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
501 length+=source_length;
502 if (~length < MaxTextExtent)
503 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
504 *destination=(char *) ResizeQuantumMemory(*destination,length+MaxTextExtent,
cristycf1667c2011-03-25 15:35:41 +0000505 sizeof(**destination));
cristy3ed852e2009-09-05 21:47:34 +0000506 if (*destination == (char *) NULL)
507 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
cristy54aad5e2010-09-03 16:02:04 +0000508 if (source_length != 0)
509 (void) memcpy((*destination)+destination_length,source,source_length);
510 (*destination)[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000511 return(MagickTrue);
512}
513
514/*
515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516% %
517% %
518% %
519% C o n c a t e n a t e S t r i n g I n f o %
520% %
521% %
522% %
523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524%
525% ConcatenateStringInfo() concatenates the source string to the destination
526% string.
527%
528% The format of the ConcatenateStringInfo method is:
529%
530% void ConcatenateStringInfo(StringInfo *string_info,
531% const StringInfo *source)
532%
533% A description of each parameter follows:
534%
535% o string_info: the string info.
536%
537% o source: the source string.
538%
539*/
540MagickExport void ConcatenateStringInfo(StringInfo *string_info,
541 const StringInfo *source)
542{
543 size_t
544 length;
545
cristy3ed852e2009-09-05 21:47:34 +0000546 assert(string_info != (StringInfo *) NULL);
547 assert(string_info->signature == MagickSignature);
548 assert(source != (const StringInfo *) NULL);
549 length=string_info->length;
550 if (~length < source->length)
551 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
552 SetStringInfoLength(string_info,length+source->length);
cristy54aad5e2010-09-03 16:02:04 +0000553 (void) memcpy(string_info->datum+length,source->datum,source->length);
cristy3ed852e2009-09-05 21:47:34 +0000554}
555
556/*
557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
558% %
559% %
560% %
561% C o n f i g u r e F i l e T o S t r i n g I n f o %
562% %
563% %
564% %
565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566%
567% ConfigureFileToStringInfo() returns the contents of a configure file as a
568% string.
569%
570% The format of the ConfigureFileToStringInfo method is:
571%
572% StringInfo *ConfigureFileToStringInfo(const char *filename)
573% ExceptionInfo *exception)
574%
575% A description of each parameter follows:
576%
577% o filename: the filename.
578%
579*/
cristy99bbf2c2011-09-26 18:27:50 +0000580MagickExport StringInfo *ConfigureFileToStringInfo(const char *filename)
cristy3ed852e2009-09-05 21:47:34 +0000581{
582 char
583 *string;
584
585 int
586 file;
587
588 MagickOffsetType
589 offset;
590
591 size_t
592 length;
593
594 StringInfo
595 *string_info;
596
597 void
598 *map;
599
600 assert(filename != (const char *) NULL);
cristy18c6c272011-09-23 14:40:37 +0000601 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000602 if (file == -1)
603 return((StringInfo *) NULL);
cristy7f317702011-02-18 20:40:28 +0000604 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000605 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
606 {
607 file=close(file)-1;
608 return((StringInfo *) NULL);
609 }
610 length=(size_t) offset;
611 string=(char *) NULL;
cristy37e0b382011-06-07 13:31:21 +0000612 if (~length >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000613 string=(char *) AcquireQuantumMemory(length+MaxTextExtent,sizeof(*string));
614 if (string == (char *) NULL)
615 {
616 file=close(file)-1;
617 return((StringInfo *) NULL);
618 }
619 map=MapBlob(file,ReadMode,0,length);
620 if (map != (void *) NULL)
621 {
cristy54aad5e2010-09-03 16:02:04 +0000622 (void) memcpy(string,map,length);
cristy3ed852e2009-09-05 21:47:34 +0000623 (void) UnmapBlob(map,length);
624 }
625 else
626 {
627 register size_t
628 i;
629
630 ssize_t
631 count;
632
cristy7f317702011-02-18 20:40:28 +0000633 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +0000634 for (i=0; i < length; i+=count)
635 {
636 count=read(file,string+i,(size_t) MagickMin(length-i,(size_t)
637 SSIZE_MAX));
638 if (count <= 0)
639 {
640 count=0;
641 if (errno != EINTR)
642 break;
643 }
644 }
645 if (i < length)
646 {
647 file=close(file)-1;
648 string=DestroyString(string);
649 return((StringInfo *) NULL);
650 }
651 }
652 string[length]='\0';
653 file=close(file)-1;
654 string_info=AcquireStringInfo(0);
cristy5ce7dac2014-05-28 12:22:17 +0000655 (void) CopyMagickString(string_info->path,filename,MaxTextExtent);
656 string_info->length=length;
cristy7fb9fc12014-05-28 01:18:24 +0000657 if (string_info->datum != (unsigned char *) NULL)
658 string_info->datum=(unsigned char *) RelinquishMagickMemory(
659 string_info->datum);
cristy3ed852e2009-09-05 21:47:34 +0000660 string_info->datum=(unsigned char *) string;
661 return(string_info);
662}
663
664/*
665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
666% %
667% %
668% %
669% C o n s t a n t S t r i n g %
670% %
671% %
672% %
673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
674%
anthony104f8932012-05-13 01:54:53 +0000675% ConstantString() allocates exactly the needed memory for a string and
676% copies the source string to that memory location. A NULL string pointer
677% will allocate an empty string containing just the NUL character.
cristy3ed852e2009-09-05 21:47:34 +0000678%
anthony104f8932012-05-13 01:54:53 +0000679% When finished the string should be freed using DestoryString()
anthony06762232012-04-29 11:45:40 +0000680%
cristy3ed852e2009-09-05 21:47:34 +0000681% The format of the ConstantString method is:
682%
683% char *ConstantString(const char *source)
684%
685% A description of each parameter follows:
686%
687% o source: A character string.
688%
689*/
690MagickExport char *ConstantString(const char *source)
691{
692 char
693 *destination;
694
695 size_t
696 length;
697
698 length=0;
699 if (source != (char *) NULL)
700 length+=strlen(source);
701 destination=(char *) NULL;
702 if (~length >= 1UL)
703 destination=(char *) AcquireQuantumMemory(length+1UL,sizeof(*destination));
704 if (destination == (char *) NULL)
705 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
706 *destination='\0';
707 if (source != (char *) NULL)
cristy54aad5e2010-09-03 16:02:04 +0000708 (void) memcpy(destination,source,length*sizeof(*destination));
709 destination[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000710 return(destination);
711}
712
713/*
714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715% %
716% %
717% %
718% C o p y M a g i c k S t r i n g %
719% %
720% %
721% %
722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723%
anthony06762232012-04-29 11:45:40 +0000724% CopyMagickString() copies the source string to the destination string, with
725% out exceeding the given pre-declared length.
726%
727% The destination buffer is always null-terminated even if the string must be
728% truncated. The return value is the minimum of the source string length or
729% the length parameter.
cristy3ed852e2009-09-05 21:47:34 +0000730%
731% The format of the CopyMagickString method is:
732%
733% size_t CopyMagickString(const char *destination,char *source,
734% const size_t length)
735%
736% A description of each parameter follows:
737%
738% o destination: the destination string.
739%
740% o source: the source string.
741%
742% o length: the length of the destination string.
743%
744*/
745MagickExport size_t CopyMagickString(char *destination,const char *source,
746 const size_t length)
747{
748 register char
749 *q;
750
751 register const char
752 *p;
753
754 register size_t
755 n;
756
cristy77e3fcc2011-10-11 00:04:41 +0000757 if (source == (const char *) NULL)
758 return(0);
cristy3ed852e2009-09-05 21:47:34 +0000759 p=source;
760 q=destination;
761 for (n=length; n > 4; n-=4)
762 {
763 *q=(*p++);
764 if (*q == '\0')
765 return((size_t) (p-source-1));
766 q++;
767 *q=(*p++);
768 if (*q == '\0')
769 return((size_t) (p-source-1));
770 q++;
771 *q=(*p++);
772 if (*q == '\0')
773 return((size_t) (p-source-1));
774 q++;
775 *q=(*p++);
776 if (*q == '\0')
777 return((size_t) (p-source-1));
778 q++;
779 }
780 if (n != 0)
781 for (n--; n != 0; n--)
782 {
783 *q=(*p++);
784 if (*q == '\0')
785 return((size_t) (p-source-1));
786 q++;
787 }
788 if (length != 0)
789 *q='\0';
790 return((size_t) (p-source-1));
791}
792
793/*
794%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795% %
796% %
797% %
798% D e s t r o y S t r i n g %
799% %
800% %
801% %
802%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803%
804% DestroyString() destroys memory associated with a string.
805%
806% The format of the DestroyString method is:
807%
808% char *DestroyString(char *string)
809%
810% A description of each parameter follows:
811%
812% o string: the string.
813%
814*/
815MagickExport char *DestroyString(char *string)
816{
817 return((char *) RelinquishMagickMemory(string));
818}
819
820/*
821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822% %
823% %
824% %
825% D e s t r o y S t r i n g I n f o %
826% %
827% %
828% %
829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830%
831% DestroyStringInfo() destroys memory associated with the StringInfo structure.
832%
833% The format of the DestroyStringInfo method is:
834%
835% StringInfo *DestroyStringInfo(StringInfo *string_info)
836%
837% A description of each parameter follows:
838%
839% o string_info: the string info.
840%
841*/
842MagickExport StringInfo *DestroyStringInfo(StringInfo *string_info)
843{
cristy3ed852e2009-09-05 21:47:34 +0000844 assert(string_info != (StringInfo *) NULL);
845 assert(string_info->signature == MagickSignature);
846 if (string_info->datum != (unsigned char *) NULL)
847 string_info->datum=(unsigned char *) RelinquishMagickMemory(
848 string_info->datum);
849 string_info->signature=(~MagickSignature);
850 string_info=(StringInfo *) RelinquishMagickMemory(string_info);
851 return(string_info);
852}
853
854/*
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856% %
857% %
858% %
859% D e s t r o y S t r i n g L i s t %
860% %
861% %
862% %
863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864%
865% DestroyStringList() zeros memory associated with a string list.
866%
867% The format of the DestroyStringList method is:
868%
869% char **DestroyStringList(char **list)
870%
871% A description of each parameter follows:
872%
873% o list: the string list.
874%
875*/
876MagickExport char **DestroyStringList(char **list)
877{
cristybb503372010-05-27 20:51:26 +0000878 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000879 i;
880
881 assert(list != (char **) NULL);
882 for (i=0; list[i] != (char *) NULL; i++)
883 list[i]=DestroyString(list[i]);
884 list=(char **) RelinquishMagickMemory(list);
885 return(list);
886}
887
888/*
889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890% %
891% %
892% %
893% E s c a p e S t r i n g %
894% %
895% %
896% %
897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898%
899% EscapeString() allocates memory for a backslash-escaped version of a
900% source text string, copies the escaped version of the text to that
901% memory location while adding backslash characters, and returns the
902% escaped string.
903%
904% The format of the EscapeString method is:
905%
906% char *EscapeString(const char *source,const char escape)
907%
908% A description of each parameter follows:
909%
910% o allocate_string: Method EscapeString returns the escaped string.
911%
912% o source: A character string.
913%
914% o escape: the quoted string termination character to escape (e.g. '"').
915%
916*/
917MagickExport char *EscapeString(const char *source,const char escape)
918{
919 char
920 *destination;
921
922 register char
923 *q;
924
925 register const char
926 *p;
927
928 size_t
929 length;
930
cristy3ed852e2009-09-05 21:47:34 +0000931 assert(source != (const char *) NULL);
932 length=strlen(source);
933 for (p=source; *p != '\0'; p++)
934 if ((*p == '\\') || (*p == escape))
935 {
936 if (~length < 1)
937 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
938 length++;
939 }
940 destination=(char *) NULL;
cristy37e0b382011-06-07 13:31:21 +0000941 if (~length >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +0000942 destination=(char *) AcquireQuantumMemory(length+MaxTextExtent,
943 sizeof(*destination));
944 if (destination == (char *) NULL)
945 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
946 *destination='\0';
947 if (source != (char *) NULL)
948 {
949 q=destination;
950 for (p=source; *p != '\0'; p++)
951 {
952 if ((*p == '\\') || (*p == escape))
953 *q++='\\';
954 *q++=(*p);
955 }
956 *q='\0';
957 }
958 return(destination);
959}
960
961/*
962%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963% %
964% %
965% %
966% F i l e T o S t r i n g %
967% %
968% %
969% %
970%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971%
972% FileToString() returns the contents of a file as a string.
973%
974% The format of the FileToString method is:
975%
976% char *FileToString(const char *filename,const size_t extent,
977% ExceptionInfo *exception)
978%
979% A description of each parameter follows:
980%
981% o filename: the filename.
982%
983% o extent: Maximum length of the string.
984%
985% o exception: return any errors or warnings in this structure.
986%
987*/
988MagickExport char *FileToString(const char *filename,const size_t extent,
989 ExceptionInfo *exception)
990{
991 size_t
992 length;
993
994 assert(filename != (const char *) NULL);
995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
996 assert(exception != (ExceptionInfo *) NULL);
997 return((char *) FileToBlob(filename,extent,&length,exception));
998}
999
1000/*
1001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002% %
1003% %
1004% %
1005% F i l e T o S t r i n g I n f o %
1006% %
1007% %
1008% %
1009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1010%
1011% FileToStringInfo() returns the contents of a file as a string.
1012%
1013% The format of the FileToStringInfo method is:
1014%
1015% StringInfo *FileToStringInfo(const char *filename,const size_t extent,
1016% ExceptionInfo *exception)
1017%
1018% A description of each parameter follows:
1019%
1020% o filename: the filename.
1021%
1022% o extent: Maximum length of the string.
1023%
1024% o exception: return any errors or warnings in this structure.
1025%
1026*/
1027MagickExport StringInfo *FileToStringInfo(const char *filename,
1028 const size_t extent,ExceptionInfo *exception)
1029{
1030 StringInfo
1031 *string_info;
1032
1033 assert(filename != (const char *) NULL);
1034 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1035 assert(exception != (ExceptionInfo *) NULL);
1036 string_info=AcquireStringInfo(0);
cristy5ce7dac2014-05-28 12:22:17 +00001037 (void) CopyMagickString(string_info->path,filename,MaxTextExtent);
cristy7fb9fc12014-05-28 01:18:24 +00001038 if (string_info->datum != (unsigned char *) NULL)
1039 string_info->datum=(unsigned char *) RelinquishMagickMemory(
1040 string_info->datum);
cristy3ed852e2009-09-05 21:47:34 +00001041 string_info->datum=FileToBlob(filename,extent,&string_info->length,exception);
1042 if (string_info->datum == (unsigned char *) NULL)
1043 {
1044 string_info=DestroyStringInfo(string_info);
1045 return((StringInfo *) NULL);
1046 }
1047 return(string_info);
1048}
1049
1050/*
1051%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1052% %
1053% %
1054% %
1055% F o r m a t M a g i c k S i z e %
1056% %
1057% %
1058% %
1059%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1060%
1061% FormatMagickSize() converts a size to a human readable format, for example,
cristy2ce15c92010-03-12 14:03:41 +00001062% 14k, 234m, 2.7g, or 3.0t. Scaling is done by repetitively dividing by
cristyc15ce492009-12-01 19:18:23 +00001063% 1000.
cristy3ed852e2009-09-05 21:47:34 +00001064%
1065% The format of the FormatMagickSize method is:
1066%
cristybb503372010-05-27 20:51:26 +00001067% ssize_t FormatMagickSize(const MagickSizeType size,char *format)
cristy3ed852e2009-09-05 21:47:34 +00001068%
1069% A description of each parameter follows:
1070%
1071% o size: convert this size to a human readable format.
1072%
cristyb9080c92009-12-01 20:13:26 +00001073% o bi: use power of two rather than power of ten.
1074%
cristy3ed852e2009-09-05 21:47:34 +00001075% o format: human readable format.
1076%
1077*/
cristy99bbf2c2011-09-26 18:27:50 +00001078MagickExport ssize_t FormatMagickSize(const MagickSizeType size,
cristyb9080c92009-12-01 20:13:26 +00001079 const MagickBooleanType bi,char *format)
cristy3ed852e2009-09-05 21:47:34 +00001080{
cristyb9080c92009-12-01 20:13:26 +00001081 const char
1082 **units;
1083
cristy3ed852e2009-09-05 21:47:34 +00001084 double
cristyb9080c92009-12-01 20:13:26 +00001085 bytes,
cristy3ed852e2009-09-05 21:47:34 +00001086 length;
1087
cristybb503372010-05-27 20:51:26 +00001088 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001089 i,
1090 j;
1091
cristy9d314ff2011-03-09 01:30:28 +00001092 ssize_t
1093 count;
1094
cristy3ed852e2009-09-05 21:47:34 +00001095 static const char
cristyb9080c92009-12-01 20:13:26 +00001096 *bi_units[] =
1097 {
cristy2ce15c92010-03-12 14:03:41 +00001098 "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", (char *) NULL
cristyb9080c92009-12-01 20:13:26 +00001099 },
1100 *traditional_units[] =
cristy9bf9da32009-09-27 16:48:34 +00001101 {
cristy2ce15c92010-03-12 14:03:41 +00001102 "", "K", "M", "G", "T", "P", "E", "Z", "Y", (char *) NULL
cristy9bf9da32009-09-27 16:48:34 +00001103 };
cristy3ed852e2009-09-05 21:47:34 +00001104
cristyb9080c92009-12-01 20:13:26 +00001105 bytes=1000.0;
1106 units=traditional_units;
1107 if (bi != MagickFalse)
1108 {
1109 bytes=1024.0;
1110 units=bi_units;
1111 }
cristy3ed852e2009-09-05 21:47:34 +00001112#if defined(_MSC_VER) && (_MSC_VER == 1200)
1113 length=(double) ((MagickOffsetType) size);
1114#else
1115 length=(double) size;
1116#endif
cristyb9080c92009-12-01 20:13:26 +00001117 for (i=0; (length >= bytes) && (units[i+1] != (const char *) NULL); i++)
1118 length/=bytes;
cristyc3b9b362013-05-25 17:16:34 +00001119 count=0;
cristy9bf9da32009-09-27 16:48:34 +00001120 for (j=2; j < 12; j++)
cristy3ed852e2009-09-05 21:47:34 +00001121 {
cristyb51dff52011-05-19 16:55:47 +00001122 count=FormatLocaleString(format,MaxTextExtent,"%.*g%sB",(int) (i+j),length,
cristy3ed852e2009-09-05 21:47:34 +00001123 units[i]);
1124 if (strchr(format,'+') == (char *) NULL)
1125 break;
1126 }
1127 return(count);
1128}
1129
1130/*
1131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132% %
1133% %
1134% %
cristy3ed852e2009-09-05 21:47:34 +00001135% F o r m a t M a g i c k T i m e %
1136% %
1137% %
1138% %
1139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1140%
1141% FormatMagickTime() returns the specified time in the Internet date/time
1142% format and the length of the timestamp.
1143%
1144% The format of the FormatMagickTime method is:
1145%
cristybb503372010-05-27 20:51:26 +00001146% ssize_t FormatMagickTime(const time_t time,const size_t length,
cristy3ed852e2009-09-05 21:47:34 +00001147% char *timestamp)
1148%
1149% A description of each parameter follows.
1150%
1151% o time: the time since the Epoch (00:00:00 UTC, January 1, 1970),
1152% measured in seconds.
1153%
1154% o length: the maximum length of the string.
1155%
1156% o timestamp: Return the Internet date/time here.
1157%
1158*/
cristybb503372010-05-27 20:51:26 +00001159MagickExport ssize_t FormatMagickTime(const time_t time,const size_t length,
cristy3ed852e2009-09-05 21:47:34 +00001160 char *timestamp)
1161{
cristybb503372010-05-27 20:51:26 +00001162 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001163 count;
1164
1165 struct tm
1166 gm_time,
1167 local_time;
1168
1169 time_t
1170 timezone;
1171
1172 assert(timestamp != (char *) NULL);
1173 (void) ResetMagickMemory(&local_time,0,sizeof(local_time));
1174 (void) ResetMagickMemory(&gm_time,0,sizeof(gm_time));
1175#if defined(MAGICKCORE_HAVE_LOCALTIME_R)
1176 (void) localtime_r(&time,&local_time);
1177#else
1178 {
cristybc3392a2009-10-06 03:15:57 +00001179 struct tm
cristy3ed852e2009-09-05 21:47:34 +00001180 *my_time;
1181
1182 my_time=localtime(&time);
1183 if (my_time != (struct tm *) NULL)
1184 (void) memcpy(&local_time,my_time,sizeof(local_time));
1185 }
1186#endif
1187#if defined(MAGICKCORE_HAVE_GMTIME_R)
1188 (void) gmtime_r(&time,&gm_time);
1189#else
1190 {
cristybc3392a2009-10-06 03:15:57 +00001191 struct tm
cristy3ed852e2009-09-05 21:47:34 +00001192 *my_time;
1193
1194 my_time=gmtime(&time);
1195 if (my_time != (struct tm *) NULL)
1196 (void) memcpy(&gm_time,my_time,sizeof(gm_time));
1197 }
1198#endif
1199 timezone=(time_t) ((local_time.tm_min-gm_time.tm_min)/60+
1200 local_time.tm_hour-gm_time.tm_hour+24*((local_time.tm_year-
1201 gm_time.tm_year) != 0 ? (local_time.tm_year-gm_time.tm_year) :
1202 (local_time.tm_yday-gm_time.tm_yday)));
cristyb51dff52011-05-19 16:55:47 +00001203 count=FormatLocaleString(timestamp,length,
cristy3ed852e2009-09-05 21:47:34 +00001204 "%04d-%02d-%02dT%02d:%02d:%02d%+03ld:00",local_time.tm_year+1900,
1205 local_time.tm_mon+1,local_time.tm_mday,local_time.tm_hour,
cristyf1d91242010-05-28 02:23:19 +00001206 local_time.tm_min,local_time.tm_sec,(long) timezone);
cristy3ed852e2009-09-05 21:47:34 +00001207 return(count);
1208}
1209
1210/*
1211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1212% %
1213% %
1214% %
1215% G e t E n v i r o n m e n t V a l u e %
1216% %
1217% %
1218% %
1219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1220%
1221% GetEnvironmentValue() returns the environment string that matches the
1222% specified name.
1223%
1224% The format of the GetEnvironmentValue method is:
1225%
1226% char *GetEnvironmentValue(const char *name)
1227%
1228% A description of each parameter follows:
1229%
1230% o name: the environment name.
1231%
1232*/
cristy99bbf2c2011-09-26 18:27:50 +00001233MagickExport char *GetEnvironmentValue(const char *name)
cristy3ed852e2009-09-05 21:47:34 +00001234{
1235 const char
1236 *environment;
1237
1238 environment=getenv(name);
1239 if (environment == (const char *) NULL)
1240 return((char *) NULL);
1241 return(ConstantString(environment));
1242}
1243
1244/*
1245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246% %
1247% %
1248% %
1249% G e t S t r i n g I n f o D a t u m %
1250% %
1251% %
1252% %
1253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254%
1255% GetStringInfoDatum() returns the datum associated with the string.
1256%
1257% The format of the GetStringInfoDatum method is:
1258%
1259% unsigned char *GetStringInfoDatum(const StringInfo *string_info)
1260%
1261% A description of each parameter follows:
1262%
1263% o string_info: the string info.
1264%
1265*/
1266MagickExport unsigned char *GetStringInfoDatum(const StringInfo *string_info)
1267{
1268 assert(string_info != (StringInfo *) NULL);
1269 assert(string_info->signature == MagickSignature);
1270 return(string_info->datum);
1271}
1272
1273/*
1274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275% %
1276% %
1277% %
1278% G e t S t r i n g I n f o L e n g t h %
1279% %
1280% %
1281% %
1282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1283%
1284% GetStringInfoLength() returns the string length.
1285%
1286% The format of the GetStringInfoLength method is:
1287%
1288% size_t GetStringInfoLength(const StringInfo *string_info)
1289%
1290% A description of each parameter follows:
1291%
1292% o string_info: the string info.
1293%
1294*/
1295MagickExport size_t GetStringInfoLength(const StringInfo *string_info)
1296{
1297 assert(string_info != (StringInfo *) NULL);
1298 assert(string_info->signature == MagickSignature);
1299 return(string_info->length);
1300}
1301
1302/*
1303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304% %
1305% %
1306% %
1307% G e t S t r i n g I n f o P a t h %
1308% %
1309% %
1310% %
1311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1312%
1313% GetStringInfoPath() returns the path associated with the string.
1314%
1315% The format of the GetStringInfoPath method is:
1316%
1317% const char *GetStringInfoPath(const StringInfo *string_info)
1318%
1319% A description of each parameter follows:
1320%
1321% o string_info: the string info.
1322%
1323*/
1324MagickExport const char *GetStringInfoPath(const StringInfo *string_info)
1325{
1326 assert(string_info != (StringInfo *) NULL);
1327 assert(string_info->signature == MagickSignature);
1328 return(string_info->path);
1329}
1330
1331/*
1332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333% %
1334% %
1335% %
cristydbdd0e32011-11-04 23:29:40 +00001336+ I n t e r p r e t S i P r e f i x V a l u e %
1337% %
1338% %
1339% %
1340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341%
1342% InterpretSiPrefixValue() converts the initial portion of the string to a
1343% double representation. It also recognizes SI prefixes (e.g. B, KB, MiB,
1344% etc.).
1345%
1346% The format of the InterpretSiPrefixValue method is:
1347%
1348% double InterpretSiPrefixValue(const char *value,char **sentinal)
1349%
1350% A description of each parameter follows:
1351%
1352% o value: the string value.
1353%
1354% o sentinal: if sentinal is not NULL, return a pointer to the character
1355% after the last character used in the conversion.
1356%
1357*/
1358MagickExport double InterpretSiPrefixValue(const char *restrict string,
1359 char **restrict sentinal)
1360{
1361 char
1362 *q;
1363
1364 double
1365 value;
1366
cristydbdd0e32011-11-04 23:29:40 +00001367 value=InterpretLocaleValue(string,&q);
1368 if (q != string)
1369 {
1370 if ((*q >= 'E') && (*q <= 'z'))
1371 {
1372 double
1373 e;
1374
cristy0c2684f2011-11-05 21:39:43 +00001375 switch ((int) ((unsigned char) *q))
1376 {
1377 case 'y': e=(-24.0); break;
1378 case 'z': e=(-21.0); break;
1379 case 'a': e=(-18.0); break;
1380 case 'f': e=(-15.0); break;
1381 case 'p': e=(-12.0); break;
1382 case 'n': e=(-9.0); break;
1383 case 'u': e=(-6.0); break;
1384 case 'm': e=(-3.0); break;
1385 case 'c': e=(-2.0); break;
1386 case 'd': e=(-1.0); break;
1387 case 'h': e=2.0; break;
1388 case 'k': e=3.0; break;
1389 case 'K': e=3.0; break;
1390 case 'M': e=6.0; break;
1391 case 'G': e=9.0; break;
1392 case 'T': e=12.0; break;
1393 case 'P': e=15.0; break;
1394 case 'E': e=18.0; break;
1395 case 'Z': e=21.0; break;
1396 case 'Y': e=24.0; break;
1397 default: e=0.0; break;
1398 }
cristydbdd0e32011-11-04 23:29:40 +00001399 if (e >= MagickEpsilon)
1400 {
1401 if (q[1] == 'i')
1402 {
1403 value*=pow(2.0,e/0.3);
1404 q+=2;
1405 }
1406 else
1407 {
1408 value*=pow(10.0,e);
1409 q++;
1410 }
1411 }
1412 }
cristyc0f1ed12011-11-09 14:50:15 +00001413 if (*q == 'B')
cristy099a7352011-11-09 14:31:35 +00001414 q++;
cristydbdd0e32011-11-04 23:29:40 +00001415 }
1416 if (sentinal != (char **) NULL)
1417 *sentinal=q;
1418 return(value);
1419}
1420
1421/*
1422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1423% %
1424% %
1425% %
anthony6f201312012-03-30 04:08:15 +00001426% I s S t r i n g T r u e %
1427% %
1428% %
1429% %
1430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431%
1432% IsStringTrue() returns MagickTrue if the value is "true", "on", "yes" or
1433% "1". Any other string or undefined returns MagickFalse.
1434%
1435% Typically this is used to look at strings (options or artifacts) which
1436% has a default value of "false", when not defined.
1437%
1438% The format of the IsStringTrue method is:
1439%
1440% MagickBooleanType IsStringTrue(const char *value)
1441%
1442% A description of each parameter follows:
1443%
1444% o value: Specifies a pointer to a character array.
1445%
1446*/
1447MagickExport MagickBooleanType IsStringTrue(const char *value)
1448{
1449 if (value == (const char *) NULL)
1450 return(MagickFalse);
1451 if (LocaleCompare(value,"true") == 0)
1452 return(MagickTrue);
1453 if (LocaleCompare(value,"on") == 0)
1454 return(MagickTrue);
1455 if (LocaleCompare(value,"yes") == 0)
1456 return(MagickTrue);
1457 if (LocaleCompare(value,"1") == 0)
1458 return(MagickTrue);
1459 return(MagickFalse);
1460}
1461
1462/*
1463%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1464% %
1465% %
1466% %
1467% I s S t r i n g N o t F a l s e %
1468% %
1469% %
1470% %
1471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1472%
1473% IsStringNotFalse() returns MagickTrue, unless the string specifically
1474% has a value that makes this false. that is if it has a value of
1475% "false", "off", "no" or "0".
1476%
1477% Typically this is used to look at strings (options or artifacts) which
1478% has a default value of "true", when it has not been defined.
1479%
1480% The format of the IsStringNotFalse method is:
1481%
1482% MagickBooleanType IsStringNotFalse(const char *value)
1483%
1484% A description of each parameter follows:
1485%
1486% o value: Specifies a pointer to a character array.
1487%
1488*/
1489MagickExport MagickBooleanType IsStringNotFalse(const char *value)
1490{
1491 if (value == (const char *) NULL)
1492 return(MagickTrue);
1493 if (LocaleCompare(value,"false") == 0)
1494 return(MagickFalse);
1495 if (LocaleCompare(value,"off") == 0)
1496 return(MagickFalse);
1497 if (LocaleCompare(value,"no") == 0)
1498 return(MagickFalse);
1499 if (LocaleCompare(value,"0") == 0)
1500 return(MagickFalse);
1501 return(MagickTrue);
1502}
1503
1504/*
1505%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1506% %
1507% %
1508% %
cristy3ed852e2009-09-05 21:47:34 +00001509% L o c a l e C o m p a r e %
1510% %
1511% %
1512% %
1513%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1514%
1515% LocaleCompare() performs a case-insensitive comparison of two strings
1516% byte-by-byte, according to the ordering of the current locale encoding.
1517% LocaleCompare returns an integer greater than, equal to, or less than 0,
1518% if the string pointed to by p is greater than, equal to, or less than the
1519% string pointed to by q respectively. The sign of a non-zero return value
cristy7a40ba82011-01-08 20:31:18 +00001520% is determined by the sign of the difference between the values of the first
1521% pair of bytes that differ in the strings being compared.
cristy3ed852e2009-09-05 21:47:34 +00001522%
1523% The format of the LocaleCompare method is:
1524%
cristyde58b412010-02-18 03:53:40 +00001525% int LocaleCompare(const char *p,const char *q)
cristy3ed852e2009-09-05 21:47:34 +00001526%
1527% A description of each parameter follows:
1528%
1529% o p: A pointer to a character string.
1530%
1531% o q: A pointer to a character string to compare to p.
1532%
1533*/
cristyde58b412010-02-18 03:53:40 +00001534MagickExport int LocaleCompare(const char *p,const char *q)
cristy3ed852e2009-09-05 21:47:34 +00001535{
1536 if ((p == (char *) NULL) && (q == (char *) NULL))
1537 return(0);
1538 if (p == (char *) NULL)
1539 return(-1);
1540 if (q == (char *) NULL)
1541 return(1);
1542#if defined(MAGICKCORE_HAVE_STRCASECMP)
cristy27397b22010-02-18 17:30:43 +00001543 return(strcasecmp(p,q));
cristy3ed852e2009-09-05 21:47:34 +00001544#else
1545 {
cristyde58b412010-02-18 03:53:40 +00001546 register int
cristy3ed852e2009-09-05 21:47:34 +00001547 c,
cristya72c2d12010-02-18 01:20:28 +00001548 d;
cristy3ed852e2009-09-05 21:47:34 +00001549
cristya72c2d12010-02-18 01:20:28 +00001550 for ( ; ; )
cristy3ed852e2009-09-05 21:47:34 +00001551 {
cristyde58b412010-02-18 03:53:40 +00001552 c=(int) *((unsigned char *) p);
1553 d=(int) *((unsigned char *) q);
1554 if ((c == 0) || (AsciiMap[c] != AsciiMap[d]))
cristy3ed852e2009-09-05 21:47:34 +00001555 break;
cristya72c2d12010-02-18 01:20:28 +00001556 p++;
1557 q++;
cristy3ed852e2009-09-05 21:47:34 +00001558 }
cristyde58b412010-02-18 03:53:40 +00001559 return(AsciiMap[c]-(int) AsciiMap[d]);
cristy3ed852e2009-09-05 21:47:34 +00001560 }
1561#endif
1562}
1563
1564/*
1565%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1566% %
1567% %
1568% %
1569% L o c a l e L o w e r %
1570% %
1571% %
1572% %
1573%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1574%
1575% LocaleLower() transforms all of the characters in the supplied
1576% null-terminated string, changing all uppercase letters to lowercase.
1577%
1578% The format of the LocaleLower method is:
1579%
1580% void LocaleLower(char *string)
1581%
1582% A description of each parameter follows:
1583%
1584% o string: A pointer to the string to convert to lower-case Locale.
1585%
1586*/
1587MagickExport void LocaleLower(char *string)
1588{
1589 register char
1590 *q;
1591
1592 assert(string != (char *) NULL);
1593 for (q=string; *q != '\0'; q++)
1594 *q=(char) tolower((int) *q);
1595}
1596
1597/*
1598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1599% %
1600% %
1601% %
1602% L o c a l e N C o m p a r e %
1603% %
1604% %
1605% %
1606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1607%
anthony06762232012-04-29 11:45:40 +00001608% LocaleNCompare() performs a case-insensitive comparison of two strings
1609% byte-by-byte, according to the ordering of the current locale encoding.
1610%
1611% LocaleNCompare returns an integer greater than, equal to, or less than 0,
1612% if the string pointed to by p is greater than, equal to, or less than the
1613% string pointed to by q respectively. The sign of a non-zero return value
1614% is determined by the sign of the difference between the values of the first
1615% pair of bytes that differ in the strings being compared.
1616%
1617% The LocaleNCompare method makes the same comparison as LocaleCompare but
1618% looks at a maximum of n bytes. Bytes following a null byte are not
1619% compared.
cristy3ed852e2009-09-05 21:47:34 +00001620%
1621% The format of the LocaleNCompare method is:
1622%
cristyde58b412010-02-18 03:53:40 +00001623% int LocaleNCompare(const char *p,const char *q,const size_t n)
cristy3ed852e2009-09-05 21:47:34 +00001624%
1625% A description of each parameter follows:
1626%
1627% o p: A pointer to a character string.
1628%
1629% o q: A pointer to a character string to compare to p.
1630%
cristy7a40ba82011-01-08 20:31:18 +00001631% o length: the number of characters to compare in strings p and q.
cristy3ed852e2009-09-05 21:47:34 +00001632%
1633*/
cristyde58b412010-02-18 03:53:40 +00001634MagickExport int LocaleNCompare(const char *p,const char *q,const size_t length)
cristy3ed852e2009-09-05 21:47:34 +00001635{
cristy78c21692011-10-06 14:57:26 +00001636 if ((p == (char *) NULL) && (q == (char *) NULL))
1637 return(0);
cristy3ed852e2009-09-05 21:47:34 +00001638 if (p == (char *) NULL)
1639 return(-1);
1640 if (q == (char *) NULL)
1641 return(1);
1642#if defined(MAGICKCORE_HAVE_STRNCASECMP)
cristy27397b22010-02-18 17:30:43 +00001643 return(strncasecmp(p,q,length));
cristy3ed852e2009-09-05 21:47:34 +00001644#else
1645 {
cristyde58b412010-02-18 03:53:40 +00001646 register int
cristy3ed852e2009-09-05 21:47:34 +00001647 c,
1648 d;
1649
cristyb6af4a52009-10-06 13:56:23 +00001650 register size_t
cristyc4cded12010-02-18 14:40:57 +00001651 i;
cristyb6af4a52009-10-06 13:56:23 +00001652
cristyc4cded12010-02-18 14:40:57 +00001653 for (i=length; i != 0; i--)
cristy3ed852e2009-09-05 21:47:34 +00001654 {
cristyde58b412010-02-18 03:53:40 +00001655 c=(int) *((unsigned char *) p);
1656 d=(int) *((unsigned char *) q);
cristy3ed852e2009-09-05 21:47:34 +00001657 if (AsciiMap[c] != AsciiMap[d])
cristyde58b412010-02-18 03:53:40 +00001658 return(AsciiMap[c]-(int) AsciiMap[d]);
1659 if (c == 0)
1660 return(0);
cristy3ed852e2009-09-05 21:47:34 +00001661 p++;
1662 q++;
1663 }
cristyde58b412010-02-18 03:53:40 +00001664 return(0);
cristy3ed852e2009-09-05 21:47:34 +00001665 }
1666#endif
1667}
1668
1669/*
1670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1671% %
1672% %
1673% %
1674% L o c a l e U p p e r %
1675% %
1676% %
1677% %
1678%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1679%
1680% LocaleUpper() transforms all of the characters in the supplied
1681% null-terminated string, changing all lowercase letters to uppercase.
1682%
1683% The format of the LocaleUpper method is:
1684%
1685% void LocaleUpper(char *string)
1686%
1687% A description of each parameter follows:
1688%
1689% o string: A pointer to the string to convert to upper-case Locale.
1690%
1691*/
1692MagickExport void LocaleUpper(char *string)
1693{
1694 register char
1695 *q;
1696
1697 assert(string != (char *) NULL);
1698 for (q=string; *q != '\0'; q++)
1699 *q=(char) toupper((int) *q);
1700}
1701
1702/*
1703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1704% %
1705% %
1706% %
1707% P r i n t S t r i n g I n f o %
1708% %
1709% %
1710% %
1711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1712%
1713% PrintStringInfo() prints the string.
1714%
1715% The format of the PrintStringInfo method is:
1716%
1717% void PrintStringInfo(FILE *file,const char *id,
1718% const StringInfo *string_info)
1719%
1720% A description of each parameter follows:
1721%
1722% o file: the file, typically stdout.
1723%
1724% o id: the string id.
1725%
1726% o string_info: the string info.
1727%
1728*/
1729MagickExport void PrintStringInfo(FILE *file,const char *id,
1730 const StringInfo *string_info)
1731{
1732 register const char
1733 *p;
1734
1735 register size_t
1736 i,
1737 j;
1738
1739 assert(id != (const char *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001740 assert(string_info != (StringInfo *) NULL);
1741 assert(string_info->signature == MagickSignature);
1742 p=(char *) string_info->datum;
1743 for (i=0; i < string_info->length; i++)
1744 {
1745 if (((int) ((unsigned char) *p) < 32) &&
1746 (isspace((int) ((unsigned char) *p)) == 0))
1747 break;
1748 p++;
1749 }
cristy2d8723c2013-11-14 16:41:27 +00001750 (void) FormatLocaleFile(file,"%s(%.20g): ",id,(double) string_info->length);
cristy3ed852e2009-09-05 21:47:34 +00001751 if (i == string_info->length)
1752 {
cristy53ea28b2012-06-10 22:11:59 +00001753 for (i=0; i < string_info->length; i++)
1754 (void) fputc(string_info->datum[i],file);
cristy3ed852e2009-09-05 21:47:34 +00001755 (void) fputc('\n',file);
1756 return;
1757 }
1758 /*
1759 Convert string to a HEX list.
1760 */
1761 p=(char *) string_info->datum;
1762 for (i=0; i < string_info->length; i+=0x14)
1763 {
cristyb51dff52011-05-19 16:55:47 +00001764 (void) FormatLocaleFile(file,"0x%08lx: ",(unsigned long) (0x14*i));
cristy3ed852e2009-09-05 21:47:34 +00001765 for (j=1; j <= MagickMin(string_info->length-i,0x14); j++)
1766 {
cristyb51dff52011-05-19 16:55:47 +00001767 (void) FormatLocaleFile(file,"%02lx",(unsigned long) (*(p+j)) & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00001768 if ((j % 0x04) == 0)
1769 (void) fputc(' ',file);
1770 }
1771 for ( ; j <= 0x14; j++)
1772 {
1773 (void) fputc(' ',file);
1774 (void) fputc(' ',file);
1775 if ((j % 0x04) == 0)
1776 (void) fputc(' ',file);
1777 }
1778 (void) fputc(' ',file);
1779 for (j=1; j <= MagickMin(string_info->length-i,0x14); j++)
1780 {
1781 if (isprint((int) ((unsigned char) *p)) != 0)
1782 (void) fputc(*p,file);
1783 else
1784 (void) fputc('-',file);
1785 p++;
1786 }
1787 (void) fputc('\n',file);
1788 }
1789}
1790
1791/*
1792%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1793% %
1794% %
1795% %
1796% R e s e t S t r i n g I n f o %
1797% %
1798% %
1799% %
1800%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1801%
1802% ResetStringInfo() reset the string to all null bytes.
1803%
1804% The format of the ResetStringInfo method is:
1805%
1806% void ResetStringInfo(StringInfo *string_info)
1807%
1808% A description of each parameter follows:
1809%
1810% o string_info: the string info.
1811%
1812*/
1813MagickExport void ResetStringInfo(StringInfo *string_info)
1814{
cristy3ed852e2009-09-05 21:47:34 +00001815 assert(string_info != (StringInfo *) NULL);
1816 assert(string_info->signature == MagickSignature);
1817 (void) ResetMagickMemory(string_info->datum,0,string_info->length);
1818}
1819
1820/*
1821%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1822% %
1823% %
1824% %
1825% S e t S t r i n g I n f o %
1826% %
1827% %
1828% %
1829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1830%
1831% SetStringInfo() copies the source string to the destination string.
1832%
1833% The format of the SetStringInfo method is:
1834%
1835% void SetStringInfo(StringInfo *string_info,const StringInfo *source)
1836%
1837% A description of each parameter follows:
1838%
1839% o string_info: the string info.
1840%
1841% o source: the source string.
1842%
1843*/
1844MagickExport void SetStringInfo(StringInfo *string_info,
1845 const StringInfo *source)
1846{
cristy3ed852e2009-09-05 21:47:34 +00001847 assert(string_info != (StringInfo *) NULL);
1848 assert(string_info->signature == MagickSignature);
1849 assert(source != (StringInfo *) NULL);
1850 assert(source->signature == MagickSignature);
1851 if (string_info->length == 0)
1852 return;
1853 (void) ResetMagickMemory(string_info->datum,0,string_info->length);
cristy54aad5e2010-09-03 16:02:04 +00001854 (void) memcpy(string_info->datum,source->datum,MagickMin(string_info->length,
1855 source->length));
cristy3ed852e2009-09-05 21:47:34 +00001856}
1857
1858/*
1859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1860% %
1861% %
1862% %
1863% S e t S t r i n g I n f o D a t u m %
1864% %
1865% %
1866% %
1867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1868%
1869% SetStringInfoDatum() copies bytes from the source string for the length of
1870% the destination string.
1871%
1872% The format of the SetStringInfoDatum method is:
1873%
1874% void SetStringInfoDatum(StringInfo *string_info,
1875% const unsigned char *source)
1876%
1877% A description of each parameter follows:
1878%
1879% o string_info: the string info.
1880%
1881% o source: the source string.
1882%
1883*/
1884MagickExport void SetStringInfoDatum(StringInfo *string_info,
1885 const unsigned char *source)
1886{
cristy3ed852e2009-09-05 21:47:34 +00001887 assert(string_info != (StringInfo *) NULL);
1888 assert(string_info->signature == MagickSignature);
1889 if (string_info->length != 0)
cristy54aad5e2010-09-03 16:02:04 +00001890 (void) memcpy(string_info->datum,source,string_info->length);
cristy3ed852e2009-09-05 21:47:34 +00001891}
1892
1893/*
1894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1895% %
1896% %
1897% %
1898% S e t S t r i n g I n f o L e n g t h %
1899% %
1900% %
1901% %
1902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1903%
1904% SetStringInfoLength() set the string length to the specified value.
1905%
1906% The format of the SetStringInfoLength method is:
1907%
1908% void SetStringInfoLength(StringInfo *string_info,const size_t length)
1909%
1910% A description of each parameter follows:
1911%
1912% o string_info: the string info.
1913%
1914% o length: the string length.
1915%
1916*/
1917MagickExport void SetStringInfoLength(StringInfo *string_info,
1918 const size_t length)
1919{
cristy3ed852e2009-09-05 21:47:34 +00001920 assert(string_info != (StringInfo *) NULL);
1921 assert(string_info->signature == MagickSignature);
1922 if (~length < MaxTextExtent)
1923 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1924 string_info->length=length;
1925 if (string_info->datum == (unsigned char *) NULL)
1926 string_info->datum=(unsigned char *) AcquireQuantumMemory(length+
1927 MaxTextExtent,sizeof(*string_info->datum));
1928 else
1929 string_info->datum=(unsigned char *) ResizeQuantumMemory(string_info->datum,
1930 length+MaxTextExtent,sizeof(*string_info->datum));
1931 if (string_info->datum == (unsigned char *) NULL)
1932 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1933}
1934
1935/*
1936%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1937% %
1938% %
1939% %
1940% S e t S t r i n g I n f o D a t u m %
1941% %
1942% %
1943% %
1944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1945%
1946% SetStringInfoPath() sets the path associated with the string.
1947%
1948% The format of the SetStringInfoPath method is:
1949%
1950% void SetStringInfoPath(StringInfo *string_info,const char *path)
1951%
1952% A description of each parameter follows:
1953%
1954% o string_info: the string info.
1955%
1956% o path: the path.
1957%
1958*/
1959MagickExport void SetStringInfoPath(StringInfo *string_info,const char *path)
1960{
cristy3ed852e2009-09-05 21:47:34 +00001961 assert(string_info != (StringInfo *) NULL);
1962 assert(string_info->signature == MagickSignature);
1963 assert(path != (const char *) NULL);
1964 (void) CopyMagickString(string_info->path,path,MaxTextExtent);
1965}
1966
1967/*
1968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1969% %
1970% %
1971% %
1972% S p l i t S t r i n g I n f o %
1973% %
1974% %
1975% %
1976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1977%
1978% SplitStringInfo() splits a string into two and returns it.
1979%
1980% The format of the SplitStringInfo method is:
1981%
1982% StringInfo *SplitStringInfo(StringInfo *string_info,const size_t offset)
1983%
1984% A description of each parameter follows:
1985%
1986% o string_info: the string info.
1987%
1988*/
1989MagickExport StringInfo *SplitStringInfo(StringInfo *string_info,
1990 const size_t offset)
1991{
1992 StringInfo
1993 *split_info;
1994
cristy3ed852e2009-09-05 21:47:34 +00001995 assert(string_info != (StringInfo *) NULL);
1996 assert(string_info->signature == MagickSignature);
1997 if (offset > string_info->length)
1998 return((StringInfo *) NULL);
1999 split_info=AcquireStringInfo(offset);
2000 SetStringInfo(split_info,string_info);
cristy1bd862c2011-05-21 13:44:38 +00002001 (void) memmove(string_info->datum,string_info->datum+offset,
cristy3ed852e2009-09-05 21:47:34 +00002002 string_info->length-offset+MaxTextExtent);
2003 SetStringInfoLength(string_info,string_info->length-offset);
2004 return(split_info);
2005}
2006
2007/*
2008%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2009% %
2010% %
2011% %
2012% S t r i n g I n f o T o S t r i n g %
2013% %
2014% %
2015% %
2016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2017%
2018% StringInfoToString() converts a string info string to a C string.
2019%
2020% The format of the StringInfoToString method is:
2021%
2022% char *StringInfoToString(const StringInfo *string_info)
2023%
2024% A description of each parameter follows:
2025%
2026% o string_info: the string.
2027%
2028*/
2029MagickExport char *StringInfoToString(const StringInfo *string_info)
2030{
2031 char
2032 *string;
2033
2034 size_t
2035 length;
2036
2037 string=(char *) NULL;
2038 length=string_info->length;
cristy37e0b382011-06-07 13:31:21 +00002039 if (~length >= (MaxTextExtent-1))
cristy3ed852e2009-09-05 21:47:34 +00002040 string=(char *) AcquireQuantumMemory(length+MaxTextExtent,sizeof(*string));
cristy208cacf2010-09-03 02:24:42 +00002041 if (string == (char *) NULL)
2042 return((char *) NULL);
cristy54aad5e2010-09-03 16:02:04 +00002043 (void) memcpy(string,(char *) string_info->datum,length*sizeof(*string));
cristy208cacf2010-09-03 02:24:42 +00002044 string[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +00002045 return(string);
2046}
2047
2048/*
2049%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2050% %
2051% %
2052% %
anthonyb1d483a2012-04-14 12:53:56 +00002053% S t r i n g I n f o T o H e x S t r i n g %
2054% %
2055% %
2056% %
2057%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2058%
2059% StringInfoToHexString() converts a string info string to a C string.
2060%
2061% The format of the StringInfoToHexString method is:
2062%
2063% char *StringInfoToHexString(const StringInfo *string_info)
2064%
2065% A description of each parameter follows:
2066%
2067% o string_info: the string.
2068%
2069*/
2070MagickExport char *StringInfoToHexString(const StringInfo *string_info)
2071{
2072 char
2073 *string;
2074
2075 register const unsigned char
2076 *p;
2077
2078 register ssize_t
2079 i;
2080
2081 register unsigned char
2082 *q;
2083
2084 size_t
2085 length;
2086
2087 unsigned char
2088 hex_digits[16];
2089
2090 length=string_info->length;
2091 if (~length < MaxTextExtent)
2092 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
2093 string=(char *) AcquireQuantumMemory(length+MaxTextExtent,2*sizeof(*string));
2094 if (string == (char *) NULL)
2095 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
2096 hex_digits[0]='0';
2097 hex_digits[1]='1';
2098 hex_digits[2]='2';
2099 hex_digits[3]='3';
2100 hex_digits[4]='4';
2101 hex_digits[5]='5';
2102 hex_digits[6]='6';
2103 hex_digits[7]='7';
2104 hex_digits[8]='8';
2105 hex_digits[9]='9';
2106 hex_digits[10]='a';
2107 hex_digits[11]='b';
2108 hex_digits[12]='c';
2109 hex_digits[13]='d';
2110 hex_digits[14]='e';
2111 hex_digits[15]='f';
2112 p=string_info->datum;
2113 q=(unsigned char *) string;
2114 for (i=0; i < (ssize_t) string_info->length; i++)
2115 {
2116 *q++=hex_digits[(*p >> 4) & 0x0f];
2117 *q++=hex_digits[*p & 0x0f];
2118 p++;
2119 }
2120 *q='\0';
2121 return(string);
2122}
2123
2124/*
2125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2126% %
2127% %
2128% %
cristy3ed852e2009-09-05 21:47:34 +00002129% S t r i n g T o A r g v %
2130% %
2131% %
2132% %
2133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2134%
2135% StringToArgv() converts a text string into command line arguments.
anthony31f1bf72012-01-30 12:37:22 +00002136% The 'argv' array of arguments, is returned while the number of arguments
2137% is returned via the provided integer variable pointer.
2138%
2139% Simple 'word' tokenizer, which allows for each word to be optionally
2140% quoted. However it will not allow use of partial quotes, or escape
2141% characters.
cristy3ed852e2009-09-05 21:47:34 +00002142%
2143% The format of the StringToArgv method is:
2144%
2145% char **StringToArgv(const char *text,int *argc)
2146%
2147% A description of each parameter follows:
2148%
2149% o argv: Method StringToArgv returns the string list unless an error
2150% occurs, otherwise NULL.
2151%
2152% o text: Specifies the string to segment into a list.
2153%
2154% o argc: This integer pointer returns the number of arguments in the
2155% list.
2156%
2157*/
2158MagickExport char **StringToArgv(const char *text,int *argc)
2159{
2160 char
2161 **argv;
2162
2163 register const char
2164 *p,
2165 *q;
2166
cristybb503372010-05-27 20:51:26 +00002167 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002168 i;
2169
2170 *argc=0;
2171 if (text == (char *) NULL)
2172 return((char **) NULL);
2173 /*
2174 Determine the number of arguments.
2175 */
2176 for (p=text; *p != '\0'; )
2177 {
2178 while (isspace((int) ((unsigned char) *p)) != 0)
2179 p++;
cristya20c9042011-05-19 13:22:18 +00002180 if (*p == '\0')
cristy74895d32011-01-22 21:30:47 +00002181 break;
cristy3ed852e2009-09-05 21:47:34 +00002182 (*argc)++;
2183 if (*p == '"')
2184 for (p++; (*p != '"') && (*p != '\0'); p++) ;
2185 if (*p == '\'')
2186 for (p++; (*p != '\'') && (*p != '\0'); p++) ;
2187 while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
2188 p++;
2189 }
2190 (*argc)++;
cristy1b26e1f2011-03-25 15:40:56 +00002191 argv=(char **) AcquireQuantumMemory((size_t) (*argc+1UL),sizeof(*argv));
cristy3ed852e2009-09-05 21:47:34 +00002192 if (argv == (char **) NULL)
2193 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
2194 /*
2195 Convert string to an ASCII list.
2196 */
2197 argv[0]=AcquireString("magick");
2198 p=text;
cristybb503372010-05-27 20:51:26 +00002199 for (i=1; i < (ssize_t) *argc; i++)
cristy3ed852e2009-09-05 21:47:34 +00002200 {
2201 while (isspace((int) ((unsigned char) *p)) != 0)
2202 p++;
2203 q=p;
2204 if (*q == '"')
2205 {
2206 p++;
2207 for (q++; (*q != '"') && (*q != '\0'); q++) ;
2208 }
2209 else
2210 if (*q == '\'')
2211 {
cristy06b15f42011-01-22 21:36:24 +00002212 p++;
cristy3ed852e2009-09-05 21:47:34 +00002213 for (q++; (*q != '\'') && (*q != '\0'); q++) ;
cristy3ed852e2009-09-05 21:47:34 +00002214 }
2215 else
2216 while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
2217 q++;
2218 argv[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
2219 sizeof(**argv));
2220 if (argv[i] == (char *) NULL)
2221 {
2222 for (i--; i >= 0; i--)
2223 argv[i]=DestroyString(argv[i]);
2224 argv=(char **) RelinquishMagickMemory(argv);
2225 ThrowFatalException(ResourceLimitFatalError,
2226 "UnableToConvertStringToARGV");
2227 }
cristy54aad5e2010-09-03 16:02:04 +00002228 (void) memcpy(argv[i],p,(size_t) (q-p));
cristy208cacf2010-09-03 02:24:42 +00002229 argv[i][q-p]='\0';
cristy3ed852e2009-09-05 21:47:34 +00002230 p=q;
2231 while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
2232 p++;
2233 }
2234 argv[i]=(char *) NULL;
2235 return(argv);
2236}
2237
2238/*
2239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2240% %
2241% %
2242% %
anthonyb1d483a2012-04-14 12:53:56 +00002243% S t r i n g T o A r r a y O f D o u b l e s %
cristy3ed852e2009-09-05 21:47:34 +00002244% %
2245% %
2246% %
2247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2248%
glennrp6ab82382013-10-28 13:54:30 +00002249% StringToArrayOfDoubles() converts a string of space or comma separated
anthonyb1d483a2012-04-14 12:53:56 +00002250% numbers into array of floating point numbers (doubles). Any number that
2251% failes to parse properly will produce a syntax error. As will two commas
2252% without a number between them. However a final comma at the end will
2253% not be regarded as an error so as to simplify automatic list generation.
cristy3ed852e2009-09-05 21:47:34 +00002254%
anthonyb1d483a2012-04-14 12:53:56 +00002255% A NULL value is returned on syntax or memory errors.
cristy3ed852e2009-09-05 21:47:34 +00002256%
anthonyb1d483a2012-04-14 12:53:56 +00002257% Use RelinquishMagickMemory() to free returned array when finished.
2258%
2259% The format of the StringToArrayOfDoubles method is:
2260%
cristy66336b02014-04-07 20:48:46 +00002261% double *StringToArrayOfDoubles(const char *string,size_t *count,
2262% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002263%
2264% A description of each parameter follows:
2265%
glennrp6ab82382013-10-28 13:54:30 +00002266% o string: the string containing the comma/space separated values.
anthonyb1d483a2012-04-14 12:53:56 +00002267%
2268% o count: returns number of arguments in returned array
2269%
cristy52085732013-11-09 02:32:27 +00002270% o exception: return any errors or warnings in this structure.
2271%
cristy3ed852e2009-09-05 21:47:34 +00002272*/
cristy52085732013-11-09 02:32:27 +00002273MagickExport double *StringToArrayOfDoubles(const char *string,ssize_t *count,
2274 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002275{
anthonyb1d483a2012-04-14 12:53:56 +00002276 char
2277 *q;
2278
cristy0a887dc2012-08-15 22:58:36 +00002279 const char
2280 *p;
2281
anthonyb1d483a2012-04-14 12:53:56 +00002282 double
2283 *array;
2284
cristybb503372010-05-27 20:51:26 +00002285 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002286 i;
2287
cristy0a887dc2012-08-15 22:58:36 +00002288 /*
2289 Determine count of values, and check syntax.
2290 */
cristyb0de93f2013-05-03 13:39:25 +00002291 assert(exception != (ExceptionInfo *) NULL);
2292 assert(exception->signature == MagickSignature);
anthonyb1d483a2012-04-14 12:53:56 +00002293 *count=0;
anthonyb1d483a2012-04-14 12:53:56 +00002294 i=0;
cristy0a887dc2012-08-15 22:58:36 +00002295 p=string;
2296 while (*p != '\0')
cristy3ed852e2009-09-05 21:47:34 +00002297 {
cristy0a887dc2012-08-15 22:58:36 +00002298 (void) StringToDouble(p,&q); /* get value - ignores leading space */
2299 if (p == q)
2300 return((double *) NULL); /* no value found */
2301 p=q;
2302 i++; /* increment value count */
2303 while (isspace((int) ((unsigned char) *p)) != 0)
2304 p++; /* skip spaces */
2305 if (*p == ',')
2306 p++; /* skip comma */
2307 while (isspace((int) ((unsigned char) *p)) != 0)
2308 p++; /* and more spaces */
cristy3ed852e2009-09-05 21:47:34 +00002309 }
cristy0a887dc2012-08-15 22:58:36 +00002310 /*
2311 Allocate floating point argument list.
2312 */
anthonyb1d483a2012-04-14 12:53:56 +00002313 *count=i;
cristy0a887dc2012-08-15 22:58:36 +00002314 array=(double *) AcquireQuantumMemory((size_t) i,sizeof(*array));
2315 if (array == (double *) NULL)
cristy70ca0222013-11-09 02:34:16 +00002316 {
2317 (void) ThrowMagickException(exception,GetMagickModule(),
2318 ResourceLimitError,"MemoryAllocationFailed","`%s'","");
2319 return((double *) NULL);
2320 }
cristy0a887dc2012-08-15 22:58:36 +00002321 /*
2322 Fill in the floating point values.
2323 */
anthonyb1d483a2012-04-14 12:53:56 +00002324 i=0;
cristy0a887dc2012-08-15 22:58:36 +00002325 p=string;
2326 while ((*p != '\0') && (i < *count))
2327 {
anthonyb1d483a2012-04-14 12:53:56 +00002328 array[i++]=StringToDouble(p,&q);
2329 p=q;
cristy0a887dc2012-08-15 22:58:36 +00002330 while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2331 p++;
anthonyb1d483a2012-04-14 12:53:56 +00002332 }
anthonyb1d483a2012-04-14 12:53:56 +00002333 return(array);
cristy3ed852e2009-09-05 21:47:34 +00002334}
2335
2336/*
2337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2338% %
2339% %
2340% %
anthonyb1d483a2012-04-14 12:53:56 +00002341+ S t r i n g T o k e n %
cristy3ed852e2009-09-05 21:47:34 +00002342% %
2343% %
2344% %
2345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346%
cristy66336b02014-04-07 20:48:46 +00002347% StringToken() looks for any one of given delimiters and splits the string
anthonyb1d483a2012-04-14 12:53:56 +00002348% into two separate strings by replacing the delimiter character found with a
2349% nul character.
2350%
2351% The given string pointer is changed to point to the string following the
2352% delimiter character found, or NULL. A pointer to the start of the
2353% string is returned, representing the token before the delimiter.
2354%
2355% In may ways this is equivent to the strtok() C library function, but with
2356% multiple delimiter characters rather than a delimiter string.
cristy3ed852e2009-09-05 21:47:34 +00002357%
2358% The format of the StringToken method is:
2359%
2360% char *StringToken(const char *delimiters,char **string)
2361%
2362% A description of each parameter follows:
2363%
2364% o delimiters: one or more delimiters.
2365%
2366% o string: return the first token in the string. If none is found, return
2367% NULL.
2368%
2369*/
2370MagickExport char *StringToken(const char *delimiters,char **string)
2371{
2372 char
2373 *q;
2374
2375 register char
2376 *p;
2377
2378 register const char
2379 *r;
2380
2381 register int
2382 c,
2383 d;
2384
2385 p=(*string);
2386 if (p == (char *) NULL)
2387 return((char *) NULL);
anthonyb1d483a2012-04-14 12:53:56 +00002388 q=p;
2389 for ( ; ; )
cristy3ed852e2009-09-05 21:47:34 +00002390 {
2391 c=(*p++);
2392 r=delimiters;
2393 do
2394 {
2395 d=(*r++);
2396 if (c == d)
2397 {
2398 if (c == '\0')
2399 p=(char *) NULL;
2400 else
2401 p[-1]='\0';
2402 *string=p;
2403 return(q);
2404 }
2405 } while (d != '\0');
2406 }
2407}
2408
2409/*
2410%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2411% %
2412% %
2413% %
2414% S t r i n g T o L i s t %
2415% %
2416% %
2417% %
2418%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2419%
2420% StringToList() converts a text string into a list by segmenting the text
2421% string at each carriage return discovered. The list is converted to HEX
2422% characters if any control characters are discovered within the text string.
2423%
2424% The format of the StringToList method is:
2425%
2426% char **StringToList(const char *text)
2427%
2428% A description of each parameter follows:
2429%
cristy3ed852e2009-09-05 21:47:34 +00002430% o text: Specifies the string to segment into a list.
2431%
2432*/
2433MagickExport char **StringToList(const char *text)
2434{
2435 char
2436 **textlist;
2437
2438 register const char
2439 *p;
2440
cristybb503372010-05-27 20:51:26 +00002441 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002442 i;
2443
cristybb503372010-05-27 20:51:26 +00002444 size_t
cristy3ed852e2009-09-05 21:47:34 +00002445 lines;
2446
2447 if (text == (char *) NULL)
2448 return((char **) NULL);
2449 for (p=text; *p != '\0'; p++)
2450 if (((int) ((unsigned char) *p) < 32) &&
2451 (isspace((int) ((unsigned char) *p)) == 0))
2452 break;
2453 if (*p == '\0')
2454 {
2455 register const char
2456 *q;
2457
2458 /*
2459 Convert string to an ASCII list.
2460 */
2461 lines=1;
2462 for (p=text; *p != '\0'; p++)
2463 if (*p == '\n')
2464 lines++;
2465 textlist=(char **) AcquireQuantumMemory((size_t) lines+1UL,
2466 sizeof(*textlist));
2467 if (textlist == (char **) NULL)
2468 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
2469 p=text;
cristybb503372010-05-27 20:51:26 +00002470 for (i=0; i < (ssize_t) lines; i++)
cristy3ed852e2009-09-05 21:47:34 +00002471 {
2472 for (q=p; *q != '\0'; q++)
2473 if ((*q == '\r') || (*q == '\n'))
2474 break;
2475 textlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
cristy2e25ee62011-03-25 15:43:12 +00002476 sizeof(**textlist));
cristy3ed852e2009-09-05 21:47:34 +00002477 if (textlist[i] == (char *) NULL)
2478 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
cristy54aad5e2010-09-03 16:02:04 +00002479 (void) memcpy(textlist[i],p,(size_t) (q-p));
cristy208cacf2010-09-03 02:24:42 +00002480 textlist[i][q-p]='\0';
cristy3ed852e2009-09-05 21:47:34 +00002481 if (*q == '\r')
2482 q++;
2483 p=q+1;
2484 }
2485 }
2486 else
2487 {
2488 char
2489 hex_string[MaxTextExtent];
2490
2491 register char
2492 *q;
2493
cristybb503372010-05-27 20:51:26 +00002494 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002495 j;
2496
2497 /*
2498 Convert string to a HEX list.
2499 */
cristybb503372010-05-27 20:51:26 +00002500 lines=(size_t) (strlen(text)/0x14)+1;
cristy3ed852e2009-09-05 21:47:34 +00002501 textlist=(char **) AcquireQuantumMemory((size_t) lines+1UL,
2502 sizeof(*textlist));
2503 if (textlist == (char **) NULL)
2504 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
2505 p=text;
cristybb503372010-05-27 20:51:26 +00002506 for (i=0; i < (ssize_t) lines; i++)
cristy3ed852e2009-09-05 21:47:34 +00002507 {
2508 textlist[i]=(char *) AcquireQuantumMemory(2UL*MaxTextExtent,
cristy2e25ee62011-03-25 15:43:12 +00002509 sizeof(**textlist));
cristy3ed852e2009-09-05 21:47:34 +00002510 if (textlist[i] == (char *) NULL)
2511 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
cristyb51dff52011-05-19 16:55:47 +00002512 (void) FormatLocaleString(textlist[i],MaxTextExtent,"0x%08lx: ",
cristyf1d91242010-05-28 02:23:19 +00002513 (long) (0x14*i));
cristy3ed852e2009-09-05 21:47:34 +00002514 q=textlist[i]+strlen(textlist[i]);
cristybb503372010-05-27 20:51:26 +00002515 for (j=1; j <= (ssize_t) MagickMin(strlen(p),0x14); j++)
cristy3ed852e2009-09-05 21:47:34 +00002516 {
cristyb51dff52011-05-19 16:55:47 +00002517 (void) FormatLocaleString(hex_string,MaxTextExtent,"%02x",*(p+j));
cristy3ed852e2009-09-05 21:47:34 +00002518 (void) CopyMagickString(q,hex_string,MaxTextExtent);
2519 q+=2;
2520 if ((j % 0x04) == 0)
2521 *q++=' ';
2522 }
2523 for ( ; j <= 0x14; j++)
2524 {
2525 *q++=' ';
2526 *q++=' ';
2527 if ((j % 0x04) == 0)
2528 *q++=' ';
2529 }
2530 *q++=' ';
cristybb503372010-05-27 20:51:26 +00002531 for (j=1; j <= (ssize_t) MagickMin(strlen(p),0x14); j++)
cristy3ed852e2009-09-05 21:47:34 +00002532 {
2533 if (isprint((int) ((unsigned char) *p)) != 0)
2534 *q++=(*p);
2535 else
2536 *q++='-';
2537 p++;
2538 }
2539 *q='\0';
2540 }
2541 }
2542 textlist[i]=(char *) NULL;
2543 return(textlist);
2544}
2545
2546/*
2547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2548% %
2549% %
2550% %
2551% S t r i n g T o S t r i n g I n f o %
2552% %
2553% %
2554% %
2555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2556%
cristybca58f32011-08-21 14:48:50 +00002557% StringToStringInfo() converts a string to a StringInfo type.
cristy3ed852e2009-09-05 21:47:34 +00002558%
2559% The format of the StringToStringInfo method is:
2560%
2561% StringInfo *StringToStringInfo(const char *string)
2562%
2563% A description of each parameter follows:
2564%
2565% o string: The string.
2566%
2567*/
2568MagickExport StringInfo *StringToStringInfo(const char *string)
2569{
2570 StringInfo
2571 *string_info;
2572
cristy3ed852e2009-09-05 21:47:34 +00002573 assert(string != (const char *) NULL);
cristybca58f32011-08-21 14:48:50 +00002574 string_info=AcquireStringInfo(strlen(string));
cristy3ed852e2009-09-05 21:47:34 +00002575 SetStringInfoDatum(string_info,(const unsigned char *) string);
2576 return(string_info);
2577}
2578
2579/*
2580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2581% %
2582% %
2583% %
2584% S t r i p S t r i n g %
2585% %
2586% %
2587% %
2588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2589%
2590% StripString() strips any whitespace or quotes from the beginning and end of
2591% a string of characters.
2592%
2593% The format of the StripString method is:
2594%
2595% void StripString(char *message)
2596%
2597% A description of each parameter follows:
2598%
2599% o message: Specifies an array of characters.
2600%
2601*/
2602MagickExport void StripString(char *message)
2603{
2604 register char
2605 *p,
2606 *q;
2607
2608 size_t
2609 length;
2610
2611 assert(message != (char *) NULL);
2612 if (*message == '\0')
2613 return;
2614 length=strlen(message);
2615 p=message;
2616 while (isspace((int) ((unsigned char) *p)) != 0)
2617 p++;
2618 if ((*p == '\'') || (*p == '"'))
2619 p++;
2620 q=message+length-1;
2621 while ((isspace((int) ((unsigned char) *q)) != 0) && (q > p))
2622 q--;
2623 if (q > p)
2624 if ((*q == '\'') || (*q == '"'))
2625 q--;
cristya63c1ba2011-06-02 20:33:43 +00002626 (void) memmove(message,p,(size_t) (q-p+1));
cristy3ed852e2009-09-05 21:47:34 +00002627 message[q-p+1]='\0';
2628 for (p=message; *p != '\0'; p++)
2629 if (*p == '\n')
2630 *p=' ';
2631}
2632
2633/*
2634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2635% %
2636% %
2637% %
2638% S u b s t i t u t e S t r i n g %
2639% %
2640% %
2641% %
2642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2643%
cristyf1b72c12009-10-06 13:25:21 +00002644% SubstituteString() performs string substitution on a string, replacing the
2645% string with the substituted version. Buffer must be allocated from the heap.
cristybc3392a2009-10-06 03:15:57 +00002646% If the string is matched and status, MagickTrue is returned otherwise
2647% MagickFalse.
cristy3ed852e2009-09-05 21:47:34 +00002648%
2649% The format of the SubstituteString method is:
2650%
cristyf1b72c12009-10-06 13:25:21 +00002651% MagickBooleanType SubstituteString(char **string,const char *search,
cristy3ed852e2009-09-05 21:47:34 +00002652% const char *replace)
2653%
2654% A description of each parameter follows:
2655%
cristyf1b72c12009-10-06 13:25:21 +00002656% o string: the string to perform replacements on; replaced with new
cristy3ed852e2009-09-05 21:47:34 +00002657% allocation if a replacement is made.
2658%
cristybc3392a2009-10-06 03:15:57 +00002659% o search: search for this string.
cristy3ed852e2009-09-05 21:47:34 +00002660%
cristybc3392a2009-10-06 03:15:57 +00002661% o replace: replace any matches with this string.
cristy3ed852e2009-09-05 21:47:34 +00002662%
2663*/
cristyf1b72c12009-10-06 13:25:21 +00002664MagickExport MagickBooleanType SubstituteString(char **string,
cristy3ed852e2009-09-05 21:47:34 +00002665 const char *search,const char *replace)
2666{
cristybc3392a2009-10-06 03:15:57 +00002667 MagickBooleanType
2668 status;
cristy3ed852e2009-09-05 21:47:34 +00002669
cristybc3392a2009-10-06 03:15:57 +00002670 register char
2671 *p;
cristy3ed852e2009-09-05 21:47:34 +00002672
cristy3ed852e2009-09-05 21:47:34 +00002673 size_t
cristybc3392a2009-10-06 03:15:57 +00002674 extent,
2675 replace_extent,
2676 search_extent;
cristy3ed852e2009-09-05 21:47:34 +00002677
cristyf1b72c12009-10-06 13:25:21 +00002678 ssize_t
2679 offset;
2680
cristybc3392a2009-10-06 03:15:57 +00002681 status=MagickFalse;
2682 search_extent=0,
2683 replace_extent=0;
cristyf1b72c12009-10-06 13:25:21 +00002684 for (p=strchr(*string,*search); p != (char *) NULL; p=strchr(p+1,*search))
cristy3ed852e2009-09-05 21:47:34 +00002685 {
cristyf1b72c12009-10-06 13:25:21 +00002686 if (search_extent == 0)
2687 search_extent=strlen(search);
2688 if (strncmp(p,search,search_extent) != 0)
cristybc3392a2009-10-06 03:15:57 +00002689 continue;
cristy3ed852e2009-09-05 21:47:34 +00002690 /*
cristybc3392a2009-10-06 03:15:57 +00002691 We found a match.
cristy3ed852e2009-09-05 21:47:34 +00002692 */
cristyf1b72c12009-10-06 13:25:21 +00002693 status=MagickTrue;
cristybc3392a2009-10-06 03:15:57 +00002694 if (replace_extent == 0)
2695 replace_extent=strlen(replace);
2696 if (replace_extent > search_extent)
cristy3ed852e2009-09-05 21:47:34 +00002697 {
cristybc3392a2009-10-06 03:15:57 +00002698 /*
2699 Make room for the replacement string.
2700 */
cristyde58b412010-02-18 03:53:40 +00002701 offset=(ssize_t) (p-(*string));
cristye08c3b82009-10-06 14:58:14 +00002702 extent=strlen(*string)+replace_extent-search_extent+1;
cristyf1b72c12009-10-06 13:25:21 +00002703 *string=(char *) ResizeQuantumMemory(*string,extent+MaxTextExtent,
2704 sizeof(*p));
2705 if (*string == (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002706 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristyf1b72c12009-10-06 13:25:21 +00002707 p=(*string)+offset;
cristy3ed852e2009-09-05 21:47:34 +00002708 }
cristy3ed852e2009-09-05 21:47:34 +00002709 /*
cristybc3392a2009-10-06 03:15:57 +00002710 Replace string.
cristy3ed852e2009-09-05 21:47:34 +00002711 */
cristybc3392a2009-10-06 03:15:57 +00002712 if (search_extent != replace_extent)
cristy0a9b3722010-10-23 18:45:49 +00002713 (void) CopyMagickMemory(p+replace_extent,p+search_extent,
2714 strlen(p+search_extent)+1);
2715 (void) CopyMagickMemory(p,replace,replace_extent);
cristyf1b72c12009-10-06 13:25:21 +00002716 p+=replace_extent-1;
cristy3ed852e2009-09-05 21:47:34 +00002717 }
cristybc3392a2009-10-06 03:15:57 +00002718 return(status);
cristy3ed852e2009-09-05 21:47:34 +00002719}