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

AbstractWriter.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file AbstractWriter.d
00004         
00005 
00006         Copyright (c) 2004 Kris Bell
00007         
00008         This software is provided 'as-is', without any express or implied
00009         warranty. In no event will the authors be held liable for damages
00010         of any kind arising from the use of this software.
00011         
00012         Permission is hereby granted to anyone to use this software for any 
00013         purpose, including commercial applications, and to alter it and/or 
00014         redistribute it freely, subject to the following restrictions:
00015         
00016         1. The origin of this software must not be misrepresented; you must 
00017            not claim that you wrote the original software. If you use this 
00018            software in a product, an acknowledgment within documentation of 
00019            said product would be appreciated but is not required.
00020 
00021         2. Altered source versions must be plainly marked as such, and must 
00022            not be misrepresented as being the original software.
00023 
00024         3. This notice may not be removed or altered from any distribution
00025            of the source.
00026 
00027         4. Derivative works are permitted, but they must carry this notice
00028            in full and credit the original source.
00029 
00030 
00031                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00032 
00033 
00034         @version        Initial version, October 2004      
00035         @author         Kris, Ivan Senji (the "alias opShl put" idea)
00036 
00037 *******************************************************************************/
00038 
00039 module mango.io.AbstractWriter;
00040 
00041 private import  mango.io.Exception;
00042 
00043 public  import  mango.io.model.IWriter,
00044                 mango.io.model.IBuffer,
00045                 mango.io.model.IConduit;
00046 
00047 /*******************************************************************************
00048 
00049         Writer base-class. Writers provide the means to append formatted 
00050         data to an IBuffer, and expose a convenient method of handling a
00051         variety of data types. In addition to writing native types such
00052         as integer and char[], writers also process any class which has
00053         implemented the IWritable interface (one method).
00054 
00055         Writers support both a C++ iostream type syntax, along with a put()
00056         syntax. Operations may be chained back-to-back.
00057 
00058         All writers support the full set of native data types, plus a full
00059         selection of array types. 
00060 
00061         The code below illustrates basic operation upon a memory buffer:
00062         
00063         @code
00064         Buffer buf = new Buffer (256);
00065 
00066         // map same buffer into both reader and writer
00067         IReader r = new Reader(buf);
00068         IWriter w = new Writer(buf);
00069 
00070         int i = 10;
00071         long j = 20;
00072         double d = 3.14159;
00073         char[] c = "fred";
00074 
00075         // write data types out
00076         w << c << i << j << d;
00077 
00078         // read them back again
00079         r >> c >> i >> j >> d;
00080 
00081         // reset
00082         buf.clear();
00083 
00084         // same thing again, but using put() syntax instead
00085         w.put(c).put(i).put(j).put(d);
00086         r.get(c).get(i).get(j).get(d);
00087 
00088         @endcode
00089 
00090         Writers may also be used with any class implementing the IWritable
00091         interface. See PickleReader for an example of how this can be put
00092         to good use.
00093         
00094 *******************************************************************************/
00095 
00096 class AbstractWriter : IWriter
00097 {     
00098         alias opShl put;
00099           
00100         /***********************************************************************
00101 
00102         ***********************************************************************/
00103 
00104         union Encoder
00105         {
00106                 struct {
00107                        BufferEncoder    int1,
00108                                         int8,
00109                                         int16,
00110                                         int32,
00111                                         int64,
00112                                         int8u,
00113                                         int16u,
00114                                         int32u,
00115                                         int64u,
00116                                         float32,
00117                                         float64,
00118                                         float80,
00119                                         char8,
00120                                         char16,
00121                                         char32;
00122                        }
00123                 BufferEncoder[15]       encoders;
00124         }
00125 
00126         // public newline adaptor
00127         static INewlineWriter           newline;                
00128 
00129         // a couple of pre-constructed exceptions 
00130         protected static IOException    ovf;
00131 
00132         protected IBuffer               buffer;
00133 
00134         protected Encoder               encode;
00135 
00136         private bool                    prefixArray = true;
00137 
00138         /***********************************************************************
00139         
00140                 Construct some static exception instances, and create the
00141                 public 'newline' instance.
00142 
00143         ***********************************************************************/
00144 
00145         static this ()
00146         {
00147                 newline = new NewlineWriter;
00148 
00149                 ovf = new IOException  ("output buffer too small");
00150         }
00151 
00152         /***********************************************************************
00153         
00154                 Construct a Writer upon the provided IBuffer. All formatted
00155                 output will be appended to this buffer.
00156 
00157         ***********************************************************************/
00158 
00159         this (IBuffer buffer)
00160         {
00161                 this.buffer = buffer;
00162         }
00163      
00164         /***********************************************************************
00165         
00166                 Return the associated buffer
00167 
00168         ***********************************************************************/
00169 
00170         final IBuffer getBuffer ()
00171         {     
00172                 return buffer;
00173         }
00174 
00175         /***********************************************************************
00176         
00177                 Bind an IEncoder to the writer. Encoders are intended to
00178                 be used as a conversion mechanism between various character
00179                 representations (encodings), or the translation of any data
00180                 type from one representation to another. Each data type may
00181                 be configured with a distinct encoder, covering all native
00182                 types (15 in total).
00183 
00184                 An appropriate encoder set should be attached to each 
00185                 IWriter, and thus be available for subsequent use. A raw 
00186                 binary implementation is attached by default (no encoding).
00187 
00188                 See module mango.icu.UMango for an example of encoder 
00189                 implementation -- those classes bind the ICU converters 
00190                 to this IO package.
00191 
00192         ***********************************************************************/
00193 
00194         final void setEncoder (IEncoder e) 
00195         {
00196                 encode.encoders[e.type] = e.bind (this);
00197         }
00198 
00199         /***********************************************************************
00200         
00201                 Flush the output of this writer. Returns false if the 
00202                 operation failed, true otherwise.
00203 
00204         ***********************************************************************/
00205 
00206         IWriter flush ()
00207         {  
00208                 buffer.flush ();
00209                 return this;
00210         }
00211 
00212         /***********************************************************************
00213         
00214                 Output a newline. Do this indirectly so that it can be 
00215                 intercepted by subclasses.
00216 
00217         ***********************************************************************/
00218 
00219         IWriter cr ()
00220         {
00221                 return put (newline);
00222         }
00223 
00224         /***********************************************************************
00225 
00226         ***********************************************************************/
00227 
00228         void enableArrayPrefix (bool on)
00229         {
00230                 prefixArray = on;
00231         }
00232 
00233         /***********************************************************************
00234         
00235                 Write a class to the current buffer-position
00236                 
00237         ***********************************************************************/
00238 
00239         private final uint length (uint len)
00240         {
00241                 if (prefixArray)
00242                     put (len);
00243                 return len;
00244         }
00245 
00246         /***********************************************************************
00247         
00248                 Write a class to the current buffer-position
00249                 
00250         ***********************************************************************/
00251 
00252         IWriter opShl (IWritable x) 
00253         {
00254                 assert (x);
00255                 x.write (this); 
00256                 return this;
00257         }
00258 
00259         /***********************************************************************
00260         
00261                 Write a boolean value to the current buffer-position    
00262                 
00263         ***********************************************************************/
00264 
00265         IWriter opShl (bool x)
00266         {
00267                 encode.int1 (&x, x.sizeof);
00268                 return this;
00269         }
00270 
00271         /***********************************************************************
00272         
00273                 Write an unsigned byte value to the current buffer-position     
00274                                 
00275         ***********************************************************************/
00276 
00277         IWriter opShl (ubyte x)
00278         {
00279                 encode.int8u (&x, x.sizeof);
00280                 return this;
00281         }
00282 
00283         /***********************************************************************
00284         
00285                 Write a byte value to the current buffer-position
00286                 
00287         ***********************************************************************/
00288 
00289         IWriter opShl (byte x)
00290         {
00291                 encode.int8 (&x, x.sizeof);
00292                 return this;
00293         }
00294 
00295         /***********************************************************************
00296         
00297                 Write an unsigned short value to the current buffer-position
00298                 
00299         ***********************************************************************/
00300 
00301         IWriter opShl (ushort x)
00302         {
00303                 encode.int16u (&x, x.sizeof);
00304                 return this;
00305         }
00306 
00307         /***********************************************************************
00308         
00309                 Write a short value to the current buffer-position
00310                 
00311         ***********************************************************************/
00312 
00313         IWriter opShl (short x)
00314         {
00315                 encode.int16 (&x, x.sizeof);
00316                 return this;
00317         }
00318 
00319         /***********************************************************************
00320         
00321                 Write a unsigned int value to the current buffer-position
00322                 
00323         ***********************************************************************/
00324 
00325         IWriter opShl (uint x)
00326         {
00327                 encode.int32u (&x, x.sizeof);
00328                 return this;
00329         }
00330 
00331         /***********************************************************************
00332         
00333                 Write an int value to the current buffer-position
00334                 
00335         ***********************************************************************/
00336 
00337         IWriter opShl (int x)
00338         {
00339                 encode.int32 (&x, x.sizeof);
00340                 return this;
00341         }
00342 
00343         /***********************************************************************
00344         
00345                 Write an unsigned long value to the current buffer-position
00346                 
00347         ***********************************************************************/
00348 
00349         IWriter opShl (ulong x)
00350         {
00351                 encode.int64u (&x, x.sizeof);
00352                 return this;
00353         }
00354 
00355         /***********************************************************************
00356         
00357                 Write a long value to the current buffer-position
00358                 
00359         ***********************************************************************/
00360 
00361         IWriter opShl (long x)
00362         {
00363                 encode.int64 (&x, x.sizeof);
00364                 return this;
00365         }
00366 
00367         /***********************************************************************
00368         
00369                 Write a float value to the current buffer-position
00370                 
00371         ***********************************************************************/
00372 
00373         IWriter opShl (float x)
00374         {
00375                 encode.float32 (&x, x.sizeof);
00376                 return this;
00377         }
00378 
00379         /***********************************************************************
00380         
00381                 Write a double value to the current buffer-position
00382                 
00383         ***********************************************************************/
00384 
00385         IWriter opShl (double x)
00386         {
00387                 encode.float64 (&x, x.sizeof);
00388                 return this;
00389         }
00390 
00391         /***********************************************************************
00392         
00393                 Write a real value to the current buffer-position
00394                 
00395         ***********************************************************************/
00396 
00397         IWriter opShl (real x)
00398         {
00399                 encode.float80 (&x, x.sizeof);
00400                 return this;
00401         }
00402 
00403         /***********************************************************************
00404         
00405                 Write a char value to the current buffer-position
00406                 
00407         ***********************************************************************/
00408 
00409         IWriter opShl (char x)
00410         {
00411                 encode.char8 (&x, x.sizeof);
00412                 return this;
00413         }
00414 
00415         /***********************************************************************
00416         
00417                 Write a wide char value to the current buffer-position
00418                 
00419         ***********************************************************************/
00420 
00421         IWriter opShl (wchar x)
00422         {
00423                 encode.char16 (&x, x.sizeof);
00424                 return this;
00425         }
00426 
00427         /***********************************************************************
00428         
00429                 Write a double char value to the current buffer-position
00430                 
00431         ***********************************************************************/
00432 
00433         IWriter opShl (dchar x)
00434         {
00435                 encode.char32 (&x, x.sizeof);
00436                 return this;
00437         }
00438 
00439         /***********************************************************************
00440         
00441                 Write a byte array to the current buffer-position     
00442                                 
00443         ***********************************************************************/
00444 
00445         IWriter opShl (byte[] x)
00446         {
00447                 encode.int8 (x, length (x.length) * byte.sizeof);
00448                 return this;
00449         }
00450 
00451         /***********************************************************************
00452         
00453                 Write an unsigned byte array to the current buffer-position     
00454                                 
00455         ***********************************************************************/
00456 
00457         IWriter opShl (ubyte[] x)
00458         {
00459                 encode.int8u (x, length (x.length) * ubyte.sizeof);
00460                 return this;
00461         }
00462 
00463         /***********************************************************************
00464         
00465                 Write a short array to the current buffer-position
00466                 
00467         ***********************************************************************/
00468 
00469         IWriter opShl (short[] x)
00470         {
00471                 encode.int16 (x, length (x.length) * short.sizeof);
00472                 return this;
00473         }
00474 
00475         /***********************************************************************
00476         
00477                 Write an unsigned short array to the current buffer-position
00478                 
00479         ***********************************************************************/
00480 
00481         IWriter opShl (ushort[] x)
00482         {
00483                 encode.int16u (x, length (x.length) * ushort.sizeof);
00484                 return this;
00485         }
00486 
00487         /***********************************************************************
00488         
00489                 Write an int array to the current buffer-position
00490                 
00491         ***********************************************************************/
00492 
00493         IWriter opShl (int[] x)
00494         {
00495                 encode.int32 (x, length (x.length) * int.sizeof);
00496                 return this;
00497         }
00498 
00499         /***********************************************************************
00500         
00501                 Write an unsigned int array to the current buffer-position
00502                 
00503         ***********************************************************************/
00504 
00505         IWriter opShl (uint[] x)
00506         {
00507                 encode.int32u (x, length (x.length) * uint.sizeof);
00508                 return this;
00509         }
00510 
00511         /***********************************************************************
00512         
00513                 Write a long array to the current buffer-position
00514                 
00515         ***********************************************************************/
00516 
00517         IWriter opShl (long[] x)
00518         {
00519                 encode.int64 (x, length (x.length) * long.sizeof);
00520                 return this;
00521         }
00522 
00523         /***********************************************************************
00524         
00525                 Write an unsigned long array to the current buffer-position
00526                 
00527         ***********************************************************************/
00528 
00529         IWriter opShl (ulong[] x)
00530         {
00531                 encode.int64u (x, length (x.length) * ulong.sizeof);
00532                 return this;
00533         }
00534 
00535         /***********************************************************************
00536         
00537                 Write a float array to the current buffer-position
00538                 
00539         ***********************************************************************/
00540 
00541         IWriter opShl (float[] x)
00542         {
00543                 encode.float32 (x, length (x.length) * float.sizeof);
00544                 return this;
00545         }
00546 
00547         /***********************************************************************
00548         
00549                 Write a double array to the current buffer-position
00550                 
00551         ***********************************************************************/
00552 
00553         IWriter opShl (double[] x)
00554         {
00555                 encode.float64 (x, length (x.length) * double.sizeof);
00556                 return this;
00557         }
00558 
00559         /***********************************************************************
00560         
00561                 Write a real array to the current buffer-position
00562                 
00563         ***********************************************************************/
00564 
00565         IWriter opShl (real[] x)
00566         {
00567                 encode.float80 (x, length (x.length) * real.sizeof);
00568                 return this;
00569         }
00570 
00571         /***********************************************************************
00572         
00573                 Write a char array to the current buffer-position
00574                 
00575         ***********************************************************************/
00576 
00577         IWriter opShl (char[] x) 
00578         {
00579                 encode.char8 (x, length (x.length) * char.sizeof);
00580                 return this;
00581         }
00582 
00583         /***********************************************************************
00584         
00585                 Write a char array to the current buffer-position
00586                 
00587         ***********************************************************************/
00588 
00589         IWriter opShlw (wchar[] x) 
00590         {
00591                 encode.char16 (x, length (x.length) * wchar.sizeof);
00592                 return this;
00593         }
00594 
00595         /***********************************************************************
00596         
00597                 Write a char array to the current buffer-position
00598                 
00599         ***********************************************************************/
00600 
00601         IWriter opShld (dchar[] x)
00602         {
00603                 encode.char32 (x, length (x.length) * dchar.sizeof);
00604                 return this;
00605         }
00606 }
00607 
00608 
00609 /*******************************************************************************
00610 
00611         A class to handle newline output. One might reasonable expect to 
00612         emit a char[] for newlines; FileSystem.NewlineString for example.
00613         Turns out that it's much more efficient to intercept line-breaks
00614         when they're implemented in a more formal manner (such as this).
00615 
00616         For example, ColumnWriter() and TextWriter() both must intercept 
00617         newline output so they can adjust formatting appropriately. It is 
00618         much more efficient for such writers to intercept the IWritable 
00619         put() method instead of scanning each char[] for the various \\n 
00620         combinations.
00621         
00622         Please use the INewlineWriter interface for emitting newlines.
00623 
00624 *******************************************************************************/
00625 
00626 private import mango.io.FileSystem;
00627 
00628 class NewlineWriter : INewlineWriter
00629 {
00630         private char[]  fmt;
00631 
00632         /***********************************************************************
00633 
00634                 Construct a default newline, using the char[] defined 
00635                 by FileSystem.NewlineString
00636         
00637         ***********************************************************************/
00638 
00639         this ()
00640         {
00641                 this (FileSystem.NewlineString);
00642         }
00643 
00644         /***********************************************************************
00645         
00646                 Construct a newline using the provided character array
00647 
00648         ***********************************************************************/
00649 
00650         this (char[] fmt)
00651         {
00652                 this.fmt = fmt;
00653         }
00654 
00655         /***********************************************************************
00656         
00657                 Write this newline through the provided writer. This makes
00658                 NewlineWriter IWritable compatible.
00659 
00660         ***********************************************************************/
00661 
00662         void write (IWriter w)
00663         {
00664                 w.put (fmt);
00665         }     
00666 }

Generated on Tue Jan 25 21:18:20 2005 for Mango by doxygen 1.3.6