(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.Web / System.Web.UI / ObjectStateFormatter.cs
blob678e939f5183a5c4cd399153079511e45ee07d16
1 //
2 // System.Web.UI.ObjectStateFormatter
3 //
4 // Authors:
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Gonzalo Paniagua (gonzalo@ximian.com)
7 //
8 // (C) 2003 Ben Maurer
9 // (c) Copyright 2004 Novell, Inc. (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //#define TRACE
35 using System.Collections;
36 using System.ComponentModel;
37 using System.Globalization;
38 using System.Drawing;
39 using System.IO;
40 using System.Reflection;
41 using System.Runtime.Serialization.Formatters.Binary;
42 using System.Runtime.Serialization;
43 using System.Text;
44 using System.Web.UI.WebControls;
45 using System.Web.Util;
46 using System.Diagnostics;
48 namespace System.Web.UI {
49 #if NET_2_0
50 public
51 #else
52 internal
53 #endif
54 sealed class ObjectStateFormatter : IFormatter {
55 public object Deserialize (Stream inputStream)
57 if (inputStream == null)
58 throw new ArgumentNullException ("inputStream");
60 return DeserializeObject (new BinaryReader (inputStream));
63 public object Deserialize (string inputString)
65 if (inputString == null)
66 throw new ArgumentNullException ("inputString");
68 if (inputString == "")
69 return null;
71 return Deserialize (new MemoryStream (Convert.FromBase64String (inputString)));
74 public string Serialize (object stateGraph)
76 if (stateGraph == null)
77 return "";
79 MemoryStream ms = new MemoryStream ();
80 Serialize (ms, stateGraph);
82 #if TRACE
83 ms.WriteTo (File.OpenWrite (Path.GetTempFileName ()));
84 #endif
86 return Convert.ToBase64String (ms.GetBuffer (), 0, (int) ms.Length);
89 public void Serialize (Stream outputStream, object stateGraph)
91 if (outputStream == null)
92 throw new ArgumentNullException ("outputStream");
94 if (stateGraph == null)
95 throw new ArgumentNullException ("stateGraph");
97 SerializeValue (new BinaryWriter (outputStream), stateGraph);
100 void SerializeValue (BinaryWriter w, object o)
102 ObjectFormatter.WriteObject (w, o, new WriterContext ());
105 object DeserializeObject (BinaryReader r)
107 return ObjectFormatter.ReadObject (r, new ReaderContext ());
110 #region IFormatter
112 object IFormatter.Deserialize (Stream serializationStream)
114 return Deserialize (serializationStream);
117 void IFormatter.Serialize (Stream serializationStream, object stateGraph)
119 Serialize (serializationStream, stateGraph);
122 SerializationBinder IFormatter.Binder {
123 get { return null; }
124 set { }
127 StreamingContext IFormatter.Context {
128 get { return new StreamingContext (StreamingContextStates.All); }
129 set { }
132 ISurrogateSelector IFormatter.SurrogateSelector {
133 get { return null; }
134 set { }
137 #endregion
139 #region Object Readers/Writers
141 class WriterContext {
142 Hashtable cache;
143 short nextKey = 0;
145 public bool RegisterCache (object o, out short key)
147 if (cache == null) {
148 cache = new Hashtable ();
149 cache.Add (o, key = nextKey++);
150 return false;
153 object posKey = cache [o];
154 if (posKey == null) {
155 cache.Add (o, key = nextKey++);
156 return false;
159 key = (short) posKey;
160 return true;
164 class ReaderContext {
165 ArrayList cache;
167 public void CacheItem (object o)
169 if (cache == null)
170 cache = new ArrayList ();
172 cache.Add (o);
175 public object GetCache (short key)
177 return cache [key];
181 abstract class ObjectFormatter {
182 static readonly Hashtable writeMap = new Hashtable ();
183 static ObjectFormatter [] readMap = new ObjectFormatter [256];
184 static BinaryObjectFormatter binaryObjectFormatter;
185 static TypeFormatter typeFormatter;
186 static EnumFormatter enumFormatter;
187 static SingleRankArrayFormatter singleRankArrayFormatter;
188 static TypeConverterFormatter typeConverterFormatter;
190 static ObjectFormatter ()
192 new StringFormatter ().Register ();
193 new Int64Formatter ().Register ();
194 new Int32Formatter ().Register ();
195 new Int16Formatter ().Register ();
196 new ByteFormatter ().Register ();
197 new BooleanFormatter ().Register ();
198 new CharFormatter ().Register ();
199 new DateTimeFormatter ().Register ();
200 new PairFormatter ().Register ();
201 new TripletFormatter ().Register ();
202 new ArrayListFormatter ().Register ();
203 new HashtableFormatter ().Register ();
204 new ObjectArrayFormatter ().Register ();
205 new UnitFormatter ().Register ();
206 new FontUnitFormatter ().Register ();
208 new ColorFormatter ().Register ();
210 enumFormatter = new EnumFormatter ();
211 enumFormatter.Register ();
213 typeFormatter = new TypeFormatter ();
214 typeFormatter.Register ();
216 singleRankArrayFormatter = new SingleRankArrayFormatter ();
217 singleRankArrayFormatter.Register ();
219 typeConverterFormatter = new TypeConverterFormatter ();
220 typeConverterFormatter.Register ();
222 binaryObjectFormatter = new BinaryObjectFormatter ();
223 binaryObjectFormatter.Register ();
226 // 0 == null
227 static byte nextId = 1;
229 public ObjectFormatter ()
231 PrimaryId = nextId ++;
232 if (NumberOfIds == 1)
233 return;
235 SecondaryId = nextId ++;
236 if (NumberOfIds == 2)
237 return;
239 TertiaryId = nextId ++;
240 if (NumberOfIds == 3)
241 return;
243 throw new Exception ();
246 protected readonly byte PrimaryId, SecondaryId = 255, TertiaryId = 255;
248 protected abstract void Write (BinaryWriter w, object o, WriterContext ctx);
249 protected abstract object Read (byte token, BinaryReader r, ReaderContext ctx);
250 protected abstract Type Type { get; }
251 protected virtual int NumberOfIds { get { return 1; } }
253 public virtual void Register ()
255 writeMap [Type] = this;
256 readMap [PrimaryId] = this;
257 if (SecondaryId != 255) {
258 readMap [SecondaryId] = this;
259 if (TertiaryId != 255)
260 readMap [TertiaryId] = this;
264 public static void WriteObject (BinaryWriter w, object o, WriterContext ctx)
266 #if TRACE
267 if (o != null) {
268 Trace.WriteLine (String.Format ("Writing {0} (type: {1})", o, o.GetType ()));
269 Trace.Indent ();
270 } else {
271 Trace.WriteLine ("Writing null");
273 long pos = w.BaseStream.Position;
274 #endif
276 if (o == null) {
277 w.Write ((byte) 0);
278 return;
281 Type t = o.GetType ();
283 ObjectFormatter fmt = writeMap [t] as ObjectFormatter;
284 if (fmt == null) {
285 // Handle abstract types here
287 if (o is Type)
288 fmt = typeFormatter;
289 else if (t.IsEnum)
290 fmt = enumFormatter;
291 else if (t.IsArray && ((Array) o).Rank == 1)
292 fmt = singleRankArrayFormatter;
293 else {
294 TypeConverter converter;
295 converter = TypeDescriptor.GetConverter (o);
296 if (converter == null ||
297 !converter.CanConvertTo (typeof (string)) ||
298 !converter.CanConvertFrom (typeof (string))) {
299 fmt = binaryObjectFormatter;
300 } else {
301 typeConverterFormatter.Converter = converter;
302 fmt = typeConverterFormatter;
307 fmt.Write (w, o, ctx);
308 #if TRACE
309 Trace.Unindent ();
310 Trace.WriteLine (String.Format ("Wrote {0} (type: {1}) {2} bytes", o, o.GetType (), w.BaseStream.Position - pos));
311 #endif
314 public static object ReadObject (BinaryReader r, ReaderContext ctx)
316 byte sig = r.ReadByte ();
318 if (sig == 0)
319 return null;
321 return readMap [sig].Read (sig, r, ctx);
324 protected void Write7BitEncodedInt (BinaryWriter w, int value)
326 do {
327 int high = (value >> 7) & 0x01ffffff;
328 byte b = (byte)(value & 0x7f);
330 if (high != 0) {
331 b = (byte)(b | 0x80);
334 w.Write(b);
335 value = high;
336 } while(value != 0);
339 protected int Read7BitEncodedInt (BinaryReader r)
341 int ret = 0;
342 int shift = 0;
343 byte b;
345 do {
346 b = r.ReadByte();
348 ret = ret | ((b & 0x7f) << shift);
349 shift += 7;
350 } while ((b & 0x80) == 0x80);
352 return ret;
356 #region Primitive Formatters
357 class StringFormatter : ObjectFormatter {
358 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
360 short key;
361 if (ctx.RegisterCache (o, out key)) {
362 w.Write (SecondaryId);
363 w.Write (key);
364 } else {
365 w.Write (PrimaryId);
366 w.Write ((string)o);
370 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
372 if (token == PrimaryId) {
373 string s = r.ReadString ();
374 ctx.CacheItem (s);
375 return s;
376 } else {
377 return ctx.GetCache (r.ReadInt16 ());
380 protected override Type Type {
381 get { return typeof (string); }
384 protected override int NumberOfIds {
385 get { return 2; }
389 class Int64Formatter : ObjectFormatter {
390 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
392 w.Write (PrimaryId);
393 w.Write ((long)o);
396 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
398 return r.ReadInt64 ();
400 protected override Type Type {
401 get { return typeof (long); }
405 class Int32Formatter : ObjectFormatter {
406 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
408 int i = (int) o;
409 if ((int)(byte) i == i) {
410 w.Write (SecondaryId);
411 w.Write ((byte) i);
412 } else {
413 w.Write (PrimaryId);
414 w.Write (i);
418 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
420 if (token == PrimaryId)
421 return r.ReadInt32 ();
422 else
423 return (int) r.ReadByte ();
425 protected override Type Type {
426 get { return typeof (int); }
429 protected override int NumberOfIds {
430 get { return 2; }
434 class Int16Formatter : ObjectFormatter {
435 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
437 w.Write (PrimaryId);
438 w.Write ((short)o);
441 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
443 return r.ReadInt16 ();
445 protected override Type Type {
446 get { return typeof (short); }
450 class ByteFormatter : ObjectFormatter {
451 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
453 w.Write (PrimaryId);
454 w.Write ((byte)o);
457 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
459 return r.ReadByte ();
461 protected override Type Type {
462 get { return typeof (byte); }
466 class BooleanFormatter : ObjectFormatter {
467 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
469 if ((bool)o == true)
470 w.Write (PrimaryId);
471 else
472 w.Write (SecondaryId);
475 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
477 return token == PrimaryId;
480 protected override Type Type {
481 get { return typeof (bool); }
484 protected override int NumberOfIds {
485 get { return 2; }
489 class CharFormatter : ObjectFormatter {
490 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
492 w.Write (PrimaryId);
493 w.Write ((char) o);
496 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
498 return r.ReadChar ();
501 protected override Type Type {
502 get { return typeof (char); }
506 class DateTimeFormatter : ObjectFormatter {
507 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
509 w.Write (PrimaryId);
510 w.Write (((DateTime) o).Ticks);
513 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
515 return new DateTime (r.ReadInt64 ());
518 protected override Type Type {
519 get { return typeof (DateTime); }
523 class PairFormatter : ObjectFormatter {
524 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
526 Pair p = (Pair) o;
527 w.Write (PrimaryId);
528 WriteObject (w, p.First, ctx);
529 WriteObject (w, p.Second, ctx);
532 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
534 Pair p = new Pair ();
535 p.First = ReadObject (r, ctx);
536 p.Second = ReadObject (r, ctx);
537 return p;
540 protected override Type Type {
541 get { return typeof (Pair); }
545 class TripletFormatter : ObjectFormatter {
546 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
548 Triplet t = (Triplet) o;
549 w.Write (PrimaryId);
550 WriteObject (w, t.First, ctx);
551 WriteObject (w, t.Second, ctx);
552 WriteObject (w, t.Third, ctx);
555 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
557 Triplet t = new Triplet ();
558 t.First = ReadObject (r, ctx);
559 t.Second = ReadObject (r, ctx);
560 t.Third = ReadObject (r, ctx);
561 return t;
564 protected override Type Type {
565 get { return typeof (Triplet); }
569 class ArrayListFormatter : ObjectFormatter {
570 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
572 ArrayList l = (ArrayList) o;
574 w.Write (PrimaryId);
575 Write7BitEncodedInt (w, l.Count);
576 foreach (object i in l)
577 WriteObject (w, i, ctx);
580 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
582 int len = Read7BitEncodedInt (r);
583 ArrayList l = new ArrayList (len);
585 for (int i = 0; i < len; i++)
586 l.Add (ReadObject (r, ctx));
588 return l;
591 protected override Type Type {
592 get { return typeof (ArrayList); }
596 class HashtableFormatter : ObjectFormatter {
597 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
599 Hashtable ht = (Hashtable) o;
601 w.Write (PrimaryId);
602 Write7BitEncodedInt (w, ht.Count);
603 foreach (DictionaryEntry de in ht) {
604 WriteObject (w, de.Key, ctx);
605 WriteObject (w, de.Value, ctx);
609 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
611 int len = Read7BitEncodedInt (r);
612 Hashtable ht = new Hashtable (len);
614 for (int i = 0; i < len; i++) {
615 object key = ReadObject (r, ctx);
616 object val = ReadObject (r, ctx);
618 ht.Add (key, val);
621 return ht;
624 protected override Type Type {
625 get { return typeof (Hashtable); }
629 class ObjectArrayFormatter : ObjectFormatter {
630 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
632 object [] val = (object []) o;
634 w.Write (PrimaryId);
635 Write7BitEncodedInt (w, val.Length);
636 foreach (object i in val)
637 WriteObject (w, i, ctx);
640 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
642 int len = Read7BitEncodedInt (r);
643 object [] ret = new object [len];
645 for (int i = 0; i < len; i++)
646 ret [i] = ReadObject (r, ctx);
648 return ret;
651 protected override Type Type {
652 get { return typeof (object []); }
656 #endregion
658 #region System.Web Optimizations
659 class ColorFormatter : ObjectFormatter {
660 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
662 Color c = (Color) o;
664 if (!c.IsKnownColor) {
665 w.Write (PrimaryId);
666 w.Write (c.ToArgb ());
667 } else {
668 w.Write (SecondaryId);
669 w.Write ((int) c.ToKnownColor ());
673 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
675 if (token == PrimaryId)
676 return Color.FromArgb (r.ReadInt32 ());
677 else
678 return Color.FromKnownColor ((KnownColor) r.ReadInt32 ());
681 protected override Type Type {
682 get { return typeof (Color); }
685 protected override int NumberOfIds {
686 get { return 2; }
690 #endregion
692 #region Special Formatters
693 class EnumFormatter : ObjectFormatter {
694 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
696 object value = Convert.ChangeType (o, ((Enum) o).GetTypeCode ());
697 w.Write (PrimaryId);
698 WriteObject (w, o.GetType (), ctx);
699 WriteObject (w, value, ctx);
702 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
704 Type t = (Type) ReadObject (r, ctx);
705 object value = ReadObject (r, ctx);
707 return Enum.ToObject (t, value);
709 protected override Type Type {
710 get { return typeof (Enum); }
714 class TypeFormatter : ObjectFormatter {
715 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
717 short key;
718 if (ctx.RegisterCache (o, out key)) {
719 w.Write (SecondaryId);
720 w.Write (key);
721 } else {
722 w.Write (PrimaryId);
723 w.Write (((Type) o).FullName);
725 // We should cache the name of the assembly
726 w.Write (((Type) o).Assembly.FullName);
730 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
732 if (token == PrimaryId) {
733 string type = r.ReadString ();
734 string assembly = r.ReadString ();
736 Type t = Assembly.Load (assembly).GetType (type);
737 ctx.CacheItem (t);
738 return t;
739 } else {
740 return ctx.GetCache (r.ReadInt16 ());
744 protected override Type Type {
745 get { return typeof (Type); }
748 protected override int NumberOfIds {
749 get { return 2; }
753 class SingleRankArrayFormatter : ObjectFormatter {
754 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
756 Array val = (Array) o;
758 w.Write (PrimaryId);
759 WriteObject (w, val.GetType ().GetElementType (), ctx);
761 Write7BitEncodedInt (w, val.Length);
762 foreach (object i in val)
763 WriteObject (w, i, ctx);
766 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
768 Type t = (Type) ReadObject (r, ctx);
769 int len = Read7BitEncodedInt (r);
770 Array val = Array.CreateInstance (t, len);
772 for (int i = 0; i < len; i++)
773 val.SetValue (ReadObject (r, ctx), i);
775 return val;
778 protected override Type Type {
779 get { return typeof (Array); }
783 class FontUnitFormatter : StringFormatter {
784 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
786 base.Write (w, o.ToString (), ctx);
789 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
791 return FontUnit.Parse ((string) base.Read (token, r, ctx));
794 protected override Type Type {
795 get { return typeof (FontUnit); }
799 class UnitFormatter : StringFormatter {
800 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
802 base.Write (w, o.ToString (), ctx);
805 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
807 return Unit.Parse ((string) base.Read (token, r, ctx));
810 protected override Type Type {
811 get { return typeof (Unit); }
815 class TypeConverterFormatter : StringFormatter {
816 TypeConverter converter;
818 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
820 w.Write (PrimaryId);
821 ObjectFormatter.WriteObject (w, o.GetType (), ctx);
822 string v = (string) converter.ConvertTo (null, CultureInfo.InvariantCulture,
823 o, typeof (string));
824 base.Write (w, v, ctx);
827 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
829 Type t = (Type) ObjectFormatter.ReadObject (r, ctx);
830 converter = TypeDescriptor.GetConverter (t);
831 token = r.ReadByte ();
832 string v = (string) base.Read (token, r, ctx);
833 return converter.ConvertFrom (null, CultureInfo.InvariantCulture, v);
836 protected override Type Type {
837 get { return typeof (TypeConverter); }
840 public TypeConverter Converter {
841 set { converter = value; }
845 class BinaryObjectFormatter : ObjectFormatter {
846 protected override void Write (BinaryWriter w, object o, WriterContext ctx)
848 w.Write (PrimaryId);
850 MemoryStream ms = new MemoryStream (128);
851 new BinaryFormatter ().Serialize (ms, o);
853 byte [] buf = ms.GetBuffer ();
854 Write7BitEncodedInt (w, buf.Length);
855 w.Write (buf, 0, buf.Length);
858 protected override object Read (byte token, BinaryReader r, ReaderContext ctx)
860 int len = Read7BitEncodedInt (r);
861 byte [] buf = r.ReadBytes (len);
862 if (buf.Length != len)
863 throw new Exception ();
865 return new BinaryFormatter ().Deserialize (new MemoryStream (buf));
868 protected override Type Type {
869 get { return typeof (object); }
873 #endregion
875 #endregion