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

Revision 7, 6.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_ENCODER_H__
33 #define __NET_RPC_LIB_CODEC_RPC_ENCODER_H__
34
35 #include <whisperlib/common/io/output_stream.h>
36 #include <whisperlib/common/io/num_streaming.h>
37 #include <whisperlib/net/rpc/lib/types/rpc_object.h>
38 #include <whisperlib/net/rpc/lib/types/rpc_object_simple.h>
39 #include <whisperlib/net/rpc/lib/types/rpc_bool.h>
40 #include <whisperlib/net/rpc/lib/types/rpc_void.h>
41 #include <whisperlib/net/rpc/lib/types/rpc_string.h>
42 #include <whisperlib/net/rpc/lib/types/rpc_date.h>
43 #include <whisperlib/net/rpc/lib/types/rpc_array.h>
44 #include <whisperlib/net/rpc/lib/types/rpc_map.h>
45 #include <whisperlib/net/rpc/lib/types/rpc_custom.h>
46 #include <whisperlib/net/rpc/lib/types/rpc_message.h>
47
48 #include <whisperlib/net/rpc/lib/codec/rpc_typename_codec.h>
49
50 namespace rpc {
51
52 class Encoder {
53  public:
54   // Construct an encoder that writes data to the given output stream.
55   explicit Encoder(io::MemoryStream& out)
56       : out_(&out),
57         tmp_() {
58   }
59   virtual ~Encoder() {
60   }
61
62  public:
63   //////////////////////////////////////////////////////////////////////
64   //
65   //                    Encoding methods
66   //
67
68   // Methods for serializing complex types: structure, array, map.
69   virtual void EncodeStructStart(uint32 nAttribs) = 0;
70   virtual void EncodeStructContinue() = 0;
71   virtual void EncodeStructEnd() = 0;
72   virtual void EncodeStructAttribStart() = 0;
73   virtual void EncodeStructAttribMiddle() = 0;
74   virtual void EncodeStructAttribEnd() = 0;
75   virtual void EncodeArrayStart(uint32 nElements) = 0;
76   virtual void EncodeArrayContinue() = 0;
77   virtual void EncodeArrayEnd() = 0;
78   virtual void EncodeArrayElementStart() = 0;
79   virtual void EncodeArrayElementEnd() = 0;
80   virtual void EncodeMapStart(uint32 nPairs) = 0;
81   virtual void EncodeMapContinue() = 0;
82   virtual void EncodeMapEnd() = 0;
83   virtual void EncodeMapPairStart() = 0;
84   virtual void EncodeMapPairMiddle() = 0;
85   virtual void EncodeMapPairEnd() = 0;
86
87  protected:
88   // Encode the value of a base type object in the output stream.
89   // The reverse of these methods is rpc::Decoder::DecodeBody(..).
90   virtual void EncodeBody(const rpc::Void& obj) = 0;
91   virtual void EncodeBody(const rpc::Bool& obj) = 0;
92   virtual void EncodeBody(const rpc::Int8& obj) = 0;
93   virtual void EncodeBody(const rpc::UInt8& obj) = 0;
94   virtual void EncodeBody(const rpc::Int16& obj) = 0;
95   virtual void EncodeBody(const rpc::UInt16& obj) = 0;
96   virtual void EncodeBody(const rpc::Int32& obj) = 0;
97   virtual void EncodeBody(const rpc::UInt32& obj) = 0;
98   virtual void EncodeBody(const rpc::Int64& obj) = 0;
99   virtual void EncodeBody(const rpc::UInt64& obj) = 0;
100   virtual void EncodeBody(const rpc::Float& obj) = 0;
101   virtual void EncodeBody(const rpc::Double& obj) = 0;
102   virtual void EncodeBody(const rpc::String& obj) = 0;
103   virtual void EncodeBody(const rpc::Date& obj) = 0;
104
105   template<typename T>
106   void EncodeBody(const rpc::Array<T>& obj) {
107     uint32 count = obj.Size();
108     EncodeArrayStart(count);            // encode the items count
109     for ( uint32 i = 0; i < count; i++ ) {
110       EncodeArrayElementStart();
111       Encode(obj.Get(i));               // encode the items themselves
112       EncodeArrayElementEnd();
113       if ( i + 1 < count ) {
114         EncodeArrayContinue();
115       }
116     }
117     EncodeArrayEnd();
118   }
119
120   template<typename K, typename V>
121   void EncodeBody(const rpc::Map<K, V>& obj) {
122     uint32 count = obj.Size();          // count
123     EncodeMapStart(count);              // encode the items count
124     uint32 i = 0;
125     for ( typename rpc::Map<K, V>::ConstIterator it = obj.Begin();
126           it != obj.End(); ++it, ++i ) {
127       EncodeMapPairStart();
128       Encode(it->first);                // encode the key for an item
129       EncodeMapPairMiddle();
130       Encode(it->second);               // encode the value for an item
131       EncodeMapPairEnd();
132       if ( i + 1 < count ) {
133         EncodeMapContinue();
134       }
135     }
136     EncodeMapEnd();
137   }
138
139   // Encode a custom type object.
140   void EncodeBody(const rpc::Custom& obj) {
141     obj.SerializeSave(*this);
142   }
143
144  public:
145   // Encode generic rpc::Object.
146   // This method has no reason to fail.
147   template <typename T>
148   void Encode(const T& obj) {
149     RPC_TYPENAME_ENCODE(T::Name());
150     EncodeBody(obj);
151   }
152   // specialization for rpc::Message
153   void Encode(const rpc::Message& p) {
154     EncodePacket(p);
155   }
156
157   template <typename T>
158   uint32 EstimateEncodingSize(const T& obj) {
159     tmp_.Clear();
160
161     // switch to this output ..
162     io::MemoryStream* originalOut = out_;
163     out_ = &tmp_;
164
165     // encode the object (using the tmp buffer);
166     Encode(obj);
167
168     // switch back to original output
169     out_ = originalOut;
170
171     uint32 size = tmp_.Size();
172     return size;
173   }
174
175
176   // Encode the given rpc::Message "p".
177   // This method has no reason to fail.
178   virtual void EncodePacket(const rpc::Message& p);
179
180  protected:
181   // the original output stream (as given in constructor)
182   io::MemoryStream* out_;
183   // an additional buffer used to temporary encode
184   // an object for size measurement.
185   io::MemoryStream tmp_;
186
187   DISALLOW_EVIL_CONSTRUCTORS(Encoder);
188 };
189 }
190 #endif   // __NET_RPC_LIB_CODEC_RPC_ENCODER_H__
Note: See TracBrowser for help on using the browser.