File: serialize.cpp

package info (click to toggle)
falconpl 0.9.6.9-git20120606-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 46,176 kB
  • sloc: cpp: 181,389; ansic: 109,025; yacc: 2,310; xml: 1,218; sh: 403; objc: 245; makefile: 82; sql: 20
file content (191 lines) | stat: -rw-r--r-- 6,674 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
   FALCON - The Falcon Programming Language.
   FILE: serialize.cpp

   Serialization support
   -------------------------------------------------------------------
   Author: Giancarlo Niccolai
   Begin: sab nov 13 2004

   -------------------------------------------------------------------
   (C) Copyright 2004: the FALCON developers (see list in AUTHORS file)

   See LICENSE file for licensing details.
*/

/** \file
   Serialization support
*/

#include <falcon/setup.h>
#include <falcon/module.h>
#include <falcon/item.h>
#include <falcon/vm.h>
#include <falcon/string.h>
#include <falcon/carray.h>
#include <falcon/memory.h>

#include <falcon/stream.h>
/*#
   @beginmodule core
*/

/*#
   @funset core_serialization Serialization functions
   @brief Function used to store items persistently.

   Serialization functions allow to flatten a Falcon item,
   or a sequence of items, on a stream for later retrieval,
   storage or transmission. At the moment, custom serialization is not supported.
   This means that all the basic items, as strings and numbers, plus arrays and
   dictionaries are supported. Objects are partially supported: when they are fully
   derived from Falcon classes, or declared as "object" by the scripts, the
   serialization and de-serialization are successful. However, there is no
   mechanism to support creation of user-specific data, as the "load" that objects
   can carry internally in behalf of embedding applications.

   Nevertheless, if there is the need, objects may be serialized/deserialized with
   the provided functions, and after the de-serialization step, a custom mechanism
   may be used to re-create application specific data.

   However, it is necessary that the deserializing application has access to the same
   classes that were used to create the serialized object.

   Notice that also functions are correctly serialized and deserialized.
   Also, static block is not re-executed in case the function is re-entered
   after a de-serialization.

   @beginset core_serialization
*/

namespace Falcon {
namespace core {

/*#
   @method serialize BOM
   @brief Serialize the item on a stream for persistent storage.
   @param stream The stream on which to perform serialization.
   @raise IoError on stream errors.

   The item is stored on the stream so that a deserialize() call on the same
   position in the stream where serialization took place will create
   an exact copy of the serialized item.

   The application must ensure that the item does not contains circular references,
   or the serialization will enter an endless loop.

   In case the underlying stream write causes an i/o failure, an error is raised.
*/


/*#
   @function serialize
   @brief Serializes an item on a stream.
   @param item The item to be serialized.
   @param stream An instance of the Stream (or derived) class.
   @raise IoError on underlying stream error.

   The item is stored on the stream so that a deserialize() call on the same
   position in the stream where serialization took place will create an exact
   copy of the serialized item.

   The application must ensure that the item does not contains circular
   references, or the serialization will enter an endless loop.

   In case the underlying stream write causes an i/o failure, an error
   is raised.

   The BOM method @a BOM.serialize is available for all the Falcon items,
   and is equivalent to call this function. 
*/
FALCON_FUNC  mth_serialize ( ::Falcon::VMachine *vm )
{
   Item *fileId;
   Item *source; 
   
   if ( vm->self().isMethodic() )
   {
      source = &vm->self();
      fileId = vm->param(0);
   }
   else
   {
      source = vm->param(0);
      fileId = vm->param(1);
   }
   
   if( fileId == 0 || source == 0 || ! fileId->isObject() || ! fileId->asObjectSafe()->derivedFrom( "Stream" ) )
   {
      throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).origin( e_orig_runtime ).
         extra( vm->self().isMethodic() ? "Stream" : "X,Stream" ) );
   }


   Stream *file = (Stream *) fileId->asObject()->getUserData();
   vm->idle();
   Item::e_sercode sc = source->serialize( file );
   vm->unidle();

   switch( sc )
   {
      case Item::sc_ok: vm->retval( 1 ); break;
      case Item::sc_ferror: 
         throw new IoError( ErrorParam( e_modio, __LINE__ ).origin( e_orig_runtime ) );
      default:
         vm->retnil(); // VM may already have raised an error.
         //TODO: repeat error.
   }
}

/*#
   @function deserialize
   @brief Deserialize an item from a stream.
   @param stream An instance of the Stream (or derived) class.
   @raise IoError on underlying stream error.
   @raise GenericError If the data is correctly de-serialized, but it refers to
         external symbols non defined by this script.
   @raise ParseError if the format of the input data is invalid.

   The returned item is a new copy of the item that has been previously serialized
   on the given stream. After the read, the stream pointer is left ready for a
   new read, so that items that are serialized in sequence may be deserialized
   in the same order.

   If the underlying stream read causes an i/o failure, an error is raised.

   Also, an error is raised if the function cannot deserialize from the stream
   because the data format is invalid.
*/

FALCON_FUNC  deserialize ( ::Falcon::VMachine *vm )
{
   Item *fileId = vm->param(0);

   if( fileId == 0 || ! fileId->isObject() || ! fileId->isObject() || ! fileId->asObjectSafe()->derivedFrom( "Stream" ) )
   {
      throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).origin( e_orig_runtime ).
         extra( "O:Stream" ) );
      return;
   }

   // deserialize rises it's error if it belives it should.
   Stream *file = (Stream *) fileId->asObject()->getUserData();
   Item::e_sercode sc = vm->regA().deserialize( file, vm );
   switch( sc )
   {
      case Item::sc_ok: return; // ok, we've nothing to do
      case Item::sc_eof: throw new IoError( ErrorParam( e_deser_eof, __LINE__ ).origin( e_orig_runtime ) );
      case Item::sc_ferror: throw new IoError( ErrorParam( e_io_error, __LINE__ ).origin( e_orig_runtime ) );
      case Item::sc_misssym: throw new GenericError( ErrorParam( e_undef_sym, __LINE__ ).origin( e_orig_runtime ) );
      case Item::sc_missclass: throw new GenericError( ErrorParam( e_undef_sym, __LINE__ ).origin( e_orig_runtime ) );
      case Item::sc_invformat: throw new ParseError( ErrorParam( e_invformat, __LINE__ ).origin( e_orig_runtime ) );

      case Item::sc_vmerror:
      default:
         vm->retnil(); // VM may already have raised an error.
         //TODO: repeat error.
   }
}

}}
/* end of serialize.cpp */