1 /******************************************************************************* 2 3 copyright: Copyright (c) 2007 Kris Bell. All rights reserved 4 5 license: BSD style: $(LICENSE) 6 7 version: Initial release: Oct 2007 8 9 author: Kris 10 11 *******************************************************************************/ 12 13 module tango.io.stream.Snoop; 14 15 private import tango.io.Console, 16 tango.io.device.Conduit; 17 18 private import tango.text.convert.Format; 19 20 version(DigitalMars) 21 { 22 private import tango.core.Vararg; 23 }else version (GNU) 24 private import tango.core.Vararg; 25 26 private alias void delegate(const(char)[]) Snoop; 27 28 /******************************************************************************* 29 30 Stream to expose call behaviour. By default, activity trace is 31 sent to Cerr. 32 33 *******************************************************************************/ 34 35 class SnoopInput : InputStream 36 { 37 private InputStream host; 38 private Snoop snoop; 39 40 /*********************************************************************** 41 42 Attach to the provided stream. 43 44 ***********************************************************************/ 45 46 this (InputStream host, Snoop snoop = null) 47 { 48 assert (host); 49 this.host = host; 50 this.snoop = snoop ? snoop : &snooper; 51 } 52 53 /*********************************************************************** 54 55 Return the upstream host of this filter. 56 57 ***********************************************************************/ 58 59 InputStream input () 60 { 61 return host; 62 } 63 64 /*********************************************************************** 65 66 Return the hosting conduit. 67 68 ***********************************************************************/ 69 70 final IConduit conduit () 71 { 72 return host.conduit; 73 } 74 75 /*********************************************************************** 76 77 Read from conduit into a target array. The provided dst 78 will be populated with content from the conduit. 79 80 Returns the number of bytes read, which may be less than 81 requested in dst. 82 83 ***********************************************************************/ 84 85 final size_t read (void[] dst) 86 { 87 auto x = host.read (dst); 88 trace ("{}: read {} bytes", host.conduit, x is -1 ? 0 : x); 89 return x; 90 } 91 92 /*********************************************************************** 93 94 Load the bits from a stream, and return them all in an 95 array. The dst array can be provided as an option, which 96 will be expanded as necessary to consume the input. 97 98 Returns an array representing the content, and throws 99 IOException on error. 100 101 ***********************************************************************/ 102 103 void[] load (size_t max=-1) 104 { 105 auto x = host.load (max); 106 trace ("{}: loaded {} bytes", x.length); 107 return x; 108 } 109 110 /*********************************************************************** 111 112 Clear any buffered content. 113 114 ***********************************************************************/ 115 116 final InputStream flush () 117 { 118 host.flush(); 119 trace ("{}: flushed/cleared", host.conduit); 120 return this; 121 } 122 123 /*********************************************************************** 124 125 Close the input. 126 127 ***********************************************************************/ 128 129 final void close () 130 { 131 host.close(); 132 trace ("{}: closed", host.conduit); 133 } 134 135 /*********************************************************************** 136 137 Seek on this stream. Target conduits that don't support 138 seeking will throw an IOException. 139 140 ***********************************************************************/ 141 142 final long seek (long offset, Anchor anchor = Anchor.Begin) 143 { 144 auto s = host.seek (offset, anchor); 145 trace ("{}: seek at offset {} from anchor {}", host.conduit, offset, anchor); 146 return s; 147 } 148 149 /*********************************************************************** 150 151 Internal trace handler. 152 153 ***********************************************************************/ 154 155 private void snooper (const(char)[] x) 156 { 157 Cerr(x).newline; 158 } 159 160 /*********************************************************************** 161 162 Internal trace handler. 163 164 ***********************************************************************/ 165 166 private void trace (const(char)[] format, ...) 167 { 168 char[256] tmp = void; 169 snoop (Format.vprint (tmp, format, _arguments, _argptr)); 170 } 171 } 172 173 174 /******************************************************************************* 175 176 Stream to expose call behaviour. By default, activity trace is 177 sent to Cerr. 178 179 *******************************************************************************/ 180 181 class SnoopOutput : OutputStream 182 { 183 private OutputStream host; 184 private Snoop snoop; 185 186 /*********************************************************************** 187 188 Attach to the provided stream. 189 190 ***********************************************************************/ 191 192 this (OutputStream host, Snoop snoop = null) 193 { 194 assert (host); 195 this.host = host; 196 this.snoop = snoop ? snoop : &snooper; 197 } 198 199 /*********************************************************************** 200 201 Return the upstream host of this filter. 202 203 ***********************************************************************/ 204 205 OutputStream output () 206 { 207 return host; 208 } 209 210 /*********************************************************************** 211 212 Write to conduit from a source array. The provided src 213 content will be written to the conduit. 214 215 Returns the number of bytes written from src, which may 216 be less than the quantity provided. 217 218 ***********************************************************************/ 219 220 final size_t write (const(void)[] src) 221 { 222 auto x = host.write (src); 223 trace ("{}: wrote {} bytes", host.conduit, x is -1 ? 0 : x); 224 return x; 225 } 226 227 /*********************************************************************** 228 229 Return the hosting conduit. 230 231 ***********************************************************************/ 232 233 final IConduit conduit () 234 { 235 return host.conduit; 236 } 237 238 /*********************************************************************** 239 240 Emit/purge buffered content. 241 242 ***********************************************************************/ 243 244 final OutputStream flush () 245 { 246 host.flush(); 247 trace ("{}: flushed", host.conduit); 248 return this; 249 } 250 251 /*********************************************************************** 252 253 Close the output. 254 255 ***********************************************************************/ 256 257 final void close () 258 { 259 host.close(); 260 trace ("{}: closed", host.conduit); 261 } 262 263 /*********************************************************************** 264 265 Transfer the content of another conduit to this one. Returns 266 a reference to this class, or throws IOException on failure. 267 268 ***********************************************************************/ 269 270 final OutputStream copy (InputStream src, size_t max=-1) 271 { 272 host.copy (src, max); 273 trace("{}: copied from {}", host.conduit, src.conduit); 274 return this; 275 } 276 277 /*********************************************************************** 278 279 Seek on this stream. Target conduits that don't support 280 seeking will throw an IOException. 281 282 ***********************************************************************/ 283 284 final long seek (long offset, Anchor anchor = Anchor.Begin) 285 { 286 auto s = host.seek (offset, anchor); 287 trace ("{}: seek at offset {} from anchor {}", host.conduit, offset, anchor); 288 return s; 289 } 290 291 /*********************************************************************** 292 293 Internal trace handler. 294 295 ***********************************************************************/ 296 297 private void snooper (const(char)[] x) 298 { 299 Cerr(x).newline; 300 } 301 302 /*********************************************************************** 303 304 Internal trace handler. 305 306 ***********************************************************************/ 307 308 private void trace (const(char)[] format, ...) 309 { 310 char[256] tmp = void; 311 snoop (Format.vprint (tmp, format, _arguments, _argptr)); 312 } 313 } 314 315 316 317 debug (Snoop) 318 { 319 void main() 320 { 321 auto s = new SnoopInput (null); 322 auto o = new SnoopOutput (null); 323 } 324 }