2 // System.Web.UI.LosFormatter
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2002 Ximian, Inc (http://www.ximian.com)
11 using System.Collections;
14 using System.Runtime.Serialization.Formatters.Binary;
17 using System.Web.UI.WebControls;
18 using System.Web.Util;
20 namespace System.Web.UI
22 public sealed class LosFormatter
24 delegate void WriteObject (LosFormatter formatter, TextWriter writer, object value);
25 static char [] specialChars = new char [] {'<', '>', ';'};
27 const char booleanID = 'o';
28 const char stringID = 's';
29 const char charID = 'c';
30 const char int16ID = 'i';
31 const char int32ID = 'I';
32 const char int64ID = 'l';
33 const char colorID = 'C';
34 const char pairID = 'p';
35 const char tripletID = 't';
36 const char arrayListID = 'L';
37 const char hashtableID = 'h';
38 const char binaryID = 'b';
39 const char arrayID = 'a';
40 const char dateTimeID = 'd';
41 const char unitID = 'u';
42 const char fontUnitID = 'f';
44 static Hashtable specialTypes;
45 static Hashtable idToType;
47 static LosFormatter ()
49 specialTypes = new Hashtable ();
50 specialTypes.Add (typeof (Boolean), new WriteObject (WriteBoolean));
51 specialTypes.Add (typeof (Pair), new WriteObject (WritePair));
52 specialTypes.Add (typeof (Triplet), new WriteObject (WriteTriplet));
53 specialTypes.Add (typeof (Color), new WriteObject (WriteColor));
54 specialTypes.Add (typeof (ArrayList), new WriteObject (WriteArrayList));
55 specialTypes.Add (typeof (Hashtable), new WriteObject (WriteHashtable));
56 specialTypes.Add (typeof (Array), new WriteObject (WriteArray));
57 specialTypes.Add (typeof (DateTime), new WriteObject (WriteDateTime));
58 specialTypes.Add (typeof (Unit), new WriteObject (WriteUnit));
59 specialTypes.Add (typeof (FontUnit), new WriteObject (WriteFontUnit));
61 idToType = new Hashtable ();
62 idToType.Add (typeof (string), stringID);
63 idToType.Add (typeof (char), charID);
64 idToType.Add (typeof (Int16), int16ID);
65 idToType.Add (typeof (Int32), int32ID);
66 idToType.Add (typeof (Int64), int64ID);
67 idToType.Add (typeof (Boolean), booleanID);
68 idToType.Add (typeof (Pair), pairID);
69 idToType.Add (typeof (Triplet), tripletID);
70 idToType.Add (typeof (Color), colorID);
71 idToType.Add (typeof (ArrayList), arrayListID);
72 idToType.Add (typeof (Hashtable), hashtableID);
73 idToType.Add (typeof (Array), arrayID);
74 idToType.Add (typeof (Unit), unitID);
75 idToType.Add (typeof (FontUnit), fontUnitID);
78 public object Deserialize (Stream stream)
81 throw new ArgumentNullException ("stream");
83 return Deserialize (new StreamReader (stream));
86 public object Deserialize (TextReader input)
89 throw new ArgumentNullException ("input");
91 return Deserialize (input.ReadToEnd ());
94 public object Deserialize (string input)
97 throw new ArgumentNullException ("input");
99 string real_input = WebEncoding.Encoding.GetString (Convert.FromBase64String (input));
100 return DeserializeObject (real_input);
103 private static string UnEscapeSpecialChars (string str)
105 if (str.IndexOf ('\\') == -1)
108 string result = str.Replace ("\\;", ";");
109 result = result.Replace ("\\>", ">");
110 result = result.Replace ("\\<", "<");
111 result = result.Replace ("\\\\", "\\");
115 private static string GetEnclosedString (string input)
117 if (input [0] != '<')
118 throw new ArgumentException (input);
121 bool escaped = false;
122 StringBuilder result = new StringBuilder ();
123 for (int i = 1; count != 0 && i < input.Length; i++) {
138 return result.ToString ();
141 private static string [] GetStringValues (string input)
143 if (input == null || input.Length == 0)
144 return new string [0];
146 int length = input.Length;
147 bool escaped = false;
149 ArrayList list = new ArrayList ();
150 StringBuilder builder = new StringBuilder ();
151 for (int i = 0; i < length; i++) {
161 else if (c == ';' && opened == 0) {
162 list.Add (builder.ToString ());
163 builder = new StringBuilder ();
170 list.Add (builder.ToString ());
172 string [] result = new string [list.Count];
173 list.CopyTo (result, 0);
177 private object DeserializeObject (string input)
179 if (input == null || input.Length < 2)
183 string enclosed = GetEnclosedString (input.Substring (1));
188 obj = enclosed.Length == 1;
191 obj = UnEscapeSpecialChars (enclosed);
194 obj = Int16.Parse (enclosed);
197 obj = Int32.Parse (enclosed);
200 obj = Int64.Parse (enclosed);
203 obj = Color.FromArgb (Int32.Parse (enclosed));
206 Pair pair = new Pair ();
208 splitted = GetStringValues (enclosed);
209 if (splitted.Length > 0) {
210 pair.First = DeserializeObject (splitted [0]);
211 if (splitted.Length > 1)
212 pair.Second = DeserializeObject (splitted [1]);
216 Triplet triplet = new Triplet ();
218 splitted = GetStringValues (enclosed);
219 if (splitted.Length == 0)
221 triplet.First = DeserializeObject (splitted [0]);
222 if (splitted.Length < 1)
224 triplet.Second = DeserializeObject (splitted [1]);
225 if (splitted.Length < 2)
227 triplet.Third = DeserializeObject (splitted [2]);
231 ArrayList list = new ArrayList ();
233 splitted = GetStringValues (enclosed);
234 foreach (string s in splitted) {
235 object o = DeserializeObject (s);
239 if (input [0] == arrayID)
240 obj = list.ToArray (typeof (object));
246 Hashtable hash = new Hashtable ();
248 splitted = GetStringValues (enclosed);
249 int length = splitted.Length;
250 for (int i = 0; i < length; i++) {
251 key = DeserializeObject (splitted [i++]);
253 value = DeserializeObject (splitted [i]);
257 hash.Add (key, value);
261 byte [] buffer = Convert.FromBase64String (enclosed);
262 MemoryStream ms = new MemoryStream (buffer);
263 BinaryFormatter fmt = new BinaryFormatter ();
264 obj = fmt.Deserialize (ms);
267 obj = new DateTime (Int64.Parse (enclosed));
270 obj = Unit.Parse (enclosed);
273 Console.WriteLine ("FontUnit: {0}", enclosed);
274 obj = FontUnit.Parse (enclosed);
277 throw new ArgumentException ("input");
283 public void Serialize (Stream stream, object value)
286 throw new ArgumentNullException ("stream");
289 throw new ArgumentNullException ("value");
291 StreamWriter writer = new StreamWriter (stream);
292 Serialize (writer, value);
296 public void Serialize (TextWriter output, object value)
302 throw new ArgumentNullException ("output");
304 StringBuilder builder = new StringBuilder ();
305 StringWriter writer = new StringWriter (builder);
306 SerializeObject (writer, value);
307 byte [] bytes = WebEncoding.Encoding.GetBytes (builder.ToString ());
308 output.Write (Convert.ToBase64String (bytes));
311 private static void WriteBoolean (LosFormatter formatter, TextWriter output, object value)
316 output.Write (booleanID);
317 bool b = (bool) value;
318 output.Write (b ? "<t>" : "<>");
321 private static void WritePair (LosFormatter formatter, TextWriter output, object value)
326 output.Write (pairID);
327 Pair pair = (Pair) value;
329 formatter.SerializeObject (output, pair.First);
331 formatter.SerializeObject (output, pair.Second);
335 private static void WriteTriplet (LosFormatter formatter, TextWriter output, object value)
340 output.Write (tripletID);
341 Triplet triplet = (Triplet) value;
343 formatter.SerializeObject (output, triplet.First);
345 formatter.SerializeObject (output, triplet.Second);
347 formatter.SerializeObject (output, triplet.Third);
351 private static void WriteColor (LosFormatter formatter, TextWriter output, object value)
356 Color c = (Color) value;
357 output.Write (String.Format ("{0}<{1}>", colorID, c.ToArgb ()));
360 private static void WriteArrayList (LosFormatter formatter, TextWriter output, object value)
365 output.Write (arrayListID);
367 ArrayList list = (ArrayList) value;
368 for (int i = 0; i < list.Count; i++) {
369 formatter.SerializeObject (output, list [i]);
370 if (i != list.Count - 1)
376 private static void WriteArray (LosFormatter formatter, TextWriter output, object value)
381 output.Write (arrayID);
383 Array array = (Array) value;
384 for (int i = 0; i < array.Length; i++) {
385 formatter.SerializeObject (output, array.GetValue (i));
386 if (i != array.Length - 1)
392 private static void WriteHashtable (LosFormatter formatter, TextWriter output, object value)
397 output.Write (hashtableID);
399 Hashtable hash = (Hashtable) value;
401 foreach (DictionaryEntry entry in hash) {
402 formatter.SerializeObject (output, entry.Key);
404 formatter.SerializeObject (output, entry.Value);
405 if (i != hash.Count - 1)
412 private static void WriteDateTime (LosFormatter formatter, TextWriter output, object value)
417 output.Write (dateTimeID);
419 output.Write (((DateTime) value).Ticks);
423 static void WriteUnit (LosFormatter formatter, TextWriter output, object value)
428 output.Write (unitID);
430 output.Write (((Unit) value).ToString ());
434 static void WriteFontUnit (LosFormatter formatter, TextWriter output, object value)
439 output.Write (fontUnitID);
441 output.Write (((FontUnit) value).ToString ());
445 private static string EscapeSpecialChars (string str)
447 if (str.IndexOfAny (specialChars) == -1)
450 string result = str.Replace ("\\", "\\\\");
451 result = result.Replace ("<", "\\<");
452 result = result.Replace (">", "\\>");
453 result = result.Replace (";", "\\;");
457 private void SerializeBinary (TextWriter output, object value)
459 WebTrace.PushContext ("LosFormatter.SerializeBinary");
460 /* This is just for debugging purposes */
461 /*if (value is Array) {
462 Array array = (Array) value;
463 for (int i = 0; i < array.Length; i++) {
464 object o = array.GetValue (i);
466 WebTrace.WriteLine ("\t{0} is null", i);
468 WebTrace.WriteLine ("\t{0} {1} {2}", i, o.GetType (), o);
473 BinaryFormatter fmt = new BinaryFormatter ();
474 MemoryStream stream = new MemoryStream ();
476 fmt.Serialize (stream, value);
477 output.Write (binaryID);
479 byte [] buffer = stream.GetBuffer ();
480 output.Write (Convert.ToBase64String (buffer));
483 WebTrace.PopContext ();
486 private void SerializeObject (TextWriter output, object value)
488 WebTrace.PushContext ("LosFormatter.SerializeObject");
490 WebTrace.WriteLine ("value is null");
491 WebTrace.PopContext ();
495 Type t = value.GetType ();
499 if (specialTypes.Contains (t)) {
500 WriteObject w = (WriteObject) specialTypes [t];
501 w (this, output, value);
502 WebTrace.WriteLine ("special type: {0}", value.GetType ());
503 WebTrace.PopContext ();
507 if (idToType.Contains (t)) {
508 char c = (char) idToType [t];
509 string s = EscapeSpecialChars (value.ToString ());
510 output.Write (String.Format ("{0}<{1}>", c, value.ToString ()));
511 WebTrace.WriteLine ("regular type: {0}", value.GetType ());
512 WebTrace.PopContext ();
516 SerializeBinary (output, value);
517 WebTrace.PopContext ();