0
|
1 ???using System; |
|
2 using System.Collections.Generic; |
|
3 using System.Text; |
|
4 using System.IO; |
|
5 |
|
6 namespace UCIS.Pml { |
|
7 public class PmlPHPWriter : IPmlWriter { |
|
8 private TextWriter pWriter; |
|
9 |
|
10 public static string GetMessageString(PmlElement Message) { |
|
11 StringWriter Buffer = new StringWriter(); |
|
12 WriteMessageTo(Message, Buffer); |
|
13 return Buffer.ToString(); |
|
14 } |
|
15 |
|
16 public PmlPHPWriter(TextWriter Writer) { |
|
17 pWriter = Writer; |
|
18 } |
|
19 public PmlPHPWriter(Stream Writer, Encoding Encoding) { |
|
20 pWriter = new StreamWriter(Writer, Encoding); |
|
21 } |
|
22 public PmlPHPWriter(StringBuilder StringBuilder) { |
|
23 pWriter = new StringWriter(StringBuilder); |
|
24 } |
|
25 |
|
26 public TextWriter BaseWriter { |
|
27 get { return pWriter; } |
|
28 set { pWriter = value; } |
|
29 } |
|
30 |
|
31 public void WriteMessage(PmlElement Message) { |
|
32 WriteMessageTo(Message, pWriter); |
|
33 } |
|
34 |
|
35 public static void WriteMessageTo(PmlElement Message, TextWriter Writer) { |
|
36 lock (Writer) { |
|
37 WriteElementTo(Message, Writer); |
|
38 Writer.Flush(); |
|
39 } |
|
40 } |
|
41 |
|
42 private static void WriteElementTo(PmlElement Element, TextWriter Writer) { |
|
43 string Str; |
|
44 if (Element == null) { |
|
45 Writer.Write("N;"); |
|
46 return; |
|
47 } |
|
48 switch (Element.Type) { |
|
49 case PmlType.Null: |
|
50 Writer.Write("N;"); |
|
51 break; |
|
52 case PmlType.String: |
|
53 case PmlType.Binary: |
|
54 Str = Element.ToString(); |
|
55 Writer.Write("s:"); |
|
56 Writer.Write(Encoding.UTF8.GetByteCount(Str).ToString()); |
|
57 Writer.Write(":\""); |
|
58 Writer.Write(Str); |
|
59 Writer.Write("\";"); |
|
60 break; |
|
61 case PmlType.Integer: |
|
62 Writer.Write("i:"); |
|
63 Writer.Write(Element.ToString()); |
|
64 Writer.Write(";"); |
|
65 break; |
|
66 case PmlType.Dictionary: |
|
67 Writer.Write("a:"); |
|
68 Writer.Write(((IDictionary<string, PmlElement>)Element).Count.ToString()); |
|
69 Writer.Write(":{"); |
|
70 foreach (KeyValuePair<string, PmlElement> Child in (IDictionary<string, PmlElement>)Element) { |
|
71 Str = Child.Key; |
|
72 Writer.Write("s:"); |
|
73 Writer.Write(Encoding.UTF8.GetByteCount(Str).ToString()); |
|
74 Writer.Write(":\""); |
|
75 Writer.Write(Str); |
|
76 Writer.Write("\";"); |
|
77 WriteElementTo(Child.Value, Writer); |
|
78 } |
|
79 |
|
80 Writer.Write("}"); |
|
81 break; |
|
82 case PmlType.Collection: |
|
83 int I = 0; |
|
84 Writer.Write("a:"); |
|
85 Writer.Write(((ICollection<PmlElement>)Element).Count.ToString()); |
|
86 Writer.Write(":{"); |
|
87 foreach (PmlElement Child in (ICollection<PmlElement>)Element) { |
|
88 Writer.Write("i:"); |
|
89 Writer.Write(I.ToString()); |
|
90 Writer.Write(";"); |
|
91 WriteElementTo(Child, Writer); |
|
92 I += 1; |
|
93 } |
|
94 |
|
95 Writer.Write("}"); |
|
96 break; |
|
97 default: |
|
98 Writer.Write("N;"); |
|
99 break; |
|
100 } |
|
101 } |
|
102 } |
|
103 public class PmlPHPReader : IPmlReader { |
|
104 private TextReader pReader; |
|
105 |
|
106 public static PmlElement GetMessageFromString(string Data) { |
|
107 StringReader Buffer = new StringReader(Data); |
|
108 return ReadMessageFrom(Buffer); |
|
109 } |
|
110 |
|
111 public PmlPHPReader(TextReader Reader) { |
|
112 pReader = Reader; |
|
113 } |
|
114 public PmlPHPReader(Stream Reader, Encoding Encoding) { |
|
115 pReader = new StreamReader(Reader, Encoding); |
|
116 } |
|
117 public PmlPHPReader(string Data) { |
|
118 pReader = new StringReader(Data); |
|
119 } |
|
120 |
|
121 public TextReader BaseReader { |
|
122 get { return pReader; } |
|
123 set { pReader = value; } |
|
124 } |
|
125 |
|
126 public PmlElement ReadMessage() { |
|
127 return ReadMessageFrom(pReader); |
|
128 } |
|
129 |
|
130 public static PmlElement ReadMessageFrom(TextReader Reader) { |
|
131 lock (Reader) { |
|
132 return ReadElementFrom(Reader); |
|
133 } |
|
134 } |
|
135 |
|
136 public class PhpSerializerException : Exception { |
|
137 |
|
138 public PhpSerializerException(int Position, char Read, char Expected) |
|
139 : base("At position " + Position.ToString() + " expected " + Expected + " but got " + Read) { |
|
140 } |
|
141 } |
|
142 |
|
143 private static char ReadChar(TextReader Reader) { |
|
144 char[] Buffer = new char[1]; |
|
145 if (Reader.Read(Buffer, 0, 1) != 1) throw new EndOfStreamException(); |
|
146 return Buffer[0]; |
|
147 } |
|
148 |
|
149 private static string ReadNumber(TextReader Reader, char TerminatedBy) { |
|
150 char Buffer = '\0'; |
|
151 string S = ""; |
|
152 do { |
|
153 Buffer = ReadChar(Reader); |
|
154 if (Buffer == TerminatedBy) break; |
|
155 if (Buffer < '0' && Buffer > '9' && Buffer != '.' && Buffer != ',' && Buffer != '-' && Buffer != 'e') |
|
156 throw new PhpSerializerException(0, Buffer, TerminatedBy); |
|
157 S += Buffer; |
|
158 } |
|
159 while (true); |
|
160 return S; |
|
161 } |
|
162 |
|
163 private static void ReadExpect(TextReader Reader, char Expect) { |
|
164 char Read = '\0'; |
|
165 Read = ReadChar(Reader); |
|
166 if (Read != Expect) throw new PhpSerializerException(0, Read, Expect); |
|
167 } |
|
168 |
|
169 private static PmlElement ReadElementFrom(TextReader Reader) { |
|
170 char Type = '\0'; |
|
171 char Read = '\0'; |
|
172 int KL; |
|
173 Type = ReadChar(Reader); |
|
174 switch (Type) { |
|
175 case 'N': |
|
176 ReadExpect(Reader, ';'); |
|
177 return new PmlNull(); |
|
178 case 'i': |
|
179 ReadExpect(Reader, ':'); |
|
180 return new PmlInteger(ReadNumber(Reader, ';')); |
|
181 case 'd': |
|
182 ReadExpect(Reader, ':'); |
|
183 return new PmlString(ReadNumber(Reader, ';')); |
|
184 //Return New PML.PMLNumber(ReadNumber(Reader, ";"c)) |
|
185 case 's': |
|
186 KL = 0; |
|
187 char[] Buffer = null; |
|
188 ReadExpect(Reader, ':'); |
|
189 KL = int.Parse(ReadNumber(Reader, ':')); |
|
190 Buffer = new Char[KL]; |
|
191 ReadExpect(Reader, '"'); |
|
192 Reader.ReadBlock(Buffer, 0, KL); |
|
193 ReadExpect(Reader, '"'); |
|
194 ReadExpect(Reader, ';'); |
|
195 return new PmlString(new String(Buffer)); |
|
196 case 'a': |
|
197 PmlDictionary D = new PmlDictionary(); |
|
198 int I = 0; |
|
199 int L = 0; |
|
200 KL = 0; |
|
201 char[] K = null; |
|
202 ReadExpect(Reader, ':'); |
|
203 L = int.Parse(ReadNumber(Reader, ':')); |
|
204 ReadExpect(Reader, '{'); |
|
205 for (I = 1; I <= L; I++) { |
|
206 Read = ReadChar(Reader); |
|
207 switch (Read) { |
|
208 case 'i': |
|
209 ReadExpect(Reader, ':'); |
|
210 K = ReadNumber(Reader, ';').ToCharArray(); |
|
211 break; |
|
212 case 's': |
|
213 ReadExpect(Reader, ':'); |
|
214 KL = int.Parse(ReadNumber(Reader, ':')); |
|
215 K = new char[KL]; |
|
216 ReadExpect(Reader, '"'); |
|
217 Reader.ReadBlock(K, 0, KL); |
|
218 ReadExpect(Reader, '"'); |
|
219 ReadExpect(Reader, ';'); |
|
220 break; |
|
221 case 'd': |
|
222 ReadExpect(Reader, ':'); |
|
223 K = ReadNumber(Reader, ';').ToCharArray(); |
|
224 break; |
|
225 default: |
|
226 throw new NotSupportedException("Only integer and string keys are supported, got: " + Read); |
|
227 } |
|
228 D.Add(new String(K), ReadElementFrom(Reader)); |
|
229 } |
|
230 |
|
231 ReadExpect(Reader, '}'); |
|
232 return D; |
|
233 default: |
|
234 throw new NotSupportedException("Unknown type: " + Type); |
|
235 } |
|
236 } |
|
237 } |
|
238 } |