00001 /******************************************************************************* 00002 00003 @file TextReader.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.TextReader; 00040 00041 private import mango.io.Token, 00042 mango.io.Tokenizer, 00043 mango.io.Exception, 00044 mango.io.AbstractReader; 00045 00046 /******************************************************************************* 00047 00048 Grok readable input from a stream. All input is tokenized from the 00049 associated buffer, and converted as necessary into the destination 00050 location. A SpaceTokenizer is used by default, but you can choose 00051 an alternative (such as a comma-delimiting tokenizer). 00052 00053 *******************************************************************************/ 00054 00055 class TextReader : AbstractReader 00056 { 00057 alias AbstractReader.get get; 00058 00059 // an individual token 00060 private Token token; 00061 00062 // internal tokenizer instance 00063 private ITokenizer tokenizer; 00064 00065 /*********************************************************************** 00066 00067 Construct a TextReader on the provided buffer, using the 00068 specified Tokenizer instead of the default one. 00069 00070 ***********************************************************************/ 00071 00072 this (IBuffer buffer, ITokenizer tokenizer = Tokenizers.line) 00073 { 00074 super (buffer); 00075 this.token = new Token; 00076 this.tokenizer = tokenizer; 00077 00078 decode.int1 = &int1; 00079 decode.int8 = 00080 decode.int8u = &int8; 00081 decode.int16 = 00082 decode.int16u = &int16; 00083 decode.int32 = 00084 decode.int32u = &int32; 00085 decode.int64 = 00086 decode.int64u = &int64; 00087 00088 decode.float32 = &float32; 00089 decode.float64 = &float64; 00090 decode.float80 = &float80; 00091 } 00092 00093 /*********************************************************************** 00094 00095 Construct a TextReader upon the buffer associated with the 00096 given conduit. 00097 00098 ***********************************************************************/ 00099 00100 this (IConduit conduit, ITokenizer tokenizer = Tokenizers.line) 00101 { 00102 this (conduit.createBuffer, tokenizer); 00103 } 00104 00105 /*********************************************************************** 00106 00107 Internal method to isolate the next token. 00108 00109 ***********************************************************************/ 00110 00111 private final Token next () 00112 { 00113 if (tokenizer.next (buffer, token) && token.getLength > 0) 00114 return token; 00115 throw new TokenException ("unexpected end of input"); 00116 } 00117 00118 /*********************************************************************** 00119 00120 ***********************************************************************/ 00121 00122 uint int1 (void* src, uint count) 00123 { 00124 for (uint i=count; i; --i) 00125 { 00126 * cast(bool*) src = (next.toString == "true"); 00127 ++src; 00128 } 00129 return count; 00130 } 00131 00132 /*********************************************************************** 00133 00134 ***********************************************************************/ 00135 00136 uint int8 (void* src, uint count) 00137 { 00138 for (uint i=count; i; i -= byte.sizeof) 00139 { 00140 * cast(byte*) src = next.toInt(); 00141 src += byte.sizeof; 00142 } 00143 return count; 00144 } 00145 00146 /*********************************************************************** 00147 00148 ***********************************************************************/ 00149 00150 uint int16 (void* src, uint count) 00151 { 00152 for (uint i=count; i; i -= short.sizeof) 00153 { 00154 * cast(short*) src = next.toInt(); 00155 src += short.sizeof; 00156 } 00157 return count; 00158 } 00159 00160 /*********************************************************************** 00161 00162 ***********************************************************************/ 00163 00164 uint int32 (void* src, uint count) 00165 { 00166 for (uint i=count; i; i -= int.sizeof) 00167 { 00168 * cast(int*) src = next.toInt(); 00169 src += int.sizeof; 00170 } 00171 return count; 00172 } 00173 00174 /*********************************************************************** 00175 00176 ***********************************************************************/ 00177 00178 uint int64 (void* src, uint count) 00179 { 00180 for (uint i=count; i; i -= long.sizeof) 00181 { 00182 * cast(long*) src = next.toLong(); 00183 src += long.sizeof; 00184 } 00185 return count; 00186 } 00187 00188 /*********************************************************************** 00189 00190 ***********************************************************************/ 00191 00192 uint float32 (void* src, uint count) 00193 { 00194 for (uint i=count; i; i -= float.sizeof) 00195 { 00196 * cast(float*) src = next.toReal(); 00197 src += float.sizeof; 00198 } 00199 return count; 00200 } 00201 00202 /*********************************************************************** 00203 00204 ***********************************************************************/ 00205 00206 uint float64 (void* src, uint count) 00207 { 00208 for (uint i=count; i; i -= double.sizeof) 00209 { 00210 * cast(double*) src = next.toReal(); 00211 src += double.sizeof; 00212 } 00213 return count; 00214 } 00215 00216 /*********************************************************************** 00217 00218 ***********************************************************************/ 00219 00220 uint float80 (void* src, uint count) 00221 { 00222 for (uint i=count; i; i -= real.sizeof) 00223 { 00224 * cast(real*) src = next.toReal(); 00225 src += real.sizeof; 00226 } 00227 return count; 00228 } 00229 00230 /*********************************************************************** 00231 00232 ***********************************************************************/ 00233 00234 override IReader get (inout char[] x, uint elements = uint.max) 00235 { 00236 // dup the input string, to avoid surprises 00237 x = next.toString (false); 00238 return this; 00239 } 00240 00241 /*********************************************************************** 00242 00243 @todo - Tokenizer needs to handle wchar[] before this will 00244 operate correctly 00245 00246 ***********************************************************************/ 00247 00248 override IReader get (inout wchar[] x, uint elements = uint.max) 00249 { 00250 assert (0); 00251 return this; 00252 } 00253 00254 /*********************************************************************** 00255 00256 @todo - Tokenizer needs to handle dchar[] before this will 00257 operate correctly 00258 00259 ***********************************************************************/ 00260 00261 override IReader get (inout dchar[] x, uint elements = uint.max) 00262 { 00263 assert (0); 00264 return this; 00265 } 00266 }