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, March 2004 00034 @author Kris 00035 00036 00037 *******************************************************************************/ 00038 00039 module mango.io.Reader; 00040 00041 public import mango.io.AbstractReader; 00042 00043 /******************************************************************************* 00044 00045 Binary data Reader. Each reader operates upon an IBuffer, which is 00046 provided at construction time. Said buffer is intended to remain 00047 consistent over the reader lifetime. 00048 00049 Readers support both a C++ iostream type syntax, along with a get() 00050 syntax. Operations may be chained back-to-back. 00051 00052 All readers support the full set of native data types, plus a 00053 selection of array types. The latter can be configured to produce 00054 either a copy (.dup) of the buffer content, or a slice. See class 00055 SimpleAllocator, BufferAllocator and SliceAllocator for more on 00056 this topic. 00057 00058 The code below illustrates basic operation upon a memory buffer: 00059 00060 @code 00061 Buffer buf = new Buffer (256); 00062 00063 // map same buffer into both reader and writer 00064 IReader r = new Reader(buf); 00065 IWriter w = new Writer(buf); 00066 00067 int i = 10; 00068 long j = 20; 00069 double d = 3.14159; 00070 char[] c = "fred"; 00071 00072 // write data types out 00073 w << c << i << j << d; 00074 00075 // read them back again 00076 r >> c >> i >> j >> d; 00077 00078 // reset 00079 buf.clear(); 00080 00081 // same thing again, but using get() syntax instead 00082 w.put(c).put(i).put(j).put(d); 00083 r.get(c).get(i).get(j).get(d); 00084 00085 @endcode 00086 00087 Readers may also be used with any class implementing the IReadable 00088 interface. See PickleReader for an example of how this can be put 00089 to good use. 00090 00091 *******************************************************************************/ 00092 00093 class Reader : AbstractReader 00094 { 00095 /*********************************************************************** 00096 00097 Construct a reader on the provided buffer. 00098 00099 ***********************************************************************/ 00100 00101 this (IBuffer buffer) 00102 { 00103 super (buffer); 00104 00105 decode.int1 = 00106 decode.int8 = 00107 decode.int8u = 00108 decode.int16 = 00109 decode.int16u = 00110 decode.int32 = 00111 decode.int32u = 00112 decode.int64 = 00113 decode.int64u = 00114 decode.float32 = 00115 decode.float64 = 00116 decode.float80 = 00117 decode.char8 = 00118 decode.char16 = 00119 decode.char32 = &read; 00120 } 00121 00122 /*********************************************************************** 00123 00124 Construct a reader on the buffer belonging to the given 00125 conduit. 00126 00127 ***********************************************************************/ 00128 00129 this (IConduit conduit) 00130 { 00131 this (conduit.createBuffer); 00132 } 00133 00134 /*********************************************************************** 00135 00136 ***********************************************************************/ 00137 00138 final uint read (void *dst, uint count) 00139 { 00140 uint i = count; 00141 while (i) 00142 { 00143 // get as much as there is available in the buffer 00144 uint available = buffer.readable(); 00145 00146 // cap bytes read 00147 if (available > i) 00148 available = i; 00149 00150 // copy them over 00151 dst[0..available] = buffer.get (available); 00152 00153 // bump counters 00154 dst += available; 00155 i -= available; 00156 00157 // if we need more, prime the input by reading 00158 if (i) 00159 buffer.get(1, false); 00160 } 00161 return count; 00162 } 00163 } 00164 00165