00001 /******************************************************************************* 00002 00003 @file IBuffer.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.model.IBuffer; 00040 00041 private import mango.io.model.IConduit; 00042 00043 00044 /******************************************************************************* 00045 00046 The basic premise behind this IO package is as follows: 00047 00048 1) the central concept is that of a buffer. The buffer acts 00049 as a queue (line) where items are removed from the front 00050 and new items are added to the back. Buffers are modeled 00051 by this interface, and mango.io.Buffer exposes a concrete 00052 implementation. 00053 00054 2) buffers can be written to directly, but a Reader and/or 00055 Writer are typically used to read & write formatted data. 00056 These readers & writers are bound to a specific buffer; 00057 often the same buffer. It's also perfectly legitimate to 00058 bind multiple writers to the same buffer; they will all 00059 behave serially as one would expect. The same applies to 00060 multiple readers on the same buffer. Readers and writers 00061 support two styles of IO: put/get, and the C++ style << 00062 and >> operators. All such operations can be chained. 00063 00064 3) Any class can be made compatable with the reader/writer 00065 framework by implementing the IReadable and/or IWritable 00066 interfaces. Each of these specify just a single method. 00067 00068 4) Buffers may also be tokenized. This is handy when one is 00069 dealing with text input, and/or the content suits a more 00070 fluid format than most typical readers & writers support. 00071 Tokens are mapped directly onto buffer content, so there 00072 is only minor overhead in using them. Tokens can be read 00073 and written by reader/writers also, using a more relaxed 00074 set of rules than those applied to integral IO. 00075 00076 5) buffers are sometimes memory-only, in which case there 00077 is nothing left to do when a reader (or tokenizer) hits 00078 end of buffer conditions. Other buffers are themselves 00079 bound to a Conduit. When this is the case, a reader will 00080 eventually cause the buffer to reload via its associated 00081 conduit. Previous buffer content will thus be lost. The 00082 same concept is applied to writers, whereby they flush 00083 the content of a full buffer to a bound conduit before 00084 continuing. 00085 00086 6) conduits provide virtualized access to external content, 00087 and represent things like files or Internet connections. 00088 They are just a different kind of stream. Conduits are 00089 modelled by mango.io.model.IConduit, and implemented via 00090 classes FileConduit and SocketConduit. Additional kinds 00091 of conduit are easy to construct: one either subclasses 00092 mango.io.Conduit, or implements mango.io.model.IConduit. A 00093 conduit reads and writes from/to a buffer in big chunks 00094 (typically the entire buffer). 00095 00096 *******************************************************************************/ 00097 00098 interface IBuffer 00099 { 00100 /*********************************************************************** 00101 00102 Create an instance of an IBuffer. Use this when you 00103 don't know anything about the concrete implementation, 00104 and have only the IBuffer interface available 00105 00106 ***********************************************************************/ 00107 00108 IBuffer create (); 00109 00110 /*********************************************************************** 00111 00112 Return the backing array 00113 00114 ***********************************************************************/ 00115 00116 void[] getContent (); 00117 00118 /*********************************************************************** 00119 00120 Return a char[] slice of the buffer up to the limit of 00121 valid content. 00122 00123 ***********************************************************************/ 00124 00125 char[] toString (); 00126 00127 /*********************************************************************** 00128 00129 Set the backing array with all content readable. Writing 00130 to this will either flush it to an associated conduit, or 00131 raise an Eof condition. Use IBuffer.clear() to reset the 00132 content (make it all writable). 00133 00134 ***********************************************************************/ 00135 00136 IBuffer setValidContent (void[] data); 00137 00138 /*********************************************************************** 00139 00140 Set the backing array with some content readable. Writing 00141 to this will either flush it to an associated conduit, or 00142 raise an Eof condition. Use IBuffer.clear() to reset the 00143 content (make it all writable). 00144 00145 ***********************************************************************/ 00146 00147 IBuffer setContent (void[] data, uint readable); 00148 00149 /*********************************************************************** 00150 00151 Write an array of data into this buffer, and flush to the 00152 conduit as necessary. Returns a chaining reference if all 00153 data was written; throws an IOException indicating eof or 00154 eob if not. 00155 00156 This is often used in lieu of a Writer. 00157 00158 ***********************************************************************/ 00159 00160 IBuffer append (void[] content); 00161 00162 /*********************************************************************** 00163 00164 Read a chunk of data from the buffer, loading from the 00165 conduit as necessary. The requested number of bytes are 00166 loaded into the buffer, and marked as having been read 00167 when the 'eat' parameter is set true. When 'eat' is set 00168 false, the read position is not adjusted. 00169 00170 Returns the corresponding buffer slice when successful, 00171 or null if there's not enough data available (Eof; Eob). 00172 00173 ***********************************************************************/ 00174 00175 void[] get (uint size, bool eat = true); 00176 00177 /*********************************************************************** 00178 00179 Exposes the raw data buffer at the current write position, 00180 The delegate is provided with a void[] representing space 00181 available within the buffer at the current write position. 00182 00183 The delegate should return the approriate number of bytes 00184 if it writes valid content, or IConduit.Eof on error. 00185 00186 Returns whatever the delegate returns. 00187 00188 ***********************************************************************/ 00189 00190 int write (int delegate (void[]) writer); 00191 00192 /*********************************************************************** 00193 00194 Exposes the raw data buffer at the current read position. The 00195 delegate is provided with a void[] representing the available 00196 data, and should return zero to leave the current read position 00197 intact. 00198 00199 If the delegate consumes data, it should return the number of 00200 bytes consumed; or IConduit.Eof to indicate an error. 00201 00202 Returns whatever the delegate returns. 00203 00204 ***********************************************************************/ 00205 00206 int read (int delegate (void[]) reader); 00207 00208 /*********************************************************************** 00209 00210 If we have some data left after an export, move it to 00211 front-of-buffer and set position to be just after the 00212 remains. This is for supporting certain conduits which 00213 choose to write just the initial portion of a request. 00214 00215 Limit is set to the amount of data remaining. Position 00216 is always reset to zero. 00217 00218 ***********************************************************************/ 00219 00220 IBuffer compress (); 00221 00222 /*********************************************************************** 00223 00224 Skip ahead by the specified number of bytes, streaming from 00225 the associated conduit as necessary. 00226 00227 Can also reverse the read position by 'size' bytes. This may 00228 be used to support lookahead-type operations. 00229 00230 Returns true if successful, false otherwise. 00231 00232 ***********************************************************************/ 00233 00234 bool skip (int size); 00235 00236 /*********************************************************************** 00237 00238 flush the contents of this buffer to the related conduit. 00239 Throws an IOException on premature eof. 00240 00241 ***********************************************************************/ 00242 00243 void flush (); 00244 00245 /*********************************************************************** 00246 00247 Reset position and limit to zero. 00248 00249 ***********************************************************************/ 00250 00251 IBuffer clear (); 00252 00253 /*********************************************************************** 00254 00255 return count of readable bytes remaining in buffer. This is 00256 calculated simply as limit() - position() 00257 00258 ***********************************************************************/ 00259 00260 uint readable (); 00261 00262 /*********************************************************************** 00263 00264 Return count of writable bytes available in buffer. This is 00265 calculated simply as capacity() - limit() 00266 00267 ***********************************************************************/ 00268 00269 uint writable (); 00270 00271 /*********************************************************************** 00272 00273 returns the limit of readable content within this buffer 00274 00275 ***********************************************************************/ 00276 00277 uint getLimit (); 00278 00279 /*********************************************************************** 00280 00281 returns the total capacity of this buffer 00282 00283 ***********************************************************************/ 00284 00285 uint getCapacity (); 00286 00287 /*********************************************************************** 00288 00289 returns the current position within this buffer 00290 00291 ***********************************************************************/ 00292 00293 uint getPosition (); 00294 00295 /*********************************************************************** 00296 00297 Overridable method to grow the buffer size when it becomes 00298 full. Default is to not grow at all. 00299 00300 ***********************************************************************/ 00301 00302 bool grow (uint size); 00303 00304 /*********************************************************************** 00305 00306 Returns the conduit associated with this buffer. Returns 00307 null if the buffer is purely memory based; that is, it's 00308 not backed by some external conduit. 00309 00310 Buffers do not require a conduit to operate, but it can 00311 be convenient to associate one. For example, the IReader 00312 and IWriter classes use this to import/export content as 00313 necessary. 00314 00315 ***********************************************************************/ 00316 00317 IConduit getConduit (); 00318 00319 /*********************************************************************** 00320 00321 Sets the external conduit associated with this buffer. 00322 00323 Buffers do not require an external conduit to operate, but 00324 it can be convenient to associate one. For example, methods 00325 read and write use it to import/export content as necessary. 00326 00327 ***********************************************************************/ 00328 00329 void setConduit (IConduit conduit); 00330 } 00331 00332 /******************************************************************************* 00333 00334 *******************************************************************************/ 00335 00336 enum ConverterType 00337 { 00338 Char=0, WChar, DChar 00339 }; 00340