blob: b82fa841847c1b1f48f4cf7385dba3576d476a84 [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% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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"
dirk007e9252015-01-15 21:02:57 +000047#include "MagickCore/image-private.h"
cristy4c08aed2011-07-01 19:47:50 +000048#include "MagickCore/list.h"
49#include "MagickCore/locale_.h"
50#include "MagickCore/log.h"
51#include "MagickCore/memory_.h"
cristyd2d11ec2012-03-28 13:53:49 +000052#include "MagickCore/nt-base-private.h"
cristy4c08aed2011-07-01 19:47:50 +000053#include "MagickCore/property.h"
54#include "MagickCore/resource_.h"
55#include "MagickCore/signature-private.h"
56#include "MagickCore/string_.h"
anthonyb1d483a2012-04-14 12:53:56 +000057#include "MagickCore/string-private.h"
cristy18c6c272011-09-23 14:40:37 +000058#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000059
60/*
cristy99bbf2c2011-09-26 18:27:50 +000061 static declarations.
cristy3ed852e2009-09-05 21:47:34 +000062*/
63#if !defined(MAGICKCORE_HAVE_STRCASECMP) || !defined(MAGICKCORE_HAVE_STRNCASECMP)
64static const unsigned char
cristy8e7a4612013-09-16 22:10:27 +000065 AsciiMap[] =
cristy3ed852e2009-09-05 21:47:34 +000066 {
67 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
68 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
69 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
70 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
71 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
72 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
73 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
74 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
75 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
76 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
77 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
78 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
79 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
80 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
81 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
82 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
83 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
84 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
85 0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
86 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
87 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
88 0xfc, 0xfd, 0xfe, 0xff,
89 };
90#endif
91
92/*
93%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94% %
95% %
96% %
97% A c q u i r e S t r i n g %
98% %
99% %
100% %
101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102%
anthony104f8932012-05-13 01:54:53 +0000103% AcquireString() returns an new extented string, containing a clone of the
104% given string.
cristy3ed852e2009-09-05 21:47:34 +0000105%
cristy151b66d2015-04-15 10:50:31 +0000106% An extended string is the string length, plus an extra MagickPathExtent space
cristy5364f9c2013-12-28 23:29:28 +0000107% to allow for the string to be actively worked on.
anthony104f8932012-05-13 01:54:53 +0000108%
109% The returned string shoud be freed using DestoryString().
anthonyb1d483a2012-04-14 12:53:56 +0000110%
cristy3ed852e2009-09-05 21:47:34 +0000111% The format of the AcquireString method is:
112%
113% char *AcquireString(const char *source)
114%
115% A description of each parameter follows:
116%
117% o source: A character string.
118%
119*/
120MagickExport char *AcquireString(const char *source)
121{
122 char
123 *destination;
124
125 size_t
126 length;
127
128 length=0;
129 if (source != (char *) NULL)
130 length+=strlen(source);
cristy151b66d2015-04-15 10:50:31 +0000131 if (~length < MagickPathExtent)
cristy54aad5e2010-09-03 16:02:04 +0000132 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristy151b66d2015-04-15 10:50:31 +0000133 destination=(char *) AcquireQuantumMemory(length+MagickPathExtent,
cristy54aad5e2010-09-03 16:02:04 +0000134 sizeof(*destination));
cristy3ed852e2009-09-05 21:47:34 +0000135 if (destination == (char *) NULL)
136 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
137 *destination='\0';
138 if (source != (char *) NULL)
cristy54aad5e2010-09-03 16:02:04 +0000139 (void) memcpy(destination,source,length*sizeof(*destination));
140 destination[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000141 return(destination);
142}
143
144/*
145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146% %
147% %
148% %
149% A c q u i r e S t r i n g I n f o %
150% %
151% %
152% %
153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154%
155% AcquireStringInfo() allocates the StringInfo structure.
156%
157% The format of the AcquireStringInfo method is:
158%
159% StringInfo *AcquireStringInfo(const size_t length)
160%
161% A description of each parameter follows:
162%
163% o length: the string length.
164%
165*/
166MagickExport StringInfo *AcquireStringInfo(const size_t length)
167{
168 StringInfo
169 *string_info;
170
cristy73bd4a52010-10-05 11:24:23 +0000171 string_info=(StringInfo *) AcquireMagickMemory(sizeof(*string_info));
cristy3ed852e2009-09-05 21:47:34 +0000172 if (string_info == (StringInfo *) NULL)
173 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
174 (void) ResetMagickMemory(string_info,0,sizeof(*string_info));
cristye1c94d92015-06-28 12:16:33 +0000175 string_info->signature=MagickCoreSignature;
cristy3ed852e2009-09-05 21:47:34 +0000176 string_info->length=length;
cristy8a68c242014-04-07 20:43:37 +0000177 string_info->datum=(unsigned char *) NULL;
cristy151b66d2015-04-15 10:50:31 +0000178 if (~string_info->length >= (MagickPathExtent-1))
cristy8a68c242014-04-07 20:43:37 +0000179 string_info->datum=(unsigned char *) AcquireQuantumMemory(
cristy151b66d2015-04-15 10:50:31 +0000180 string_info->length+MagickPathExtent,sizeof(*string_info->datum));
cristy8a68c242014-04-07 20:43:37 +0000181 if (string_info->datum == (unsigned char *) NULL)
182 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristy3ed852e2009-09-05 21:47:34 +0000183 return(string_info);
184}
185
186/*
187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188% %
189% %
190% %
cristy8723e4b2011-09-01 13:11:19 +0000191% B l o b T o S t r i n g I n f o %
192% %
193% %
194% %
195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196%
anthony104f8932012-05-13 01:54:53 +0000197% BlobToStringInfo() returns the contents of a blob as a StringInfo structure
cristy151b66d2015-04-15 10:50:31 +0000198% with MagickPathExtent extra space.
cristy8723e4b2011-09-01 13:11:19 +0000199%
200% The format of the BlobToStringInfo method is:
201%
202% StringInfo *BlobToStringInfo(const void *blob,const size_t length)
203%
204% A description of each parameter follows:
205%
206% o blob: the blob.
207%
208% o length: the length of the blob.
209%
210*/
211MagickExport StringInfo *BlobToStringInfo(const void *blob,const size_t length)
212{
213 StringInfo
214 *string_info;
215
216 string_info=AcquireStringInfo(0);
cristy151b66d2015-04-15 10:50:31 +0000217 if (~length < MagickPathExtent)
cristy5ce7dac2014-05-28 12:22:17 +0000218 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
cristyf8316342011-09-01 13:55:00 +0000219 string_info->length=length;
cristy5ce7dac2014-05-28 12:22:17 +0000220 if (string_info->datum == (unsigned char *) NULL)
221 string_info->datum=(unsigned char *) AcquireQuantumMemory(length+
cristy151b66d2015-04-15 10:50:31 +0000222 MagickPathExtent,sizeof(*string_info->datum));
cristy5ce7dac2014-05-28 12:22:17 +0000223 else
224 string_info->datum=(unsigned char *) ResizeQuantumMemory(string_info->datum,
cristy151b66d2015-04-15 10:50:31 +0000225 length+MagickPathExtent,sizeof(*string_info->datum));
cristy8723e4b2011-09-01 13:11:19 +0000226 if (string_info->datum == (unsigned char *) NULL)
227 {
228 string_info=DestroyStringInfo(string_info);
229 return((StringInfo *) NULL);
230 }
231 if (blob != (const void *) NULL)
232 (void) memcpy(string_info->datum,blob,length);
233 return(string_info);
234}
235
236/*
237%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238% %
239% %
240% %
cristy3ed852e2009-09-05 21:47:34 +0000241% C l o n e S t r i n g %
242% %
243% %
244% %
245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246%
anthony104f8932012-05-13 01:54:53 +0000247% CloneString() replaces or frees the destination string to make it
cristya42df252015-04-15 22:33:45 +0000248% a clone of the input string plus MagickPathExtent more space so the string
249% may be worked on.
cristy3ed852e2009-09-05 21:47:34 +0000250%
anthony104f8932012-05-13 01:54:53 +0000251% If source is a NULL pointer the destination string will be freed and set to
252% a NULL pointer. A pointer to the stored in the destination is also returned.
anthony72feaa62012-01-17 06:46:23 +0000253%
anthony104f8932012-05-13 01:54:53 +0000254% When finished the non-NULL string should be freed using DestoryString()
255% or using CloneString() with a NULL pointed for the source.
anthony06762232012-04-29 11:45:40 +0000256%
cristy3ed852e2009-09-05 21:47:34 +0000257% The format of the CloneString method is:
258%
259% char *CloneString(char **destination,const char *source)
260%
261% A description of each parameter follows:
262%
263% o destination: A pointer to a character string.
264%
265% o source: A character string.
266%
267*/
268MagickExport char *CloneString(char **destination,const char *source)
269{
270 size_t
271 length;
272
cristy3ed852e2009-09-05 21:47:34 +0000273 assert(destination != (char **) NULL);
274 if (source == (const char *) NULL)
275 {
276 if (*destination != (char *) NULL)
277 *destination=DestroyString(*destination);
278 return(*destination);
279 }
280 if (*destination == (char *) NULL)
281 {
282 *destination=AcquireString(source);
283 return(*destination);
284 }
285 length=strlen(source);
cristy151b66d2015-04-15 10:50:31 +0000286 if (~length < MagickPathExtent)
cristy3ed852e2009-09-05 21:47:34 +0000287 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristya42df252015-04-15 22:33:45 +0000288 *destination=(char *) ResizeQuantumMemory(*destination,length+
289 MagickPathExtent,sizeof(**destination));
cristy3ed852e2009-09-05 21:47:34 +0000290 if (*destination == (char *) NULL)
291 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristy54aad5e2010-09-03 16:02:04 +0000292 if (length != 0)
cristyf7e6ab42011-03-25 12:32:09 +0000293 (void) memcpy(*destination,source,length*sizeof(**destination));
cristy208cacf2010-09-03 02:24:42 +0000294 (*destination)[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000295 return(*destination);
296}
297
298/*
299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300% %
301% %
302% %
303% C l o n e S t r i n g I n f o %
304% %
305% %
306% %
307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308%
309% CloneStringInfo() clones a copy of the StringInfo structure.
310%
311% The format of the CloneStringInfo method is:
312%
313% StringInfo *CloneStringInfo(const StringInfo *string_info)
314%
315% A description of each parameter follows:
316%
317% o string_info: the string info.
318%
319*/
320MagickExport StringInfo *CloneStringInfo(const StringInfo *string_info)
321{
322 StringInfo
323 *clone_info;
324
cristy3ed852e2009-09-05 21:47:34 +0000325 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000326 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000327 clone_info=AcquireStringInfo(string_info->length);
328 if (string_info->length != 0)
cristy54aad5e2010-09-03 16:02:04 +0000329 (void) memcpy(clone_info->datum,string_info->datum,string_info->length+1);
cristy3ed852e2009-09-05 21:47:34 +0000330 return(clone_info);
331}
332
333/*
334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335% %
336% %
337% %
338% C o m p a r e S t r i n g I n f o %
339% %
340% %
341% %
342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343%
344% CompareStringInfo() compares the two datums target and source. It returns
345% an integer less than, equal to, or greater than zero if target is found,
346% respectively, to be less than, to match, or be greater than source.
347%
348% The format of the CompareStringInfo method is:
349%
350% int CompareStringInfo(const StringInfo *target,const StringInfo *source)
351%
352% A description of each parameter follows:
353%
354% o target: the target string.
355%
356% o source: the source string.
357%
358*/
359
cristy3ed852e2009-09-05 21:47:34 +0000360MagickExport int CompareStringInfo(const StringInfo *target,
361 const StringInfo *source)
362{
363 int
364 status;
365
cristy3ed852e2009-09-05 21:47:34 +0000366 assert(target != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000367 assert(target->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000368 assert(source != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000369 assert(source->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000370 status=memcmp(target->datum,source->datum,MagickMin(target->length,
371 source->length));
372 if (status != 0)
373 return(status);
374 if (target->length == source->length)
375 return(0);
376 return(target->length < source->length ? -1 : 1);
377}
378
379/*
380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381% %
382% %
383% %
384% C o n c a t e n a t e M a g i c k S t r i n g %
385% %
386% %
387% %
388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389%
390% ConcatenateMagickString() concatenates the source string to the destination
391% string. The destination buffer is always null-terminated even if the
392% string must be truncated.
393%
394% The format of the ConcatenateMagickString method is:
395%
396% size_t ConcatenateMagickString(char *destination,const char *source,
397% const size_t length)
398%
399% A description of each parameter follows:
400%
401% o destination: the destination string.
402%
403% o source: the source string.
404%
405% o length: the length of the destination string.
406%
407*/
408MagickExport size_t ConcatenateMagickString(char *destination,
409 const char *source,const size_t length)
410{
411 register char
412 *q;
413
414 register const char
415 *p;
416
417 register size_t
418 i;
419
420 size_t
421 count;
422
423 assert(destination != (char *) NULL);
424 assert(source != (const char *) NULL);
425 assert(length >= 1);
426 p=source;
427 q=destination;
428 i=length;
429 while ((i-- != 0) && (*q != '\0'))
430 q++;
431 count=(size_t) (q-destination);
432 i=length-count;
433 if (i == 0)
434 return(count+strlen(p));
435 while (*p != '\0')
436 {
437 if (i != 1)
438 {
439 *q++=(*p);
440 i--;
441 }
442 p++;
443 }
444 *q='\0';
445 return(count+(p-source));
446}
447
448/*
449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
450% %
451% %
452% %
453% C o n c a t e n a t e S t r i n g %
454% %
455% %
456% %
457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458%
459% ConcatenateString() appends a copy of string source, including the
460% terminating null character, to the end of string destination.
461%
462% The format of the ConcatenateString method is:
463%
464% MagickBooleanType ConcatenateString(char **destination,
465% const char *source)
466%
467% A description of each parameter follows:
468%
469% o destination: A pointer to a character string.
470%
471% o source: A character string.
472%
473*/
474MagickExport MagickBooleanType ConcatenateString(char **destination,
475 const char *source)
476{
477 size_t
cristy54aad5e2010-09-03 16:02:04 +0000478 destination_length,
cristy3ed852e2009-09-05 21:47:34 +0000479 length,
480 source_length;
481
482 assert(destination != (char **) NULL);
483 if (source == (const char *) NULL)
484 return(MagickTrue);
485 if (*destination == (char *) NULL)
486 {
487 *destination=AcquireString(source);
488 return(MagickTrue);
489 }
cristy54aad5e2010-09-03 16:02:04 +0000490 destination_length=strlen(*destination);
cristy3ed852e2009-09-05 21:47:34 +0000491 source_length=strlen(source);
cristy54aad5e2010-09-03 16:02:04 +0000492 length=destination_length;
cristy3ed852e2009-09-05 21:47:34 +0000493 if (~length < source_length)
494 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
495 length+=source_length;
cristy151b66d2015-04-15 10:50:31 +0000496 if (~length < MagickPathExtent)
cristy3ed852e2009-09-05 21:47:34 +0000497 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
cristya42df252015-04-15 22:33:45 +0000498 *destination=(char *) ResizeQuantumMemory(*destination,length+
499 MagickPathExtent,sizeof(**destination));
cristy3ed852e2009-09-05 21:47:34 +0000500 if (*destination == (char *) NULL)
501 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
cristy54aad5e2010-09-03 16:02:04 +0000502 if (source_length != 0)
503 (void) memcpy((*destination)+destination_length,source,source_length);
504 (*destination)[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000505 return(MagickTrue);
506}
507
508/*
509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510% %
511% %
512% %
513% C o n c a t e n a t e S t r i n g I n f o %
514% %
515% %
516% %
517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518%
519% ConcatenateStringInfo() concatenates the source string to the destination
520% string.
521%
522% The format of the ConcatenateStringInfo method is:
523%
524% void ConcatenateStringInfo(StringInfo *string_info,
525% const StringInfo *source)
526%
527% A description of each parameter follows:
528%
529% o string_info: the string info.
530%
531% o source: the source string.
532%
533*/
534MagickExport void ConcatenateStringInfo(StringInfo *string_info,
535 const StringInfo *source)
536{
537 size_t
538 length;
539
cristy3ed852e2009-09-05 21:47:34 +0000540 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000541 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000542 assert(source != (const StringInfo *) NULL);
543 length=string_info->length;
544 if (~length < source->length)
545 ThrowFatalException(ResourceLimitFatalError,"UnableToConcatenateString");
546 SetStringInfoLength(string_info,length+source->length);
cristy54aad5e2010-09-03 16:02:04 +0000547 (void) memcpy(string_info->datum+length,source->datum,source->length);
cristy3ed852e2009-09-05 21:47:34 +0000548}
549
550/*
551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552% %
553% %
554% %
555% 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 %
556% %
557% %
558% %
559%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560%
561% ConfigureFileToStringInfo() returns the contents of a configure file as a
562% string.
563%
564% The format of the ConfigureFileToStringInfo method is:
565%
566% StringInfo *ConfigureFileToStringInfo(const char *filename)
567% ExceptionInfo *exception)
568%
569% A description of each parameter follows:
570%
571% o filename: the filename.
572%
573*/
cristy99bbf2c2011-09-26 18:27:50 +0000574MagickExport StringInfo *ConfigureFileToStringInfo(const char *filename)
cristy3ed852e2009-09-05 21:47:34 +0000575{
576 char
577 *string;
578
579 int
580 file;
581
582 MagickOffsetType
583 offset;
584
585 size_t
586 length;
587
588 StringInfo
589 *string_info;
590
591 void
592 *map;
593
594 assert(filename != (const char *) NULL);
cristy18c6c272011-09-23 14:40:37 +0000595 file=open_utf8(filename,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000596 if (file == -1)
597 return((StringInfo *) NULL);
cristy7f317702011-02-18 20:40:28 +0000598 offset=(MagickOffsetType) lseek(file,0,SEEK_END);
cristy3ed852e2009-09-05 21:47:34 +0000599 if ((offset < 0) || (offset != (MagickOffsetType) ((ssize_t) offset)))
600 {
601 file=close(file)-1;
602 return((StringInfo *) NULL);
603 }
604 length=(size_t) offset;
605 string=(char *) NULL;
cristy151b66d2015-04-15 10:50:31 +0000606 if (~length >= (MagickPathExtent-1))
cristya42df252015-04-15 22:33:45 +0000607 string=(char *) AcquireQuantumMemory(length+MagickPathExtent,
608 sizeof(*string));
cristy3ed852e2009-09-05 21:47:34 +0000609 if (string == (char *) NULL)
610 {
611 file=close(file)-1;
612 return((StringInfo *) NULL);
613 }
614 map=MapBlob(file,ReadMode,0,length);
615 if (map != (void *) NULL)
616 {
cristy54aad5e2010-09-03 16:02:04 +0000617 (void) memcpy(string,map,length);
cristy3ed852e2009-09-05 21:47:34 +0000618 (void) UnmapBlob(map,length);
619 }
620 else
621 {
622 register size_t
623 i;
624
625 ssize_t
626 count;
627
cristy7f317702011-02-18 20:40:28 +0000628 (void) lseek(file,0,SEEK_SET);
cristy3ed852e2009-09-05 21:47:34 +0000629 for (i=0; i < length; i+=count)
630 {
631 count=read(file,string+i,(size_t) MagickMin(length-i,(size_t)
632 SSIZE_MAX));
633 if (count <= 0)
634 {
635 count=0;
636 if (errno != EINTR)
637 break;
638 }
639 }
640 if (i < length)
641 {
642 file=close(file)-1;
643 string=DestroyString(string);
644 return((StringInfo *) NULL);
645 }
646 }
647 string[length]='\0';
648 file=close(file)-1;
649 string_info=AcquireStringInfo(0);
dirkcecec522015-04-14 20:17:56 +0000650 string_info->path=ConstantString(filename);
cristy5ce7dac2014-05-28 12:22:17 +0000651 string_info->length=length;
cristy7fb9fc12014-05-28 01:18:24 +0000652 if (string_info->datum != (unsigned char *) NULL)
653 string_info->datum=(unsigned char *) RelinquishMagickMemory(
654 string_info->datum);
cristy3ed852e2009-09-05 21:47:34 +0000655 string_info->datum=(unsigned char *) string;
656 return(string_info);
657}
658
659/*
660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661% %
662% %
663% %
664% C o n s t a n t S t r i n g %
665% %
666% %
667% %
668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669%
anthony104f8932012-05-13 01:54:53 +0000670% ConstantString() allocates exactly the needed memory for a string and
671% copies the source string to that memory location. A NULL string pointer
672% will allocate an empty string containing just the NUL character.
cristy3ed852e2009-09-05 21:47:34 +0000673%
anthony104f8932012-05-13 01:54:53 +0000674% When finished the string should be freed using DestoryString()
anthony06762232012-04-29 11:45:40 +0000675%
cristy3ed852e2009-09-05 21:47:34 +0000676% The format of the ConstantString method is:
677%
678% char *ConstantString(const char *source)
679%
680% A description of each parameter follows:
681%
682% o source: A character string.
683%
684*/
685MagickExport char *ConstantString(const char *source)
686{
687 char
688 *destination;
689
690 size_t
691 length;
692
693 length=0;
694 if (source != (char *) NULL)
695 length+=strlen(source);
696 destination=(char *) NULL;
697 if (~length >= 1UL)
698 destination=(char *) AcquireQuantumMemory(length+1UL,sizeof(*destination));
699 if (destination == (char *) NULL)
700 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
701 *destination='\0';
702 if (source != (char *) NULL)
cristy54aad5e2010-09-03 16:02:04 +0000703 (void) memcpy(destination,source,length*sizeof(*destination));
704 destination[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +0000705 return(destination);
706}
707
708/*
709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710% %
711% %
712% %
713% C o p y M a g i c k S t r i n g %
714% %
715% %
716% %
717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718%
anthony06762232012-04-29 11:45:40 +0000719% CopyMagickString() copies the source string to the destination string, with
720% out exceeding the given pre-declared length.
721%
722% The destination buffer is always null-terminated even if the string must be
723% truncated. The return value is the minimum of the source string length or
724% the length parameter.
cristy3ed852e2009-09-05 21:47:34 +0000725%
726% The format of the CopyMagickString method is:
727%
728% size_t CopyMagickString(const char *destination,char *source,
729% const size_t length)
730%
731% A description of each parameter follows:
732%
733% o destination: the destination string.
734%
735% o source: the source string.
736%
737% o length: the length of the destination string.
738%
739*/
740MagickExport size_t CopyMagickString(char *destination,const char *source,
741 const size_t length)
742{
743 register char
744 *q;
745
746 register const char
747 *p;
748
749 register size_t
750 n;
751
cristy77e3fcc2011-10-11 00:04:41 +0000752 if (source == (const char *) NULL)
753 return(0);
cristy3ed852e2009-09-05 21:47:34 +0000754 p=source;
755 q=destination;
756 for (n=length; n > 4; n-=4)
757 {
758 *q=(*p++);
759 if (*q == '\0')
760 return((size_t) (p-source-1));
761 q++;
762 *q=(*p++);
763 if (*q == '\0')
764 return((size_t) (p-source-1));
765 q++;
766 *q=(*p++);
767 if (*q == '\0')
768 return((size_t) (p-source-1));
769 q++;
770 *q=(*p++);
771 if (*q == '\0')
772 return((size_t) (p-source-1));
773 q++;
774 }
775 if (n != 0)
776 for (n--; n != 0; n--)
777 {
778 *q=(*p++);
779 if (*q == '\0')
780 return((size_t) (p-source-1));
781 q++;
782 }
783 if (length != 0)
784 *q='\0';
785 return((size_t) (p-source-1));
786}
787
788/*
789%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790% %
791% %
792% %
793% D e s t r o y S t r i n g %
794% %
795% %
796% %
797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798%
799% DestroyString() destroys memory associated with a string.
800%
801% The format of the DestroyString method is:
802%
803% char *DestroyString(char *string)
804%
805% A description of each parameter follows:
806%
807% o string: the string.
808%
809*/
810MagickExport char *DestroyString(char *string)
811{
812 return((char *) RelinquishMagickMemory(string));
813}
814
815/*
816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817% %
818% %
819% %
820% D e s t r o y S t r i n g I n f o %
821% %
822% %
823% %
824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825%
826% DestroyStringInfo() destroys memory associated with the StringInfo structure.
827%
828% The format of the DestroyStringInfo method is:
829%
830% StringInfo *DestroyStringInfo(StringInfo *string_info)
831%
832% A description of each parameter follows:
833%
834% o string_info: the string info.
835%
836*/
837MagickExport StringInfo *DestroyStringInfo(StringInfo *string_info)
838{
cristy3ed852e2009-09-05 21:47:34 +0000839 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000840 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000841 if (string_info->datum != (unsigned char *) NULL)
842 string_info->datum=(unsigned char *) RelinquishMagickMemory(
843 string_info->datum);
dirkcecec522015-04-14 20:17:56 +0000844 if (string_info->path != (char *) NULL)
dirk1e7a6d02015-04-14 20:20:42 +0000845 string_info->path=DestroyString(string_info->path);
cristye1c94d92015-06-28 12:16:33 +0000846 string_info->signature=(~MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000847 string_info=(StringInfo *) RelinquishMagickMemory(string_info);
848 return(string_info);
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853% %
854% %
855% %
856% D e s t r o y S t r i n g L i s t %
857% %
858% %
859% %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862% DestroyStringList() zeros memory associated with a string list.
863%
864% The format of the DestroyStringList method is:
865%
866% char **DestroyStringList(char **list)
867%
868% A description of each parameter follows:
869%
870% o list: the string list.
871%
872*/
873MagickExport char **DestroyStringList(char **list)
874{
cristybb503372010-05-27 20:51:26 +0000875 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000876 i;
877
878 assert(list != (char **) NULL);
879 for (i=0; list[i] != (char *) NULL; i++)
880 list[i]=DestroyString(list[i]);
881 list=(char **) RelinquishMagickMemory(list);
882 return(list);
883}
884
885/*
886%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887% %
888% %
889% %
890% E s c a p e S t r i n g %
891% %
892% %
893% %
894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895%
896% EscapeString() allocates memory for a backslash-escaped version of a
897% source text string, copies the escaped version of the text to that
898% memory location while adding backslash characters, and returns the
899% escaped string.
900%
901% The format of the EscapeString method is:
902%
903% char *EscapeString(const char *source,const char escape)
904%
905% A description of each parameter follows:
906%
907% o allocate_string: Method EscapeString returns the escaped string.
908%
909% o source: A character string.
910%
911% o escape: the quoted string termination character to escape (e.g. '"').
912%
913*/
914MagickExport char *EscapeString(const char *source,const char escape)
915{
916 char
917 *destination;
918
919 register char
920 *q;
921
922 register const char
923 *p;
924
925 size_t
926 length;
927
cristy3ed852e2009-09-05 21:47:34 +0000928 assert(source != (const char *) NULL);
929 length=strlen(source);
930 for (p=source; *p != '\0'; p++)
931 if ((*p == '\\') || (*p == escape))
932 {
933 if (~length < 1)
934 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
935 length++;
936 }
937 destination=(char *) NULL;
cristy151b66d2015-04-15 10:50:31 +0000938 if (~length >= (MagickPathExtent-1))
939 destination=(char *) AcquireQuantumMemory(length+MagickPathExtent,
cristy3ed852e2009-09-05 21:47:34 +0000940 sizeof(*destination));
941 if (destination == (char *) NULL)
942 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
943 *destination='\0';
cristy4662a132015-01-19 19:27:00 +0000944 q=destination;
945 for (p=source; *p != '\0'; p++)
946 {
947 if ((*p == '\\') || (*p == escape))
948 *q++='\\';
949 *q++=(*p);
950 }
951 *q='\0';
cristy3ed852e2009-09-05 21:47:34 +0000952 return(destination);
953}
954
955/*
956%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957% %
958% %
959% %
960% F i l e T o S t r i n g %
961% %
962% %
963% %
964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965%
966% FileToString() returns the contents of a file as a string.
967%
968% The format of the FileToString method is:
969%
970% char *FileToString(const char *filename,const size_t extent,
971% ExceptionInfo *exception)
972%
973% A description of each parameter follows:
974%
975% o filename: the filename.
976%
977% o extent: Maximum length of the string.
978%
979% o exception: return any errors or warnings in this structure.
980%
981*/
982MagickExport char *FileToString(const char *filename,const size_t extent,
983 ExceptionInfo *exception)
984{
985 size_t
986 length;
987
988 assert(filename != (const char *) NULL);
989 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
990 assert(exception != (ExceptionInfo *) NULL);
991 return((char *) FileToBlob(filename,extent,&length,exception));
992}
993
994/*
995%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996% %
997% %
998% %
999% F i l e T o S t r i n g I n f o %
1000% %
1001% %
1002% %
1003%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004%
1005% FileToStringInfo() returns the contents of a file as a string.
1006%
1007% The format of the FileToStringInfo method is:
1008%
1009% StringInfo *FileToStringInfo(const char *filename,const size_t extent,
1010% ExceptionInfo *exception)
1011%
1012% A description of each parameter follows:
1013%
1014% o filename: the filename.
1015%
1016% o extent: Maximum length of the string.
1017%
1018% o exception: return any errors or warnings in this structure.
1019%
1020*/
1021MagickExport StringInfo *FileToStringInfo(const char *filename,
1022 const size_t extent,ExceptionInfo *exception)
1023{
1024 StringInfo
1025 *string_info;
1026
1027 assert(filename != (const char *) NULL);
1028 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1029 assert(exception != (ExceptionInfo *) NULL);
1030 string_info=AcquireStringInfo(0);
dirkcecec522015-04-14 20:17:56 +00001031 string_info->path=ConstantString(filename);
cristy7fb9fc12014-05-28 01:18:24 +00001032 if (string_info->datum != (unsigned char *) NULL)
1033 string_info->datum=(unsigned char *) RelinquishMagickMemory(
1034 string_info->datum);
dirkcecec522015-04-14 20:17:56 +00001035 string_info->datum=(unsigned char *) FileToBlob(filename,extent,
1036 &string_info->length,exception);
cristy3ed852e2009-09-05 21:47:34 +00001037 if (string_info->datum == (unsigned char *) NULL)
1038 {
1039 string_info=DestroyStringInfo(string_info);
1040 return((StringInfo *) NULL);
1041 }
1042 return(string_info);
1043}
1044
1045/*
1046%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1047% %
1048% %
1049% %
1050% F o r m a t M a g i c k S i z e %
1051% %
1052% %
1053% %
1054%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1055%
1056% FormatMagickSize() converts a size to a human readable format, for example,
cristy2ce15c92010-03-12 14:03:41 +00001057% 14k, 234m, 2.7g, or 3.0t. Scaling is done by repetitively dividing by
cristyc15ce492009-12-01 19:18:23 +00001058% 1000.
cristy3ed852e2009-09-05 21:47:34 +00001059%
1060% The format of the FormatMagickSize method is:
1061%
cristy40937042014-12-22 01:44:59 +00001062% ssize_t FormatMagickSize(const MagickSizeType size,const char *suffix,
cristyd4618c02015-04-14 23:54:43 +00001063% const size_t length,char *format)
cristy3ed852e2009-09-05 21:47:34 +00001064%
1065% A description of each parameter follows:
1066%
1067% o size: convert this size to a human readable format.
1068%
cristyb9080c92009-12-01 20:13:26 +00001069% o bi: use power of two rather than power of ten.
1070%
cristy40937042014-12-22 01:44:59 +00001071% o suffix: append suffix, typically B or P.
1072%
cristyd4618c02015-04-14 23:54:43 +00001073% o length: the maximum length of the string.
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,
cristyd4618c02015-04-14 23:54:43 +00001079 const MagickBooleanType bi,const char *suffix,const size_t length,
1080 char *format)
cristy3ed852e2009-09-05 21:47:34 +00001081{
cristyb9080c92009-12-01 20:13:26 +00001082 const char
1083 **units;
1084
cristy3ed852e2009-09-05 21:47:34 +00001085 double
cristyb9080c92009-12-01 20:13:26 +00001086 bytes,
cristyd4618c02015-04-14 23:54:43 +00001087 extent;
cristy3ed852e2009-09-05 21:47:34 +00001088
cristybb503372010-05-27 20:51:26 +00001089 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001090 i,
1091 j;
1092
cristy9d314ff2011-03-09 01:30:28 +00001093 ssize_t
1094 count;
1095
cristy3ed852e2009-09-05 21:47:34 +00001096 static const char
cristyb9080c92009-12-01 20:13:26 +00001097 *bi_units[] =
1098 {
cristy2ce15c92010-03-12 14:03:41 +00001099 "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi", (char *) NULL
cristyb9080c92009-12-01 20:13:26 +00001100 },
1101 *traditional_units[] =
cristy9bf9da32009-09-27 16:48:34 +00001102 {
cristy2ce15c92010-03-12 14:03:41 +00001103 "", "K", "M", "G", "T", "P", "E", "Z", "Y", (char *) NULL
cristy9bf9da32009-09-27 16:48:34 +00001104 };
cristy3ed852e2009-09-05 21:47:34 +00001105
cristyb9080c92009-12-01 20:13:26 +00001106 bytes=1000.0;
1107 units=traditional_units;
1108 if (bi != MagickFalse)
1109 {
1110 bytes=1024.0;
1111 units=bi_units;
1112 }
cristy3ed852e2009-09-05 21:47:34 +00001113#if defined(_MSC_VER) && (_MSC_VER == 1200)
cristyd4618c02015-04-14 23:54:43 +00001114 extent=(double) ((MagickOffsetType) size);
cristy3ed852e2009-09-05 21:47:34 +00001115#else
cristyd4618c02015-04-14 23:54:43 +00001116 extent=(double) size;
cristy3ed852e2009-09-05 21:47:34 +00001117#endif
cristyd4618c02015-04-14 23:54:43 +00001118 for (i=0; (extent >= bytes) && (units[i+1] != (const char *) NULL); i++)
1119 extent/=bytes;
cristyc3b9b362013-05-25 17:16:34 +00001120 count=0;
cristy9bf9da32009-09-27 16:48:34 +00001121 for (j=2; j < 12; j++)
cristy3ed852e2009-09-05 21:47:34 +00001122 {
cristy40937042014-12-22 01:44:59 +00001123 if (suffix == (const char *) NULL)
cristyd4618c02015-04-14 23:54:43 +00001124 count=FormatLocaleString(format,length,"%.*g%s",(int) (i+j),extent,
1125 units[i]);
cristy40937042014-12-22 01:44:59 +00001126 else
cristyd4618c02015-04-14 23:54:43 +00001127 count=FormatLocaleString(format,length,"%.*g%s%s",(int) (i+j),extent,
1128 units[i],suffix);
cristy3ed852e2009-09-05 21:47:34 +00001129 if (strchr(format,'+') == (char *) NULL)
1130 break;
1131 }
1132 return(count);
1133}
1134
1135/*
1136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1137% %
1138% %
1139% %
cristy3ed852e2009-09-05 21:47:34 +00001140% F o r m a t M a g i c k T i m e %
1141% %
1142% %
1143% %
1144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1145%
1146% FormatMagickTime() returns the specified time in the Internet date/time
1147% format and the length of the timestamp.
1148%
1149% The format of the FormatMagickTime method is:
1150%
cristybb503372010-05-27 20:51:26 +00001151% ssize_t FormatMagickTime(const time_t time,const size_t length,
cristy3ed852e2009-09-05 21:47:34 +00001152% char *timestamp)
1153%
1154% A description of each parameter follows.
1155%
cristyd4618c02015-04-14 23:54:43 +00001156% o time: the time since the Epoch (00:00:00 UTC, January 1, 1970),
1157% measured in seconds.
cristy3ed852e2009-09-05 21:47:34 +00001158%
cristyd4618c02015-04-14 23:54:43 +00001159% o length: the maximum length of the string.
cristy3ed852e2009-09-05 21:47:34 +00001160%
cristyd4618c02015-04-14 23:54:43 +00001161% o timestamp: Return the Internet date/time here.
cristy3ed852e2009-09-05 21:47:34 +00001162%
1163*/
cristybb503372010-05-27 20:51:26 +00001164MagickExport ssize_t FormatMagickTime(const time_t time,const size_t length,
cristy3ed852e2009-09-05 21:47:34 +00001165 char *timestamp)
1166{
cristybb503372010-05-27 20:51:26 +00001167 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001168 count;
1169
1170 struct tm
1171 gm_time,
1172 local_time;
1173
1174 time_t
1175 timezone;
1176
1177 assert(timestamp != (char *) NULL);
1178 (void) ResetMagickMemory(&local_time,0,sizeof(local_time));
1179 (void) ResetMagickMemory(&gm_time,0,sizeof(gm_time));
1180#if defined(MAGICKCORE_HAVE_LOCALTIME_R)
1181 (void) localtime_r(&time,&local_time);
1182#else
1183 {
cristybc3392a2009-10-06 03:15:57 +00001184 struct tm
cristy3ed852e2009-09-05 21:47:34 +00001185 *my_time;
1186
1187 my_time=localtime(&time);
1188 if (my_time != (struct tm *) NULL)
1189 (void) memcpy(&local_time,my_time,sizeof(local_time));
1190 }
1191#endif
1192#if defined(MAGICKCORE_HAVE_GMTIME_R)
1193 (void) gmtime_r(&time,&gm_time);
1194#else
1195 {
cristybc3392a2009-10-06 03:15:57 +00001196 struct tm
cristy3ed852e2009-09-05 21:47:34 +00001197 *my_time;
1198
1199 my_time=gmtime(&time);
1200 if (my_time != (struct tm *) NULL)
1201 (void) memcpy(&gm_time,my_time,sizeof(gm_time));
1202 }
1203#endif
1204 timezone=(time_t) ((local_time.tm_min-gm_time.tm_min)/60+
1205 local_time.tm_hour-gm_time.tm_hour+24*((local_time.tm_year-
1206 gm_time.tm_year) != 0 ? (local_time.tm_year-gm_time.tm_year) :
1207 (local_time.tm_yday-gm_time.tm_yday)));
cristyb51dff52011-05-19 16:55:47 +00001208 count=FormatLocaleString(timestamp,length,
cristy3ed852e2009-09-05 21:47:34 +00001209 "%04d-%02d-%02dT%02d:%02d:%02d%+03ld:00",local_time.tm_year+1900,
1210 local_time.tm_mon+1,local_time.tm_mday,local_time.tm_hour,
cristyf1d91242010-05-28 02:23:19 +00001211 local_time.tm_min,local_time.tm_sec,(long) timezone);
cristy3ed852e2009-09-05 21:47:34 +00001212 return(count);
1213}
1214
1215/*
1216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217% %
1218% %
1219% %
1220% G e t E n v i r o n m e n t V a l u e %
1221% %
1222% %
1223% %
1224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225%
1226% GetEnvironmentValue() returns the environment string that matches the
1227% specified name.
1228%
1229% The format of the GetEnvironmentValue method is:
1230%
1231% char *GetEnvironmentValue(const char *name)
1232%
1233% A description of each parameter follows:
1234%
1235% o name: the environment name.
1236%
1237*/
cristy99bbf2c2011-09-26 18:27:50 +00001238MagickExport char *GetEnvironmentValue(const char *name)
cristy3ed852e2009-09-05 21:47:34 +00001239{
1240 const char
1241 *environment;
1242
1243 environment=getenv(name);
1244 if (environment == (const char *) NULL)
1245 return((char *) NULL);
1246 return(ConstantString(environment));
1247}
1248
1249/*
1250%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1251% %
1252% %
1253% %
1254% G e t S t r i n g I n f o D a t u m %
1255% %
1256% %
1257% %
1258%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1259%
1260% GetStringInfoDatum() returns the datum associated with the string.
1261%
1262% The format of the GetStringInfoDatum method is:
1263%
1264% unsigned char *GetStringInfoDatum(const StringInfo *string_info)
1265%
1266% A description of each parameter follows:
1267%
1268% o string_info: the string info.
1269%
1270*/
1271MagickExport unsigned char *GetStringInfoDatum(const StringInfo *string_info)
1272{
1273 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001274 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001275 return(string_info->datum);
1276}
1277
1278/*
1279%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1280% %
1281% %
1282% %
1283% G e t S t r i n g I n f o L e n g t h %
1284% %
1285% %
1286% %
1287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1288%
1289% GetStringInfoLength() returns the string length.
1290%
1291% The format of the GetStringInfoLength method is:
1292%
1293% size_t GetStringInfoLength(const StringInfo *string_info)
1294%
1295% A description of each parameter follows:
1296%
1297% o string_info: the string info.
1298%
1299*/
1300MagickExport size_t GetStringInfoLength(const StringInfo *string_info)
1301{
1302 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001303 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001304 return(string_info->length);
1305}
1306
1307/*
1308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1309% %
1310% %
1311% %
1312% G e t S t r i n g I n f o P a t h %
1313% %
1314% %
1315% %
1316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1317%
1318% GetStringInfoPath() returns the path associated with the string.
1319%
1320% The format of the GetStringInfoPath method is:
1321%
1322% const char *GetStringInfoPath(const StringInfo *string_info)
1323%
1324% A description of each parameter follows:
1325%
1326% o string_info: the string info.
1327%
1328*/
1329MagickExport const char *GetStringInfoPath(const StringInfo *string_info)
1330{
1331 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001332 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001333 return(string_info->path);
1334}
1335
1336/*
1337%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1338% %
1339% %
1340% %
cristydbdd0e32011-11-04 23:29:40 +00001341+ I n t e r p r e t S i P r e f i x V a l u e %
1342% %
1343% %
1344% %
1345%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1346%
1347% InterpretSiPrefixValue() converts the initial portion of the string to a
1348% double representation. It also recognizes SI prefixes (e.g. B, KB, MiB,
1349% etc.).
1350%
1351% The format of the InterpretSiPrefixValue method is:
1352%
1353% double InterpretSiPrefixValue(const char *value,char **sentinal)
1354%
1355% A description of each parameter follows:
1356%
1357% o value: the string value.
1358%
1359% o sentinal: if sentinal is not NULL, return a pointer to the character
1360% after the last character used in the conversion.
1361%
1362*/
1363MagickExport double InterpretSiPrefixValue(const char *restrict string,
1364 char **restrict sentinal)
1365{
1366 char
1367 *q;
1368
1369 double
1370 value;
1371
cristydbdd0e32011-11-04 23:29:40 +00001372 value=InterpretLocaleValue(string,&q);
1373 if (q != string)
1374 {
1375 if ((*q >= 'E') && (*q <= 'z'))
1376 {
1377 double
1378 e;
1379
cristy0c2684f2011-11-05 21:39:43 +00001380 switch ((int) ((unsigned char) *q))
1381 {
1382 case 'y': e=(-24.0); break;
1383 case 'z': e=(-21.0); break;
1384 case 'a': e=(-18.0); break;
1385 case 'f': e=(-15.0); break;
1386 case 'p': e=(-12.0); break;
1387 case 'n': e=(-9.0); break;
1388 case 'u': e=(-6.0); break;
1389 case 'm': e=(-3.0); break;
1390 case 'c': e=(-2.0); break;
1391 case 'd': e=(-1.0); break;
1392 case 'h': e=2.0; break;
1393 case 'k': e=3.0; break;
1394 case 'K': e=3.0; break;
1395 case 'M': e=6.0; break;
1396 case 'G': e=9.0; break;
1397 case 'T': e=12.0; break;
1398 case 'P': e=15.0; break;
1399 case 'E': e=18.0; break;
1400 case 'Z': e=21.0; break;
1401 case 'Y': e=24.0; break;
1402 default: e=0.0; break;
1403 }
cristydbdd0e32011-11-04 23:29:40 +00001404 if (e >= MagickEpsilon)
1405 {
1406 if (q[1] == 'i')
1407 {
1408 value*=pow(2.0,e/0.3);
1409 q+=2;
1410 }
1411 else
1412 {
1413 value*=pow(10.0,e);
1414 q++;
1415 }
1416 }
1417 }
cristy40937042014-12-22 01:44:59 +00001418 if ((*q == 'B') || (*q == 'P'))
cristy099a7352011-11-09 14:31:35 +00001419 q++;
cristydbdd0e32011-11-04 23:29:40 +00001420 }
1421 if (sentinal != (char **) NULL)
1422 *sentinal=q;
1423 return(value);
1424}
1425
1426/*
1427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428% %
1429% %
1430% %
anthony6f201312012-03-30 04:08:15 +00001431% I s S t r i n g T r u e %
1432% %
1433% %
1434% %
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436%
1437% IsStringTrue() returns MagickTrue if the value is "true", "on", "yes" or
1438% "1". Any other string or undefined returns MagickFalse.
1439%
1440% Typically this is used to look at strings (options or artifacts) which
1441% has a default value of "false", when not defined.
1442%
1443% The format of the IsStringTrue method is:
1444%
1445% MagickBooleanType IsStringTrue(const char *value)
1446%
1447% A description of each parameter follows:
1448%
1449% o value: Specifies a pointer to a character array.
1450%
1451*/
1452MagickExport MagickBooleanType IsStringTrue(const char *value)
1453{
1454 if (value == (const char *) NULL)
1455 return(MagickFalse);
1456 if (LocaleCompare(value,"true") == 0)
1457 return(MagickTrue);
1458 if (LocaleCompare(value,"on") == 0)
1459 return(MagickTrue);
1460 if (LocaleCompare(value,"yes") == 0)
1461 return(MagickTrue);
1462 if (LocaleCompare(value,"1") == 0)
1463 return(MagickTrue);
1464 return(MagickFalse);
1465}
1466
1467/*
1468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1469% %
1470% %
1471% %
dirk9a846de2015-07-25 16:51:01 +00001472% I s S t r i n g F a l s e %
anthony6f201312012-03-30 04:08:15 +00001473% %
1474% %
1475% %
1476%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1477%
dirk9a846de2015-07-25 16:51:01 +00001478% IsStringFalse() returns MagickTrue if the value is "false", "off", "no" or
1479% "0". Any other string or undefined returns MagickFalse.
anthony6f201312012-03-30 04:08:15 +00001480%
1481% Typically this is used to look at strings (options or artifacts) which
1482% has a default value of "true", when it has not been defined.
1483%
dirk9a846de2015-07-25 16:51:01 +00001484% The format of the IsStringFalse method is:
anthony6f201312012-03-30 04:08:15 +00001485%
dirk9a846de2015-07-25 16:51:01 +00001486% MagickBooleanType IsStringFalse(const char *value)
anthony6f201312012-03-30 04:08:15 +00001487%
1488% A description of each parameter follows:
1489%
1490% o value: Specifies a pointer to a character array.
1491%
1492*/
dirk9a846de2015-07-25 16:51:01 +00001493MagickExport MagickBooleanType IsStringFalse(const char *value)
anthony6f201312012-03-30 04:08:15 +00001494{
1495 if (value == (const char *) NULL)
dirk9a846de2015-07-25 16:51:01 +00001496 return(MagickFalse);
anthony6f201312012-03-30 04:08:15 +00001497 if (LocaleCompare(value,"false") == 0)
dirk9a846de2015-07-25 16:51:01 +00001498 return(MagickTrue);
anthony6f201312012-03-30 04:08:15 +00001499 if (LocaleCompare(value,"off") == 0)
dirk9a846de2015-07-25 16:51:01 +00001500 return(MagickTrue);
anthony6f201312012-03-30 04:08:15 +00001501 if (LocaleCompare(value,"no") == 0)
dirk9a846de2015-07-25 16:51:01 +00001502 return(MagickTrue);
anthony6f201312012-03-30 04:08:15 +00001503 if (LocaleCompare(value,"0") == 0)
dirk9a846de2015-07-25 16:51:01 +00001504 return(MagickTrue);
1505 return(MagickFalse);
anthony6f201312012-03-30 04:08:15 +00001506}
1507
1508/*
1509%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1510% %
1511% %
1512% %
cristy3ed852e2009-09-05 21:47:34 +00001513% L o c a l e C o m p a r e %
1514% %
1515% %
1516% %
1517%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1518%
1519% LocaleCompare() performs a case-insensitive comparison of two strings
1520% byte-by-byte, according to the ordering of the current locale encoding.
1521% LocaleCompare returns an integer greater than, equal to, or less than 0,
1522% if the string pointed to by p is greater than, equal to, or less than the
1523% string pointed to by q respectively. The sign of a non-zero return value
cristy7a40ba82011-01-08 20:31:18 +00001524% is determined by the sign of the difference between the values of the first
1525% pair of bytes that differ in the strings being compared.
cristy3ed852e2009-09-05 21:47:34 +00001526%
1527% The format of the LocaleCompare method is:
1528%
cristyde58b412010-02-18 03:53:40 +00001529% int LocaleCompare(const char *p,const char *q)
cristy3ed852e2009-09-05 21:47:34 +00001530%
1531% A description of each parameter follows:
1532%
1533% o p: A pointer to a character string.
1534%
1535% o q: A pointer to a character string to compare to p.
1536%
1537*/
cristyde58b412010-02-18 03:53:40 +00001538MagickExport int LocaleCompare(const char *p,const char *q)
cristy3ed852e2009-09-05 21:47:34 +00001539{
1540 if ((p == (char *) NULL) && (q == (char *) NULL))
1541 return(0);
1542 if (p == (char *) NULL)
1543 return(-1);
1544 if (q == (char *) NULL)
1545 return(1);
1546#if defined(MAGICKCORE_HAVE_STRCASECMP)
cristy27397b22010-02-18 17:30:43 +00001547 return(strcasecmp(p,q));
cristy3ed852e2009-09-05 21:47:34 +00001548#else
1549 {
cristyde58b412010-02-18 03:53:40 +00001550 register int
cristy3ed852e2009-09-05 21:47:34 +00001551 c,
cristya72c2d12010-02-18 01:20:28 +00001552 d;
cristy3ed852e2009-09-05 21:47:34 +00001553
cristya72c2d12010-02-18 01:20:28 +00001554 for ( ; ; )
cristy3ed852e2009-09-05 21:47:34 +00001555 {
cristyde58b412010-02-18 03:53:40 +00001556 c=(int) *((unsigned char *) p);
1557 d=(int) *((unsigned char *) q);
1558 if ((c == 0) || (AsciiMap[c] != AsciiMap[d]))
cristy3ed852e2009-09-05 21:47:34 +00001559 break;
cristya72c2d12010-02-18 01:20:28 +00001560 p++;
1561 q++;
cristy3ed852e2009-09-05 21:47:34 +00001562 }
cristyde58b412010-02-18 03:53:40 +00001563 return(AsciiMap[c]-(int) AsciiMap[d]);
cristy3ed852e2009-09-05 21:47:34 +00001564 }
1565#endif
1566}
1567
1568/*
1569%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1570% %
1571% %
1572% %
1573% L o c a l e L o w e r %
1574% %
1575% %
1576% %
1577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1578%
1579% LocaleLower() transforms all of the characters in the supplied
1580% null-terminated string, changing all uppercase letters to lowercase.
1581%
1582% The format of the LocaleLower method is:
1583%
1584% void LocaleLower(char *string)
1585%
1586% A description of each parameter follows:
1587%
1588% o string: A pointer to the string to convert to lower-case Locale.
1589%
1590*/
1591MagickExport void LocaleLower(char *string)
1592{
1593 register char
1594 *q;
1595
1596 assert(string != (char *) NULL);
1597 for (q=string; *q != '\0'; q++)
1598 *q=(char) tolower((int) *q);
1599}
1600
1601/*
1602%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1603% %
1604% %
1605% %
1606% L o c a l e N C o m p a r e %
1607% %
1608% %
1609% %
1610%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1611%
anthony06762232012-04-29 11:45:40 +00001612% LocaleNCompare() performs a case-insensitive comparison of two strings
1613% byte-by-byte, according to the ordering of the current locale encoding.
1614%
1615% LocaleNCompare returns an integer greater than, equal to, or less than 0,
1616% if the string pointed to by p is greater than, equal to, or less than the
1617% string pointed to by q respectively. The sign of a non-zero return value
1618% is determined by the sign of the difference between the values of the first
1619% pair of bytes that differ in the strings being compared.
1620%
1621% The LocaleNCompare method makes the same comparison as LocaleCompare but
1622% looks at a maximum of n bytes. Bytes following a null byte are not
1623% compared.
cristy3ed852e2009-09-05 21:47:34 +00001624%
1625% The format of the LocaleNCompare method is:
1626%
cristyde58b412010-02-18 03:53:40 +00001627% int LocaleNCompare(const char *p,const char *q,const size_t n)
cristy3ed852e2009-09-05 21:47:34 +00001628%
1629% A description of each parameter follows:
1630%
1631% o p: A pointer to a character string.
1632%
1633% o q: A pointer to a character string to compare to p.
1634%
cristy7a40ba82011-01-08 20:31:18 +00001635% o length: the number of characters to compare in strings p and q.
cristy3ed852e2009-09-05 21:47:34 +00001636%
1637*/
cristyde58b412010-02-18 03:53:40 +00001638MagickExport int LocaleNCompare(const char *p,const char *q,const size_t length)
cristy3ed852e2009-09-05 21:47:34 +00001639{
cristy78c21692011-10-06 14:57:26 +00001640 if ((p == (char *) NULL) && (q == (char *) NULL))
1641 return(0);
cristy3ed852e2009-09-05 21:47:34 +00001642 if (p == (char *) NULL)
1643 return(-1);
1644 if (q == (char *) NULL)
1645 return(1);
1646#if defined(MAGICKCORE_HAVE_STRNCASECMP)
cristy27397b22010-02-18 17:30:43 +00001647 return(strncasecmp(p,q,length));
cristy3ed852e2009-09-05 21:47:34 +00001648#else
1649 {
cristyde58b412010-02-18 03:53:40 +00001650 register int
cristy3ed852e2009-09-05 21:47:34 +00001651 c,
1652 d;
1653
cristyb6af4a52009-10-06 13:56:23 +00001654 register size_t
cristyc4cded12010-02-18 14:40:57 +00001655 i;
cristyb6af4a52009-10-06 13:56:23 +00001656
cristyc4cded12010-02-18 14:40:57 +00001657 for (i=length; i != 0; i--)
cristy3ed852e2009-09-05 21:47:34 +00001658 {
cristyde58b412010-02-18 03:53:40 +00001659 c=(int) *((unsigned char *) p);
1660 d=(int) *((unsigned char *) q);
cristy3ed852e2009-09-05 21:47:34 +00001661 if (AsciiMap[c] != AsciiMap[d])
cristyde58b412010-02-18 03:53:40 +00001662 return(AsciiMap[c]-(int) AsciiMap[d]);
1663 if (c == 0)
1664 return(0);
cristy3ed852e2009-09-05 21:47:34 +00001665 p++;
1666 q++;
1667 }
cristyde58b412010-02-18 03:53:40 +00001668 return(0);
cristy3ed852e2009-09-05 21:47:34 +00001669 }
1670#endif
1671}
1672
1673/*
1674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1675% %
1676% %
1677% %
1678% L o c a l e U p p e r %
1679% %
1680% %
1681% %
1682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1683%
1684% LocaleUpper() transforms all of the characters in the supplied
1685% null-terminated string, changing all lowercase letters to uppercase.
1686%
1687% The format of the LocaleUpper method is:
1688%
1689% void LocaleUpper(char *string)
1690%
1691% A description of each parameter follows:
1692%
1693% o string: A pointer to the string to convert to upper-case Locale.
1694%
1695*/
1696MagickExport void LocaleUpper(char *string)
1697{
1698 register char
1699 *q;
1700
1701 assert(string != (char *) NULL);
1702 for (q=string; *q != '\0'; q++)
1703 *q=(char) toupper((int) *q);
1704}
1705
1706/*
1707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1708% %
1709% %
1710% %
1711% P r i n t S t r i n g I n f o %
1712% %
1713% %
1714% %
1715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716%
1717% PrintStringInfo() prints the string.
1718%
1719% The format of the PrintStringInfo method is:
1720%
1721% void PrintStringInfo(FILE *file,const char *id,
1722% const StringInfo *string_info)
1723%
1724% A description of each parameter follows:
1725%
1726% o file: the file, typically stdout.
1727%
1728% o id: the string id.
1729%
1730% o string_info: the string info.
1731%
1732*/
1733MagickExport void PrintStringInfo(FILE *file,const char *id,
1734 const StringInfo *string_info)
1735{
1736 register const char
1737 *p;
1738
1739 register size_t
1740 i,
1741 j;
1742
1743 assert(id != (const char *) NULL);
cristy3ed852e2009-09-05 21:47:34 +00001744 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001745 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001746 p=(char *) string_info->datum;
1747 for (i=0; i < string_info->length; i++)
1748 {
1749 if (((int) ((unsigned char) *p) < 32) &&
1750 (isspace((int) ((unsigned char) *p)) == 0))
1751 break;
1752 p++;
1753 }
cristy2d8723c2013-11-14 16:41:27 +00001754 (void) FormatLocaleFile(file,"%s(%.20g): ",id,(double) string_info->length);
cristy3ed852e2009-09-05 21:47:34 +00001755 if (i == string_info->length)
1756 {
cristy53ea28b2012-06-10 22:11:59 +00001757 for (i=0; i < string_info->length; i++)
1758 (void) fputc(string_info->datum[i],file);
cristy3ed852e2009-09-05 21:47:34 +00001759 (void) fputc('\n',file);
1760 return;
1761 }
1762 /*
1763 Convert string to a HEX list.
1764 */
1765 p=(char *) string_info->datum;
1766 for (i=0; i < string_info->length; i+=0x14)
1767 {
cristyb51dff52011-05-19 16:55:47 +00001768 (void) FormatLocaleFile(file,"0x%08lx: ",(unsigned long) (0x14*i));
cristy3ed852e2009-09-05 21:47:34 +00001769 for (j=1; j <= MagickMin(string_info->length-i,0x14); j++)
1770 {
cristyb51dff52011-05-19 16:55:47 +00001771 (void) FormatLocaleFile(file,"%02lx",(unsigned long) (*(p+j)) & 0xff);
cristy3ed852e2009-09-05 21:47:34 +00001772 if ((j % 0x04) == 0)
1773 (void) fputc(' ',file);
1774 }
1775 for ( ; j <= 0x14; j++)
1776 {
1777 (void) fputc(' ',file);
1778 (void) fputc(' ',file);
1779 if ((j % 0x04) == 0)
1780 (void) fputc(' ',file);
1781 }
1782 (void) fputc(' ',file);
1783 for (j=1; j <= MagickMin(string_info->length-i,0x14); j++)
1784 {
1785 if (isprint((int) ((unsigned char) *p)) != 0)
1786 (void) fputc(*p,file);
1787 else
1788 (void) fputc('-',file);
1789 p++;
1790 }
1791 (void) fputc('\n',file);
1792 }
1793}
1794
1795/*
1796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1797% %
1798% %
1799% %
1800% R e s e t S t r i n g I n f o %
1801% %
1802% %
1803% %
1804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805%
1806% ResetStringInfo() reset the string to all null bytes.
1807%
1808% The format of the ResetStringInfo method is:
1809%
1810% void ResetStringInfo(StringInfo *string_info)
1811%
1812% A description of each parameter follows:
1813%
1814% o string_info: the string info.
1815%
1816*/
1817MagickExport void ResetStringInfo(StringInfo *string_info)
1818{
cristy3ed852e2009-09-05 21:47:34 +00001819 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001820 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001821 (void) ResetMagickMemory(string_info->datum,0,string_info->length);
1822}
1823
1824/*
1825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1826% %
1827% %
1828% %
1829% S e t S t r i n g I n f o %
1830% %
1831% %
1832% %
1833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1834%
1835% SetStringInfo() copies the source string to the destination string.
1836%
1837% The format of the SetStringInfo method is:
1838%
1839% void SetStringInfo(StringInfo *string_info,const StringInfo *source)
1840%
1841% A description of each parameter follows:
1842%
1843% o string_info: the string info.
1844%
1845% o source: the source string.
1846%
1847*/
1848MagickExport void SetStringInfo(StringInfo *string_info,
1849 const StringInfo *source)
1850{
cristy3ed852e2009-09-05 21:47:34 +00001851 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001852 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001853 assert(source != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001854 assert(source->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001855 if (string_info->length == 0)
1856 return;
1857 (void) ResetMagickMemory(string_info->datum,0,string_info->length);
cristy54aad5e2010-09-03 16:02:04 +00001858 (void) memcpy(string_info->datum,source->datum,MagickMin(string_info->length,
1859 source->length));
cristy3ed852e2009-09-05 21:47:34 +00001860}
1861
1862/*
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864% %
1865% %
1866% %
1867% S e t S t r i n g I n f o D a t u m %
1868% %
1869% %
1870% %
1871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1872%
1873% SetStringInfoDatum() copies bytes from the source string for the length of
1874% the destination string.
1875%
1876% The format of the SetStringInfoDatum method is:
1877%
1878% void SetStringInfoDatum(StringInfo *string_info,
1879% const unsigned char *source)
1880%
1881% A description of each parameter follows:
1882%
1883% o string_info: the string info.
1884%
1885% o source: the source string.
1886%
1887*/
1888MagickExport void SetStringInfoDatum(StringInfo *string_info,
1889 const unsigned char *source)
1890{
cristy3ed852e2009-09-05 21:47:34 +00001891 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001892 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001893 if (string_info->length != 0)
cristy54aad5e2010-09-03 16:02:04 +00001894 (void) memcpy(string_info->datum,source,string_info->length);
cristy3ed852e2009-09-05 21:47:34 +00001895}
1896
1897/*
1898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1899% %
1900% %
1901% %
1902% S e t S t r i n g I n f o L e n g t h %
1903% %
1904% %
1905% %
1906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1907%
1908% SetStringInfoLength() set the string length to the specified value.
1909%
1910% The format of the SetStringInfoLength method is:
1911%
1912% void SetStringInfoLength(StringInfo *string_info,const size_t length)
1913%
1914% A description of each parameter follows:
1915%
1916% o string_info: the string info.
1917%
1918% o length: the string length.
1919%
1920*/
1921MagickExport void SetStringInfoLength(StringInfo *string_info,
1922 const size_t length)
1923{
cristy3ed852e2009-09-05 21:47:34 +00001924 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001925 assert(string_info->signature == MagickCoreSignature);
cristy151b66d2015-04-15 10:50:31 +00001926 if (~length < MagickPathExtent)
cristy3ed852e2009-09-05 21:47:34 +00001927 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1928 string_info->length=length;
1929 if (string_info->datum == (unsigned char *) NULL)
1930 string_info->datum=(unsigned char *) AcquireQuantumMemory(length+
cristy151b66d2015-04-15 10:50:31 +00001931 MagickPathExtent,sizeof(*string_info->datum));
cristy3ed852e2009-09-05 21:47:34 +00001932 else
1933 string_info->datum=(unsigned char *) ResizeQuantumMemory(string_info->datum,
cristy151b66d2015-04-15 10:50:31 +00001934 length+MagickPathExtent,sizeof(*string_info->datum));
cristy3ed852e2009-09-05 21:47:34 +00001935 if (string_info->datum == (unsigned char *) NULL)
1936 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1937}
1938
1939/*
1940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941% %
1942% %
1943% %
1944% S e t S t r i n g I n f o D a t u m %
1945% %
1946% %
1947% %
1948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1949%
1950% SetStringInfoPath() sets the path associated with the string.
1951%
1952% The format of the SetStringInfoPath method is:
1953%
1954% void SetStringInfoPath(StringInfo *string_info,const char *path)
1955%
1956% A description of each parameter follows:
1957%
1958% o string_info: the string info.
1959%
1960% o path: the path.
1961%
1962*/
1963MagickExport void SetStringInfoPath(StringInfo *string_info,const char *path)
1964{
cristy3ed852e2009-09-05 21:47:34 +00001965 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00001966 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00001967 assert(path != (const char *) NULL);
dirkcecec522015-04-14 20:17:56 +00001968 string_info->path=ConstantString(path);
cristy3ed852e2009-09-05 21:47:34 +00001969}
1970
1971/*
1972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1973% %
1974% %
1975% %
1976% S p l i t S t r i n g I n f o %
1977% %
1978% %
1979% %
1980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1981%
1982% SplitStringInfo() splits a string into two and returns it.
1983%
1984% The format of the SplitStringInfo method is:
1985%
1986% StringInfo *SplitStringInfo(StringInfo *string_info,const size_t offset)
1987%
1988% A description of each parameter follows:
1989%
1990% o string_info: the string info.
1991%
1992*/
1993MagickExport StringInfo *SplitStringInfo(StringInfo *string_info,
1994 const size_t offset)
1995{
1996 StringInfo
1997 *split_info;
1998
cristy3ed852e2009-09-05 21:47:34 +00001999 assert(string_info != (StringInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002000 assert(string_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +00002001 if (offset > string_info->length)
2002 return((StringInfo *) NULL);
2003 split_info=AcquireStringInfo(offset);
2004 SetStringInfo(split_info,string_info);
cristy1bd862c2011-05-21 13:44:38 +00002005 (void) memmove(string_info->datum,string_info->datum+offset,
cristy151b66d2015-04-15 10:50:31 +00002006 string_info->length-offset+MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00002007 SetStringInfoLength(string_info,string_info->length-offset);
2008 return(split_info);
2009}
2010
2011/*
2012%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2013% %
2014% %
2015% %
2016% S t r i n g I n f o T o S t r i n g %
2017% %
2018% %
2019% %
2020%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2021%
2022% StringInfoToString() converts a string info string to a C string.
2023%
2024% The format of the StringInfoToString method is:
2025%
2026% char *StringInfoToString(const StringInfo *string_info)
2027%
2028% A description of each parameter follows:
2029%
2030% o string_info: the string.
2031%
2032*/
2033MagickExport char *StringInfoToString(const StringInfo *string_info)
2034{
2035 char
2036 *string;
2037
2038 size_t
2039 length;
2040
2041 string=(char *) NULL;
2042 length=string_info->length;
cristy151b66d2015-04-15 10:50:31 +00002043 if (~length >= (MagickPathExtent-1))
cristya42df252015-04-15 22:33:45 +00002044 string=(char *) AcquireQuantumMemory(length+MagickPathExtent,
2045 sizeof(*string));
cristy208cacf2010-09-03 02:24:42 +00002046 if (string == (char *) NULL)
2047 return((char *) NULL);
cristy54aad5e2010-09-03 16:02:04 +00002048 (void) memcpy(string,(char *) string_info->datum,length*sizeof(*string));
cristy208cacf2010-09-03 02:24:42 +00002049 string[length]='\0';
cristy3ed852e2009-09-05 21:47:34 +00002050 return(string);
2051}
2052
2053/*
2054%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2055% %
2056% %
2057% %
anthonyb1d483a2012-04-14 12:53:56 +00002058% S t r i n g I n f o T o H e x S t r i n g %
2059% %
2060% %
2061% %
2062%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2063%
2064% StringInfoToHexString() converts a string info string to a C string.
2065%
2066% The format of the StringInfoToHexString method is:
2067%
2068% char *StringInfoToHexString(const StringInfo *string_info)
2069%
2070% A description of each parameter follows:
2071%
2072% o string_info: the string.
2073%
2074*/
2075MagickExport char *StringInfoToHexString(const StringInfo *string_info)
2076{
2077 char
2078 *string;
2079
2080 register const unsigned char
2081 *p;
2082
2083 register ssize_t
2084 i;
2085
2086 register unsigned char
2087 *q;
2088
2089 size_t
2090 length;
2091
2092 unsigned char
2093 hex_digits[16];
2094
2095 length=string_info->length;
cristy151b66d2015-04-15 10:50:31 +00002096 if (~length < MagickPathExtent)
anthonyb1d483a2012-04-14 12:53:56 +00002097 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristya42df252015-04-15 22:33:45 +00002098 string=(char *) AcquireQuantumMemory(length+MagickPathExtent,2*
2099 sizeof(*string));
anthonyb1d483a2012-04-14 12:53:56 +00002100 if (string == (char *) NULL)
2101 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
2102 hex_digits[0]='0';
2103 hex_digits[1]='1';
2104 hex_digits[2]='2';
2105 hex_digits[3]='3';
2106 hex_digits[4]='4';
2107 hex_digits[5]='5';
2108 hex_digits[6]='6';
2109 hex_digits[7]='7';
2110 hex_digits[8]='8';
2111 hex_digits[9]='9';
2112 hex_digits[10]='a';
2113 hex_digits[11]='b';
2114 hex_digits[12]='c';
2115 hex_digits[13]='d';
2116 hex_digits[14]='e';
2117 hex_digits[15]='f';
2118 p=string_info->datum;
2119 q=(unsigned char *) string;
2120 for (i=0; i < (ssize_t) string_info->length; i++)
2121 {
2122 *q++=hex_digits[(*p >> 4) & 0x0f];
2123 *q++=hex_digits[*p & 0x0f];
2124 p++;
2125 }
2126 *q='\0';
2127 return(string);
2128}
2129
2130/*
2131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2132% %
2133% %
2134% %
cristy3ed852e2009-09-05 21:47:34 +00002135% S t r i n g T o A r g v %
2136% %
2137% %
2138% %
2139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2140%
2141% StringToArgv() converts a text string into command line arguments.
anthony31f1bf72012-01-30 12:37:22 +00002142% The 'argv' array of arguments, is returned while the number of arguments
2143% is returned via the provided integer variable pointer.
2144%
2145% Simple 'word' tokenizer, which allows for each word to be optionally
2146% quoted. However it will not allow use of partial quotes, or escape
2147% characters.
cristy3ed852e2009-09-05 21:47:34 +00002148%
2149% The format of the StringToArgv method is:
2150%
2151% char **StringToArgv(const char *text,int *argc)
2152%
2153% A description of each parameter follows:
2154%
2155% o argv: Method StringToArgv returns the string list unless an error
2156% occurs, otherwise NULL.
2157%
2158% o text: Specifies the string to segment into a list.
2159%
2160% o argc: This integer pointer returns the number of arguments in the
2161% list.
2162%
2163*/
2164MagickExport char **StringToArgv(const char *text,int *argc)
2165{
2166 char
2167 **argv;
2168
2169 register const char
2170 *p,
2171 *q;
2172
cristybb503372010-05-27 20:51:26 +00002173 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002174 i;
2175
2176 *argc=0;
2177 if (text == (char *) NULL)
2178 return((char **) NULL);
2179 /*
2180 Determine the number of arguments.
2181 */
2182 for (p=text; *p != '\0'; )
2183 {
2184 while (isspace((int) ((unsigned char) *p)) != 0)
2185 p++;
cristya20c9042011-05-19 13:22:18 +00002186 if (*p == '\0')
cristy74895d32011-01-22 21:30:47 +00002187 break;
cristy3ed852e2009-09-05 21:47:34 +00002188 (*argc)++;
2189 if (*p == '"')
2190 for (p++; (*p != '"') && (*p != '\0'); p++) ;
2191 if (*p == '\'')
2192 for (p++; (*p != '\'') && (*p != '\0'); p++) ;
2193 while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
2194 p++;
2195 }
2196 (*argc)++;
cristy1b26e1f2011-03-25 15:40:56 +00002197 argv=(char **) AcquireQuantumMemory((size_t) (*argc+1UL),sizeof(*argv));
cristy3ed852e2009-09-05 21:47:34 +00002198 if (argv == (char **) NULL)
2199 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertStringToARGV");
2200 /*
2201 Convert string to an ASCII list.
2202 */
2203 argv[0]=AcquireString("magick");
2204 p=text;
cristybb503372010-05-27 20:51:26 +00002205 for (i=1; i < (ssize_t) *argc; i++)
cristy3ed852e2009-09-05 21:47:34 +00002206 {
2207 while (isspace((int) ((unsigned char) *p)) != 0)
2208 p++;
2209 q=p;
2210 if (*q == '"')
2211 {
2212 p++;
2213 for (q++; (*q != '"') && (*q != '\0'); q++) ;
2214 }
2215 else
2216 if (*q == '\'')
2217 {
cristy06b15f42011-01-22 21:36:24 +00002218 p++;
cristy3ed852e2009-09-05 21:47:34 +00002219 for (q++; (*q != '\'') && (*q != '\0'); q++) ;
cristy3ed852e2009-09-05 21:47:34 +00002220 }
2221 else
2222 while ((isspace((int) ((unsigned char) *q)) == 0) && (*q != '\0'))
2223 q++;
cristy151b66d2015-04-15 10:50:31 +00002224 argv[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MagickPathExtent,
cristy3ed852e2009-09-05 21:47:34 +00002225 sizeof(**argv));
2226 if (argv[i] == (char *) NULL)
2227 {
2228 for (i--; i >= 0; i--)
2229 argv[i]=DestroyString(argv[i]);
2230 argv=(char **) RelinquishMagickMemory(argv);
2231 ThrowFatalException(ResourceLimitFatalError,
2232 "UnableToConvertStringToARGV");
2233 }
cristy54aad5e2010-09-03 16:02:04 +00002234 (void) memcpy(argv[i],p,(size_t) (q-p));
cristy208cacf2010-09-03 02:24:42 +00002235 argv[i][q-p]='\0';
cristy3ed852e2009-09-05 21:47:34 +00002236 p=q;
2237 while ((isspace((int) ((unsigned char) *p)) == 0) && (*p != '\0'))
2238 p++;
2239 }
2240 argv[i]=(char *) NULL;
2241 return(argv);
2242}
2243
2244/*
2245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2246% %
2247% %
2248% %
anthonyb1d483a2012-04-14 12:53:56 +00002249% 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 +00002250% %
2251% %
2252% %
2253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2254%
glennrp6ab82382013-10-28 13:54:30 +00002255% StringToArrayOfDoubles() converts a string of space or comma separated
anthonyb1d483a2012-04-14 12:53:56 +00002256% numbers into array of floating point numbers (doubles). Any number that
2257% failes to parse properly will produce a syntax error. As will two commas
2258% without a number between them. However a final comma at the end will
2259% not be regarded as an error so as to simplify automatic list generation.
cristy3ed852e2009-09-05 21:47:34 +00002260%
anthonyb1d483a2012-04-14 12:53:56 +00002261% A NULL value is returned on syntax or memory errors.
cristy3ed852e2009-09-05 21:47:34 +00002262%
anthonyb1d483a2012-04-14 12:53:56 +00002263% Use RelinquishMagickMemory() to free returned array when finished.
2264%
2265% The format of the StringToArrayOfDoubles method is:
2266%
cristy66336b02014-04-07 20:48:46 +00002267% double *StringToArrayOfDoubles(const char *string,size_t *count,
2268% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002269%
2270% A description of each parameter follows:
2271%
glennrp6ab82382013-10-28 13:54:30 +00002272% o string: the string containing the comma/space separated values.
anthonyb1d483a2012-04-14 12:53:56 +00002273%
2274% o count: returns number of arguments in returned array
2275%
cristy52085732013-11-09 02:32:27 +00002276% o exception: return any errors or warnings in this structure.
2277%
cristy3ed852e2009-09-05 21:47:34 +00002278*/
cristy52085732013-11-09 02:32:27 +00002279MagickExport double *StringToArrayOfDoubles(const char *string,ssize_t *count,
2280 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00002281{
anthonyb1d483a2012-04-14 12:53:56 +00002282 char
2283 *q;
2284
cristy0a887dc2012-08-15 22:58:36 +00002285 const char
2286 *p;
2287
anthonyb1d483a2012-04-14 12:53:56 +00002288 double
2289 *array;
2290
cristybb503372010-05-27 20:51:26 +00002291 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002292 i;
2293
cristy0a887dc2012-08-15 22:58:36 +00002294 /*
2295 Determine count of values, and check syntax.
2296 */
cristyb0de93f2013-05-03 13:39:25 +00002297 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +00002298 assert(exception->signature == MagickCoreSignature);
anthonyb1d483a2012-04-14 12:53:56 +00002299 *count=0;
anthonyb1d483a2012-04-14 12:53:56 +00002300 i=0;
cristy0a887dc2012-08-15 22:58:36 +00002301 p=string;
2302 while (*p != '\0')
cristy3ed852e2009-09-05 21:47:34 +00002303 {
cristy0a887dc2012-08-15 22:58:36 +00002304 (void) StringToDouble(p,&q); /* get value - ignores leading space */
2305 if (p == q)
2306 return((double *) NULL); /* no value found */
2307 p=q;
2308 i++; /* increment value count */
2309 while (isspace((int) ((unsigned char) *p)) != 0)
2310 p++; /* skip spaces */
2311 if (*p == ',')
2312 p++; /* skip comma */
2313 while (isspace((int) ((unsigned char) *p)) != 0)
2314 p++; /* and more spaces */
cristy3ed852e2009-09-05 21:47:34 +00002315 }
cristy0a887dc2012-08-15 22:58:36 +00002316 /*
2317 Allocate floating point argument list.
2318 */
anthonyb1d483a2012-04-14 12:53:56 +00002319 *count=i;
cristy0a887dc2012-08-15 22:58:36 +00002320 array=(double *) AcquireQuantumMemory((size_t) i,sizeof(*array));
2321 if (array == (double *) NULL)
cristy70ca0222013-11-09 02:34:16 +00002322 {
2323 (void) ThrowMagickException(exception,GetMagickModule(),
2324 ResourceLimitError,"MemoryAllocationFailed","`%s'","");
2325 return((double *) NULL);
2326 }
cristy0a887dc2012-08-15 22:58:36 +00002327 /*
2328 Fill in the floating point values.
2329 */
anthonyb1d483a2012-04-14 12:53:56 +00002330 i=0;
cristy0a887dc2012-08-15 22:58:36 +00002331 p=string;
2332 while ((*p != '\0') && (i < *count))
2333 {
anthonyb1d483a2012-04-14 12:53:56 +00002334 array[i++]=StringToDouble(p,&q);
2335 p=q;
cristy0a887dc2012-08-15 22:58:36 +00002336 while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2337 p++;
anthonyb1d483a2012-04-14 12:53:56 +00002338 }
anthonyb1d483a2012-04-14 12:53:56 +00002339 return(array);
cristy3ed852e2009-09-05 21:47:34 +00002340}
2341
2342/*
2343%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2344% %
2345% %
2346% %
anthonyb1d483a2012-04-14 12:53:56 +00002347+ S t r i n g T o k e n %
cristy3ed852e2009-09-05 21:47:34 +00002348% %
2349% %
2350% %
2351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2352%
cristy66336b02014-04-07 20:48:46 +00002353% StringToken() looks for any one of given delimiters and splits the string
anthonyb1d483a2012-04-14 12:53:56 +00002354% into two separate strings by replacing the delimiter character found with a
2355% nul character.
2356%
2357% The given string pointer is changed to point to the string following the
2358% delimiter character found, or NULL. A pointer to the start of the
2359% string is returned, representing the token before the delimiter.
2360%
2361% In may ways this is equivent to the strtok() C library function, but with
2362% multiple delimiter characters rather than a delimiter string.
cristy3ed852e2009-09-05 21:47:34 +00002363%
2364% The format of the StringToken method is:
2365%
2366% char *StringToken(const char *delimiters,char **string)
2367%
2368% A description of each parameter follows:
2369%
2370% o delimiters: one or more delimiters.
2371%
2372% o string: return the first token in the string. If none is found, return
2373% NULL.
2374%
2375*/
2376MagickExport char *StringToken(const char *delimiters,char **string)
2377{
2378 char
2379 *q;
2380
2381 register char
2382 *p;
2383
2384 register const char
2385 *r;
2386
2387 register int
2388 c,
2389 d;
2390
2391 p=(*string);
2392 if (p == (char *) NULL)
2393 return((char *) NULL);
anthonyb1d483a2012-04-14 12:53:56 +00002394 q=p;
2395 for ( ; ; )
cristy3ed852e2009-09-05 21:47:34 +00002396 {
2397 c=(*p++);
2398 r=delimiters;
2399 do
2400 {
2401 d=(*r++);
2402 if (c == d)
2403 {
2404 if (c == '\0')
2405 p=(char *) NULL;
2406 else
2407 p[-1]='\0';
2408 *string=p;
2409 return(q);
2410 }
2411 } while (d != '\0');
2412 }
2413}
2414
2415/*
2416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2417% %
2418% %
2419% %
2420% S t r i n g T o L i s t %
2421% %
2422% %
2423% %
2424%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2425%
2426% StringToList() converts a text string into a list by segmenting the text
2427% string at each carriage return discovered. The list is converted to HEX
2428% characters if any control characters are discovered within the text string.
2429%
2430% The format of the StringToList method is:
2431%
2432% char **StringToList(const char *text)
2433%
2434% A description of each parameter follows:
2435%
cristy3ed852e2009-09-05 21:47:34 +00002436% o text: Specifies the string to segment into a list.
2437%
2438*/
2439MagickExport char **StringToList(const char *text)
2440{
2441 char
2442 **textlist;
2443
2444 register const char
2445 *p;
2446
cristybb503372010-05-27 20:51:26 +00002447 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002448 i;
2449
cristybb503372010-05-27 20:51:26 +00002450 size_t
cristy3ed852e2009-09-05 21:47:34 +00002451 lines;
2452
2453 if (text == (char *) NULL)
2454 return((char **) NULL);
2455 for (p=text; *p != '\0'; p++)
2456 if (((int) ((unsigned char) *p) < 32) &&
2457 (isspace((int) ((unsigned char) *p)) == 0))
2458 break;
2459 if (*p == '\0')
2460 {
2461 register const char
2462 *q;
2463
2464 /*
2465 Convert string to an ASCII list.
2466 */
2467 lines=1;
2468 for (p=text; *p != '\0'; p++)
2469 if (*p == '\n')
2470 lines++;
2471 textlist=(char **) AcquireQuantumMemory((size_t) lines+1UL,
2472 sizeof(*textlist));
2473 if (textlist == (char **) NULL)
2474 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
2475 p=text;
cristybb503372010-05-27 20:51:26 +00002476 for (i=0; i < (ssize_t) lines; i++)
cristy3ed852e2009-09-05 21:47:34 +00002477 {
2478 for (q=p; *q != '\0'; q++)
2479 if ((*q == '\r') || (*q == '\n'))
2480 break;
cristya42df252015-04-15 22:33:45 +00002481 textlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+
2482 MagickPathExtent,sizeof(**textlist));
cristy3ed852e2009-09-05 21:47:34 +00002483 if (textlist[i] == (char *) NULL)
2484 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
cristy54aad5e2010-09-03 16:02:04 +00002485 (void) memcpy(textlist[i],p,(size_t) (q-p));
cristy208cacf2010-09-03 02:24:42 +00002486 textlist[i][q-p]='\0';
cristy3ed852e2009-09-05 21:47:34 +00002487 if (*q == '\r')
2488 q++;
2489 p=q+1;
2490 }
2491 }
2492 else
2493 {
2494 char
cristy151b66d2015-04-15 10:50:31 +00002495 hex_string[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +00002496
2497 register char
2498 *q;
2499
cristybb503372010-05-27 20:51:26 +00002500 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002501 j;
2502
2503 /*
2504 Convert string to a HEX list.
2505 */
cristybb503372010-05-27 20:51:26 +00002506 lines=(size_t) (strlen(text)/0x14)+1;
cristy3ed852e2009-09-05 21:47:34 +00002507 textlist=(char **) AcquireQuantumMemory((size_t) lines+1UL,
2508 sizeof(*textlist));
2509 if (textlist == (char **) NULL)
2510 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
2511 p=text;
cristybb503372010-05-27 20:51:26 +00002512 for (i=0; i < (ssize_t) lines; i++)
cristy3ed852e2009-09-05 21:47:34 +00002513 {
cristy151b66d2015-04-15 10:50:31 +00002514 textlist[i]=(char *) AcquireQuantumMemory(2UL*MagickPathExtent,
cristy2e25ee62011-03-25 15:43:12 +00002515 sizeof(**textlist));
cristy3ed852e2009-09-05 21:47:34 +00002516 if (textlist[i] == (char *) NULL)
2517 ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
cristy151b66d2015-04-15 10:50:31 +00002518 (void) FormatLocaleString(textlist[i],MagickPathExtent,"0x%08lx: ",
cristyf1d91242010-05-28 02:23:19 +00002519 (long) (0x14*i));
cristy3ed852e2009-09-05 21:47:34 +00002520 q=textlist[i]+strlen(textlist[i]);
cristybb503372010-05-27 20:51:26 +00002521 for (j=1; j <= (ssize_t) MagickMin(strlen(p),0x14); j++)
cristy3ed852e2009-09-05 21:47:34 +00002522 {
cristy151b66d2015-04-15 10:50:31 +00002523 (void) FormatLocaleString(hex_string,MagickPathExtent,"%02x",*(p+j));
2524 (void) CopyMagickString(q,hex_string,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00002525 q+=2;
2526 if ((j % 0x04) == 0)
2527 *q++=' ';
2528 }
2529 for ( ; j <= 0x14; j++)
2530 {
2531 *q++=' ';
2532 *q++=' ';
2533 if ((j % 0x04) == 0)
2534 *q++=' ';
2535 }
2536 *q++=' ';
cristybb503372010-05-27 20:51:26 +00002537 for (j=1; j <= (ssize_t) MagickMin(strlen(p),0x14); j++)
cristy3ed852e2009-09-05 21:47:34 +00002538 {
2539 if (isprint((int) ((unsigned char) *p)) != 0)
2540 *q++=(*p);
2541 else
2542 *q++='-';
2543 p++;
2544 }
2545 *q='\0';
2546 }
2547 }
2548 textlist[i]=(char *) NULL;
2549 return(textlist);
2550}
2551
2552/*
2553%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2554% %
2555% %
2556% %
2557% S t r i n g T o S t r i n g I n f o %
2558% %
2559% %
2560% %
2561%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2562%
cristybca58f32011-08-21 14:48:50 +00002563% StringToStringInfo() converts a string to a StringInfo type.
cristy3ed852e2009-09-05 21:47:34 +00002564%
2565% The format of the StringToStringInfo method is:
2566%
2567% StringInfo *StringToStringInfo(const char *string)
2568%
2569% A description of each parameter follows:
2570%
2571% o string: The string.
2572%
2573*/
2574MagickExport StringInfo *StringToStringInfo(const char *string)
2575{
2576 StringInfo
2577 *string_info;
2578
cristy3ed852e2009-09-05 21:47:34 +00002579 assert(string != (const char *) NULL);
cristybca58f32011-08-21 14:48:50 +00002580 string_info=AcquireStringInfo(strlen(string));
cristy3ed852e2009-09-05 21:47:34 +00002581 SetStringInfoDatum(string_info,(const unsigned char *) string);
2582 return(string_info);
2583}
2584
2585/*
2586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2587% %
2588% %
2589% %
2590% S t r i p S t r i n g %
2591% %
2592% %
2593% %
2594%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2595%
2596% StripString() strips any whitespace or quotes from the beginning and end of
2597% a string of characters.
2598%
2599% The format of the StripString method is:
2600%
2601% void StripString(char *message)
2602%
2603% A description of each parameter follows:
2604%
2605% o message: Specifies an array of characters.
2606%
2607*/
2608MagickExport void StripString(char *message)
2609{
2610 register char
2611 *p,
2612 *q;
2613
2614 size_t
2615 length;
2616
2617 assert(message != (char *) NULL);
2618 if (*message == '\0')
2619 return;
2620 length=strlen(message);
2621 p=message;
2622 while (isspace((int) ((unsigned char) *p)) != 0)
2623 p++;
2624 if ((*p == '\'') || (*p == '"'))
2625 p++;
2626 q=message+length-1;
2627 while ((isspace((int) ((unsigned char) *q)) != 0) && (q > p))
2628 q--;
2629 if (q > p)
2630 if ((*q == '\'') || (*q == '"'))
2631 q--;
cristya63c1ba2011-06-02 20:33:43 +00002632 (void) memmove(message,p,(size_t) (q-p+1));
cristy3ed852e2009-09-05 21:47:34 +00002633 message[q-p+1]='\0';
2634 for (p=message; *p != '\0'; p++)
2635 if (*p == '\n')
2636 *p=' ';
2637}
2638
2639/*
2640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2641% %
2642% %
2643% %
2644% S u b s t i t u t e S t r i n g %
2645% %
2646% %
2647% %
2648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2649%
cristyf1b72c12009-10-06 13:25:21 +00002650% SubstituteString() performs string substitution on a string, replacing the
2651% string with the substituted version. Buffer must be allocated from the heap.
cristybc3392a2009-10-06 03:15:57 +00002652% If the string is matched and status, MagickTrue is returned otherwise
2653% MagickFalse.
cristy3ed852e2009-09-05 21:47:34 +00002654%
2655% The format of the SubstituteString method is:
2656%
cristyf1b72c12009-10-06 13:25:21 +00002657% MagickBooleanType SubstituteString(char **string,const char *search,
cristy3ed852e2009-09-05 21:47:34 +00002658% const char *replace)
2659%
2660% A description of each parameter follows:
2661%
cristyf1b72c12009-10-06 13:25:21 +00002662% o string: the string to perform replacements on; replaced with new
cristy3ed852e2009-09-05 21:47:34 +00002663% allocation if a replacement is made.
2664%
cristybc3392a2009-10-06 03:15:57 +00002665% o search: search for this string.
cristy3ed852e2009-09-05 21:47:34 +00002666%
cristybc3392a2009-10-06 03:15:57 +00002667% o replace: replace any matches with this string.
cristy3ed852e2009-09-05 21:47:34 +00002668%
2669*/
cristyf1b72c12009-10-06 13:25:21 +00002670MagickExport MagickBooleanType SubstituteString(char **string,
cristy3ed852e2009-09-05 21:47:34 +00002671 const char *search,const char *replace)
2672{
cristybc3392a2009-10-06 03:15:57 +00002673 MagickBooleanType
2674 status;
cristy3ed852e2009-09-05 21:47:34 +00002675
cristybc3392a2009-10-06 03:15:57 +00002676 register char
2677 *p;
cristy3ed852e2009-09-05 21:47:34 +00002678
cristy3ed852e2009-09-05 21:47:34 +00002679 size_t
cristybc3392a2009-10-06 03:15:57 +00002680 extent,
2681 replace_extent,
2682 search_extent;
cristy3ed852e2009-09-05 21:47:34 +00002683
cristyf1b72c12009-10-06 13:25:21 +00002684 ssize_t
2685 offset;
2686
cristybc3392a2009-10-06 03:15:57 +00002687 status=MagickFalse;
2688 search_extent=0,
2689 replace_extent=0;
cristyf1b72c12009-10-06 13:25:21 +00002690 for (p=strchr(*string,*search); p != (char *) NULL; p=strchr(p+1,*search))
cristy3ed852e2009-09-05 21:47:34 +00002691 {
cristyf1b72c12009-10-06 13:25:21 +00002692 if (search_extent == 0)
2693 search_extent=strlen(search);
2694 if (strncmp(p,search,search_extent) != 0)
cristybc3392a2009-10-06 03:15:57 +00002695 continue;
cristy3ed852e2009-09-05 21:47:34 +00002696 /*
cristybc3392a2009-10-06 03:15:57 +00002697 We found a match.
cristy3ed852e2009-09-05 21:47:34 +00002698 */
cristyf1b72c12009-10-06 13:25:21 +00002699 status=MagickTrue;
cristybc3392a2009-10-06 03:15:57 +00002700 if (replace_extent == 0)
2701 replace_extent=strlen(replace);
2702 if (replace_extent > search_extent)
cristy3ed852e2009-09-05 21:47:34 +00002703 {
cristybc3392a2009-10-06 03:15:57 +00002704 /*
2705 Make room for the replacement string.
2706 */
cristyde58b412010-02-18 03:53:40 +00002707 offset=(ssize_t) (p-(*string));
cristye08c3b82009-10-06 14:58:14 +00002708 extent=strlen(*string)+replace_extent-search_extent+1;
cristy151b66d2015-04-15 10:50:31 +00002709 *string=(char *) ResizeQuantumMemory(*string,extent+MagickPathExtent,
cristyf1b72c12009-10-06 13:25:21 +00002710 sizeof(*p));
2711 if (*string == (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00002712 ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
cristyf1b72c12009-10-06 13:25:21 +00002713 p=(*string)+offset;
cristy3ed852e2009-09-05 21:47:34 +00002714 }
cristy3ed852e2009-09-05 21:47:34 +00002715 /*
cristybc3392a2009-10-06 03:15:57 +00002716 Replace string.
cristy3ed852e2009-09-05 21:47:34 +00002717 */
cristybc3392a2009-10-06 03:15:57 +00002718 if (search_extent != replace_extent)
cristy0a9b3722010-10-23 18:45:49 +00002719 (void) CopyMagickMemory(p+replace_extent,p+search_extent,
2720 strlen(p+search_extent)+1);
2721 (void) CopyMagickMemory(p,replace,replace_extent);
cristyf1b72c12009-10-06 13:25:21 +00002722 p+=replace_extent-1;
cristy3ed852e2009-09-05 21:47:34 +00002723 }
cristybc3392a2009-10-06 03:15:57 +00002724 return(status);
cristy3ed852e2009-09-05 21:47:34 +00002725}