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

ColumnWriter.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file ColumnWriter.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, March 2004      
00034         @author         Kris
00035 
00036 
00037 *******************************************************************************/
00038 
00039 module mango.io.ColumnWriter;
00040 
00041 private import  mango.io.Exception;
00042 
00043 private import  mango.convert.Type;
00044 
00045 public  import  mango.io.DisplayWriter;
00046 
00047 /*******************************************************************************
00048 
00049         Print readable output to an IWriter, distributed across a set of
00050         columns. Columns start at zero rather than one, so adjust counts
00051         appropriately. All output is currently left-aligned. 
00052 
00053         This is how one might use ColumnWriter:
00054         
00055         @code
00056         static int[] columns = [0, 4, 14, 24];
00057 
00058         // map a ColumnWriter directly onto Stdout
00059         ColumnWriter write = new ColumnWriter (Stdout.getBuffer(), new ColumnList(columns));
00060 
00061         // set 2 digits of precision
00062         write.setPrecision (2);
00063 
00064         // Mango style     
00065         write (1) (20.34944) ("test") (CR);
00066 
00067         // iostream style     
00068         write << 1 << 20.34944 << "test" << CR;
00069         
00070         // put() style
00071         write.put(1).put(20.34944).put("test").cr();
00072         @endcode
00073 
00074         Note that ColumnWriter may be used with files, sockets, or any other
00075         buffer-oriented construct.
00076 
00077 *******************************************************************************/
00078 
00079 class ColumnWriter : DisplayWriter
00080 {
00081         alias DisplayWriter.put put;
00082 
00083         private int             output;
00084         private ColumnList      columns;
00085         private static ubyte    spaces[256];
00086 
00087         /***********************************************************************
00088         
00089                 Construct a ColumnWriter upon the given IBuffer, with the
00090                 specified set of columns.
00091                 
00092         ***********************************************************************/
00093 
00094         this (IBuffer buffer, ColumnList columns)
00095         in {
00096            assert (buffer);
00097            assert (columns);
00098            }
00099         body
00100         {
00101                 super (buffer);
00102                 
00103                 this.columns = columns;
00104                 reset ();
00105         }
00106      
00107         /***********************************************************************
00108         
00109                 Populate the space padding with valid spaces.
00110 
00111         ***********************************************************************/
00112 
00113         static this ()
00114         {
00115                 spaces[] = ' ';
00116         }
00117      
00118         /***********************************************************************
00119         
00120                 Reset everything back to zero. Typical usage will invoke
00121                 this whenever a Newline is emitted. 
00122                 
00123                 Note that we maintain our own internal count of how many 
00124                 bytes have been output: this is because we cannot depend 
00125                 on the Buffer to provide that for us if (a) the buffer is 
00126                 very small, or (b) the buffer is flushed after each write 
00127                 (Stdout etc).
00128 
00129         ***********************************************************************/
00130 
00131         void reset ()
00132         {
00133                 output = 0;
00134                 columns.reset ();
00135         }
00136 /+     
00137         /***********************************************************************
00138         
00139                 Return the width of the current column.
00140 
00141         ***********************************************************************/
00142 
00143         override int getWidth ()
00144         {
00145                 return columns.getWidth;
00146         }
00147 +/
00148         /***********************************************************************
00149         
00150                 Intercept the IWritable type so we can reset our columns
00151                 when a newline is emitted.
00152 
00153         ***********************************************************************/
00154 
00155         override IWriter put (IWritable x)
00156         {                       
00157                // have superclass print the IWritable
00158                 super.put (x);
00159 
00160                 // reset columns on a newline
00161                 if (cast (INewlineWriter) x)
00162                     reset ();
00163 
00164                 return this;
00165         }
00166      
00167         /***********************************************************************
00168         
00169                 Intercept the output so we can write some spaces first. 
00170                 Note that our superclass (DisplayWriter) converts each
00171                 of its arguments to a char[] first, so this override is
00172                 able to catch everything emitted.
00173 
00174                 @todo - add the equivalent intercepts for both wchar[] 
00175                         and dchar[] methods.
00176 
00177         ***********************************************************************/
00178 
00179         protected override IWriter encode (void* src, uint bytes, int type)
00180         {
00181                 pad();
00182 /+
00183                 // encode the string
00184                 void[] x = buffer.getCodec.from (src[0..bytes], type);
00185 
00186                 // adjust output with the encoded length
00187                 int t = buffer.type();
00188                 output += (x.length / ((t is Type.Raw) ? 1 : Type.widths[t]));
00189 
00190                 // append encoded string
00191                 buffer.append (x);
00192                 return this;
00193 +/
00194                 output += bytes;
00195                 return super.encode (src, bytes, type);
00196         }
00197 
00198         /***********************************************************************
00199 
00200                 Pad the output with spaces to reach the next column
00201                 position. This should be invoked before anything is
00202                 written to the buffer.
00203         
00204         ***********************************************************************/
00205 
00206         private final void pad ()
00207         {    
00208                 int padding = columns.next() - output;
00209 
00210                 // pad output to next column position?
00211                 if (padding > 0)
00212                    if (padding <= spaces.sizeof)
00213                       {
00214                       // yep - write a set of spaces
00215                       super.encode (spaces, padding, Type.Utf8);
00216                       output += padding;
00217                       }
00218                    else
00219                       throw new IOException ("Invalid column step (> 256)");
00220         }
00221 }
00222 
00223 
00224 /*******************************************************************************
00225 
00226         A list of columns for the ColumnWriter to utilize.
00227 
00228 *******************************************************************************/
00229 
00230 class ColumnList
00231 {
00232         private int     index;
00233         private int[]   columns;
00234 
00235         private bool    rightAlign;  // this needs to be per column instead
00236 
00237         /***********************************************************************
00238         
00239                 Construct a ColumnList via an array of integers.
00240 
00241         ***********************************************************************/
00242 
00243         this (int[] columns)
00244         in {
00245            assert (columns);
00246            }
00247         body
00248         {
00249                 reset ();
00250                 this.columns = columns;
00251         }
00252 
00253         /***********************************************************************
00254         
00255                 Start returning columns from the beginning.
00256 
00257         ***********************************************************************/
00258 
00259         void reset ()
00260         {
00261                 index = 0;
00262         }
00263 
00264         /***********************************************************************
00265         
00266                 Return width of the current column
00267 
00268         ***********************************************************************/
00269 
00270         int getWidth ()
00271         {
00272                 if (rightAlign)
00273                    {
00274                    int i = index;
00275                 
00276                    if (i == 0)
00277                        ++i;
00278 
00279                    if (i < columns.length)
00280                        return columns[i] - columns[i-1];
00281                    }
00282                 return 0;
00283         }
00284 
00285         /***********************************************************************
00286         
00287                 Returns next column in the sequence. Assume that we'll be
00288                 invoked (quasi-legally) when there's no more columns left.
00289 
00290         ***********************************************************************/
00291 
00292         int next ()
00293         {
00294                 if (index < columns.length)
00295                     ++index;
00296 
00297                 return columns [index-1];
00298         }
00299 }
00300 

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