00001 /******************************************************************************* 00002 00003 @file Writer.d 00004 00005 00006 Copyright (c) 2004 Kris Bell 00007 00008 This software is provided 'as-is', without any express or implied 00009 warranty. In no event will the authors be held liable for damages 00010 of any kind arising from the use of this software. 00011 00012 Permission is hereby granted to anyone to use this software for any 00013 purpose, including commercial applications, and to alter it and/or 00014 redistribute it freely, subject to the following restrictions: 00015 00016 1. The origin of this software must not be misrepresented; you must 00017 not claim that you wrote the original software. If you use this 00018 software in a product, an acknowledgment within documentation of 00019 said product would be appreciated but is not required. 00020 00021 2. Altered source versions must be plainly marked as such, and must 00022 not be misrepresented as being the original software. 00023 00024 3. This notice may not be removed or altered from any distribution 00025 of the source. 00026 00027 4. Derivative works are permitted, but they must carry this notice 00028 in full and credit the original source. 00029 00030 00031 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00032 00033 00034 @version Initial version, March 2004 00035 @author Kris 00036 00037 *******************************************************************************/ 00038 00039 module mango.io.Writer; 00040 00041 public import mango.io.AbstractWriter; 00042 00043 /******************************************************************************* 00044 00045 Binary data Writer. Writers provide the means to append formatted 00046 data to an IBuffer, and expose a convenient method of handling a 00047 variety of data types. In addition to writing native types such 00048 as integer and char[], writers also process any class which has 00049 implemented the IWritable interface (one method). 00050 00051 See AbstractWriter for usage examples. 00052 00053 *******************************************************************************/ 00054 00055 class Writer : AbstractWriter 00056 { 00057 typedef void function (void* dst, uint count) Mutator; 00058 00059 /*********************************************************************** 00060 00061 Construct a Writer upon the provided IBuffer. All formatted 00062 output will be directed to this buffer. 00063 00064 ***********************************************************************/ 00065 00066 this (IBuffer buffer) 00067 { 00068 super (buffer); 00069 00070 encode.int1 = 00071 encode.int8 = 00072 encode.int8u = 00073 encode.int16 = 00074 encode.int16u = 00075 encode.int32 = 00076 encode.int32u = 00077 encode.int64 = 00078 encode.int64u = 00079 encode.float32 = 00080 encode.float64 = 00081 encode.float80 = 00082 encode.char8 = 00083 encode.char16 = 00084 encode.char32 = &write; 00085 } 00086 00087 /*********************************************************************** 00088 00089 Construct a Writer on the buffer associated with the given 00090 conduit. 00091 00092 ***********************************************************************/ 00093 00094 this (IConduit conduit) 00095 { 00096 this (conduit.createBuffer); 00097 } 00098 00099 /*********************************************************************** 00100 00101 ***********************************************************************/ 00102 00103 final void write (void* src, uint count) 00104 { 00105 static void mutate (void* dst, uint count) 00106 { 00107 } 00108 00109 write (src, count, ~0, &mutate); 00110 } 00111 00112 /*********************************************************************** 00113 00114 ***********************************************************************/ 00115 00116 final void write (void* src, uint count, int mask, Mutator mutate) 00117 { 00118 int writer (void[] dst) 00119 { 00120 // cap bytes written 00121 uint len = dst.length & mask; 00122 if (len > count) 00123 len = count; 00124 00125 dst [0..len] = src [0..len]; 00126 mutate (dst, len); 00127 return len; 00128 } 00129 00130 while (count) 00131 { 00132 //flush if we used all buffer space 00133 if (count -= buffer.write (&writer)) 00134 if (buffer.getConduit) 00135 buffer.flush (); 00136 else 00137 if (! buffer.grow (count)) 00138 throw ovf; 00139 } 00140 } 00141 00142 /+ 00143 /*********************************************************************** 00144 00145 ***********************************************************************/ 00146 00147 final void write (void* src, uint count, int mask, Mutator mutate) 00148 { 00149 while (count) 00150 { 00151 // write as much space as there is available in the buffer 00152 uint available = buffer.writable() & mask; 00153 00154 // cap bytes written 00155 if (available > count) 00156 available = count; 00157 00158 // copy them over and adjust output 00159 mutate (buffer.put(src, available), available); 00160 00161 // bump counters; flush if we used all buffer space 00162 src += available; 00163 if (count -= available) 00164 if (buffer.getConduit) 00165 buffer.flush (); 00166 else 00167 if (! buffer.grow (count)) 00168 throw ovf; 00169 } 00170 } 00171 +/ 00172 }