source: OniSplit/BinaryWriter.cs@ 1170

Last change on this file since 1170 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 7.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.IO;
5using System.Text;
6using Oni.Imaging;
7
8namespace Oni
9{
10 internal class BinaryWriter : System.IO.BinaryWriter
11 {
12 private static readonly byte[] padding = new byte[32];
13 private static readonly Encoding encoding = Encoding.UTF8;
14 private readonly Stack<int> positionStack = new Stack<int>();
15
16 public BinaryWriter(Stream stream)
17 : base(stream, encoding)
18 {
19 }
20
21 public void WriteInstanceId(int index)
22 {
23 Write(InstanceFileWriter.MakeInstanceId(index));
24 }
25
26 public void Write(IEnumerable<ImporterDescriptor> descriptors)
27 {
28 foreach (var descriptor in descriptors)
29 Write(descriptor);
30 }
31
32 public void Write(ImporterDescriptor descriptor)
33 {
34 if (descriptor == null)
35 Write(0);
36 else
37 Write(InstanceFileWriter.MakeInstanceId(descriptor.Index));
38 }
39
40 public void Write(Color c)
41 {
42 Write(c.ToBgra32());
43 }
44
45 public void Write(Vector2 v)
46 {
47 Write(v.X);
48 Write(v.Y);
49 }
50
51 public void Write(Vector3 v)
52 {
53 Write(v.X);
54 Write(v.Y);
55 Write(v.Z);
56 }
57
58 public void Write(Vector4 v)
59 {
60 Write(v.X);
61 Write(v.Y);
62 Write(v.Z);
63 Write(v.W);
64 }
65
66 public void Write(Quaternion q)
67 {
68 Write(q.X);
69 Write(q.Y);
70 Write(q.Z);
71 Write(-q.W);
72 }
73
74 public void Write(Plane p)
75 {
76 Write(p.Normal);
77 Write(p.D);
78 }
79
80 public void Write(BoundingBox bbox)
81 {
82 Write(bbox.Min);
83 Write(bbox.Max);
84 }
85
86 public void Write(BoundingSphere bsphere)
87 {
88 Write(bsphere.Center);
89 Write(bsphere.Radius);
90 }
91
92 public void WriteMatrix4x3(Matrix m)
93 {
94 Write(m.M11);
95 Write(m.M12);
96 Write(m.M13);
97 Write(m.M21);
98 Write(m.M22);
99 Write(m.M23);
100 Write(m.M31);
101 Write(m.M32);
102 Write(m.M33);
103 Write(m.M41);
104 Write(m.M42);
105 Write(m.M43);
106 }
107
108 public void Write(short[] a)
109 {
110 foreach (short v in a)
111 Write(v);
112 }
113
114 public void Write(ushort[] a)
115 {
116 foreach (ushort v in a)
117 Write(v);
118 }
119
120 public void Write(int[] a)
121 {
122 foreach (int v in a)
123 Write(v);
124 }
125
126 public void Write(int[] v, int startIndex, int length)
127 {
128 for (int i = startIndex; i < startIndex + length; i++)
129 Write(v[i]);
130 }
131
132 public void Write(IEnumerable<float> a)
133 {
134 foreach (float v in a)
135 Write(v);
136 }
137
138 public void Write(IEnumerable<int> a)
139 {
140 foreach (int i in a)
141 Write(i);
142 }
143
144 public void Write(Color[] a)
145 {
146 foreach (Color v in a)
147 Write(v);
148 }
149
150 public void Write(IEnumerable<Vector2> a)
151 {
152 foreach (Vector2 v in a)
153 Write(v);
154 }
155
156 public void Write(IEnumerable<Vector3> a)
157 {
158 foreach (Vector3 v in a)
159 Write(v);
160 }
161
162 public void Write(IEnumerable<Plane> a)
163 {
164 foreach (Plane v in a)
165 Write(v);
166 }
167
168 public void Write(string s, int maxLength)
169 {
170 if (s == null)
171 {
172 Skip(maxLength);
173 return;
174 }
175
176 if (encoding.GetByteCount(s) > maxLength)
177 throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "The string '{0}' is too long (max length is {1})", s, maxLength));
178
179 byte[] data = new byte[maxLength];
180 encoding.GetBytes(s, 0, s.Length, data, 0);
181 Write(data);
182 }
183
184 public void WriteByte(int value)
185 {
186 if (value < byte.MinValue || byte.MaxValue < value)
187 throw new ArgumentOutOfRangeException("Value too large for Byte", "value");
188
189 Write((byte)value);
190 }
191
192 public void WriteInt16(int value)
193 {
194 if (value < short.MinValue || short.MaxValue < value)
195 throw new ArgumentOutOfRangeException("Value too large for Int16", "value");
196
197 Write((short)value);
198 }
199
200 public void WriteUInt16(int value)
201 {
202 if (value < 0 || value > UInt16.MaxValue)
203 throw new ArgumentOutOfRangeException("Value too large for UInt16", "value");
204
205 Write((ushort)value);
206 }
207
208 public void Write(byte value, int count)
209 {
210 if (value == 0 && Position == OutStream.Length)
211 {
212 Seek(count, SeekOrigin.Current);
213 }
214 else
215 {
216 for (int i = 0; i < count; i++)
217 Write(value);
218 }
219 }
220
221 public void Skip(int length)
222 {
223 Position += length;
224 }
225
226 public override Stream BaseStream
227 {
228 get
229 {
230 //
231 // Note: return base OutStream directly instead of BaseStream to avoid
232 // flushing the stream.
233 //
234
235 return base.OutStream;
236 }
237 }
238
239 public void PushPosition(int newPosition)
240 {
241 positionStack.Push(Position);
242 Position = newPosition;
243 }
244
245 public void PopPosition()
246 {
247 Position = positionStack.Pop();
248 }
249
250 public int Position
251 {
252 get
253 {
254 return (int)BaseStream.Position;
255 }
256 set
257 {
258 int currentPosition = (int)OutStream.Position;
259 int delta = value - currentPosition;
260
261 if (delta == 0)
262 return;
263
264 //
265 // Prevent changing the output stream position for small changes of position.
266 // This avoids flushing the write cache of the stream which results in poor perf.
267 //
268
269 if (0 < delta && delta <= 32 && Position == OutStream.Length)
270 OutStream.Write(padding, 0, delta);
271 else
272 OutStream.Position = value;
273 }
274 }
275
276 public void WriteAt(int position, int value)
277 {
278 PushPosition(position);
279 Write(value);
280 PopPosition();
281 }
282
283 public void WriteAt(int position, short value)
284 {
285 PushPosition(position);
286 Write(value);
287 PopPosition();
288 }
289
290 public int Align32()
291 {
292 int position = Utils.Align32(Position);
293 Position = position;
294 return position;
295 }
296 }
297}
Note: See TracBrowser for help on using the repository browser.