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 int copy (void[] src) 00141 { 00142 uint len = src.length; 00143 if (len > count) 00144 len = count; 00145 00146 dst[0..len] = src[0..len]; 00147 count -= len; 00148 dst += len; 00149 return len; 00150 } 00151 00152 uint i = count; 00153 while (count) 00154 { 00155 buffer.get (1, false); 00156 buffer.read (©); 00157 } 00158 return i; 00159 } 00160 +/ 00161 /*********************************************************************** 00162 00163 ***********************************************************************/ 00164 00165 final uint read (void *dst, uint count) 00166 { 00167 uint i = count; 00168 while (i) 00169 { 00170 // get as much as there is available in the buffer 00171 uint available = buffer.readable(); 00172 00173 // cap bytes read 00174 if (available > i) 00175 available = i; 00176 00177 // copy them over 00178 dst[0..available] = buffer.get (available); 00179 00180 // bump counters 00181 dst += available; 00182 i -= available; 00183 00184 // if we need more input, get it 00185 if (i) 00186 buffer.get(1, false); 00187 } 00188 return count; 00189 } 00190 } 00191 00192