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 4. Derivative works are permitted, but they must carry this notice 00027 in full and credit the original source. 00028 00029 00030 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00031 00032 00033 @version Initial version, March 2004 00034 @author Kris 00035 00036 00037 *******************************************************************************/ 00038 00039 module mango.io.PickleReader; 00040 00041 private import mango.io.EndianReader, 00042 mango.io.PickleRegistry; 00043 00044 00045 /******************************************************************************* 00046 00047 Reads serialized content from the bound Buffer, and reconstructs 00048 the 'original' object from the data therein. 00049 00050 All content must be in Network byte-order, so as to span machine 00051 boundaries. Here's an example of how this class is expected to be 00052 used in conjunction with PickleWriter & PickleRegistry: 00053 00054 @code 00055 // define a pickle class (via interfaces) 00056 class Bar : IPickled 00057 { 00058 private int x = 11; 00059 private int y = 112; 00060 00061 void write (IWriter writer) 00062 { 00063 writer.put(x).put(y); 00064 } 00065 00066 void read (IReader reader) 00067 { 00068 reader.get(x).get(y); 00069 } 00070 00071 Object create (IReader reader) 00072 { 00073 Bar bar = new Bar; 00074 bar.read (reader); 00075 assert (bar.x == 11 && bar.y == 112); 00076 return bar; 00077 } 00078 00079 char[] getGuid () 00080 { 00081 return "a network guid"; 00082 } 00083 } 00084 00085 // setup for serialization 00086 Buffer buf = new Buffer (256); 00087 PickleWriter w = new PickleWriter (buf); 00088 PickleReader r = new PickleReader (buf); 00089 00090 // construct a Bar 00091 Bar bar = new Bar; 00092 00093 // tell registry about this object 00094 PickleRegistry.enroll (bar); 00095 00096 // serialize it 00097 w.freeze (bar); 00098 00099 // create a new instance and populate. This just shows the basic 00100 // concept, not a fully operational implementation 00101 Object o = r.thaw (); 00102 @endcode 00103 00104 00105 An alternative approach uses a proxy function instead of a class: 00106 00107 @code 00108 // define a pickle class (via interface) 00109 class Bar : IPickle 00110 { 00111 private int x = 11; 00112 private int y = 112; 00113 00114 void write (IWriter writer) 00115 { 00116 writer.put(x).put(y); 00117 } 00118 00119 void read (IReader reader) 00120 { 00121 reader.get(x).get(y); 00122 assert (x == 11 && y == 112); 00123 } 00124 00125 char[] getGuid () 00126 { 00127 return "a network guid"; 00128 } 00129 00130 // note that this is a static method, as opposed to 00131 // the IPickleFactory method of the same name 00132 static Object create (IReader reader) 00133 { 00134 Bar bar = new Bar; 00135 bar.read (reader); 00136 return bar; 00137 } 00138 } 00139 00140 // setup for serialization 00141 Buffer buf = new Buffer (256); 00142 PickleWriter w = new PickleWriter (buf); 00143 PickleReader r = new PickleReader (buf); 00144 00145 // tell registry about this object 00146 PickleRegistry.enroll (&Bar.create, "a network guid"); 00147 00148 // serialize it 00149 w.freeze (new Bar); 00150 00151 // create a new (populated) instance via the proxy function 00152 Object o = r.thaw (); 00153 @endcode 00154 00155 Note that in the latter case you must ensure that the enroll() method 00156 is passed a guid identical to the one exposed by the IPickle instance. 00157 00158 *******************************************************************************/ 00159 00160 version (BigEndian) 00161 alias Reader SuperClass; 00162 else 00163 alias EndianReader SuperClass; 00164 00165 class PickleReader : SuperClass 00166 { 00167 /*********************************************************************** 00168 00169 Construct a PickleReader with the given buffer, and 00170 an appropriate EndianReader. 00171 00172 Note that serialized data is always in Network order. 00173 00174 ***********************************************************************/ 00175 00176 this (IBuffer buffer) 00177 { 00178 super (buffer); 00179 } 00180 00181 /*********************************************************************** 00182 00183 Reconstruct an Object from the current buffer content. It 00184 is considered optimal to configure the underlying IReader 00185 with an allocator that slices array-references, rather than 00186 copying them into the heap (the default configuration). 00187 00188 ***********************************************************************/ 00189 00190 Object thaw () 00191 { 00192 char[] name; 00193 00194 get(name); 00195 return PickleRegistry.create (this, name); 00196 } 00197 }