diff Pml/RW/PmlPHPRW.cs @ 0:3ab940a0c7a0

Initial commit
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 11 Sep 2012 16:28:53 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Pml/RW/PmlPHPRW.cs	Tue Sep 11 16:28:53 2012 +0200
@@ -0,0 +1,238 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace UCIS.Pml {
+	public class PmlPHPWriter : IPmlWriter {
+		private TextWriter pWriter;
+
+		public static string GetMessageString(PmlElement Message) {
+			StringWriter Buffer = new StringWriter();
+			WriteMessageTo(Message, Buffer);
+			return Buffer.ToString();
+		}
+
+		public PmlPHPWriter(TextWriter Writer) {
+			pWriter = Writer;
+		}
+		public PmlPHPWriter(Stream Writer, Encoding Encoding) {
+			pWriter = new StreamWriter(Writer, Encoding);
+		}
+		public PmlPHPWriter(StringBuilder StringBuilder) {
+			pWriter = new StringWriter(StringBuilder);
+		}
+
+		public TextWriter BaseWriter {
+			get { return pWriter; }
+			set { pWriter = value; }
+		}
+
+		public void WriteMessage(PmlElement Message) {
+			WriteMessageTo(Message, pWriter);
+		}
+
+		public static void WriteMessageTo(PmlElement Message, TextWriter Writer) {
+			lock (Writer) {
+				WriteElementTo(Message, Writer);
+				Writer.Flush();
+			}
+		}
+
+		private static void WriteElementTo(PmlElement Element, TextWriter Writer) {
+			string Str;
+			if (Element == null) {
+				Writer.Write("N;");
+				return;
+			}
+			switch (Element.Type) {
+				case PmlType.Null:
+					Writer.Write("N;");
+					break;
+				case PmlType.String:
+				case PmlType.Binary:
+					Str = Element.ToString();
+					Writer.Write("s:");
+					Writer.Write(Encoding.UTF8.GetByteCount(Str).ToString());
+					Writer.Write(":\"");
+					Writer.Write(Str);
+					Writer.Write("\";");
+					break;
+				case PmlType.Integer:
+					Writer.Write("i:");
+					Writer.Write(Element.ToString());
+					Writer.Write(";");
+					break;
+				case PmlType.Dictionary:
+					Writer.Write("a:");
+					Writer.Write(((IDictionary<string, PmlElement>)Element).Count.ToString());
+					Writer.Write(":{");
+					foreach (KeyValuePair<string, PmlElement> Child in (IDictionary<string, PmlElement>)Element) {
+						Str = Child.Key;
+						Writer.Write("s:");
+						Writer.Write(Encoding.UTF8.GetByteCount(Str).ToString());
+						Writer.Write(":\"");
+						Writer.Write(Str);
+						Writer.Write("\";");
+						WriteElementTo(Child.Value, Writer);
+					}
+
+					Writer.Write("}");
+					break;
+				case PmlType.Collection:
+					int I = 0;
+					Writer.Write("a:");
+					Writer.Write(((ICollection<PmlElement>)Element).Count.ToString());
+					Writer.Write(":{");
+					foreach (PmlElement Child in (ICollection<PmlElement>)Element) {
+						Writer.Write("i:");
+						Writer.Write(I.ToString());
+						Writer.Write(";");
+						WriteElementTo(Child, Writer);
+						I += 1;
+					}
+
+					Writer.Write("}");
+					break;
+				default:
+					Writer.Write("N;");
+					break;
+			}
+		}
+	}
+	public class PmlPHPReader : IPmlReader {
+		private TextReader pReader;
+
+		public static PmlElement GetMessageFromString(string Data) {
+			StringReader Buffer = new StringReader(Data);
+			return ReadMessageFrom(Buffer);
+		}
+
+		public PmlPHPReader(TextReader Reader) {
+			pReader = Reader;
+		}
+		public PmlPHPReader(Stream Reader, Encoding Encoding) {
+			pReader = new StreamReader(Reader, Encoding);
+		}
+		public PmlPHPReader(string Data) {
+			pReader = new StringReader(Data);
+		}
+
+		public TextReader BaseReader {
+			get { return pReader; }
+			set { pReader = value; }
+		}
+
+		public PmlElement ReadMessage() {
+			return ReadMessageFrom(pReader);
+		}
+
+		public static PmlElement ReadMessageFrom(TextReader Reader) {
+			lock (Reader) {
+				return ReadElementFrom(Reader);
+			}
+		}
+
+		public class PhpSerializerException : Exception {
+
+			public PhpSerializerException(int Position, char Read, char Expected)
+				: base("At position " + Position.ToString() + " expected " + Expected + " but got " + Read) {
+			}
+		}
+
+		private static char ReadChar(TextReader Reader) {
+			char[] Buffer = new char[1];
+			if (Reader.Read(Buffer, 0, 1) != 1) throw new EndOfStreamException();
+			return Buffer[0];
+		}
+
+		private static string ReadNumber(TextReader Reader, char TerminatedBy) {
+			char Buffer = '\0';
+			string S = "";
+			do {
+				Buffer = ReadChar(Reader);
+				if (Buffer == TerminatedBy) break;
+				if (Buffer < '0' && Buffer > '9' && Buffer != '.' && Buffer != ',' && Buffer != '-' && Buffer != 'e')
+					throw new PhpSerializerException(0, Buffer, TerminatedBy);
+				S += Buffer;
+			}
+			while (true);
+			return S;
+		}
+
+		private static void ReadExpect(TextReader Reader, char Expect) {
+			char Read = '\0';
+			Read = ReadChar(Reader);
+			if (Read != Expect) throw new PhpSerializerException(0, Read, Expect);
+		}
+
+		private static PmlElement ReadElementFrom(TextReader Reader) {
+			char Type = '\0';
+			char Read = '\0';
+			int KL;
+			Type = ReadChar(Reader);
+			switch (Type) {
+				case 'N':
+					ReadExpect(Reader, ';');
+					return new PmlNull();
+				case 'i':
+					ReadExpect(Reader, ':');
+					return new PmlInteger(ReadNumber(Reader, ';'));
+				case 'd':
+					ReadExpect(Reader, ':');
+					return new PmlString(ReadNumber(Reader, ';'));
+				//Return New PML.PMLNumber(ReadNumber(Reader, ";"c))
+				case 's':
+					KL = 0;
+					char[] Buffer = null;
+					ReadExpect(Reader, ':');
+					KL = int.Parse(ReadNumber(Reader, ':'));
+					Buffer = new Char[KL];
+					ReadExpect(Reader, '"');
+					Reader.ReadBlock(Buffer, 0, KL);
+					ReadExpect(Reader, '"');
+					ReadExpect(Reader, ';');
+					return new PmlString(new String(Buffer));
+				case 'a':
+					PmlDictionary D = new PmlDictionary();
+					int I = 0;
+					int L = 0;
+					KL = 0;
+					char[] K = null;
+					ReadExpect(Reader, ':');
+					L = int.Parse(ReadNumber(Reader, ':'));
+					ReadExpect(Reader, '{');
+					for (I = 1; I <= L; I++) {
+						Read = ReadChar(Reader);
+						switch (Read) {
+							case 'i':
+								ReadExpect(Reader, ':');
+								K = ReadNumber(Reader, ';').ToCharArray();
+								break;
+							case 's':
+								ReadExpect(Reader, ':');
+								KL = int.Parse(ReadNumber(Reader, ':'));
+								K = new char[KL];
+								ReadExpect(Reader, '"');
+								Reader.ReadBlock(K, 0, KL);
+								ReadExpect(Reader, '"');
+								ReadExpect(Reader, ';');
+								break;
+							case 'd':
+								ReadExpect(Reader, ':');
+								K = ReadNumber(Reader, ';').ToCharArray();
+								break;
+							default:
+								throw new NotSupportedException("Only integer and string keys are supported, got: " + Read);
+						}
+						D.Add(new String(K), ReadElementFrom(Reader));
+					}
+
+					ReadExpect(Reader, '}');
+					return D;
+				default:
+					throw new NotSupportedException("Unknown type: " + Type);
+			}
+		}
+	}
+}
\ No newline at end of file