serialize._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2006 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: serialize.pike,v 1.2 2009/05/02 05:44:39 astra Exp $
18  */
19  * made availiable via add_constant. If you really have to inherit this file,
20 #include <macros.h>
21 #include <database.h>
22 #include <attributes.h>
23 class serialize {
24 public:
25 
26 
27 
28 /*
29  * serialization mechanisms for sTeam. They are inherited into _Database and
30  * note that you have to provide an implementation for the prototype
31  * find_object(), see database.pike for an example. Since _Database inherits
32  * serialize.pike, it is compiled without the add_constant on
33  * _Database->find_object(), so you can't rely on the constant. If your Object
34  * knows about _Database you could do
35  * object find_object(int oid) { return _Database->find_object(oid); }
36  */
37 
38 
39 
40 object find_object(int id);
41 //object oLocal; // assume this to be this_object()
42 
43 private string serialize_object(object obj);
44 private string serialize_mapping(mapping map);
45 private string serialize_array(array arr);
46 private string serialize_function(function f);
47  string serialize(mixed arg,void|string encoding);
48 private mapping unserialize_map(string stream);
49 private array unserialize_array(string stream);
50 private int unserialize_number(string stream);
51 private function unserialize_function(string stream);
52  mixed unserialize(string stream, void|object oThis);
53 private object unserialize_object(string stream);
54 
55 private Thread.Local fStringSerializer = Thread.Local();
56 
57 #define STRING_CLOSED 1
58 #define STRING_OPEN 2
59 #define STRING_MASKED 4
60 
61 private:
62 private string
63 serialize_object(object obj)
64 {
65  if ( !functionp(obj->get_object_id) ) {
66  return "";
67  }
68  int oid = obj->get_object_id();
69  return "%" + oid;
70 }
71 
72 public:
73 
74 private:
75 private string
76 serialize_function(function f)
77 {
78  int iFOID;
79  object o;
80 
81  o = function_object(f);
82 
83  if ( !objectp(o) || !functionp(o->get_object_id) ) return 0;
84 
85  iFOID = o->get_object_id();
86  return "$" + function_name(f) + " " + iFOID;
87 }
88 
89 public:
90 
91 private:
92 private string
93 serialize_mapping(mapping map)
94 {
95  int i, sz;
96  string composed;
97  mixed val;
98  array index;
99 
100  index = indices(map);
101 
102  composed = "[";
103  for ( i = 0, sz = sizeof(index); i < sz; i++ ) {
104  if ( stringp(index[i]) )
105  composed += "\"" + index[i] + "\":";
106  else if ( objectp(index[i]) )
107  composed += serialize_object(index[i]) + ":";
108  else if ( arrayp(index[i]))
109  composed += serialize_array(index[i]) + ":";
110  else if ( functionp(index[i]))
111  composed += serialize_function(index[i]) + ":";
112  else
113  composed += index[i] + ":";
114  val = map[index[i]];
115 
116  if ( arrayp(val) )
117  composed += serialize_array(val) + ",";
118  else if ( mappingp(val) )
119  composed += serialize_mapping(val) + ",";
120  else if ( stringp(val) )
121  composed += fStringSerializer->get()(val) + ",";
122  else if ( objectp(val) )
123  composed += serialize_object(val) + ",";
124  else if ( functionp(val) )
125  composed += serialize_function(val) + ",";
126  else
127  composed += val + ",";
128  }
129  composed += "]";
130  return composed;
131 }
132 
133 public:
134 
135 private:
136 private string
137 serialize_array(array arr)
138 {
139  int i, sz;
140  string composed;
141 
142  composed = "{";
143  for ( i = 0, sz = sizeof(arr); i < sz; i++ ) {
144  if ( arrayp(arr[i]) )
145  composed += serialize_array(arr[i]) + ",";
146  else if ( mappingp(arr[i]) )
147  composed += serialize_mapping(arr[i]) + ",";
148  else if ( stringp(arr[i]) )
149  // composed += "\"" + replace(arr[i],"\"","\\char34") + "\",";
150  composed += fStringSerializer->get()(arr[i]) + ",";
151  else if ( objectp(arr[i]) )
152  composed += serialize_object(arr[i]) + ",";
153  else if ( functionp(arr[i]) )
154  composed += serialize_function(arr[i]) + ",";
155  else if ( intp(arr[i]) )
156  composed += sprintf("%d,", arr[i]);
157  else
158  composed += sprintf("%O,", arr[i]);
159  }
160  composed += "}";
161  return composed;
162 }
163 
164 public:
165 
166 private:
167 private string serialize_string(string s)
168 {
169  return "\"" + replace(s, "\"", "\\char34") + "\"";
170 }
171 
172 public:
173 
174 private:
175 private string serialize_utf8(string s)
176 {
177  return "\"" + string_to_utf8(replace(s, "\"", "\\char34")) + "\"";
178 }
179 
180 public:
181 
182 string
183 serialize(mixed arg, void|string encoding)
184 {
185  if (encoding == "utf-8")
186  fStringSerializer->set(serialize_utf8);
187  else
188  fStringSerializer->set(serialize_string);
189 
190  if ( arrayp(arg) )
191  return serialize_array(arg);
192  else if ( mappingp(arg) )
193  return serialize_mapping(arg);
194  else if ( stringp(arg) )
195  // return "\"" + replace(arg,"\"", "\\char34") + "\"";
196  return fStringSerializer->get()(arg);
197  else if ( objectp(arg) )
198  return serialize_object(arg);
199  else if ( functionp(arg) )
200  return serialize_function(arg);
201  else
202  return (string) arg;
203 }
204 
205 
206 private:
207 private array
208 unserialize_array(string sArray)
209 {
210  int i, len;
211  int open_arr_brace;
212  int open_map_brace;
213  int start;
214  array arr;
215  string part;
216  int open_string;
217 
218  arr = ({ });
219  len = strlen(sArray);
220  i = 0; start = 0;
221  open_arr_brace = 0;
222  open_map_brace = 0;
223 
224  open_string = STRING_CLOSED;
225 
226  while ( len > i ) {
227  if ( sArray[i] == '\"' && !(open_string & STRING_MASKED) ) {
228  if ( open_string & STRING_CLOSED )
229  open_string = STRING_OPEN;
230  else
231  open_string = STRING_CLOSED;
232  }
233  else if ( sArray[i] == '\\' ) {
234  open_string |= STRING_MASKED;
235  }
236  else if ( open_string == STRING_CLOSED )
237  {
238  if ( sArray[i] == '{' ) {
239  open_arr_brace++;
240  }
241  else if ( sArray[i] == '[' ) {
242  open_map_brace++;
243  }
244  else if ( sArray[i] == '}' ) {
245  open_arr_brace--;
246  }
247  else if ( sArray[i] == ']' ) {
248  open_map_brace--;
249  }
250  else if ( sArray[i] == ',' &&
251  open_arr_brace == 0 &&
252  open_map_brace == 0 )
253  {
254  part = sArray[start..i-1];
255  mixed res = unserialize(part);
256  arr += ({ res });
257  start = i+1;
258  }
259  if ( open_string & STRING_MASKED )
260  open_string -= STRING_MASKED;
261  }
262  else if ( open_string & STRING_MASKED )
263  open_string -= STRING_MASKED;
264  i++;
265  }
266 
267 public:
268  return arr;
269 }
270 
271 
272 #define EXTRACT_MODE_INDEX 1
273 #define EXTRACT_MODE_DATA 2
274 
275 private:
276 private mapping
277 unserialize_map(string map)
278 {
279  mapping mapp;
280  int i, len;
281  int open_arr_brace;
282  int open_map_brace;
283  int start;
284  int mode;
285  string part;
286  mixed index;
287  int open_string;
288 
289  len = strlen(map);
290  i = 0; start = 0;
291  open_arr_brace = 0;
292  open_map_brace = 0;
293  mapp = ([ ]);
294 
295  /*
296  * first thing expected is an index ...
297  */
298  mode = EXTRACT_MODE_INDEX;
299  open_string = STRING_CLOSED;
300 
301  while ( len > i ) {
302  if ( map[i] == '\"' && !(open_string & STRING_MASKED) )
303  {
304  if ( open_string & STRING_CLOSED )
305  open_string = STRING_OPEN;
306  else
307  open_string = STRING_CLOSED;
308  }
309  else if ( map[i] == '\\' ) {
310  open_string |= STRING_MASKED;
311  }
312  else if ( open_string == STRING_CLOSED )
313  {
314  if ( mode == EXTRACT_MODE_INDEX )
315  {
316  /* no [ or { here */
317  if ( map[i] == ':' )
318  {
319  part = map[start..i-1];
320  index = unserialize(part);
321  start = i+1;
322  mode = EXTRACT_MODE_DATA;
323  }
324  }
325  else
326  {
327  if ( map[i] == '{' ) {
328  open_arr_brace++;
329  }
330  else if ( map[i] == '[' ) {
331  open_map_brace++;
332  }
333  else if ( map[i] == '}' ) {
334  open_arr_brace--;
335  }
336  else if ( map[i] == ']' ) {
337  open_map_brace--;
338  }
339  else if ( map[i] == ',' &&
340  open_arr_brace == 0 &&
341  open_map_brace == 0 )
342  {
343  part = map[start..i-1];
344 
345 /* ASSERTINFO(stringp(index) || intp(index) ||
346  objectp(index) || arrayp(index),
347  "False index, not string, integer, "+
348  "object or array!");*/
349  mapp[index] = unserialize(part);
350  start = i+1;
351  mode = EXTRACT_MODE_INDEX;
352  }
353  }
354  }
355  else if ( open_string & STRING_MASKED )
356  open_string -= STRING_MASKED;
357  i++;
358  }
359  return mapp;
360 }
361 
362 public:
363 
364 private:
365 private mixed
366 unserialize_number(string str)
367 {
368  mixed res;
369  int a, b;
370 
371  if ( sscanf(str, "%d.%d", a, b) == 2 ) {
372  sscanf(str,"%f", res);
373  return (float)res;
374  }
375  sscanf(str, "%d", res);
376  return (int)res;
377 }
378 
379 public:
380 
381 private:
382 private object
383 unserialize_object(string stream)
384 {
385  int res;
386  object proxy;
387 
388  sscanf(stream, "%d", res);
389 
390  proxy = find_object(res);
391 
392  return proxy;
393 }
394 
395 public:
396 
397 private:
398 private function
399 unserialize_function(string f)
400 {
401  object o;
402  mixed res;
403  int iOID;
404  string sFunctionName;
405 
406 
407  if ( sscanf(f, "%s %d", sFunctionName, iOID) == 2 ) {
408  o = find_object(iOID);
409  }
410  else
411  return 0;
412 
413  if (objectp(o))
414  {
415  if ( !functionp(o->get_function) )
416  return 0;
417  res = o->get_function(sFunctionName);
418  }
419  else
420  res = 0;// failed to unserialize function
421  return res;
422 }
423 
424 public:
425 
426 mixed
427 unserialize(string stream, void|object oThis)
428 {
429  int len = strlen(stream);
430 
431  if ( len == 0 )
432  return 0;
433  if ( stream[0] == '\"' )
434  return replace((string)stream[1..len-2], "\\char34", "\"");
435  else if ( stream[0] == '\{' )
436  return (array)unserialize_array(stream[1..len-2]);
437  else if ( stream[0] == '\[' )
438  return (mapping)unserialize_map(stream[1..len-2]);
439  else if ( stream[0] == '#' )
440  return unserialize_object(stream[1..len-1]);
441  else if ( stream[0] == '%')
442  return unserialize_object(stream[1..len-1]);
443  else if ( stream[0] == '$')
444  return unserialize_function(stream[1..len-1]);
445 
446  return unserialize_number(stream);
447 }
448 
449 
450 
451 };