source: OniSplit/Xml/RawXmlExporter.cs

Last change on this file 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: 6.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Xml;
4using Oni.Imaging;
5using Oni.Metadata;
6
7namespace Oni.Xml
8{
9 internal class RawXmlExporter : IMetaTypeVisitor
10 {
11 private readonly BinaryReader reader;
12 private readonly XmlWriter xml;
13 private Stack<int> startOffsetStack;
14
15 public RawXmlExporter(BinaryReader reader, XmlWriter xml)
16 {
17 this.reader = reader;
18 this.xml = xml;
19
20 BeginStruct(reader.Position);
21 }
22
23 protected BinaryReader Reader => reader;
24
25 protected XmlWriter Xml => xml;
26
27 protected void BeginStruct(int startOffset)
28 {
29 startOffsetStack = new Stack<int>();
30 startOffsetStack.Push(startOffset);
31 }
32
33 #region IMetaTypeVisitor Members
34
35 void IMetaTypeVisitor.VisitEnum(MetaEnum type)
36 {
37 type.BinaryToXml(reader, xml);
38 }
39
40 void IMetaTypeVisitor.VisitByte(MetaByte type)
41 {
42 xml.WriteValue(reader.ReadByte());
43 }
44
45 void IMetaTypeVisitor.VisitInt16(MetaInt16 type)
46 {
47 xml.WriteValue(reader.ReadInt16());
48 }
49
50 void IMetaTypeVisitor.VisitUInt16(MetaUInt16 type)
51 {
52 xml.WriteValue(reader.ReadUInt16());
53 }
54
55 void IMetaTypeVisitor.VisitInt32(MetaInt32 type)
56 {
57 xml.WriteValue(reader.ReadInt32());
58 }
59
60 void IMetaTypeVisitor.VisitUInt32(MetaUInt32 type)
61 {
62 xml.WriteValue(reader.ReadUInt32());
63 }
64
65 void IMetaTypeVisitor.VisitInt64(MetaInt64 type)
66 {
67 xml.WriteValue(reader.ReadInt64());
68 }
69
70 void IMetaTypeVisitor.VisitUInt64(MetaUInt64 type)
71 {
72 xml.WriteValue(XmlConvert.ToString(reader.ReadUInt64()));
73 }
74
75 void IMetaTypeVisitor.VisitFloat(MetaFloat type)
76 {
77 xml.WriteValue(reader.ReadSingle());
78 }
79
80 void IMetaTypeVisitor.VisitVector2(MetaVector2 type)
81 {
82 xml.WriteFloatArray(reader.ReadSingleArray(2));
83 }
84
85 void IMetaTypeVisitor.VisitVector3(MetaVector3 type)
86 {
87 xml.WriteFloatArray(reader.ReadSingleArray(3));
88 }
89
90 void IMetaTypeVisitor.VisitMatrix4x3(MetaMatrix4x3 type)
91 {
92 xml.WriteFloatArray(reader.ReadSingleArray(12));
93 }
94
95 void IMetaTypeVisitor.VisitPlane(MetaPlane type)
96 {
97 xml.WriteFloatArray(reader.ReadSingleArray(4));
98 }
99
100 void IMetaTypeVisitor.VisitQuaternion(MetaQuaternion type)
101 {
102 xml.WriteFloatArray(reader.ReadSingleArray(4));
103 }
104
105 void IMetaTypeVisitor.VisitBoundingSphere(MetaBoundingSphere type)
106 {
107 WriteFields(type.Fields);
108 }
109
110 void IMetaTypeVisitor.VisitBoundingBox(MetaBoundingBox type)
111 {
112 WriteFields(type.Fields);
113 }
114
115 void IMetaTypeVisitor.VisitColor(MetaColor type)
116 {
117 Color color = reader.ReadColor();
118
119 if (color.A == 255)
120 xml.WriteValue(string.Format("{0} {1} {2}", color.R, color.G, color.B));
121 else
122 xml.WriteValue(string.Format("{0} {1} {2} {3}", color.R, color.G, color.B, color.A));
123 }
124
125 void IMetaTypeVisitor.VisitRawOffset(MetaRawOffset type)
126 {
127 xml.WriteValue(reader.ReadInt32());
128 }
129
130 void IMetaTypeVisitor.VisitSepOffset(MetaSepOffset type)
131 {
132 xml.WriteValue(reader.ReadInt32());
133 }
134
135 void IMetaTypeVisitor.VisitPointer(MetaPointer type)
136 {
137 VisitLink(type);
138 }
139
140 void IMetaTypeVisitor.VisitString(MetaString type)
141 {
142 string s = reader.ReadString(type.Count);
143 s = CleanupInvalidCharacters(s);
144 xml.WriteValue(s);
145 }
146
147 void IMetaTypeVisitor.VisitPadding(MetaPadding type)
148 {
149 reader.Position += type.Count;
150 }
151
152 void IMetaTypeVisitor.VisitStruct(MetaStruct type)
153 {
154 WriteFields(type.Fields);
155 }
156
157 void IMetaTypeVisitor.VisitArray(MetaArray type)
158 {
159 WriteArray(type.ElementType, type.Count);
160 }
161
162 void IMetaTypeVisitor.VisitVarArray(MetaVarArray type)
163 {
164 int count;
165
166 if (type.CountField.Type == MetaType.Int16)
167 count = reader.ReadInt16();
168 else
169 count = reader.ReadInt32();
170
171 WriteArray(type.ElementType, count);
172 }
173
174 #endregion
175
176 protected virtual void VisitLink(MetaPointer link)
177 {
178 throw new NotSupportedException();
179 }
180
181 private void WriteFields(IEnumerable<Field> fields)
182 {
183 foreach (Field field in fields)
184 {
185 if (field.Type is MetaPadding)
186 {
187 field.Type.Accept(this);
188 continue;
189 }
190
191 string name = field.Name;
192
193 if (string.IsNullOrEmpty(name))
194 {
195 int fieldOffset = reader.Position - startOffsetStack.Peek();
196 name = string.Format("Offset_{0:X4}", fieldOffset);
197 }
198
199 xml.WriteStartElement(name);
200 field.Type.Accept(this);
201 xml.WriteEndElement();
202 }
203 }
204
205 private void WriteArray(MetaType elementType, int count)
206 {
207 bool simpleArray = elementType.IsBlittable;
208 simpleArray = false;
209
210 for (int i = 0; i < count; i++)
211 {
212 startOffsetStack.Push(reader.Position);
213
214 if (!simpleArray)
215 xml.WriteStartElement(elementType.Name);
216
217 elementType.Accept(this);
218
219 if (!simpleArray)
220 xml.WriteEndElement();
221 else if (i != count - 1)
222 xml.WriteWhitespace(" \n");
223
224 startOffsetStack.Pop();
225 }
226 }
227
228 private static string CleanupInvalidCharacters(string s)
229 {
230 char[] c = null;
231
232 for (int i = 0; i < s.Length; i++)
233 {
234 if (s[i] >= ' ')
235 continue;
236
237 switch (s[i])
238 {
239 case '\t':
240 case '\n':
241 case '\r':
242 continue;
243 }
244
245 if (c == null)
246 c = s.ToCharArray();
247
248 c[i] = ' ';
249 }
250
251 if (c == null)
252 return s;
253
254 return new string(c);
255 }
256 }
257}
Note: See TracBrowser for help on using the repository browser.