]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/string.c
(no commit message)
[imagemagick] / MagickCore / string.c
index dd6ded76958f43ad9b2e6715dddc9e076ad082e3..31023be8916bf1825211e22e69b2d5f3b7d9425b 100644 (file)
 %                        MagickCore String Methods                            %
 %                                                                             %
 %                             Software Design                                 %
-%                               John Cristy                                   %
+%                                  Cristy                                     %
 %                               August 2003                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
 %  dedicated to making software imaging solutions freely available.           %
 %                                                                             %
 %  You may not use this file except in compliance with the license.  You may  %
 #include "MagickCore/locale_.h"
 #include "MagickCore/log.h"
 #include "MagickCore/memory_.h"
+#include "MagickCore/nt-base-private.h"
 #include "MagickCore/property.h"
 #include "MagickCore/resource_.h"
 #include "MagickCore/signature-private.h"
 #include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
 #include "MagickCore/utility-private.h"
 \f
 /*
@@ -59,7 +61,7 @@
 */
 #if !defined(MAGICKCORE_HAVE_STRCASECMP) || !defined(MAGICKCORE_HAVE_STRNCASECMP)
 static const unsigned char
-  asciimap[] =
+  AsciiMap[] =
   {
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
     0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -97,8 +99,13 @@ static const unsigned char
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  AcquireString() allocates memory for a string and copies the source string
-%  to that memory location (and returns it).
+%  AcquireString() returns an new extented string, containing a clone of the
+%  given string.
+%
+%  An extended string is the string length, plus an extra MaxTextExtent space
+%  to allow for the string to be activally worked on.
+%
+%  The returned string shoud be freed using DestoryString().
 %
 %  The format of the AcquireString method is:
 %
@@ -189,7 +196,8 @@ MagickExport StringInfo *AcquireStringInfo(const size_t length)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  BlobToStringInfo() returns the contents of a blob as a string.
+%  BlobToStringInfo() returns the contents of a blob as a StringInfo structure
+%  with MaxTextExtent extra space.
 %
 %  The format of the BlobToStringInfo method is:
 %
@@ -233,8 +241,15 @@ MagickExport StringInfo *BlobToStringInfo(const void *blob,const size_t length)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  CloneString() allocates memory for the destination string and copies
-%  the source string to that memory location.
+%  CloneString() replaces or frees the destination string to make it
+%  a clone of the input string plus MaxTextExtent more space so the string may
+%  be worked on on.
+%
+%  If source is a NULL pointer the destination string will be freed and set to
+%  a NULL pointer.  A pointer to the stored in the destination is also returned.
+%
+%  When finished the non-NULL string should be freed using DestoryString()
+%  or using CloneString() with a NULL pointed for the source.
 %
 %  The format of the CloneString method is:
 %
@@ -252,7 +267,6 @@ MagickExport char *CloneString(char **destination,const char *source)
   size_t
     length;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(destination != (char **) NULL);
   if (source == (const char *) NULL)
     {
@@ -305,7 +319,6 @@ MagickExport StringInfo *CloneStringInfo(const StringInfo *string_info)
   StringInfo
     *clone_info;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   clone_info=AcquireStringInfo(string_info->length);
@@ -354,7 +367,6 @@ MagickExport int CompareStringInfo(const StringInfo *target,
   int
     status;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(target != (StringInfo *) NULL);
   assert(target->signature == MagickSignature);
   assert(source != (StringInfo *) NULL);
@@ -529,7 +541,6 @@ MagickExport void ConcatenateStringInfo(StringInfo *string_info,
   size_t
     length;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   assert(source != (const StringInfo *) NULL);
@@ -656,9 +667,11 @@ MagickExport StringInfo *ConfigureFileToStringInfo(const char *filename)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  ConstantString() allocates memory for a string and copies the source string
-%  to that memory location (and returns it).  Use it for strings that you do
-%  do not expect to change over its lifetime.
+%  ConstantString() allocates exactly the needed memory for a string and
+%  copies the source string to that memory location.  A NULL string pointer
+%  will allocate an empty string containing just the NUL character.
+%
+%  When finished the string should be freed using DestoryString()
 %
 %  The format of the ConstantString method is:
 %
@@ -703,10 +716,12 @@ MagickExport char *ConstantString(const char *source)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  CopyMagickString() copies the source string to the destination string.  The
-%  destination buffer is always null-terminated even if the string must be
-%  truncated.  The return value is the minimum of the source string length
-%  or the length parameter.
+%  CopyMagickString() copies the source string to the destination string, with
+%  out exceeding the given pre-declared length.
+%
+%  The destination buffer is always null-terminated even if the string must be
+%  truncated.  The return value is the minimum of the source string length or
+%  the length parameter.
 %
 %  The format of the CopyMagickString method is:
 %
@@ -821,7 +836,6 @@ MagickExport char *DestroyString(char *string)
 */
 MagickExport StringInfo *DestroyStringInfo(StringInfo *string_info)
 {
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   if (string_info->datum != (unsigned char *) NULL)
@@ -909,7 +923,6 @@ MagickExport char *EscapeString(const char *source,const char escape)
   size_t
     length;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(source != (const char *) NULL);
   length=strlen(source);
   for (p=source; *p != '\0'; p++)
@@ -1095,6 +1108,7 @@ MagickExport ssize_t FormatMagickSize(const MagickSizeType size,
 #endif
   for (i=0; (length >= bytes) && (units[i+1] != (const char *) NULL); i++)
     length/=bytes;
+  count=0;
   for (j=2; j < 12; j++)
   {
     count=FormatLocaleString(format,MaxTextExtent,"%.*g%sB",(int) (i+j),length,
@@ -1311,6 +1325,179 @@ MagickExport const char *GetStringInfoPath(const StringInfo *string_info)
 %                                                                             %
 %                                                                             %
 %                                                                             %
++   I n t e r p r e t S i P r e f i x V a l u e                               %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  InterpretSiPrefixValue() converts the initial portion of the string to a
+%  double representation.  It also recognizes SI prefixes (e.g. B, KB, MiB,
+%  etc.).
+%
+%  The format of the InterpretSiPrefixValue method is:
+%
+%      double InterpretSiPrefixValue(const char *value,char **sentinal)
+%
+%  A description of each parameter follows:
+%
+%    o value: the string value.
+%
+%    o sentinal:  if sentinal is not NULL, return a pointer to the character
+%      after the last character used in the conversion.
+%
+*/
+MagickExport double InterpretSiPrefixValue(const char *restrict string,
+  char **restrict sentinal)
+{
+  char
+    *q;
+
+  double
+    value;
+
+  value=InterpretLocaleValue(string,&q);
+  if (q != string)
+    {
+      if ((*q >= 'E') && (*q <= 'z'))
+        {
+          double
+            e;
+
+          switch ((int) ((unsigned char) *q))
+          {
+            case 'y': e=(-24.0); break;
+            case 'z': e=(-21.0); break;
+            case 'a': e=(-18.0); break;
+            case 'f': e=(-15.0); break;
+            case 'p': e=(-12.0); break;
+            case 'n': e=(-9.0); break;
+            case 'u': e=(-6.0); break;
+            case 'm': e=(-3.0); break;
+            case 'c': e=(-2.0); break;
+            case 'd': e=(-1.0); break;
+            case 'h': e=2.0; break;
+            case 'k': e=3.0; break;
+            case 'K': e=3.0; break;
+            case 'M': e=6.0; break;
+            case 'G': e=9.0; break;
+            case 'T': e=12.0; break;
+            case 'P': e=15.0; break;
+            case 'E': e=18.0; break;
+            case 'Z': e=21.0; break;
+            case 'Y': e=24.0; break;
+            default: e=0.0; break;
+          }
+          if (e >= MagickEpsilon)
+            {
+              if (q[1] == 'i')
+                {
+                  value*=pow(2.0,e/0.3);
+                  q+=2;
+                }
+              else
+                {
+                  value*=pow(10.0,e);
+                  q++;
+                }
+            }
+        }
+      if (*q == 'B')
+        q++;
+    }
+  if (sentinal != (char **) NULL)
+    *sentinal=q;
+  return(value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   I s S t r i n g T r u e                                                   %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  IsStringTrue() returns MagickTrue if the value is "true", "on", "yes" or
+%  "1". Any other string or undefined returns MagickFalse.
+%
+%  Typically this is used to look at strings (options or artifacts) which
+%  has a default value of "false", when not defined.
+%
+%  The format of the IsStringTrue method is:
+%
+%      MagickBooleanType IsStringTrue(const char *value)
+%
+%  A description of each parameter follows:
+%
+%    o value: Specifies a pointer to a character array.
+%
+*/
+MagickExport MagickBooleanType IsStringTrue(const char *value)
+{
+  if (value == (const char *) NULL)
+    return(MagickFalse);
+  if (LocaleCompare(value,"true") == 0)
+    return(MagickTrue);
+  if (LocaleCompare(value,"on") == 0)
+    return(MagickTrue);
+  if (LocaleCompare(value,"yes") == 0)
+    return(MagickTrue);
+  if (LocaleCompare(value,"1") == 0)
+    return(MagickTrue);
+  return(MagickFalse);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%   I s S t r i n g N o t F a l s e                                           %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  IsStringNotFalse() returns MagickTrue, unless the string specifically
+%  has a value that makes this false.  that is if it has a value of
+%  "false", "off", "no" or "0".
+%
+%  Typically this is used to look at strings (options or artifacts) which
+%  has a default value of "true", when it has not been defined.
+%
+%  The format of the IsStringNotFalse method is:
+%
+%      MagickBooleanType IsStringNotFalse(const char *value)
+%
+%  A description of each parameter follows:
+%
+%    o value: Specifies a pointer to a character array.
+%
+*/
+MagickExport MagickBooleanType IsStringNotFalse(const char *value)
+{
+  if (value == (const char *) NULL)
+    return(MagickTrue);
+  if (LocaleCompare(value,"false") == 0)
+    return(MagickFalse);
+  if (LocaleCompare(value,"off") == 0)
+    return(MagickFalse);
+  if (LocaleCompare(value,"no") == 0)
+    return(MagickFalse);
+  if (LocaleCompare(value,"0") == 0)
+    return(MagickFalse);
+  return(MagickTrue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %   L o c a l e C o m p a r e                                                 %
 %                                                                             %
 %                                                                             %
@@ -1410,16 +1597,18 @@ MagickExport void LocaleLower(char *string)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  LocaleNCompare() performs a case-insensitive comparison of two
-%  strings byte-by-byte, according to the ordering of the current locale
-%  encoding. LocaleNCompare returns an integer greater than, equal to, or
-%  less than 0, if the string pointed to by p is greater than, equal to, or
-%  less than the string pointed to by q respectively.  The sign of a non-zero
-%  return value is determined by the sign of the difference between the
-%  values of the first pair of bytes that differ in the strings being
-%  compared.  The LocaleNCompare method makes the same comparison as
-%  LocaleCompare but looks at a maximum of n bytes.  Bytes following a
-%  null byte are not compared.
+%  LocaleNCompare() performs a case-insensitive comparison of two strings
+%  byte-by-byte, according to the ordering of the current locale encoding.
+%
+%  LocaleNCompare returns an integer greater than, equal to, or less than 0,
+%  if the string pointed to by p is greater than, equal to, or less than the
+%  string pointed to by q respectively.  The sign of a non-zero return value
+%  is determined by the sign of the difference between the values of the first
+%  pair of bytes that differ in the strings being compared.
+%
+%  The LocaleNCompare method makes the same comparison as LocaleCompare but
+%  looks at a maximum of n bytes.  Bytes following a null byte are not
+%  compared.
 %
 %  The format of the LocaleNCompare method is:
 %
@@ -1540,7 +1729,6 @@ MagickExport void PrintStringInfo(FILE *file,const char *id,
     j;
 
   assert(id != (const char *) NULL);
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",id);
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   p=(char *) string_info->datum;
@@ -1551,9 +1739,11 @@ MagickExport void PrintStringInfo(FILE *file,const char *id,
       break;
     p++;
   }
+  (void) FormatLocaleFile(file,"%s(%.20g): ",id,(double) string_info->length);
   if (i == string_info->length)
     {
-      (void) fputs((char *) string_info->datum,file);
+      for (i=0; i < string_info->length; i++)
+        (void) fputc(string_info->datum[i],file);
       (void) fputc('\n',file);
       return;
     }
@@ -1614,7 +1804,6 @@ MagickExport void PrintStringInfo(FILE *file,const char *id,
 */
 MagickExport void ResetStringInfo(StringInfo *string_info)
 {
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   (void) ResetMagickMemory(string_info->datum,0,string_info->length);
@@ -1647,7 +1836,6 @@ MagickExport void ResetStringInfo(StringInfo *string_info)
 MagickExport void SetStringInfo(StringInfo *string_info,
   const StringInfo *source)
 {
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   assert(source != (StringInfo *) NULL);
@@ -1688,7 +1876,6 @@ MagickExport void SetStringInfo(StringInfo *string_info,
 MagickExport void SetStringInfoDatum(StringInfo *string_info,
   const unsigned char *source)
 {
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   if (string_info->length != 0)
@@ -1722,7 +1909,6 @@ MagickExport void SetStringInfoDatum(StringInfo *string_info,
 MagickExport void SetStringInfoLength(StringInfo *string_info,
   const size_t length)
 {
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   if (~length < MaxTextExtent)
@@ -1764,7 +1950,6 @@ MagickExport void SetStringInfoLength(StringInfo *string_info,
 */
 MagickExport void SetStringInfoPath(StringInfo *string_info,const char *path)
 {
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   assert(path != (const char *) NULL);
@@ -1799,7 +1984,6 @@ MagickExport StringInfo *SplitStringInfo(StringInfo *string_info,
   StringInfo
     *split_info;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string_info != (StringInfo *) NULL);
   assert(string_info->signature == MagickSignature);
   if (offset > string_info->length)
@@ -1858,6 +2042,82 @@ MagickExport char *StringInfoToString(const StringInfo *string_info)
 %                                                                             %
 %                                                                             %
 %                                                                             %
+%   S t r i n g I n f o T o H e x S t r i n g                                 %
+%                                                                             %
+%                                                                             %
+%                                                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%  StringInfoToHexString() converts a string info string to a C string.
+%
+%  The format of the StringInfoToHexString method is:
+%
+%      char *StringInfoToHexString(const StringInfo *string_info)
+%
+%  A description of each parameter follows:
+%
+%    o string_info: the string.
+%
+*/
+MagickExport char *StringInfoToHexString(const StringInfo *string_info)
+{
+  char
+    *string;
+
+  register const unsigned char
+    *p;
+
+  register ssize_t
+    i;
+
+  register unsigned char
+    *q;
+
+  size_t
+    length;
+
+  unsigned char
+    hex_digits[16];
+
+  length=string_info->length;
+  if (~length < MaxTextExtent)
+    ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
+  string=(char *) AcquireQuantumMemory(length+MaxTextExtent,2*sizeof(*string));
+  if (string == (char *) NULL)
+    ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
+  hex_digits[0]='0';
+  hex_digits[1]='1';
+  hex_digits[2]='2';
+  hex_digits[3]='3';
+  hex_digits[4]='4';
+  hex_digits[5]='5';
+  hex_digits[6]='6';
+  hex_digits[7]='7';
+  hex_digits[8]='8';
+  hex_digits[9]='9';
+  hex_digits[10]='a';
+  hex_digits[11]='b';
+  hex_digits[12]='c';
+  hex_digits[13]='d';
+  hex_digits[14]='e';
+  hex_digits[15]='f';
+  p=string_info->datum;
+  q=(unsigned char *) string;
+  for (i=0; i < (ssize_t) string_info->length; i++)
+  {
+    *q++=hex_digits[(*p >> 4) & 0x0f];
+    *q++=hex_digits[*p & 0x0f];
+    p++;
+  }
+  *q='\0';
+  return(string);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%                                                                             %
+%                                                                             %
+%                                                                             %
 %  S t r i n g T o A r g v                                                    %
 %                                                                             %
 %                                                                             %
@@ -1865,6 +2125,12 @@ MagickExport char *StringInfoToString(const StringInfo *string_info)
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %  StringToArgv() converts a text string into command line arguments.
+%  The 'argv' array of arguments, is returned while the number of arguments
+%  is returned via the provided integer variable pointer.
+%
+%  Simple 'word' tokenizer, which allows for each word to be optionally
+%  quoted.  However it will not allow use of partial quotes, or escape
+%  characters.
 %
 %  The format of the StringToArgv method is:
 %
@@ -1966,75 +2232,96 @@ MagickExport char **StringToArgv(const char *text,int *argc)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   S t r i n g I n f o T o H e x S t r i n g                                 %
+%   S t r i n g T o A r r a y O f D o u b l e s                               %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  StringInfoToHexString() converts a string info string to a C string.
+%  StringToArrayOfDoubles() converts a string of space or comma separated
+%  numbers into array of floating point numbers (doubles). Any number that
+%  failes to parse properly will produce a syntax error. As will two commas
+%  without a  number between them.  However a final comma at the end will
+%  not be regarded as an error so as to simplify automatic list generation.
 %
-%  The format of the StringInfoToHexString method is:
+%  A NULL value is returned on syntax or memory errors.
 %
-%      char *StringInfoToHexString(const StringInfo *string_info)
+%  Use RelinquishMagickMemory() to free returned array when finished.
+%
+%  The format of the StringToArrayOfDoubles method is:
+%
+%     double *StringToArrayOfDoubles(const char *string,size_t *count)
 %
 %  A description of each parameter follows:
 %
-%    o string_info: the string.
+%    o string: the string containing the comma/space separated values.
+%
+%    o count: returns number of arguments in returned array
+%
+%    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport char *StringInfoToHexString(const StringInfo *string_info)
+MagickExport double *StringToArrayOfDoubles(const char *string,ssize_t *count,
+  ExceptionInfo *exception)
 {
   char
-    *string;
+    *q;
 
-  register const unsigned char
+  const char
     *p;
 
+  double
+    *array;
+
   register ssize_t
     i;
 
-  register unsigned char
-    *q;
-
-  size_t
-    length;
-
-  unsigned char
-    hex_digits[16];
-
-  length=string_info->length;
-  if (~length < MaxTextExtent)
-    ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
-  string=(char *) AcquireQuantumMemory(length+MaxTextExtent,2*sizeof(*string));
-  if (string == (char *) NULL)
-    ThrowFatalException(ResourceLimitFatalError,"UnableToAcquireString");
-  hex_digits[0]='0';
-  hex_digits[1]='1';
-  hex_digits[2]='2';
-  hex_digits[3]='3';
-  hex_digits[4]='4';
-  hex_digits[5]='5';
-  hex_digits[6]='6';
-  hex_digits[7]='7';
-  hex_digits[8]='8';
-  hex_digits[9]='9';
-  hex_digits[10]='a';
-  hex_digits[11]='b';
-  hex_digits[12]='c';
-  hex_digits[13]='d';
-  hex_digits[14]='e';
-  hex_digits[15]='f';
-  p=string_info->datum;
-  q=(unsigned char *) string;
-  for (i=0; i < (ssize_t) string_info->length; i++)
+  /*
+    Determine count of values, and check syntax.
+  */
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  *count=0;
+  i=0;
+  p=string;
+  while (*p != '\0')
   {
-    *q++=hex_digits[(*p >> 4) & 0x0f];
-    *q++=hex_digits[*p & 0x0f];
-    p++;
+    (void) StringToDouble(p,&q);  /* get value - ignores leading space */
+    if (p == q)
+      return((double *) NULL);  /* no value found */
+    p=q;
+    i++;  /* increment value count */
+    while (isspace((int) ((unsigned char) *p)) != 0)
+      p++;  /* skip spaces */
+    if (*p == ',')
+      p++;  /* skip comma */
+    while (isspace((int) ((unsigned char) *p)) != 0)
+      p++;  /* and more spaces */
   }
-  *q='\0';
-  return(string);
+  /*
+    Allocate floating point argument list.
+  */
+  *count=i;
+  array=(double *) AcquireQuantumMemory((size_t) i,sizeof(*array));
+  if (array == (double *) NULL)
+    {
+      (void) ThrowMagickException(exception,GetMagickModule(),
+        ResourceLimitError,"MemoryAllocationFailed","`%s'","");
+      return((double *) NULL);
+    }
+  /*
+    Fill in the floating point values.
+  */
+  i=0;
+  p=string;
+  while ((*p != '\0') && (i < *count))
+  {
+    array[i++]=StringToDouble(p,&q);
+    p=q;
+    while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
+      p++;
+  }
+  return(array);
 }
 \f
 /*
@@ -2042,13 +2329,22 @@ MagickExport char *StringInfoToHexString(const StringInfo *string_info)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   S t r i n g T o k e n                                                     %
++   S t r i n g T o k e n                                                     %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  StringToken() extracts a token a from the string.
+%  StringToken() Looks for any one of given delimiters and splits the string
+%  into two separate strings by replacing the delimiter character found with a
+%  nul character.
+%
+%  The given string pointer is changed to point to the string following the
+%  delimiter character found, or NULL.  A pointer to the start of the
+%  string is returned, representing the token before the delimiter.
+%
+%  In may ways this is equivent to the strtok() C library function, but with
+%  multiple delimiter characters rather than a delimiter string.
 %
 %  The format of the StringToken method is:
 %
@@ -2080,7 +2376,8 @@ MagickExport char *StringToken(const char *delimiters,char **string)
   p=(*string);
   if (p == (char *) NULL)
     return((char *) NULL);
-  for (q=p; ; )
+  q=p;
+  for ( ; ; )
   {
     c=(*p++);
     r=delimiters;
@@ -2264,7 +2561,6 @@ MagickExport StringInfo *StringToStringInfo(const char *string)
   StringInfo
     *string_info;
 
-  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(string != (const char *) NULL);
   string_info=AcquireStringInfo(strlen(string));
   SetStringInfoDatum(string_info,(const unsigned char *) string);