root/trunk/whisperlib/net/rpc/lib/codec/rpc_decoder.h

Revision 7, 9.6 kB (checked in by whispercastorg, 2 years ago)

version 0.2.0

Line 
1 // Copyright (c) 2009, Whispersoft s.r.l.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Whispersoft s.r.l. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Cosmin Tudorache
31
32 #ifndef __NET_RPC_LIB_CODEC_RPC_DECODER_H__
33 #define __NET_RPC_LIB_CODEC_RPC_DECODER_H__
34
35 #include <list>
36
37 #include <whisperlib/common/base/types.h>
38 #include <whisperlib/common/io/input_stream.h>
39 #include <whisperlib/common/io/output_stream.h>
40 #include <whisperlib/net/rpc/lib/types/rpc_object.h>
41 #include <whisperlib/net/rpc/lib/types/rpc_object_simple.h>
42 #include <whisperlib/net/rpc/lib/types/rpc_bool.h>
43 #include <whisperlib/net/rpc/lib/types/rpc_void.h>
44 #include <whisperlib/net/rpc/lib/types/rpc_string.h>
45 #include <whisperlib/net/rpc/lib/types/rpc_date.h>
46 #include <whisperlib/net/rpc/lib/types/rpc_array.h>
47 #include <whisperlib/net/rpc/lib/types/rpc_map.h>
48 #include <whisperlib/net/rpc/lib/types/rpc_custom.h>
49 #include <whisperlib/net/rpc/lib/types/rpc_message.h>
50
51 #include <whisperlib/net/rpc/lib/codec/rpc_decode_result.h>
52 #include <whisperlib/net/rpc/lib/codec/rpc_typename_codec.h>
53
54 namespace rpc {
55
56 class Decoder {
57  public:
58   // Construct a decoder that reads data from the given input stream.
59   explicit Decoder(io::MemoryStream& in)
60       : in_(in) {
61   }
62   virtual ~Decoder() {
63   }
64
65  public:
66   //  Methods for unwinding complex types: structure, array, map.
67   // returns:
68   //  success status.
69   // NOTE: in case of error or not-enough-data, the read data is not restored.
70   virtual DECODE_RESULT DecodeStructStart(uint32& nAttribs) = 0;
71   virtual DECODE_RESULT DecodeStructContinue(bool& bMoreAttribs) = 0;
72   virtual DECODE_RESULT DecodeStructAttribStart() = 0;
73   virtual DECODE_RESULT DecodeStructAttribMiddle() = 0;
74   virtual DECODE_RESULT DecodeStructAttribEnd() = 0;
75   virtual DECODE_RESULT DecodeArrayStart(uint32& nElements) = 0;
76   virtual DECODE_RESULT DecodeArrayContinue(bool& bMoreElements) = 0;
77   virtual DECODE_RESULT DecodeMapStart(uint32& nPairs) = 0;
78   virtual DECODE_RESULT DecodeMapContinue(bool& bMorePairs) = 0;
79   virtual DECODE_RESULT DecodeMapPairStart() = 0;
80   virtual DECODE_RESULT DecodeMapPairMiddle() = 0;
81   virtual DECODE_RESULT DecodeMapPairEnd() = 0;
82
83  protected:
84   //  Decode a basic type value from the input stream. Usually the object type
85   //  is not stored in stream, so the decoder cannot check data correctness.
86   //  You must know somehow the type of data you're expecting.
87   //  These methods are the oposite of rpc::Encoder::EncodeBody(..).
88   // returns:
89   //   -   1  if the object succeessfully loads from stream
90   //   -   0  if there is not enough data in stream
91   //   - (-1) error loading object. Bad data in stream.
92   // NOTE: in case of error or not-enough-data, the read data is not restored.
93   virtual DECODE_RESULT DecodeBody(rpc::Void& out) = 0;
94   virtual DECODE_RESULT DecodeBody(rpc::Bool& out) = 0;
95   virtual DECODE_RESULT DecodeBody(rpc::Int8& out) = 0;
96   virtual DECODE_RESULT DecodeBody(rpc::UInt8& out) = 0;
97   virtual DECODE_RESULT DecodeBody(rpc::Int16& out) = 0;
98   virtual DECODE_RESULT DecodeBody(rpc::UInt16& out) = 0;
99   virtual DECODE_RESULT DecodeBody(rpc::Int32& out) = 0;
100   virtual DECODE_RESULT DecodeBody(rpc::UInt32& out) = 0;
101   virtual DECODE_RESULT DecodeBody(rpc::Int64& out) = 0;
102   virtual DECODE_RESULT DecodeBody(rpc::UInt64& out) = 0;
103   virtual DECODE_RESULT DecodeBody(rpc::Float& out) = 0;
104   virtual DECODE_RESULT DecodeBody(rpc::Double& out) = 0;
105   virtual DECODE_RESULT DecodeBody(rpc::String& out) = 0;
106   virtual DECODE_RESULT DecodeBody(rpc::Date& out) = 0;
107
108 #define DECODE_VERIFY(dec_op)                     \
109   do {                                            \
110     const rpc::DECODE_RESULT result = dec_op;     \
111     if ( result != rpc::DECODE_RESULT_SUCCESS ) { \
112       return result;                              \
113     }                                             \
114   } while ( false )
115
116   template <typename T>
117   DECODE_RESULT DecodeBody(rpc::Array<T>& out) {
118     // decode array items count
119     uint32 count;
120     DECODE_VERIFY(DecodeArrayStart(count));
121     if ( count != kMaxUInt32 ) {
122       // TODO(cpopescu): well, this may not be that smart - to check
123       out.Resize(count);
124
125       // decode elements
126       bool has_more = false;
127       for ( int i = 0; i < count; i++ ) {
128         DECODE_VERIFY(DecodeArrayContinue(has_more));
129         CHECK(has_more);
130         T& item = out.Get(i);
131
132         DECODE_VERIFY(Decode(item));
133       }
134
135       // bug-trap
136       has_more = false;
137       DECODE_VERIFY(DecodeArrayContinue(has_more));
138       CHECK(!has_more);
139       return DECODE_RESULT_SUCCESS;
140     }
141     list<T> tmp;
142     T empty_item;
143
144     // decode elements in a temporary list
145     bool has_more = false;
146     while ( true ) {
147       DECODE_VERIFY(DecodeArrayContinue(has_more));
148       if ( !has_more ) {
149         break;
150       }
151       tmp.push_back(empty_item);
152       T& item = tmp.back();
153       DECODE_VERIFY(Decode(item));
154     }
155
156     // copy elements from temporary list to output array
157     //
158     out.Resize(tmp.size());
159     uint32 i = 0;
160     for ( typename list<T>::iterator it = tmp.begin();
161           it != tmp.end(); ++it, ++i ) {
162       T& item = *it;
163       out.Set(i, item);
164     }
165     return DECODE_RESULT_SUCCESS;
166   }
167
168   template <typename K, typename V>
169   DECODE_RESULT DecodeBody(rpc::Map<K, V>& out) {
170     // decode map pairs count
171     //
172     uint32 count;
173     DECODE_RESULT result = DecodeMapStart(count);
174     if ( result != DECODE_RESULT_SUCCESS ) {
175       return result;
176     }
177
178     out.Clear();
179
180     // decode [key, value] pairs
181     //
182     bool has_more = true;
183     K key;
184     V value;
185     while ( (result = DecodeMapContinue(has_more)) == DECODE_RESULT_SUCCESS &&
186             has_more ) {
187       DECODE_VERIFY(DecodeMapPairStart());
188       DECODE_VERIFY(Decode(key));
189       DECODE_VERIFY(DecodeMapPairMiddle());
190       DECODE_VERIFY(Decode(value));
191       DECODE_VERIFY(DecodeMapPairEnd());
192       out.Insert(key, value);
193     }
194     if ( result != DECODE_RESULT_SUCCESS ) {
195       return result;
196     }
197
198     // TODO(cpopescu): wtf is w/ this check here ?
199     if ( count != kMaxUInt32 ) {
200       CHECK_EQ(count, out.Size());
201     }
202     return DECODE_RESULT_SUCCESS;
203   }
204   // TODO(cpopescu): shall we leave this around or redefine it (is needed
205   //   in rpc_json_decoder.cc
206   // #undef DECODE_VERIFY
207
208   //  Decode a custom type object.
209   DECODE_RESULT DecodeBody(rpc::Custom& out) {
210     return out.SerializeLoad(*this);
211   }
212
213  public:
214   //  Reset internal state. Should be called before Decode.
215   //  If a previous try to Decode failed for insufficient data,
216   //  the internal state may be mangled.
217   virtual void Reset() = 0;
218
219   //  Decode generic rpc::Object.
220   // Returns:
221   //   DECODE_RESULT_SUCCESS: if the object was successfully read.
222   //   DECODE_RESULT_NOT_ENOUGH_DATA: if there is not enough data
223   //                                  in the input buffer.
224   //                                  The read data is not restored.
225   //   DECODE_RESULT_ERROR: if the data does not look like the expected object.
226   //          The read data is not restored.
227   template<typename T>
228   DECODE_RESULT Decode(T& out) {
229     RPC_TYPENAME_DECODE_AND_CHECK(T::Name());   // this normally is emptyx
230     return DecodeBody(out);
231   }
232   // specialization for rpc::Message
233   DECODE_RESULT Decode(rpc::Message& out) {
234     return DecodePacket(out);
235   }
236
237   //  Skip bytes. Used to skip over unknown fields of custom objects.
238   // returns:
239   //   1 - on success.
240   //   0 - error: the input stream contains less than "size" bytes.
241   //       NOTE: on error the input stream is modified!
242   int32 SkipBytes_TODO_DeleteMe(uint32 size) {
243     const uint32 skipped = in_.Skip(size);
244     return skipped < size ? 0 : 1;
245   }
246
247   // Decodes data from the "input" stream trying to recompose a rpc::Message
248   //  which is stored in "out".
249   // returns:
250   //   DECODE_RESULT_SUCCESS: if a rpc::Message was successfully read.
251   //   DECODE_RESULT_NOT_ENOUGH_DATA: if there is not enough data
252   //                                  in the input buffer.
253   //                                  The read data is not restored.
254   //   DECODE_RESULT_ERROR: if the data does not look like a rpc::Message.
255   //          The read data is not restored.
256   // NOTE: in case of error or not-enough-data, the read data is not restored.
257   virtual DECODE_RESULT DecodePacket(rpc::Message& out);
258
259  protected:
260   io::MemoryStream& in_;
261
262   DISALLOW_EVIL_CONSTRUCTORS(Decoder);
263 };
264 }
265
266 #endif   // __NET_RPC_LIB_CODEC_RPC_DECODER_H__
Note: See TracBrowser for help on using the browser.