00001 /******************************************************************************* 00002 00003 @file PickleReader.d 00004 00005 Copyright (C) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 00027 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00028 00029 00030 @version Initial version, March 2004 00031 @author Kris 00032 00033 00034 *******************************************************************************/ 00035 00036 module mango.io.PickleReader; 00037 00038 private import mango.io.EndianReader, 00039 mango.io.PickleRegistry; 00040 00041 00042 /******************************************************************************* 00043 00044 Reads serialized content from the bound Buffer, and reconstructs 00045 the 'original' object from the data therein. 00046 00047 All content must be in Network byte-order, so as to span machine 00048 boundaries. Here's an example of how this class is expected to be 00049 used in conjunction with PickleWriter & PickleRegistry: 00050 00051 @code 00052 // define a pickle class (via interfaces) 00053 class Bar : IPickled 00054 { 00055 private int x = 11; 00056 private int y = 112; 00057 00058 void write (IWriter writer) 00059 { 00060 writer.put(x).put(y); 00061 } 00062 00063 void read (IReader reader) 00064 { 00065 reader.get(x).get(y); 00066 } 00067 00068 Object create (IReader reader) 00069 { 00070 Bar bar = new Bar; 00071 bar.read (reader); 00072 assert (bar.x == 11 && bar.y == 112); 00073 return bar; 00074 } 00075 00076 char[] getGuid () 00077 { 00078 return "a network guid"; 00079 } 00080 } 00081 00082 // setup for serialization 00083 Buffer buf = new Buffer (256); 00084 PickleWriter w = new PickleWriter (buf); 00085 PickleReader r = new PickleReader (buf); 00086 00087 // construct a Bar 00088 Bar bar = new Bar; 00089 00090 // tell registry about this object 00091 PickleRegistry.enroll (bar); 00092 00093 // serialize it 00094 w.freeze (bar); 00095 00096 // create a new instance and populate. This just shows the basic 00097 // concept, not a fully operational implementation 00098 Object o = r.thaw (); 00099 @endcode 00100 00101 00102 An alternative approach uses a proxy function instead of a class: 00103 00104 @code 00105 // define a pickle class (via interface) 00106 class Bar : IPickle 00107 { 00108 private int x = 11; 00109 private int y = 112; 00110 00111 void write (IWriter writer) 00112 { 00113 writer.put(x).put(y); 00114 } 00115 00116 void read (IReader reader) 00117 { 00118 reader.get(x).get(y); 00119 assert (x == 11 && y == 112); 00120 } 00121 00122 char[] getGuid () 00123 { 00124 return "a network guid"; 00125 } 00126 00127 // note that this is a static method, as opposed to 00128 // the IPickleFactory method of the same name 00129 static Object create (IReader reader) 00130 { 00131 Bar bar = new Bar; 00132 bar.read (reader); 00133 return bar; 00134 } 00135 } 00136 00137 // setup for serialization 00138 Buffer buf = new Buffer (256); 00139 PickleWriter w = new PickleWriter (buf); 00140 PickleReader r = new PickleReader (buf); 00141 00142 // tell registry about this object 00143 PickleRegistry.enroll (&Bar.create, "a network guid"); 00144 00145 // serialize it 00146 w.freeze (new Bar); 00147 00148 // create a new (populated) instance via the proxy function 00149 Object o = r.thaw (); 00150 @endcode 00151 00152 Note that in the latter case you must ensure that the enroll() method 00153 is passed a guid identical to the one exposed by the IPickle instance. 00154 00155 *******************************************************************************/ 00156 00157 version (BigEndian) 00158 alias Reader SuperClass; 00159 else 00160 alias EndianReader SuperClass; 00161 00162 class PickleReader : SuperClass 00163 { 00164 /*********************************************************************** 00165 00166 Construct a PickleReader with the given buffer, and 00167 an appropriate EndianReader. 00168 00169 Note that serialized data is always in Network order. 00170 00171 ***********************************************************************/ 00172 00173 this (IBuffer buffer) 00174 { 00175 super (buffer); 00176 } 00177 00178 /*********************************************************************** 00179 00180 Reconstruct an Object from the current buffer content. It 00181 is considered optimal to configure the underlying IReader 00182 with an allocator that slices array-references, rather than 00183 copying them into the heap (the default configuration). 00184 00185 ***********************************************************************/ 00186 00187 Object thaw () 00188 { 00189 char[] name; 00190 00191 get(name); 00192 return PickleRegistry.create (this, name); 00193 } 00194 }