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.Digester; 14 15 private import tango.io.device.Conduit; 16 17 private import tango.util.digest.Digest; 18 19 /******************************************************************************* 20 21 Inject a digest filter into an input stream, updating the digest 22 as information flows through it. 23 24 *******************************************************************************/ 25 26 class DigestInput : InputFilter, InputFilter.Mutator 27 { 28 private Digest filter; 29 30 /*********************************************************************** 31 32 Accepts any input stream, and any digest derivation. 33 34 ***********************************************************************/ 35 36 this (InputStream stream, Digest digest) 37 { 38 super (stream); 39 filter = digest; 40 } 41 42 /*********************************************************************** 43 44 Read from conduit into a target array. The provided dst 45 will be populated with content from the conduit. 46 47 Returns the number of bytes read, which may be less than 48 requested in dst (or IOStream.Eof for end-of-flow.) 49 50 ***********************************************************************/ 51 52 final override size_t read (void[] dst) 53 { 54 auto len = source.read (dst); 55 if (len != Eof) 56 filter.update (dst [0 .. len]); 57 return len; 58 } 59 60 /*********************************************************************** 61 62 Slurp remaining stream content and return this. 63 64 ***********************************************************************/ 65 66 final DigestInput slurp (void[] dst = null) 67 { 68 if (dst.length is 0) 69 dst.length = conduit.bufferSize; 70 71 while (read(dst) != Eof) {} 72 return this; 73 } 74 75 /******************************************************************** 76 77 Return the Digest instance we were created with. Use this 78 to access the resultant binary or hex digest value. 79 80 *********************************************************************/ 81 82 final Digest digest() 83 { 84 return filter; 85 } 86 } 87 88 89 /******************************************************************************* 90 91 Inject a digest filter into an output stream, updating the digest 92 as information flows through it. Here's an example where we calculate 93 an MD5 digest as a side-effect of copying a file: 94 --- 95 auto output = new DigestOutput(new FileOutput("output"), new Md5); 96 output.copy (new FileInput("input")); 97 98 Stdout.formatln ("hex digest: {}", output.digest.hexDigest); 99 --- 100 101 *******************************************************************************/ 102 103 class DigestOutput : OutputFilter, InputFilter.Mutator 104 { 105 private Digest filter; 106 107 /*********************************************************************** 108 109 Accepts any output stream, and any digest derivation. 110 111 ***********************************************************************/ 112 113 this (OutputStream stream, Digest digest) 114 { 115 super (stream); 116 filter = digest; 117 } 118 119 /*********************************************************************** 120 121 Write to conduit from a source array. The provided src 122 content will be written to the conduit. 123 124 Returns the number of bytes written from src, which may 125 be less than the quantity provided. 126 127 ***********************************************************************/ 128 129 final override size_t write (const(void)[] src) 130 { 131 auto len = sink.write (src); 132 if (len != Eof) 133 filter.update (src[0 .. len]); 134 return len; 135 } 136 137 /******************************************************************** 138 139 Return the Digest instance we were created with. Use this 140 to access the resultant binary or hex digest value. 141 142 *********************************************************************/ 143 144 final Digest digest() 145 { 146 return filter; 147 } 148 } 149 150 151 /******************************************************************************* 152 153 *******************************************************************************/ 154 155 debug (DigestStream) 156 { 157 import tango.io.Stdout; 158 import tango.io.device.Array; 159 import tango.util.digest.Md5; 160 import tango.io.stream.FileStream; 161 162 void main() 163 { 164 auto output = new DigestOutput(new Array(1024, 1024), new Md5); 165 output.copy (new FileInput("Digester.d")); 166 167 Stdout.formatln ("hex digest:{}", output.digest.hexDigest); 168 } 169 }