comparison tango/tango/io/stream/EndianStream.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2007 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Initial release: Nov 2007
8
9 author: Kris
10
11 Streams for swapping endian-order. The stream is treated as a set
12 of same-sized elements. Note that partial elements are not mutated
13
14 *******************************************************************************/
15
16 module tango.io.stream.EndianStream;
17
18 private import tango.io.Buffer,
19 tango.io.Conduit;
20
21 private import tango.core.ByteSwap;
22
23 /*******************************************************************************
24
25 Type T is the element type
26
27 *******************************************************************************/
28
29 class EndianInput(T) : InputFilter
30 {
31 static if ((T.sizeof != 2) && (T.sizeof != 4) && (T.sizeof != 8))
32 pragma (msg, "EndianInput :: type should be of length 2, 4, or 8 bytes");
33
34
35 private IBuffer input;
36
37 /***********************************************************************
38
39 ***********************************************************************/
40
41 this (InputStream stream)
42 {
43 super (input = Buffer.share (stream));
44 }
45
46 /***********************************************************************
47
48 Buffered interface
49
50 ***********************************************************************/
51
52 final IBuffer buffer ()
53 {
54 return input;
55 }
56
57 /***********************************************************************
58
59 Read from conduit into a target array. The provided dst
60 will be populated with content from the conduit.
61
62 Returns the number of bytes read, which may be less than
63 requested in dst (or IOStream.Eof for end-of-flow). Note
64 that a trailing partial element will be placed into dst,
65 but the returned length will effectively ignore it
66
67 ***********************************************************************/
68
69 final override uint read (void[] dst)
70 {
71 uint len = input.fill (dst[0 .. dst.length & ~(T.sizeof-1)]);
72 if (len != Eof)
73 {
74 // the final read may be misaligned ...
75 len &= ~(T.sizeof - 1);
76
77 static if (T.sizeof == 2)
78 ByteSwap.swap16 (dst.ptr, len);
79
80 static if (T.sizeof == 4)
81 ByteSwap.swap32 (dst.ptr, len);
82
83 static if (T.sizeof == 8)
84 ByteSwap.swap64 (dst.ptr, len);
85 }
86 return len;
87 }
88 }
89
90
91
92 /*******************************************************************************
93
94 Type T is the element type
95
96 *******************************************************************************/
97
98 class EndianOutput (T) : OutputFilter
99 {
100 static if ((T.sizeof != 2) && (T.sizeof != 4) && (T.sizeof != 8))
101 pragma (msg, "EndianOutput :: type should be of length 2, 4, or 8 bytes");
102
103 private IBuffer output;
104
105 /***********************************************************************
106
107 ***********************************************************************/
108
109 this (OutputStream stream)
110 {
111 super (output = Buffer.share (stream));
112 }
113
114 /***********************************************************************
115
116 Write to output stream from a source array. The provided
117 src content will be consumed and left intact.
118
119 Returns the number of bytes written from src, which may
120 be less than the quantity provided. Note that any partial
121 elements will not be consumed
122
123 ***********************************************************************/
124
125 final override uint write (void[] src)
126 {
127 uint writer (void[] dst)
128 {
129 auto len = dst.length;
130 if (len > src.length)
131 len = src.length;
132
133 len &= ~(T.sizeof - 1);
134 dst [0..len] = src [0..len];
135
136 static if (T.sizeof == 2)
137 ByteSwap.swap16 (dst.ptr, len);
138
139 static if (T.sizeof == 4)
140 ByteSwap.swap32 (dst.ptr, len);
141
142 static if (T.sizeof == 8)
143 ByteSwap.swap64 (dst.ptr, len);
144
145 return len;
146 }
147
148 uint bytes = src.length;
149
150 // flush if we used all buffer space
151 if ((bytes -= output.write (&writer)) >= T.sizeof)
152 if (output.output)
153 output.drain (output.output);
154 else
155 return Eof;
156 return src.length - bytes;
157 }
158 }
159
160
161 /*******************************************************************************
162
163 *******************************************************************************/
164
165 debug (UnitTest)
166 {
167 import tango.io.Stdout;
168
169 unittest
170 {
171 auto inp = new EndianInput!(dchar)(new Buffer("hello world"d));
172 auto oot = new EndianOutput!(dchar)(new Buffer(64));
173 oot.copy (inp);
174 assert (oot.output.slice == "hello world"d);
175 }
176 }