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

Reader.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file Reader.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, October 2004      
00034 
00035         @author         Kris
00036 
00037 
00038 *******************************************************************************/
00039 
00040 module mango.io.Reader;
00041 
00042 private import  mango.sys.Type;
00043 
00044 private import  mango.io.Exception,
00045                 mango.io.ArrayAllocator;
00046 
00047 public  import  mango.io.model.IReader,
00048                 mango.io.model.IBuffer,
00049                 mango.io.model.IConduit;
00050 
00051 
00052 /*******************************************************************************
00053 
00054         Reader base-class. Each reader operates upon an IBuffer, which is
00055         provided at construction time. Said buffer is intended to remain 
00056         consistent over the reader lifetime.
00057 
00058         All readers support the full set of native data types, plus a full
00059         selection of array types. The latter can be configured to produce
00060         either a copy (.dup) of the buffer content, or a slice. See class
00061         SimpleAllocator, BufferAllocator and SliceAllocator for more on 
00062         this topic.
00063 
00064         Readers support a C++ iostream type syntax, along with Java-esque 
00065         get() notation. However, the Mango style is to place IO elements 
00066         within their own parenthesis, like so:
00067         
00068                 int count;
00069                 char[] verse;
00070 
00071                 read (verse) (count);
00072 
00073         Note that each element is distict; this enables "strong typing", 
00074         which should catch any typo errors at compile-time.
00075 
00076         The code below illustrates basic operation upon a memory buffer:
00077         
00078         @code
00079         Buffer buf = new Buffer (256);
00080 
00081         // map same buffer into both reader and writer
00082         IReader read = new Reader (buf);
00083         IWriter write = new Writer (buf);
00084 
00085         int i = 10;
00086         long j = 20;
00087         double d = 3.14159;
00088         char[] c = "fred";
00089 
00090         // write data types out
00091         write (c) (i) (j) (d);
00092 
00093         // read them back again
00094         read (c) (i) (j) (d);
00095 
00096         // reset
00097         buf.clear();
00098 
00099         // same thing again, but using iostream syntax instead
00100         write << c << i << j << d;
00101 
00102         // read them back again
00103         read >> c >> i >> j >> d;
00104 
00105         // reset
00106         buf.clear();
00107 
00108         // same thing again, but using put() syntax instead
00109         write.put(c).put(i).put(j).put(d);
00110         read.get(c).get(i).get(j).get(d);
00111 
00112         @endcode
00113 
00114         Note that certain Readers, such as the basic binary implementation, 
00115         expect to retrieve the number of array elements from the source. 
00116         For example; when reading an array from a file, the number of elements 
00117         is read from the file also. If the content is not arranged in such a 
00118         manner, you may specify how many elements to read via a second argument:
00119 
00120         @code
00121                 read (myArray, 11);
00122         @endcode
00123 
00124         Readers may also be used with any class implementing the IReadable
00125         interface. See PickleReader for an example of how this can be put
00126         to good use.
00127         
00128 *******************************************************************************/
00129 
00130 class Reader : SimpleAllocator, IReader
00131 {       
00132         /***********************************************************************
00133 
00134         ***********************************************************************/
00135 
00136         union Decoder
00137         {
00138                 struct {
00139                        BufferDecoder    char8,
00140                                         char16,
00141                                         char32;
00142                        }
00143                 BufferDecoder[3]        decoders;
00144         }
00145 
00146         // the buffer associated with this reader. Note that this
00147         // must not change for the lifetime of the reader, since
00148         // it is assumed to be immutable elsewhere (subclass may
00149         // keep its own copy).
00150         protected IBuffer               buffer;         
00151 
00152         // buffer decoders
00153         protected Decoder               decode;
00154 
00155         // memory-manager for array requests
00156         private IArrayAllocator         memory;
00157 
00158         /***********************************************************************
00159         
00160                 Construct a Reader upon the provided buffer
00161 
00162         ***********************************************************************/
00163 
00164         this (IBuffer buffer)
00165         {
00166                 this.buffer = buffer;
00167 
00168                 decode.char8  = 
00169                 decode.char16 = 
00170                 decode.char32 = &read;
00171 
00172                 setAllocator (this);
00173         }
00174 
00175         /***********************************************************************
00176                 
00177                 Construct a Reader upon the buffer associated with the
00178                 given conduit.
00179 
00180         ***********************************************************************/
00181 
00182         this (IConduit conduit)
00183         {
00184                 this (conduit.createBuffer);
00185         }
00186 
00187         /***********************************************************************
00188         
00189                 Return the buffer associated with this reader
00190 
00191         ***********************************************************************/
00192 
00193         final IBuffer getBuffer ()
00194         {
00195                 return buffer;
00196         }
00197 
00198         /***********************************************************************
00199         
00200                 Return the allocator associated with this reader. See 
00201                 ArrayAllocator for more information.
00202 
00203         ***********************************************************************/
00204 
00205         final IArrayAllocator getAllocator ()
00206         {
00207                 return memory;
00208         }
00209 
00210         /***********************************************************************
00211         
00212                 Set the allocator to use for array management. Arrays are
00213                 always allocated by the IReader. That is, you cannot read
00214                 data into an array slice (for example). Instead, a number
00215                 of IArrayAllocator classes are available to manage memory
00216                 allocation when reading array content. 
00217 
00218                 By default, an IReader will allocate each array from the 
00219                 heap. You can change that behavior by calling this method
00220                 with an IArrayAllocator of choice. For instance, there 
00221                 is a BufferAllocator which will slice an array directly 
00222                 from the buffer where possible. Also available is the 
00223                 record-oriented SliceAllocator, which slices memory from 
00224                 within a pre-allocated heap area, and should be reset by
00225                 the client code after each record has been read (to avoid 
00226                 unnecessary growth).
00227 
00228                 See ArrayAllocator for more information.
00229 
00230         ***********************************************************************/
00231 
00232         final void setAllocator (IArrayAllocator memory) 
00233         {
00234                 memory.bind (this);
00235                 this.memory = memory;
00236         }
00237 
00238         /***********************************************************************
00239         
00240                 Bind an IDecoder to the writer. Decoders are intended to
00241                 be used as a conversion mechanism between various character
00242                 representations (encodings), or the translation of any data
00243                 type from one representation to another. Each data type may
00244                 be configured with a distinct decoder, covering all native
00245                 types (15 in total).
00246 
00247                 An appropriate decoder set should be attached to each 
00248                 IReader, and thus be available for subsequent use. A raw 
00249                 binary implementation is attached by default (no encoding).
00250 
00251                 See module mango.icu.UMango for an example of decoder 
00252                 implementation -- those classes bind the ICU converters 
00253                 to this IO package.
00254 
00255         ***********************************************************************/
00256 
00257         final void setDecoder (IDecoder d) 
00258         {
00259                 decode.decoders[d.type] = d.bind (this);
00260         }
00261 
00262         /***********************************************************************
00263         
00264                 Read and return an integer from the input stream. This is
00265                 used to extract the element count of a subsequent array.
00266 
00267         ***********************************************************************/
00268 
00269         private final uint count (uint elements)
00270         {
00271                 if (elements == uint.max)
00272                     get (elements);
00273                 return elements;
00274         }
00275 
00276         /***********************************************************************
00277         
00278                 Wait for something to arrive in the buffer. This may stall
00279                 the current thread forever, although usage of SocketConduit 
00280                 will take advantage of the timeout facilities provided there.
00281 
00282         ***********************************************************************/
00283 
00284         final void wait ()
00285         {       
00286                 buffer.get (1, false);
00287         }
00288 
00289         /***********************************************************************
00290         
00291         ***********************************************************************/
00292 
00293         uint read (void *dst, uint bytes, uint type)
00294         {
00295                 uint i = bytes;
00296                 while (i)
00297                       {
00298                       // get as much as there is available in the buffer
00299                       uint available = buffer.readable();
00300                       
00301                       // cap bytes read
00302                       if (available > i)
00303                           available = i;
00304 
00305                       // copy them over
00306                       dst[0..available] = buffer.get (available);
00307 
00308                       // bump counters
00309                       dst += available;
00310                       i -= available;
00311 
00312                       // if we need more, prime the input by reading
00313                       if (i)
00314                           buffer.get (1, false);
00315                       }
00316                 return bytes;
00317         }
00318 
00319         /***********************************************************************
00320         
00321                 Extract a readable class from the current read-position
00322                 
00323         ***********************************************************************/
00324 
00325         final IReader get (IReadable x) 
00326         {
00327                 assert (x);
00328                 x.read (this); 
00329                 return this;
00330         }
00331 
00332         /***********************************************************************
00333 
00334                 Extract a boolean value from the current read-position  
00335                 
00336         ***********************************************************************/
00337 
00338         IReader get (inout bool x)
00339         {
00340                 read (&x, x.sizeof, Type.Bool);
00341                 return this;
00342         }
00343 
00344         /***********************************************************************
00345 
00346                 Extract an unsigned byte value from the current read-position   
00347                                 
00348         ***********************************************************************/
00349 
00350         IReader get (inout ubyte x) 
00351         {       
00352                 read (&x, x.sizeof, Type.UByte);
00353                 return this;
00354         }
00355 
00356         /***********************************************************************
00357         
00358                 Extract a byte value from the current read-position
00359                 
00360         ***********************************************************************/
00361 
00362         IReader get (inout byte x)
00363         {
00364                 read (&x, x.sizeof, Type.Byte);
00365                 return this;
00366         }
00367 
00368         /***********************************************************************
00369         
00370                 Extract an unsigned short value from the current read-position
00371                 
00372         ***********************************************************************/
00373 
00374         IReader get (inout ushort x)
00375         {
00376                 read (&x, x.sizeof, Type.UShort);
00377                 return this;
00378         }
00379 
00380         /***********************************************************************
00381         
00382                 Extract a short value from the current read-position
00383                 
00384         ***********************************************************************/
00385 
00386         IReader get (inout short x)
00387         {
00388                 read (&x, x.sizeof, Type.Short);
00389                 return this;
00390         }
00391 
00392         /***********************************************************************
00393         
00394                 Extract a unsigned int value from the current read-position
00395                 
00396         ***********************************************************************/
00397 
00398         IReader get (inout uint x)
00399         {
00400                 read (&x, x.sizeof, Type.UInt);
00401                 return this;
00402         }
00403 
00404         /***********************************************************************
00405         
00406                 Extract an int value from the current read-position
00407                 
00408         ***********************************************************************/
00409 
00410         IReader get (inout int x)
00411         {
00412                 read (&x, x.sizeof, Type.Int);
00413                 return this;
00414         }
00415 
00416         /***********************************************************************
00417         
00418                 Extract an unsigned long value from the current read-position
00419                 
00420         ***********************************************************************/
00421 
00422         IReader get (inout ulong x)
00423         {
00424                 read (&x, x.sizeof, Type.ULong);
00425                 return this;
00426         }
00427 
00428         /***********************************************************************
00429         
00430                 Extract a long value from the current read-position
00431                 
00432         ***********************************************************************/
00433 
00434         IReader get (inout long x)
00435         {
00436                 read (&x, x.sizeof, Type.Long);
00437                 return this;
00438         }
00439 
00440         /***********************************************************************
00441         
00442                 Extract a float value from the current read-position
00443                 
00444         ***********************************************************************/
00445 
00446         IReader get (inout float x)
00447         {
00448                 read (&x, x.sizeof, Type.Float);
00449                 return this;
00450         }
00451 
00452         /***********************************************************************
00453         
00454                 Extract a double value from the current read-position
00455                 
00456         ***********************************************************************/
00457 
00458         IReader get (inout double x)
00459         {
00460                 read (&x, x.sizeof, Type.Double);
00461                 return this;
00462         }
00463 
00464         /***********************************************************************
00465         
00466                 Extract a real value from the current read-position
00467                 
00468         ***********************************************************************/
00469 
00470         IReader get (inout real x)
00471         {
00472                 read (&x, x.sizeof, Type.Real);
00473                 return this;
00474         }
00475 
00476         /***********************************************************************
00477         
00478                 Extract a char value from the current read-position
00479                 
00480         ***********************************************************************/
00481 
00482         IReader get (inout char x)
00483         {
00484                 decode.char8 (&x, x.sizeof, Type.Utf8);
00485                 return this;
00486         }
00487 
00488         /***********************************************************************
00489         
00490                 Extract a wide char value from the current read-position
00491                 
00492         ***********************************************************************/
00493 
00494         IReader get (inout wchar x)
00495         {
00496                 decode.char16 (&x, x.sizeof, Type.Utf16);
00497                 return this;
00498         }
00499 
00500         /***********************************************************************
00501         
00502                 Extract a double char value from the current read-position
00503                 
00504         ***********************************************************************/
00505 
00506         IReader get (inout dchar x)
00507         {
00508                 decode.char32 (&x, x.sizeof, Type.Utf32);
00509                 return this;
00510         }
00511 
00512         /***********************************************************************
00513 
00514                 Extract an unsigned byte array from the current read-position   
00515                                 
00516         ***********************************************************************/
00517 
00518         IReader get (inout ubyte[] x, uint elements = uint.max) 
00519         {
00520                 memory.allocate (cast(void[]*) &x, count(elements)*ubyte.sizeof, 
00521                                  ubyte.sizeof, Type.UByte, &read);
00522                 return this;
00523         }
00524 
00525         /***********************************************************************
00526         
00527                 Extract a byte array from the current read-position
00528                 
00529         ***********************************************************************/
00530 
00531         IReader get (inout byte[] x, uint elements = uint.max)
00532         {
00533                 memory.allocate (cast(void[]*) &x, count(elements)*byte.sizeof, 
00534                                  byte.sizeof, Type.Byte, &read);
00535                 return this;
00536         }
00537 
00538         /***********************************************************************
00539         
00540                 Extract an unsigned short array from the current read-position
00541                 
00542         ***********************************************************************/
00543 
00544         IReader get (inout ushort[] x, uint elements = uint.max)
00545         {
00546                 memory.allocate (cast(void[]*) &x, count(elements)*ushort.sizeof, 
00547                                  ushort.sizeof, Type.UShort, &read);
00548                 return this;
00549         }
00550 
00551         /***********************************************************************
00552         
00553                 Extract a short array from the current read-position
00554                 
00555         ***********************************************************************/
00556 
00557         IReader get (inout short[] x, uint elements = uint.max)
00558         {
00559                 memory.allocate (cast(void[]*) &x, count(elements)*short.sizeof, 
00560                                  short.sizeof, Type.Short, &read);
00561                 return this;
00562         }
00563 
00564         /***********************************************************************
00565         
00566                 Extract a unsigned int array from the current read-position
00567                 
00568         ***********************************************************************/
00569 
00570         IReader get (inout uint[] x, uint elements = uint.max)
00571         {
00572                 memory.allocate (cast(void[]*) &x, count(elements)*uint.sizeof, 
00573                                  uint.sizeof, Type.UInt, &read);
00574                 return this;
00575         }
00576 
00577         /***********************************************************************
00578         
00579                 Extract an int array from the current read-position
00580                 
00581         ***********************************************************************/
00582 
00583         IReader get (inout int[] x, uint elements = uint.max)
00584         {
00585                 memory.allocate (cast(void[]*) &x, count(elements)*int.sizeof, 
00586                                  int.sizeof, Type.Int, &read);
00587                 return this;
00588         }
00589 
00590         /***********************************************************************
00591         
00592                 Extract an unsigned long array from the current read-position
00593                 
00594         ***********************************************************************/
00595 
00596         IReader get (inout ulong[] x, uint elements = uint.max)
00597         {
00598                 memory.allocate (cast(void[]*) &x, count(elements)*ulong.sizeof, 
00599                                  ulong.sizeof, Type.ULong, &read);
00600                 return this;
00601         }
00602 
00603         /***********************************************************************
00604         
00605                 Extract a long array from the current read-position
00606                 
00607         ***********************************************************************/
00608 
00609         IReader get (inout long[] x, uint elements = uint.max)
00610         {
00611                 memory.allocate (cast(void[]*) &x, count(elements)*long.sizeof, 
00612                                  long.sizeof, Type.Long, &read);
00613                 return this;
00614         }
00615 
00616         /***********************************************************************
00617         
00618                 Extract a float array from the current read-position
00619                 
00620         ***********************************************************************/
00621 
00622         IReader get (inout float[] x, uint elements = uint.max)
00623         {
00624                 memory.allocate (cast(void[]*) &x, count(elements)*float.sizeof, 
00625                                  float.sizeof, Type.Float, &read);
00626                 return this;
00627         }
00628 
00629         /***********************************************************************
00630         
00631                 Extract a double array from the current read-position
00632                 
00633         ***********************************************************************/
00634 
00635         IReader get (inout double[] x, uint elements = uint.max)
00636         {
00637                 memory.allocate (cast(void[]*) &x, count(elements)*double.sizeof, 
00638                                  double.sizeof, Type.Double, &read);
00639                 return this;
00640         }
00641 
00642         /***********************************************************************
00643         
00644                 Extract a real array from the current read-position
00645                 
00646         ***********************************************************************/
00647 
00648         IReader get (inout real[] x, uint elements = uint.max)
00649         {
00650                 memory.allocate (cast(void[]*) &x, count(elements)*real.sizeof, 
00651                                  real.sizeof, Type.Real, &read);
00652                 return this;
00653         }
00654 
00655         /***********************************************************************
00656         
00657         ***********************************************************************/
00658 
00659         IReader get (inout char[] x, uint elements = uint.max)
00660         {
00661                 memory.allocate (cast(void[]*) &x, count(elements)*char.sizeof, 
00662                                  char.sizeof, Type.Utf8, decode.char8);
00663                 return this;
00664         }
00665 
00666         /***********************************************************************
00667         
00668         ***********************************************************************/
00669 
00670         IReader get (inout wchar[] x, uint elements = uint.max)
00671         {
00672                 memory.allocate (cast(void[]*) &x, count(elements)*wchar.sizeof, 
00673                                  wchar.sizeof, Type.Utf16, decode.char16);
00674                 return this;
00675         }
00676 
00677         /***********************************************************************
00678         
00679         ***********************************************************************/
00680 
00681         IReader get (inout dchar[] x, uint elements = uint.max)
00682         {
00683                 memory.allocate (cast(void[]*) &x, count(elements)*dchar.sizeof, 
00684                                  dchar.sizeof, Type.Utf32, decode.char32);
00685                 return this;
00686         }
00687 }

Generated on Fri Nov 11 18:44:21 2005 for Mango by  doxygen 1.4.0