00001 /******************************************************************************* 00002 00003 @file DisplayWriter.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.DisplayWriter; 00040 00041 private import std.c.stdio; 00042 00043 public import mango.io.Writer; 00044 00045 /******************************************************************************* 00046 00047 Format output suitable for presentation. There is no corresponding 00048 reader, since there are no explicit delimiters emitted to isolate 00049 each formatted item. One can use TextReader to read input from the 00050 console (or from some other input buffer). 00051 00052 *******************************************************************************/ 00053 00054 class DisplayWriter : Writer 00055 { 00056 // temporary buffer space for encoding 00057 private char[64] tmp; 00058 00059 // number of floating-point digits to write 00060 private uint digits = 2; 00061 00062 version (Win32) 00063 { 00064 alias _vsnprintf vsnprintf; 00065 alias _snprintf snprintf; 00066 } 00067 00068 /*********************************************************************** 00069 00070 Construct a DisplayWriter upon the specified IBuffer 00071 00072 ***********************************************************************/ 00073 00074 this (IBuffer buffer) 00075 { 00076 super (buffer); 00077 00078 // disable array length output (for strings and so on) 00079 enableArrayPrefix (false); 00080 00081 encode.int1 = &int1; 00082 encode.int8 = &int8; 00083 encode.int8u = &int8u; 00084 encode.int16 = &int16; 00085 encode.int16u = &int16u; 00086 encode.int32 = &int32; 00087 encode.int32u = &int32u; 00088 encode.int64 = &int64; 00089 encode.int64u = &int64u; 00090 00091 encode.float32 = &float32; 00092 encode.float64 = &float64; 00093 encode.float80 = &float80; 00094 } 00095 00096 /*********************************************************************** 00097 00098 Construct a DisplayWriter upon the specified IConduit 00099 00100 ***********************************************************************/ 00101 00102 this (IConduit conduit) 00103 { 00104 this (conduit.createBuffer); 00105 } 00106 00107 /*********************************************************************** 00108 00109 Set the number of floating point digits 00110 00111 ***********************************************************************/ 00112 00113 void setPrecision (uint digits) 00114 { 00115 this.digits = digits; 00116 } 00117 00118 /*********************************************************************** 00119 00120 Convert to a string and send back through the framework 00121 such that it may be intercepted by a subclass. 00122 00123 ***********************************************************************/ 00124 00125 final void format (char[] fmt, void* src) 00126 { 00127 put (tmp[0..vsnprintf (tmp, tmp.length, fmt, src)]); 00128 } 00129 00130 /*********************************************************************** 00131 00132 ***********************************************************************/ 00133 00134 final void int8f (ubyte* src, uint count, char[] fmt) 00135 { 00136 while (count) 00137 { 00138 uint i = *src; 00139 format (fmt, &i); 00140 00141 ++src; 00142 --count; 00143 } 00144 } 00145 00146 /*********************************************************************** 00147 00148 ***********************************************************************/ 00149 00150 final void int16f (ushort* src, uint count, char[] fmt) 00151 { 00152 while (count) 00153 { 00154 uint i = *src; 00155 format (fmt, &i); 00156 00157 ++src; 00158 count -= 2; 00159 } 00160 } 00161 00162 /*********************************************************************** 00163 00164 ***********************************************************************/ 00165 00166 final void format (void* src, uint count, uint width, char[] fmt) 00167 { 00168 while (count) 00169 { 00170 format (fmt, src); 00171 00172 src += width; 00173 count -= width; 00174 } 00175 } 00176 00177 /*********************************************************************** 00178 00179 ***********************************************************************/ 00180 00181 final void fformat (void* src, uint count, uint width) 00182 { 00183 real x; 00184 00185 while (count) 00186 { 00187 if (width == float.sizeof) 00188 x = *cast(float*) src; 00189 else 00190 if (width == double.sizeof) 00191 x = *cast(double*) src; 00192 else 00193 x = *cast(real*) src; 00194 00195 put (tmp[0..snprintf (tmp, tmp.length, "%.*Lf", digits, x)]); 00196 count -= width; 00197 src += width; 00198 } 00199 } 00200 00201 /*********************************************************************** 00202 00203 ***********************************************************************/ 00204 00205 final void int1 (void* src, uint count) 00206 { 00207 while (count) 00208 { 00209 if (*cast(ubyte *) src) 00210 encode.char8 (cast(char*) "true", 4); 00211 else 00212 encode.char8 (cast(char*) "false", 5); 00213 00214 ++src; 00215 --count; 00216 } 00217 } 00218 00219 /*********************************************************************** 00220 00221 ***********************************************************************/ 00222 00223 final void int8 (void* src, uint count) 00224 { 00225 int8f (cast(ubyte*) src, count, "%d"); 00226 } 00227 00228 /*********************************************************************** 00229 00230 ***********************************************************************/ 00231 00232 final void int8u (void* src, uint count) 00233 { 00234 int8f (cast(ubyte*) src, count, "%u"); 00235 } 00236 00237 /*********************************************************************** 00238 00239 ***********************************************************************/ 00240 00241 final void int16 (void* src, uint count) 00242 { 00243 int16f (cast(ushort*) src, count, "%d"); 00244 } 00245 00246 /*********************************************************************** 00247 00248 ***********************************************************************/ 00249 00250 final void int16u (void* src, uint count) 00251 { 00252 int16f (cast(ushort*) src, count, "%u"); 00253 } 00254 00255 /*********************************************************************** 00256 00257 ***********************************************************************/ 00258 00259 final void int32 (void* src, uint count) 00260 { 00261 format (src, count, uint.sizeof, "%d"); 00262 } 00263 00264 /*********************************************************************** 00265 00266 ***********************************************************************/ 00267 00268 final void int32u (void* src, uint count) 00269 { 00270 format (src, count, uint.sizeof, "%u"); 00271 } 00272 00273 /*********************************************************************** 00274 00275 ***********************************************************************/ 00276 00277 final void int64 (void* src, uint count) 00278 { 00279 format (src, count, long.sizeof, "%lld"); 00280 } 00281 00282 /*********************************************************************** 00283 00284 ***********************************************************************/ 00285 00286 final void int64u (void* src, uint count) 00287 { 00288 format (src, count, long.sizeof, "%llu"); 00289 } 00290 00291 /*********************************************************************** 00292 00293 ***********************************************************************/ 00294 00295 final void float32 (void* src, uint count) 00296 { 00297 fformat (src, count, float.sizeof); 00298 } 00299 00300 /*********************************************************************** 00301 00302 ***********************************************************************/ 00303 00304 final void float64 (void* src, uint count) 00305 { 00306 fformat (src, count, double.sizeof); 00307 } 00308 00309 /*********************************************************************** 00310 00311 ***********************************************************************/ 00312 00313 final void float80 (void* src, uint count) 00314 { 00315 fformat (src, count, real.sizeof); 00316 } 00317 } 00318 00319 00320 00321 /******************************************************************************* 00322 00323 Subclass to support automatic flushing. This can be used for 00324 Stdout, Stderr, and other related conduits. 00325 00326 *******************************************************************************/ 00327 00328 class FlushWriter : DisplayWriter 00329 { 00330 alias opShl put; 00331 alias DisplayWriter.opShl opShl; 00332 00333 /*********************************************************************** 00334 00335 Construct a FlushWriter upon the specified IBuffer 00336 00337 ***********************************************************************/ 00338 00339 this (IBuffer buffer) 00340 { 00341 super (buffer); 00342 } 00343 00344 /*********************************************************************** 00345 00346 Construct a FlushWriter upon the specified IConduit 00347 00348 ***********************************************************************/ 00349 00350 this (IConduit conduit) 00351 { 00352 this (conduit.createBuffer); 00353 } 00354 00355 /********************************************************************** 00356 00357 Intercept the IWritable method to catch newlines, and 00358 flush the buffer whenever one is emitted 00359 00360 ***********************************************************************/ 00361 00362 override IWriter opShl (IWritable x) 00363 { 00364 // have superclass handle the IWritable 00365 super.opShl (x); 00366 00367 // flush output when we see a newline 00368 if (cast(INewlineWriter) x) 00369 flush (); 00370 00371 return this; 00372 } 00373 } 00374