Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Integer.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file Integer.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032         
00033         @version        Initial version, Nov 2005
00034                         
00035         @author         Kris
00036 
00037 
00038 *******************************************************************************/
00039 
00040 module mango.convert.Integer;
00041 
00042 private import mango.convert.Atoi;
00043 
00044 /******************************************************************************
00045 
00046         A set of functions for converting between string and integer 
00047         values. 
00048 
00049 ******************************************************************************/
00050 
00051 struct IntegerTemplate(T)
00052 {       
00053         private alias AtoiTemplate!(T) Atoi;
00054 
00055         enum Format {Binary='b', Octal='o', Hex='x', HexUpper='X', Integer='d', Unsigned='u'};
00056 
00057         /**********************************************************************
00058 
00059                 Declare stylistic flags 
00060 
00061         **********************************************************************/
00062 
00063         enum Flags 
00064         {
00065                 None    = 0,                    // no flags
00066                 Fill    = 1,                    // do some kind of padding
00067                 Left    = Fill << 1,            // left justify
00068                 Prec    = Left << 1,            // precision was provided
00069                 Hash    = Prec << 1,            // prefix integer with type
00070                 Space   = Hash << 1,            // prefix with space
00071                 Zero    = Space << 1,           // prefix integer with zero
00072                 Sign    = Zero << 1,            // unused
00073                 Comma   = Sign << 1,            // unused
00074                 Plus    = Comma << 1,           // prefix decimal with '+'
00075                 Array   = Plus << 1,            // array flag
00076         };
00077 
00078 
00079         /***********************************************************************
00080         
00081                 Format numeric values into the provided output buffer. The
00082                 traditional printf() conversion specifiers are adhered to,
00083                 and the following types are supported:
00084 
00085                 u - unsigned decimal
00086                 d - signed decimal
00087                 o - octal
00088                 x - lowercase hexadecimal
00089                 X - uppercase hexadecimal
00090                 b - binary
00091 
00092                 Modifiers supported include:
00093 
00094                 #      : prefix the conversion with a type identifier
00095                 +      : prefix positive decimals with a '+'
00096                 space  : prefix positive decimals with one space
00097                 0      : left-pad the number with zeros
00098 
00099                 These modifiers are specifed via the 'flags' provided, 
00100                 and are represented via these identifiers:
00101 
00102                 #     : Flags.Hash
00103                 +     : Flags.Plus
00104                 space : Flags.Space
00105                 0     : Flags.Zero
00106 
00107                 The provided 'dst' buffer should be sufficiently large
00108                 enough to house the output. A 64-element array is often
00109                 the maximum required (for a padded binary 64-bit string)
00110 
00111         ***********************************************************************/
00112 
00113         final static T[] format (T[] dst, long i, Format fmt = Format.Integer, Flags flags = Flags.None)
00114         {
00115                 T[]     prefix;
00116                 int     len = dst.length;
00117                    
00118                 // must have some buffer space to operate within! 
00119                 if (len)
00120                    {
00121                    uint radix;
00122                    T[]  numbers = "0123456789abcdef";
00123 
00124                    // pre-conversion setup
00125                    switch (fmt)
00126                           {
00127                           case Format.Integer:
00128                                if (i < 0)
00129                                   {
00130                                   prefix = "-";
00131                                   i = -i;
00132                                   }
00133                                else
00134                                   if (flags & Flags.Space)
00135                                       prefix = " ";
00136                                   else
00137                                      if (flags & Flags.Plus)
00138                                          prefix = "+";
00139                                // fall through!
00140                           case Format.Unsigned:
00141                                radix = 10;
00142                                break;
00143 
00144                           case Format.Binary:
00145                                radix = 2;
00146                                if (flags & Flags.Hash)
00147                                    prefix = "0b";
00148                                break;
00149 
00150                           case Format.Octal:
00151                                radix = 8;
00152                                if (flags & Flags.Hash)
00153                                    prefix = "0o";
00154                                break;
00155 
00156                           case Format.Hex:
00157                                radix = 16;
00158                                if (flags & Flags.Hash)
00159                                    prefix = "0x";
00160                                break;
00161 
00162                           case Format.HexUpper:
00163                                radix = 16;
00164                                numbers = "0123456789ABCDEF";
00165                                if (flags & Flags.Hash)
00166                                    prefix = "0X";
00167                                break;
00168 
00169                           default:
00170                                // raw output; no formatting
00171                                assert (fmt >= 2 && fmt <= 16);
00172                                radix = fmt;
00173                                break;
00174                           }
00175         
00176                    // convert number to text
00177                    T* p = dst.ptr + len;
00178                    if (i <= uint.max)
00179                       {
00180                       uint v = cast (uint) i;
00181                       do {
00182                          *--p = numbers[v % radix];
00183                          } while ((v /= radix) && --len);
00184                       }
00185                    else
00186                       {
00187                       ulong v = cast (ulong) i;
00188                       do {
00189                          *--p = numbers[cast(uint) (v % radix)];
00190                          } while ((v /= radix) && --len);
00191                       }
00192                    }
00193 
00194                 // are we about to overflow?
00195                 if (--len < 0 || 0 > (len -= prefix.length))
00196                     error ("Integer.format : output buffer too small");
00197 
00198                 // prefix number with zeros? 
00199                 if (flags & Flags.Zero)
00200                    {
00201                    dst [prefix.length .. len + prefix.length] = '0';
00202                    len = 0;
00203                    }
00204                 
00205                 // write optional prefix string ...
00206                 dst [len .. len + prefix.length] = prefix[];
00207 
00208                 // return slice of provided output buffer
00209                 return dst [len .. dst.length];                               
00210         } 
00211 
00212 
00213         /**********************************************************************
00214 
00215                 Parse an integer value from the provided 'src' string. 
00216                 The string is also inspected for a radix (defaults to 10), 
00217                 which can be overridden by setting 'radix' to non-zero. 
00218 
00219                 A non-null 'ate' will return the number of characters used
00220                 to construct the returned value.
00221 
00222         **********************************************************************/
00223 
00224         final static long parse (T[] src, uint radix=0, uint* ate=null)
00225         {
00226                 return Atoi.parse (src, radix, ate);
00227         }
00228 
00229 
00230         /**********************************************************************
00231 
00232                 Throw a format error. This is used by a number of other
00233                 modules in this package
00234 
00235         **********************************************************************/
00236 
00237         package final static void error (char[] msg)
00238         {
00239                 static class FormatException : Exception
00240                 {
00241                         this (char[] msg)
00242                         {
00243                                 super (msg);
00244                         }
00245                 }
00246 
00247                 throw new FormatException (msg);
00248         }
00249 }
00250 
00251 
00252 /******************************************************************************
00253 
00254 ******************************************************************************/
00255 
00256 alias IntegerTemplate!(char) Integer;
00257 

Generated on Sat Dec 24 17:28:33 2005 for Mango by  doxygen 1.4.0