comparison Pml/RW/PmlAmfRW.cs @ 0:3ab940a0c7a0

Initial commit
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 11 Sep 2012 16:28:53 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3ab940a0c7a0
1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Collections.Generic;
5 using UCIS.Pml;
6
7 namespace UCIS.Pml {
8 internal enum AmfDataType : byte {
9 Number = 0,
10 Boolean = 1,
11 String = 2,
12 UntypedObject = 3,
13 MovieClip = 4,
14 Null = 5,
15 Undefined = 6,
16 ReferencedObject = 7,
17 MixedArray = 8,
18 End = 9,
19 Array = 10,
20 Date = 11,
21 LongString = 12,
22 TypeAsObject = 13,
23 Recordset = 14,
24 Xml = 15,
25 TypedObject = 16
26 }
27 public class PmlAmfWriter : IPmlWriter {
28 private BinaryWriter pWriter;
29
30 public PmlAmfWriter(BinaryWriter Writer) {
31 pWriter = Writer;
32 }
33 public PmlAmfWriter(Stream Stream) {
34 pWriter = new BinaryWriter(Stream, Encoding.UTF8);
35 }
36
37 public BinaryWriter BaseWriter {
38 get { return pWriter; }
39 set { pWriter = value; }
40 }
41
42 public void WriteMessage(PmlElement Message) {
43 WriteMessageTo(Message, pWriter);
44 }
45
46 public static void WriteMessageTo(PmlElement Message, BinaryWriter Writer) {
47 lock (Writer) {
48 WriteElementTo(Message, Writer);
49 Writer.Flush();
50 }
51 }
52
53 private static void WriteElementTo(PmlElement Element, BinaryWriter Writer) {
54 if (Element == null) {
55 Writer.Write((byte)AmfDataType.Null);
56 return;
57 }
58 switch (Element.Type) {
59 case PmlType.Null:
60 Writer.Write((byte)AmfDataType.Null);
61 break;
62 case PmlType.Dictionary:
63 Writer.Write((byte)AmfDataType.UntypedObject);
64 //WriteDictionary(Writer, (PmlDictionary)Element);
65 WriteUntypedObject(Writer, (PmlDictionary)Element);
66 break;
67 case PmlType.Collection:
68 Writer.Write((byte)AmfDataType.Array);
69 WriteCollection(Writer, (PmlCollection)Element);
70 break;
71 case PmlType.Binary:
72 Writer.Write((byte)AmfDataType.String);
73 byte[] bytes = Element.ToByteArray();
74 if (bytes.Length > UInt16.MaxValue) {
75 Writer.Write((byte)AmfDataType.String);
76 WriteString(Writer, bytes);
77 } else {
78 Writer.Write((byte)AmfDataType.LongString);
79 WriteLongString(Writer, bytes);
80 }
81 break;
82 case PmlType.String:
83 string str = Element.ToString();
84 if (str.Length < UInt16.MaxValue) {
85 Writer.Write((byte)AmfDataType.String);
86 WriteString(Writer, str);
87 } else {
88 Writer.Write((byte)AmfDataType.LongString);
89 WriteLongString(Writer, str);
90 }
91 break;
92 case PmlType.Integer:
93 Writer.Write((byte)AmfDataType.Number);
94 WriteDouble(Writer, (Element as PmlInteger).ToDouble());
95 break;
96 }
97 }
98 private static void WriteEnd(BinaryWriter w) {
99 WriteUInt16(w, 0);
100 w.Write((byte)AmfDataType.End);
101 }
102 private static void WriteUntypedObject(BinaryWriter w, PmlDictionary value) {
103 foreach (KeyValuePair<String, PmlElement> kvp in value) {
104 WriteString(w, kvp.Key);
105 WriteElementTo(kvp.Value, w);
106 }
107 WriteEnd(w);
108 }
109 private static void WriteDictionary(BinaryWriter w, PmlDictionary value) {
110 WriteUInt32(w, (UInt32)value.Count);
111 foreach (KeyValuePair<String, PmlElement> kvp in value) {
112 WriteString(w, kvp.Key);
113 WriteElementTo(kvp.Value, w);
114 }
115 }
116 private static void WriteCollection(BinaryWriter w, PmlCollection value) {
117 WriteUInt32(w,(UInt32)value.Count);
118 foreach (PmlElement o in value) {
119 WriteElementTo(o, w);
120 }
121 }
122 private static void WriteDouble(BinaryWriter w, double value) {
123 WriteReverse(w, BitConverter.GetBytes(value));
124 }
125 private static void WriteUInt32(BinaryWriter w, UInt32 value) {
126 WriteReverse(w, BitConverter.GetBytes(value));
127 }
128 private static void WriteUInt16(BinaryWriter w, UInt16 value) {
129 WriteReverse(w, BitConverter.GetBytes(value));
130 }
131 private static void WriteString(BinaryWriter w, string value) {
132 WriteString(w, Encoding.UTF8.GetBytes(value));
133 }
134 private static void WriteLongString(BinaryWriter w, string value) {
135 WriteLongString(w, Encoding.UTF8.GetBytes(value));
136 }
137 private static void WriteString(BinaryWriter w, byte[] buffer) {
138 WriteUInt16(w, (UInt16)buffer.Length);
139 w.Write(buffer, 0, buffer.Length);
140 }
141 private static void WriteLongString(BinaryWriter w, byte[] buffer) {
142 WriteUInt32(w, (UInt32)buffer.Length);
143 w.Write(buffer, 0, buffer.Length);
144 }
145 private static void WriteReverse(BinaryWriter w, byte[] value) {
146 Array.Reverse(value);
147 w.Write(value);
148 }
149 }
150
151 public class PmlAmfReader : IPmlReader {
152 private BinaryReader pReader;
153
154 public PmlAmfReader(BinaryReader Reader) {
155 pReader = Reader;
156 }
157 public PmlAmfReader(Stream Stream) {
158 pReader = new BinaryReader(Stream, Encoding.UTF8);
159 }
160
161 public BinaryReader BaseReader {
162 get { return pReader; }
163 set { pReader = value; }
164 }
165
166 public PmlElement ReadMessage() {
167 return ReadMessageFrom(pReader);
168 }
169
170 public static PmlElement ReadMessageFrom(BinaryReader Reader) {
171 PmlElement Element = null;
172 lock (Reader) {
173 Element = ReadElementFrom(Reader);
174 }
175 return Element;
176 }
177
178
179 private static PmlElement ReadElementFrom(BinaryReader Reader) {
180 AmfDataType EType = (AmfDataType)Reader.ReadByte();
181 return ReadData(Reader, EType);
182 }
183 private static PmlElement ReadData(BinaryReader Reader, AmfDataType EType) {
184 switch (EType) {
185 case AmfDataType.Number:
186 Double d = ReadDouble(Reader);
187 if (d == (double)(Int64)d) {
188 return new PmlInteger((Int64)d);
189 } else if (d == (double)(UInt64)d) {
190 return new PmlInteger((UInt64)d);
191 } else {
192 return new PmlString(d.ToString());
193 }
194 case AmfDataType.Boolean:
195 return new PmlInteger(Reader.ReadByte());
196 case AmfDataType.String:
197 return new PmlString(ReadShortString(Reader));
198 case AmfDataType.Array:
199 PmlCollection ElementC = new PmlCollection();
200 int size = ReadInt32(Reader);
201 for (int i = 0; i < size; ++i) {
202 ElementC.Add(ReadElementFrom(Reader));
203 }
204 return ElementC;
205 case AmfDataType.Date:
206 return new PmlString(ReadDate(Reader).ToString());
207 case AmfDataType.LongString:
208 return new PmlString(ReadLongString(Reader));
209 case AmfDataType.TypedObject:
210 ReadShortString(Reader);
211 return ReadUntypedObject(Reader);
212 case AmfDataType.MixedArray:
213 return ReadDictionary(Reader);
214 case AmfDataType.Null:
215 case AmfDataType.Undefined:
216 case AmfDataType.End:
217 return new PmlNull();
218 case AmfDataType.UntypedObject:
219 return ReadUntypedObject(Reader);
220 case AmfDataType.Xml:
221 return new PmlString(ReadLongString(Reader));
222 case AmfDataType.MovieClip:
223 case AmfDataType.ReferencedObject:
224 case AmfDataType.TypeAsObject:
225 case AmfDataType.Recordset:
226 default:
227 throw new NotSupportedException("The AMF type is not supported: " + EType.ToString());
228 }
229 }
230
231 private static PmlDictionary ReadUntypedObject(BinaryReader Reader) {
232 PmlDictionary ElementD = new PmlDictionary();
233 string key = ReadShortString(Reader);
234 for (byte type = Reader.ReadByte(); type != 9; type = Reader.ReadByte()) {
235 ElementD.Add(key, ReadData(Reader, (AmfDataType)type));
236 key = ReadShortString(Reader);
237 }
238 return ElementD;
239 }
240 private static PmlDictionary ReadDictionary(BinaryReader Reader) {
241 PmlDictionary ElementD = new PmlDictionary();
242 int size = ReadInt32(Reader);
243 return ReadUntypedObject(Reader);
244 }
245
246 private static DateTime ReadDate(BinaryReader r) {
247 double ms = ReadDouble(r);
248 DateTime date = (new DateTime(1970, 1, 1)).AddMilliseconds(ms);
249 ReadUInt16(r); //gets the timezone
250 return date;
251 }
252 private static double ReadDouble(BinaryReader r) {
253 return BitConverter.ToDouble(ReadReverse(r, 8), 0);
254 }
255
256 private static int ReadInt32(BinaryReader r) {
257 return BitConverter.ToInt32(ReadReverse(r, 4), 0);
258 }
259
260 private static ushort ReadUInt16(BinaryReader r) {
261 return BitConverter.ToUInt16(ReadReverse(r, 2), 0);
262 }
263
264 private static byte[] ReadReverse(BinaryReader r, int size) {
265 byte[] buffer = r.ReadBytes(size);
266 Array.Reverse(buffer);
267 return buffer;
268 }
269 private static string ReadLongString(BinaryReader r) {
270 int length = ReadInt32(r);
271 return ReadString(r, length);
272 }
273 private static string ReadShortString(BinaryReader r) {
274 int length = ReadUInt16(r);
275 return ReadString(r, length);
276 }
277 private static string ReadString(BinaryReader r, int length) {
278 byte[] buffer = r.ReadBytes(length);
279 return Encoding.UTF8.GetString(buffer);
280 }
281 }
282 }