 |
Changeset 2490
- Timestamp:
- 08/17/07 12:19:02
(1 year ago)
- Author:
- kris
- Message:
- exposed conduit read & write again, since there's really no harm in doing so
- cleaned up close() mechanics across some conduit instances
- added commit() support to OutputStream? (for ZipFilter?, ChunkingFilter?, etc)
- added a dispose() method to conduit, intended to be used instead of close() in general usage (it flushes and commits the filter chain, closes the conduit, and deletes the instance).
- added a tentative dispose() to buffer, for similar usage
- added a divert() method to Cout, Cerr, and Cin. These should be used instead of hacking the filter-chain for those entities
- removed the interim notify() support from conduit, and from console. It was too brittle for long-term usage
- renamed 'next' to 'host' within the stream filters
- added override to a number of conduit-oriented method decls
- removed some remaining support for closing a resource via dtors
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r2465 |
r2490 |
|
| 265 | 265 | |
|---|
| 266 | 266 | bucket.file.seek (offset); |
|---|
| 267 | | if (bucket.file.input.read (data) != length) |
|---|
| | 267 | if (bucket.file.read (data) != length) |
|---|
| 268 | 268 | eof (bucket); |
|---|
| 269 | 269 | |
|---|
| … | … | |
| 290 | 290 | |
|---|
| 291 | 291 | // write content |
|---|
| 292 | | if (bucket.file.output.write (data) != length) |
|---|
| | 292 | if (bucket.file.write (data) != length) |
|---|
| 293 | 293 | eof (bucket); |
|---|
| 294 | 294 | } |
|---|
| r2465 |
r2490 |
|
| 17 | 17 | // copy each file onto dst |
|---|
| 18 | 18 | foreach (char[] arg; args[2..args.length]) |
|---|
| 19 | | dst.output.copy (new FileConduit(arg)); |
|---|
| | 19 | dst.copy (new FileConduit(arg)); |
|---|
| 20 | 20 | |
|---|
| 21 | 21 | // flush output and close |
|---|
| 22 | | dst.close; |
|---|
| | 22 | dst.dispose; |
|---|
| 23 | 23 | } |
|---|
| 24 | 24 | else |
|---|
| r2465 |
r2490 |
|
| 8 | 8 | |
|---|
| 9 | 9 | Read a file line-by-line, sending each one to the console. This |
|---|
| 10 | | illustrates how to bind a conduit to a text iterator. Iterators |
|---|
| 11 | | also support the binding of buffer and string instances. |
|---|
| 12 | | |
|---|
| 13 | | Note that iterators are templated for char, wchar and dchar ~ |
|---|
| 14 | | this example uses char |
|---|
| | 10 | illustrates how to bind a conduit to a stream iterator (iterators |
|---|
| | 11 | also support the binding of a buffer). Note that stream iterators |
|---|
| | 12 | are templated for char, wchar and dchar types. |
|---|
| 15 | 13 | |
|---|
| 16 | 14 | *******************************************************************************/ |
|---|
| … | … | |
| 21 | 19 | { |
|---|
| 22 | 20 | // open a file for reading |
|---|
| 23 | | auto file = new FileConduit (args[1]); |
|---|
| | 21 | scope file = new FileConduit (args[1]); |
|---|
| 24 | 22 | |
|---|
| 25 | 23 | // process file one line at a time |
|---|
| r2465 |
r2490 |
|
| 172 | 172 | log.trace(sprint("[{0}] Receiving message from client", i)); |
|---|
| 173 | 173 | |
|---|
| 174 | | count = (cast(SocketConduit) selectionKey.conduit).input.read(buffer); |
|---|
| | 174 | count = (cast(SocketConduit) selectionKey.conduit).read(buffer); |
|---|
| 175 | 175 | if (count != IConduit.Eof) |
|---|
| 176 | 176 | { |
|---|
| … | … | |
| 199 | 199 | log.trace(sprint("[{0}] Sending PONG to client", i)); |
|---|
| 200 | 200 | |
|---|
| 201 | | count = (cast(SocketConduit) selectionKey.conduit).output.write("PONG"); |
|---|
| | 201 | count = (cast(SocketConduit) selectionKey.conduit).write("PONG"); |
|---|
| 202 | 202 | if (count != IConduit.Eof) |
|---|
| 203 | 203 | { |
|---|
| … | … | |
| 334 | 334 | try |
|---|
| 335 | 335 | { |
|---|
| 336 | | count = socket.output.write("PING"); |
|---|
| | 336 | count = socket.write("PING"); |
|---|
| 337 | 337 | break; |
|---|
| 338 | 338 | } |
|---|
| … | … | |
| 355 | 355 | try |
|---|
| 356 | 356 | { |
|---|
| 357 | | count = socket.input.read(buffer); |
|---|
| | 357 | count = socket.read(buffer); |
|---|
| 358 | 358 | break; |
|---|
| 359 | 359 | } |
|---|
| r2486 |
r2490 |
|
| 16 | 16 | private import tango.core.Exception; |
|---|
| 17 | 17 | |
|---|
| 18 | | public import tango.io.model.IBuffer; |
|---|
| 19 | | |
|---|
| 20 | | public import tango.io.model.IConduit; |
|---|
| | 18 | public import tango.io.model.IBuffer, |
|---|
| | 19 | tango.io.model.IConduit; |
|---|
| 21 | 20 | |
|---|
| 22 | 21 | /****************************************************************************** |
|---|
| … | … | |
| 199 | 198 | class Buffer : IBuffer |
|---|
| 200 | 199 | { |
|---|
| 201 | | protected IConduit root; // optional conduit |
|---|
| | 200 | protected IConduit host; // optional conduit |
|---|
| 202 | 201 | protected OutputStream sink; // optional data sink |
|---|
| 203 | 202 | protected InputStream source; // optional data source |
|---|
| … | … | |
| 1002 | 1001 | ***********************************************************************/ |
|---|
| 1003 | 1002 | |
|---|
| 1004 | | void flush () |
|---|
| | 1003 | override void flush () |
|---|
| 1005 | 1004 | { |
|---|
| 1006 | 1005 | if (sink) |
|---|
| … | … | |
| 1018 | 1017 | Clear buffer content |
|---|
| 1019 | 1018 | |
|---|
| 1020 | | Returns: |
|---|
| 1021 | | the buffer instance |
|---|
| 1022 | | |
|---|
| 1023 | 1019 | Remarks: |
|---|
| 1024 | 1020 | Reset 'position' and 'limit' to zero. This effectively |
|---|
| … | … | |
| 1027 | 1023 | ***********************************************************************/ |
|---|
| 1028 | 1024 | |
|---|
| 1029 | | void clear () |
|---|
| | 1025 | override void clear () |
|---|
| 1030 | 1026 | { |
|---|
| 1031 | 1027 | index = extent = 0; |
|---|
| … | … | |
| 1034 | 1030 | if (source) |
|---|
| 1035 | 1031 | source.clear; |
|---|
| 1036 | | |
|---|
| 1037 | | return this; |
|---|
| 1038 | 1032 | } |
|---|
| 1039 | 1033 | |
|---|
| 1040 | 1034 | /*********************************************************************** |
|---|
| 1041 | 1035 | |
|---|
| 1042 | | Truncate buffer content |
|---|
| 1043 | | |
|---|
| 1044 | | Remarks: |
|---|
| 1045 | | Truncate the buffer within its extent. Returns true if |
|---|
| 1046 | | the new 'extent' is valid, false otherwise. |
|---|
| 1047 | | |
|---|
| 1048 | | ***********************************************************************/ |
|---|
| 1049 | | |
|---|
| 1050 | | bool truncate (uint extent) |
|---|
| 1051 | | { |
|---|
| 1052 | | if (extent <= data.length) |
|---|
| 1053 | | { |
|---|
| 1054 | | extent = extent; |
|---|
| 1055 | | return true; |
|---|
| 1056 | | } |
|---|
| 1057 | | return false; |
|---|
| 1058 | | } |
|---|
| | 1036 | Commit the output |
|---|
| | 1037 | |
|---|
| | 1038 | Remarks: |
|---|
| | 1039 | Propogate request to an attached OutputStream (this is a |
|---|
| | 1040 | requirment for the OutputStream interface) |
|---|
| | 1041 | |
|---|
| | 1042 | ***********************************************************************/ |
|---|
| | 1043 | |
|---|
| | 1044 | final override void commit () |
|---|
| | 1045 | { |
|---|
| | 1046 | if (sink) |
|---|
| | 1047 | sink.commit; |
|---|
| | 1048 | } |
|---|
| 1059 | 1049 | |
|---|
| 1060 | 1050 | /*********************************************************************** |
|---|
| … | … | |
| 1073 | 1063 | ***********************************************************************/ |
|---|
| 1074 | 1064 | |
|---|
| 1075 | | OutputStream copy (InputStream src) |
|---|
| | 1065 | override OutputStream copy (InputStream src) |
|---|
| 1076 | 1066 | { |
|---|
| 1077 | 1067 | assert (sink && src); |
|---|
| … | … | |
| 1086 | 1076 | /*********************************************************************** |
|---|
| 1087 | 1077 | |
|---|
| | 1078 | Truncate buffer content |
|---|
| | 1079 | |
|---|
| | 1080 | Remarks: |
|---|
| | 1081 | Truncate the buffer within its extent. Returns true if |
|---|
| | 1082 | the new length is valid, false otherwise. |
|---|
| | 1083 | |
|---|
| | 1084 | ***********************************************************************/ |
|---|
| | 1085 | |
|---|
| | 1086 | bool truncate (uint length) |
|---|
| | 1087 | { |
|---|
| | 1088 | if (length <= data.length) |
|---|
| | 1089 | { |
|---|
| | 1090 | extent = length; |
|---|
| | 1091 | return true; |
|---|
| | 1092 | } |
|---|
| | 1093 | return false; |
|---|
| | 1094 | } |
|---|
| | 1095 | |
|---|
| | 1096 | /*********************************************************************** |
|---|
| | 1097 | |
|---|
| 1088 | 1098 | Access buffer limit |
|---|
| 1089 | 1099 | |
|---|
| … | … | |
| 1160 | 1170 | ***********************************************************************/ |
|---|
| 1161 | 1171 | |
|---|
| 1162 | | IConduit conduit () |
|---|
| 1163 | | { |
|---|
| 1164 | | return root; |
|---|
| | 1172 | override IConduit conduit () |
|---|
| | 1173 | { |
|---|
| | 1174 | return host; |
|---|
| 1165 | 1175 | } |
|---|
| 1166 | 1176 | |
|---|
| … | … | |
| 1183 | 1193 | IBuffer setConduit (IConduit conduit) |
|---|
| 1184 | 1194 | { |
|---|
| 1185 | | root = conduit; |
|---|
| | 1195 | // setHost (host = conduit); |
|---|
| | 1196 | host = conduit; |
|---|
| 1186 | 1197 | sink = conduit.output; |
|---|
| 1187 | 1198 | source = conduit.input; |
|---|
| 1188 | 1199 | return this; |
|---|
| | 1200 | } |
|---|
| | 1201 | |
|---|
| | 1202 | /*********************************************************************** |
|---|
| | 1203 | |
|---|
| | 1204 | Dispose of this buffer |
|---|
| | 1205 | |
|---|
| | 1206 | Remarks: |
|---|
| | 1207 | Dispose flushes & commits itself, closes any associated |
|---|
| | 1208 | conduit, and deletes both that and the buffer instance. |
|---|
| | 1209 | |
|---|
| | 1210 | ***********************************************************************/ |
|---|
| | 1211 | |
|---|
| | 1212 | final void dispose () |
|---|
| | 1213 | { |
|---|
| | 1214 | if (sink) |
|---|
| | 1215 | { |
|---|
| | 1216 | flush; |
|---|
| | 1217 | commit; |
|---|
| | 1218 | sink.conduit.dispose (false); |
|---|
| | 1219 | } |
|---|
| | 1220 | delete this; |
|---|
| 1189 | 1221 | } |
|---|
| 1190 | 1222 | |
|---|
| r2434 |
r2490 |
|
| 37 | 37 | *******************************************************************************/ |
|---|
| 38 | 38 | |
|---|
| 39 | | class Conduit : IConduit, InputStream, OutputStream |
|---|
| | 39 | class Conduit : IConduit |
|---|
| 40 | 40 | { |
|---|
| 41 | | private InputStream input_; |
|---|
| 42 | | private OutputStream output_; |
|---|
| 43 | | private void delegate(bool) notify_; |
|---|
| | 41 | private OutputStream sink; |
|---|
| | 42 | private InputStream source; |
|---|
| 44 | 43 | |
|---|
| 45 | 44 | /*********************************************************************** |
|---|
| … | … | |
| 72 | 71 | ***********************************************************************/ |
|---|
| 73 | 72 | |
|---|
| 74 | | abstract protected uint read (void[] dst); |
|---|
| | 73 | abstract uint read (void[] dst); |
|---|
| 75 | 74 | |
|---|
| 76 | 75 | /*********************************************************************** |
|---|
| … | … | |
| 84 | 83 | ***********************************************************************/ |
|---|
| 85 | 84 | |
|---|
| 86 | | abstract protected uint write (void [] src); |
|---|
| 87 | | |
|---|
| 88 | | /*********************************************************************** |
|---|
| 89 | | |
|---|
| 90 | | default ctor assigns input and output streams to their |
|---|
| 91 | | initial value (this conduit) |
|---|
| | 85 | abstract uint write (void [] src); |
|---|
| | 86 | |
|---|
| | 87 | /*********************************************************************** |
|---|
| | 88 | |
|---|
| | 89 | Close this conduit |
|---|
| | 90 | |
|---|
| | 91 | ***********************************************************************/ |
|---|
| | 92 | |
|---|
| | 93 | abstract void close (); |
|---|
| | 94 | |
|---|
| | 95 | /*********************************************************************** |
|---|
| | 96 | |
|---|
| | 97 | Constructor to initialize the default sink & source |
|---|
| 92 | 98 | |
|---|
| 93 | 99 | ***********************************************************************/ |
|---|
| … | … | |
| 95 | 101 | this () |
|---|
| 96 | 102 | { |
|---|
| 97 | | input_ = this; |
|---|
| 98 | | output_ = this; |
|---|
| 99 | | |
|---|
| 100 | | // assign a default notification handler that does nothing |
|---|
| 101 | | notify_ = (bool){return;}; |
|---|
| 102 | | } |
|---|
| 103 | | |
|---|
| 104 | | /*********************************************************************** |
|---|
| 105 | | |
|---|
| 106 | | Return the host conduit. This is part of the Stream interface |
|---|
| | 103 | sink = this; |
|---|
| | 104 | source = this; |
|---|
| | 105 | } |
|---|
| | 106 | |
|---|
| | 107 | /*********************************************************************** |
|---|
| | 108 | |
|---|
| | 109 | Is the conduit alive? Default behaviour returns true |
|---|
| | 110 | |
|---|
| | 111 | ***********************************************************************/ |
|---|
| | 112 | |
|---|
| | 113 | bool isAlive () |
|---|
| | 114 | { |
|---|
| | 115 | return true; |
|---|
| | 116 | } |
|---|
| | 117 | |
|---|
| | 118 | /*********************************************************************** |
|---|
| | 119 | |
|---|
| | 120 | Return the host. This is part of the Stream interface |
|---|
| 107 | 121 | |
|---|
| 108 | 122 | ***********************************************************************/ |
|---|
| … | … | |
| 115 | 129 | /*********************************************************************** |
|---|
| 116 | 130 | |
|---|
| 117 | | Is the conduit alive? Default behaviour returns true |
|---|
| 118 | | |
|---|
| 119 | | ***********************************************************************/ |
|---|
| 120 | | |
|---|
| 121 | | bool isAlive () |
|---|
| 122 | | { |
|---|
| 123 | | return true; |
|---|
| 124 | | } |
|---|
| 125 | | |
|---|
| 126 | | /*********************************************************************** |
|---|
| 127 | | |
|---|
| 128 | | dump any output buffering |
|---|
| 129 | | |
|---|
| 130 | | ***********************************************************************/ |
|---|
| 131 | | |
|---|
| 132 | | void flush () |
|---|
| 133 | | { |
|---|
| 134 | | } |
|---|
| 135 | | |
|---|
| 136 | | /*********************************************************************** |
|---|
| 137 | | |
|---|
| 138 | | clear any input buffering |
|---|
| 139 | | |
|---|
| 140 | | ***********************************************************************/ |
|---|
| 141 | | |
|---|
| 142 | | void clear () |
|---|
| 143 | | { |
|---|
| 144 | | } |
|---|
| 145 | | |
|---|
| 146 | | /*********************************************************************** |
|---|
| 147 | | |
|---|
| 148 | | Close this conduit |
|---|
| 149 | | |
|---|
| 150 | | ***********************************************************************/ |
|---|
| 151 | | |
|---|
| 152 | | void close () |
|---|
| 153 | | { |
|---|
| | 131 | clear any buffered input |
|---|
| | 132 | |
|---|
| | 133 | ***********************************************************************/ |
|---|
| | 134 | |
|---|
| | 135 | void clear () {} |
|---|
| | 136 | |
|---|
| | 137 | /*********************************************************************** |
|---|
| | 138 | |
|---|
| | 139 | Write buffered output |
|---|
| | 140 | |
|---|
| | 141 | ***********************************************************************/ |
|---|
| | 142 | |
|---|
| | 143 | void flush () {} |
|---|
| | 144 | |
|---|
| | 145 | /*********************************************************************** |
|---|
| | 146 | |
|---|
| | 147 | commit the output |
|---|
| | 148 | |
|---|
| | 149 | ***********************************************************************/ |
|---|
| | 150 | |
|---|
| | 151 | final void commit () {} |
|---|
| | 152 | |
|---|
| | 153 | /*********************************************************************** |
|---|
| | 154 | |
|---|
| | 155 | Dispose of this conduit |
|---|
| | 156 | |
|---|
| | 157 | Remarks: |
|---|
| | 158 | Dispose flushes & commits any filters, closes the conduit, |
|---|
| | 159 | and deletes it. This should be used in preference to close() |
|---|
| | 160 | |
|---|
| | 161 | ***********************************************************************/ |
|---|
| | 162 | |
|---|
| | 163 | final void dispose (bool clean=true) |
|---|
| | 164 | { |
|---|
| | 165 | if (clean) |
|---|
| | 166 | { |
|---|
| | 167 | sink.flush; |
|---|
| | 168 | sink.commit; |
|---|
| | 169 | } |
|---|
| | 170 | |
|---|
| | 171 | this.close; |
|---|
| | 172 | delete this; |
|---|
| 154 | 173 | } |
|---|
| 155 | 174 | |
|---|
| … | … | |
| 158 | 177 | Return the current input stream. The initial input stream |
|---|
| 159 | 178 | is hosted by the conduit itself. Subsequent attachment of |
|---|
| 160 | | stream 'filters' will alter this value. |
|---|
| | 179 | stream filters will alter this value. |
|---|
| 161 | 180 | |
|---|
| 162 | 181 | ***********************************************************************/ |
|---|
| … | … | |
| 164 | 183 | final InputStream input () |
|---|
| 165 | 184 | { |
|---|
| 166 | | return input_; |
|---|
| | 185 | return source; |
|---|
| 167 | 186 | } |
|---|
| 168 | 187 | |
|---|
| … | … | |
| 171 | 190 | Return the current output stream. The initial output stream |
|---|
| 172 | 191 | is hosted by the conduit itself. Subsequent attachment of |
|---|
| 173 | | stream 'filters' will alter this value. |
|---|
| | 192 | stream filters will alter this value. |
|---|
| 174 | 193 | |
|---|
| 175 | 194 | ***********************************************************************/ |
|---|
| … | … | |
| 177 | 196 | final OutputStream output () |
|---|
| 178 | 197 | { |
|---|
| 179 | | return output_; |
|---|
| 180 | | } |
|---|
| 181 | | |
|---|
| 182 | | /*********************************************************************** |
|---|
| 183 | | |
|---|
| 184 | | Replace the input stream and return the prior one. The |
|---|
| 185 | | return value should be used as the 'ancestor' attribute |
|---|
| 186 | | of attached filter, to be invoked appropriately during |
|---|
| 187 | | subsequent filter activity. However, it is entirely up |
|---|
| 188 | | to the intercepting stream to decide whether to follow |
|---|
| 189 | | that recommendation or not. |
|---|
| 190 | | |
|---|
| 191 | | ***********************************************************************/ |
|---|
| 192 | | |
|---|
| 193 | | final InputStream attach (InputStream filter) |
|---|
| 194 | | { |
|---|
| 195 | | auto tmp = input_; |
|---|
| 196 | | input_ = filter; |
|---|
| 197 | | notify_ (true); |
|---|
| 198 | | return tmp; |
|---|
| 199 | | } |
|---|
| 200 | | |
|---|
| 201 | | /*********************************************************************** |
|---|
| 202 | | |
|---|
| 203 | | Replace the output stream and return the prior one. The |
|---|
| 204 | | return value should be used as the 'ancestor' attribute |
|---|
| 205 | | of attached filter, to be invoked appropriately during |
|---|
| 206 | | subsequent filter activity. However, it is entirely up |
|---|
| 207 | | to the intercepting stream to decide whether to follow |
|---|
| 208 | | that recommendation or not. |
|---|
| 209 | | |
|---|
| 210 | | ***********************************************************************/ |
|---|
| 211 | | |
|---|
| 212 | | final OutputStream attach (OutputStream filter) |
|---|
| 213 | | { |
|---|
| 214 | | auto tmp = output_; |
|---|
| 215 | | output_ = filter; |
|---|
| 216 | | notify_ (false); |
|---|
| 217 | | return tmp; |
|---|
| 218 | | } |
|---|
| 219 | | |
|---|
| 220 | | /*********************************************************************** |
|---|
| 221 | | |
|---|
| 222 | | Attach a notification handler, to be invoked when a filter |
|---|
| 223 | | is added to the conduit. This is used in some very specific |
|---|
| 224 | | cases, and should never need to support multiple clients. |
|---|
| 225 | | |
|---|
| 226 | | ***********************************************************************/ |
|---|
| 227 | | |
|---|
| 228 | | final void notify (void delegate(bool) dg) |
|---|
| 229 | | { |
|---|
| 230 | | notify_ = dg; |
|---|
| 231 | | } |
|---|
| 232 | | |
|---|
| | 198 | return sink; |
|---|
| | 199 | } |
|---|
| | 200 | |
|---|
| | 201 | /*********************************************************************** |
|---|
| | 202 | |
|---|
| | 203 | Attach an input filter |
|---|
| | 204 | |
|---|
| | 205 | ***********************************************************************/ |
|---|
| | 206 | |
|---|
| | 207 | final IConduit attach (InputStream source) |
|---|
| | 208 | { |
|---|
| | 209 | this.source = source; |
|---|
| | 210 | return this; |
|---|
| | 211 | } |
|---|
| | 212 | |
|---|
| | 213 | /*********************************************************************** |
|---|
| | 214 | |
|---|
| | 215 | Attach an output filter |
|---|
| | 216 | |
|---|
| | 217 | ***********************************************************************/ |
|---|
| | 218 | |
|---|
| | 219 | final IConduit attach (OutputStream sink) |
|---|
| | 220 | { |
|---|
| | 221 | this.sink = sink; |
|---|
| | 222 | return this; |
|---|
| | 223 | } |
|---|
| | 224 | |
|---|
| 233 | 225 | /*********************************************************************** |
|---|
| 234 | 226 | |
|---|
| … | … | |
| 287 | 279 | class InputFilter : InputStream |
|---|
| 288 | 280 | { |
|---|
| 289 | | protected InputStream next; |
|---|
| | 281 | protected InputStream host; |
|---|
| 290 | 282 | |
|---|
| 291 | 283 | /*********************************************************************** |
|---|
| … | … | |
| 299 | 291 | ***********************************************************************/ |
|---|
| 300 | 292 | |
|---|
| 301 | | this (InputStream stream) |
|---|
| 302 | | { |
|---|
| 303 | | next = stream.conduit.attach (this); |
|---|
| | 293 | this (InputStream host) |
|---|
| | 294 | { |
|---|
| | 295 | this.host = host; |
|---|
| | 296 | host.conduit.attach (this); |
|---|
| 304 | 297 | } |
|---|
| 305 | 298 | |
|---|
| … | … | |
| 310 | 303 | IConduit conduit () |
|---|
| 311 | 304 | { |
|---|
| 312 | | return next.conduit; |
|---|
| | 305 | return host.conduit; |
|---|
| 313 | 306 | } |
|---|
| 314 | 307 | |
|---|
| … | … | |
| 319 | 312 | void clear () |
|---|
| 320 | 313 | { |
|---|
| 321 | | next.clear; |
|---|
| | 314 | host.clear; |
|---|
| 322 | 315 | } |
|---|
| 323 | 316 | } |
|---|
| … | … | |
| 330 | 323 | class OutputFilter : OutputStream |
|---|
| 331 | 324 | { |
|---|
| 332 | | protected OutputStream next; |
|---|
| | 325 | protected OutputStream host; |
|---|
| 333 | 326 | |
|---|
| 334 | 327 | /*********************************************************************** |
|---|
| … | … | |
| 342 | 335 | ***********************************************************************/ |
|---|
| 343 | 336 | |
|---|
| 344 | | this (OutputStream stream) |
|---|
| 345 | | { |
|---|
| 346 | | next = stream.conduit.attach (this); |
|---|
| | 337 | this (OutputStream host) |
|---|
| | 338 | { |
|---|
| | 339 | this.host = host; |
|---|
| | 340 | host.conduit.attach (this); |
|---|
| 347 | 341 | } |
|---|
| 348 | 342 | |
|---|
| … | … | |
| 353 | 347 | IConduit conduit () |
|---|
| 354 | 348 | { |
|---|
| 355 | | return next.conduit; |
|---|
| | 349 | return host.conduit; |
|---|
| 356 | 350 | } |
|---|
| 357 | 351 | |
|---|
| … | … | |
| 362 | 356 | void flush () |
|---|
| 363 | 357 | { |
|---|
| 364 | | next.flush; |
|---|
| | 358 | host.flush; |
|---|
| | 359 | } |
|---|
| | 360 | |
|---|
| | 361 | /*********************************************************************** |
|---|
| | 362 | |
|---|
| | 363 | ***********************************************************************/ |
|---|
| | 364 | |
|---|
| | 365 | void commit () |
|---|
| | 366 | { |
|---|
| | 367 | host.commit; |
|---|
| 365 | 368 | } |
|---|
| 366 | 369 | |
|---|
| r2474 |
r2490 |
|
| 68 | 68 | **************************************************************/ |
|---|
| 69 | 69 | |
|---|
| 70 | | private this (Conduit conduit, bool redirect) |
|---|
| 71 | | { |
|---|
| 72 | | this.redirect = redirected; |
|---|
| 73 | | this.buffer = new Buffer (conduit); |
|---|
| 74 | | } |
|---|
| 75 | | |
|---|
| 76 | | /************************************************************** |
|---|
| 77 | | |
|---|
| 78 | | Return the associated conduit |
|---|
| | 70 | private this (Conduit conduit, bool redirected) |
|---|
| | 71 | { |
|---|
| | 72 | redirect = redirected; |
|---|
| | 73 | buffer = new Buffer (conduit); |
|---|
| | 74 | } |
|---|
| | 75 | |
|---|
| | 76 | /************************************************************** |
|---|
| | 77 | |
|---|
| | 78 | Return the associated stream |
|---|
| 79 | 79 | |
|---|
| 80 | 80 | **************************************************************/ |
|---|
| … | … | |
| 157 | 157 | return redirect; |
|---|
| 158 | 158 | } |
|---|
| | 159 | |
|---|
| | 160 | /************************************************************** |
|---|
| | 161 | |
|---|
| | 162 | Divert input to an alternate device |
|---|
| | 163 | |
|---|
| | 164 | Remarks: |
|---|
| | 165 | Diverts input to the specified conduit, and sets |
|---|
| | 166 | the redirection status. |
|---|
| | 167 | |
|---|
| | 168 | **************************************************************/ |
|---|
| | 169 | |
|---|
| | 170 | final void divert (IConduit conduit, bool redirected) |
|---|
| | 171 | { |
|---|
| | 172 | buffer.setConduit (conduit); |
|---|
| | 173 | redirect = redirected; |
|---|
| | 174 | } |
|---|
| 159 | 175 | } |
|---|
| 160 | 176 | |
|---|
| … | … | |
| 162 | 178 | /********************************************************************** |
|---|
| 163 | 179 | |
|---|
| 164 | | Model console output as a buffer. Note that we accept |
|---|
| 165 | | utf8 only: the superclass append() methods are hidden |
|---|
| 166 | | from view. Buffer.consume is left open, for those who |
|---|
| 167 | | require lower-level access ~ along with Buffer.write |
|---|
| | 180 | Console output accepts utf8 only, by default |
|---|
| 168 | 181 | |
|---|
| 169 | 182 | **********************************************************************/ |
|---|
| … | … | |
| 183 | 196 | **************************************************************/ |
|---|
| 184 | 197 | |
|---|
| 185 | | private this (Conduit conduit, bool redirect) |
|---|
| 186 | | { |
|---|
| 187 | | // get conduit to notify us of attachments so |
|---|
| 188 | | // that we can adjust our buffer accordingly |
|---|
| 189 | | conduit.notify (¬ify); |
|---|
| 190 | | |
|---|
| 191 | | this.redirect = redirected; |
|---|
| 192 | | this.buffer = new Buffer (conduit); |
|---|
| 193 | | } |
|---|
| 194 | | |
|---|
| 195 | | /************************************************************** |
|---|
| 196 | | |
|---|
| 197 | | Return the associated conduit |
|---|
| | 198 | private this (Conduit conduit, bool redirected) |
|---|
| | 199 | { |
|---|
| | 200 | redirect = redirected; |
|---|
| | 201 | buffer = new Buffer (conduit); |
|---|
| | 202 | } |
|---|
| | 203 | |
|---|
| | 204 | /************************************************************** |
|---|
| | 205 | |
|---|
| | 206 | Return the associated stream |
|---|
| 198 | 207 | |
|---|
| 199 | 208 | **************************************************************/ |
|---|
| … | … | |
| 235 | 244 | **************************************************************/ |
|---|
| 236 | 245 | |
|---|
| 237 | | final Output append (Object o) |
|---|
| | 246 | final Output append (Object other) |
|---|
| 238 | 247 | { |
|---|
| 239 | | return append (o.toUtf8); |
|---|
| | 248 | return append (other.toUtf8); |
|---|
| 240 | 249 | } |
|---|
| 241 | 250 | |
|---|
| … | … | |
| 294 | 303 | |
|---|
| 295 | 304 | Remarks: |
|---|
| 296 | | Reflects the console redirection status from when |
|---|
| 297 | | this module was instantiated |
|---|
| | 305 | Reflects the console redirection status |
|---|
| 298 | 306 | |
|---|
| 299 | 307 | **************************************************************/ |
|---|
| … | … | |
| 306 | 314 | /************************************************************** |
|---|
| 307 | 315 | |
|---|
| 308 | | Invoked when an attachment is made to the console |
|---|
| 309 | | Conduit. We use this to point our buffer at the |
|---|
| 310 | | filter being attached. Without this, said filter |
|---|
| 311 | | would be ignored since Buffer operates in a mode |
|---|
| 312 | | termed 'snapshot' i.e. it doesn't look for changes |
|---|
| 313 | | in the conduit after being connected to it (which |
|---|
| 314 | | is both correct and required behaviour). |
|---|
| 315 | | |
|---|
| 316 | | An alternative would be to simply insert a buffered |
|---|
| 317 | | filter. However, Cin requires readln() support and |
|---|
| 318 | | therefore needs to directly address a buffer rather |
|---|
| 319 | | than an InputStream. |
|---|
| 320 | | |
|---|
| 321 | | **************************************************************/ |
|---|
| 322 | | |
|---|
| 323 | | private void notify (bool) |
|---|
| 324 | | { |
|---|
| 325 | | buffer.setConduit (buffer.conduit); |
|---|
| 326 | | } |
|---|
| | 316 | Divert output to an alternate device |
|---|
| | 317 | |
|---|
| | 318 | Remarks: |
|---|
| | 319 | Diverts output to the specified conduit, and sets |
|---|
| | 320 | the redirection status. The latter dictates whether |
|---|
| | 321 | newline() performs automatic flushing or not |
|---|
| | 322 | |
|---|
| | 323 | **************************************************************/ |
|---|
| | 324 | |
|---|
| | 325 | final void divert (IConduit conduit, bool redirected) |
|---|
| | 326 | { |
|---|
| | 327 | buffer.setConduit (conduit); |
|---|
| | 328 | redirect = redirected; |
|---|
| | 329 | } |
|---|
| 327 | 330 | } |
|---|
| 328 | 331 | |
|---|
| r2322 |
r2490 |
|
| 31 | 31 | /*********************************************************************** |
|---|
| 32 | 32 | |
|---|
| 33 | | Callback to close the file. This is invoked from the Resource |
|---|
| 34 | | base-class when the resource is being closed. |
|---|
| 35 | | |
|---|
| 36 | | ***********************************************************************/ |
|---|
| 37 | | |
|---|
| 38 | | override void close () |
|---|
| 39 | | { |
|---|
| 40 | | super.close (); |
|---|
| 41 | | _close (); |
|---|
| 42 | | } |
|---|
| 43 | | |
|---|
| 44 | | /*********************************************************************** |
|---|
| 45 | | |
|---|
| 46 | | Return a preferred size for buffering conduit I/O |
|---|
| 47 | | |
|---|
| 48 | | ***********************************************************************/ |
|---|
| 49 | | |
|---|
| 50 | | uint bufferSize () |
|---|
| 51 | | { |
|---|
| 52 | | return 1024 * 16; |
|---|
| 53 | | } |
|---|
| 54 | | |
|---|
| 55 | | /*********************************************************************** |
|---|
| 56 | | |
|---|
| 57 | | Return the name of this device |
|---|
| 58 | | |
|---|
| 59 | | ***********************************************************************/ |
|---|
| 60 | | |
|---|
| 61 | | protected char[] toUtf8() |
|---|
| 62 | | { |
|---|
| 63 | | return "<device>"; |
|---|
| 64 | | } |
|---|
| 65 | | |
|---|
| 66 | | /*********************************************************************** |
|---|
| 67 | | |
|---|
| 68 | 33 | Throw an IOException noting the last error |
|---|
| 69 | 34 | |
|---|
| … | … | |
| 77 | 42 | /*********************************************************************** |
|---|
| 78 | 43 | |
|---|
| | 44 | Return the name of this device |
|---|
| | 45 | |
|---|
| | 46 | ***********************************************************************/ |
|---|
| | 47 | |
|---|
| | 48 | override char[] toUtf8() |
|---|
| | 49 | { |
|---|
| | 50 | return "<device>"; |
|---|
| | 51 | } |
|---|
| | 52 | |
|---|
| | 53 | /*********************************************************************** |
|---|
| | 54 | |
|---|
| | 55 | Return a preferred size for buffering conduit I/O |
|---|
| | 56 | |
|---|
| | 57 | ***********************************************************************/ |
|---|
| | 58 | |
|---|
| | 59 | override uint bufferSize () |
|---|
| | 60 | { |
|---|
| | 61 | return 1024 * 16; |
|---|
| | 62 | } |
|---|
| | 63 | |
|---|
| | 64 | /*********************************************************************** |
|---|
| | 65 | |
|---|
| 79 | 66 | Windows-specific code |
|---|
| 80 | 67 | |
|---|
| … | … | |
| 87 | 74 | /*************************************************************** |
|---|
| 88 | 75 | |
|---|
| | 76 | Gain access to the standard IO handles (console etc). |
|---|
| | 77 | |
|---|
| | 78 | ***************************************************************/ |
|---|
| | 79 | |
|---|
| | 80 | protected void reopen (Handle handle) |
|---|
| | 81 | { |
|---|
| | 82 | this.handle = cast(HANDLE) handle; |
|---|
| | 83 | } |
|---|
| | 84 | |
|---|
| | 85 | /*************************************************************** |
|---|
| | 86 | |
|---|
| 89 | 87 | Return the underlying OS handle of this Conduit |
|---|
| 90 | 88 | |
|---|
| 91 | 89 | ***************************************************************/ |
|---|
| 92 | 90 | |
|---|
| 93 | | final Handle fileHandle () |
|---|
| | 91 | final override Handle fileHandle () |
|---|
| 94 | 92 | { |
|---|
| 95 | 93 | return cast(Handle) handle; |
|---|
| … | … | |
| 98 | 96 | /*************************************************************** |
|---|
| 99 | 97 | |
|---|
| 100 | | Gain access to the standard IO handles (console etc). |
|---|
| 101 | | |
|---|
| 102 | | ***************************************************************/ |
|---|
| 103 | | |
|---|
| 104 | | protected void reopen (Handle handle) |
|---|
| 105 | | { |
|---|
| 106 | | this.handle = cast(HANDLE) handle; |
|---|
| 107 | | } |
|---|
| 108 | | |
|---|
| 109 | | /*************************************************************** |
|---|
| 110 | | |
|---|
| 111 | 98 | Close the underlying file |
|---|
| 112 | 99 | |
|---|
| 113 | 100 | ***************************************************************/ |
|---|
| 114 | 101 | |
|---|
| 115 | | protected void _close () |
|---|
| | 102 | override void close () |
|---|
| 116 | 103 | { |
|---|
| 117 | 104 | if (handle) |
|---|
| … | … | |
| 125 | 112 | ***************************************************************/ |
|---|
| 126 | 113 | |
|---|
| 127 | | protected override void flush () |
|---|
| | 114 | override void flush () |
|---|
| 128 | 115 | { |
|---|
| 129 | 116 | if (! FlushFileBuffers (handle)) |
|---|
| 130 | 117 | error (); |
|---|
| | 118 | return this; |
|---|
| 131 | 119 | } |
|---|
| 132 | 120 | |
|---|
| … | … | |
| 141 | 129 | ***************************************************************/ |
|---|
| 142 | 130 | |
|---|
| 143 | | protected override uint read (void[] dst) |
|---|
| | 131 | override uint read (void[] dst) |
|---|
| 144 | 132 | { |
|---|
| 145 | 133 | DWORD read; |
|---|
| … | … | |
| 165 | 153 | ***************************************************************/ |
|---|
| 166 | 154 | |
|---|
| 167 | | protected override uint write (void[] src) |
|---|
| | 155 | override uint write (void[] src) |
|---|
| 168 | 156 | { |
|---|
| 169 | 157 | DWORD written; |
|---|
| … | … | |
| 189 | 177 | /*************************************************************** |
|---|
| 190 | 178 | |
|---|
| | 179 | Gain access to the standard IO handles (console etc). |
|---|
| | 180 | |
|---|
| | 181 | ***************************************************************/ |
|---|
|