Panda3D
dcPacker.h
1 // Filename: dcPacker.h
2 // Created by: drose (15Jun04)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef DCPACKER_H
16 #define DCPACKER_H
17 
18 #include "dcbase.h"
19 #include "dcPackerInterface.h"
20 #include "dcSubatomicType.h"
21 #include "dcPackData.h"
22 #include "dcPackerCatalog.h"
23 #include "dcPython.h"
24 
25 class DCClass;
26 class DCSwitchParameter;
27 
28 ////////////////////////////////////////////////////////////////////
29 // Class : DCPacker
30 // Description : This class can be used for packing a series of
31 // numeric and string data into a binary stream,
32 // according to the DC specification.
33 //
34 // See also direct/src/doc/dcPacker.txt for a more
35 // complete description and examples of using this
36 // class.
37 ////////////////////////////////////////////////////////////////////
38 class EXPCL_DIRECT DCPacker {
39 PUBLISHED:
40  DCPacker();
41  ~DCPacker();
42 
43  INLINE void clear_data();
44 
45  void begin_pack(const DCPackerInterface *root);
46  bool end_pack();
47 
48  void set_unpack_data(const string &data);
49 public:
50  void set_unpack_data(const char *unpack_data, size_t unpack_length,
51  bool owns_unpack_data);
52 
53 PUBLISHED:
54  void begin_unpack(const DCPackerInterface *root);
55  bool end_unpack();
56 
57  void begin_repack(const DCPackerInterface *root);
58  bool end_repack();
59 
60  bool seek(const string &field_name);
61  bool seek(int seek_index);
62 
63  INLINE bool has_nested_fields() const;
64  INLINE int get_num_nested_fields() const;
65  INLINE bool more_nested_fields() const;
66 
67  INLINE const DCPackerInterface *get_current_parent() const;
68  INLINE const DCPackerInterface *get_current_field() const;
69  INLINE const DCSwitchParameter *get_last_switch() const;
70  INLINE DCPackType get_pack_type() const;
71  INLINE string get_current_field_name() const;
72 
73  void push();
74  void pop();
75 
76  INLINE void pack_double(double value);
77  INLINE void pack_int(int value);
78  INLINE void pack_uint(unsigned int value);
79  INLINE void pack_int64(PN_int64 value);
80  INLINE void pack_uint64(PN_uint64 value);
81  INLINE void pack_string(const string &value);
82  INLINE void pack_literal_value(const string &value);
83  void pack_default_value();
84 
85  INLINE double unpack_double();
86  INLINE int unpack_int();
87  INLINE unsigned int unpack_uint();
88  INLINE PN_int64 unpack_int64();
89  INLINE PN_uint64 unpack_uint64();
90  INLINE string unpack_string();
91  INLINE string unpack_literal_value();
92  void unpack_validate();
93  void unpack_skip();
94 
95 public:
96  // The following are variants on the above unpack() calls that pass
97  // the result back by reference instead of as a return value.
98  INLINE void unpack_double(double &value);
99  INLINE void unpack_int(int &value);
100  INLINE void unpack_uint(unsigned int &value);
101  INLINE void unpack_int64(PN_int64 &value);
102  INLINE void unpack_uint64(PN_uint64 &value);
103  INLINE void unpack_string(string &value);
104  INLINE void unpack_literal_value(string &value);
105 
106 PUBLISHED:
107 
108 #ifdef HAVE_PYTHON
109  void pack_object(PyObject *object);
110  PyObject *unpack_object();
111 #endif
112 
113  bool parse_and_pack(const string &formatted_object);
114  bool parse_and_pack(istream &in);
115  string unpack_and_format(bool show_field_names = true);
116  void unpack_and_format(ostream &out, bool show_field_names = true);
117 
118  INLINE bool had_parse_error() const;
119  INLINE bool had_pack_error() const;
120  INLINE bool had_range_error() const;
121  INLINE bool had_error() const;
122  INLINE size_t get_num_unpacked_bytes() const;
123 
124  INLINE size_t get_length() const;
125  INLINE string get_string() const;
126  INLINE size_t get_unpack_length() const;
127  INLINE string get_unpack_string() const;
128 public:
129  INLINE void get_string(string &data) const;
130  INLINE const char *get_data() const;
131  INLINE char *take_data();
132 
133  INLINE void append_data(const char *buffer, size_t size);
134  INLINE char *get_write_pointer(size_t size);
135 
136  INLINE const char *get_unpack_data() const;
137 
138 PUBLISHED:
139  INLINE static int get_num_stack_elements_ever_allocated();
140 
141  // The following methods are used only for packing (or unpacking)
142  // raw data into the buffer between packing sessions (e.g. between
143  // calls to end_pack() and the next begin_pack()).
144 
145  INLINE void raw_pack_int8(int value);
146  INLINE void raw_pack_int16(int value);
147  INLINE void raw_pack_int32(int value);
148  INLINE void raw_pack_int64(PN_int64 value);
149  INLINE void raw_pack_uint8(unsigned int value);
150  INLINE void raw_pack_uint16(unsigned int value);
151  INLINE void raw_pack_uint32(unsigned int value);
152  INLINE void raw_pack_uint64(PN_uint64 value);
153  INLINE void raw_pack_float64(double value);
154  INLINE void raw_pack_string(const string &value);
155 
156 // this is a hack to allw me to get in and out of 32bit Mode Faster
157 // need to agree with channel_type in dcbase.h
158 #define RAW_PACK_CHANNEL(in) raw_pack_uint64(in)
159 #define RAW_UNPACK_CHANNEL() raw_unpack_uint64()
160 
161 
162  INLINE int raw_unpack_int8();
163  INLINE int raw_unpack_int16();
164  INLINE int raw_unpack_int32();
165  INLINE PN_int64 raw_unpack_int64();
166  INLINE unsigned int raw_unpack_uint8();
167  INLINE unsigned int raw_unpack_uint16();
168  INLINE unsigned int raw_unpack_uint32();
169  INLINE PN_uint64 raw_unpack_uint64();
170  INLINE double raw_unpack_float64();
171  INLINE string raw_unpack_string();
172 
173 public:
174  INLINE void raw_unpack_int8(int &value);
175  INLINE void raw_unpack_int16(int &value);
176  INLINE void raw_unpack_int32(int &value);
177  INLINE void raw_unpack_int64(PN_int64 &value);
178  INLINE void raw_unpack_uint8(unsigned int &value);
179  INLINE void raw_unpack_uint16(unsigned int &value);
180  INLINE void raw_unpack_uint32(unsigned int &value);
181  INLINE void raw_unpack_uint64(PN_uint64 &value);
182  INLINE void raw_unpack_float64(double &value);
183  INLINE void raw_unpack_string(string &value);
184 
185 public:
186  static void enquote_string(ostream &out, char quote_mark, const string &str);
187  static void output_hex_string(ostream &out, const string &str);
188 
189 private:
190  INLINE void advance();
191  void handle_switch(const DCSwitchParameter *switch_parameter);
192  void clear();
193  void clear_stack();
194 
195 #ifdef HAVE_PYTHON
196  void pack_class_object(const DCClass *dclass, PyObject *object);
197  PyObject *unpack_class_object(const DCClass *dclass);
198  void set_class_element(PyObject *class_def, PyObject *&object,
199  const DCField *field);
200  void get_class_element(const DCClass *dclass, PyObject *object,
201  const DCField *field);
202 #endif
203 
204 private:
205  enum Mode {
206  M_idle,
207  M_pack,
208  M_unpack,
209  M_repack,
210  };
211  Mode _mode;
212 
213  DCPackData _pack_data;
214  const char *_unpack_data;
215  size_t _unpack_length;
216  bool _owns_unpack_data;
217  size_t _unpack_p;
218 
219  const DCPackerInterface *_root;
220  const DCPackerCatalog *_catalog;
221  const DCPackerCatalog::LiveCatalog *_live_catalog;
222 
223  class EXPCL_DIRECT StackElement {
224  public:
225  // As an optimization, we implement operator new and delete here
226  // to minimize allocation overhead during push() and pop().
227  INLINE void *operator new(size_t size);
228  INLINE void operator delete(void *ptr);
229 
230  const DCPackerInterface *_current_parent;
231  int _current_field_index;
232  size_t _push_marker;
233  size_t _pop_marker;
234  StackElement *_next;
235 
236  static StackElement *_deleted_chain;
237  static int _num_ever_allocated;
238  };
239  StackElement *_stack;
240 
241  const DCPackerInterface *_current_field;
242  const DCPackerInterface *_current_parent;
243  int _current_field_index;
244 
245  // _push_marker marks the beginning of the push record (so we can go
246  // back and write in the length later, or figure out the switch
247  // parameter).
248  size_t _push_marker;
249  // _pop_marker is used in unpack mode with certain data structures
250  // (like dynamic arrays) to mark the end of the push record (so we
251  // know when we've reached the end). It is zero when it is not in
252  // use.
253  size_t _pop_marker;
254  int _num_nested_fields;
255  const DCSwitchParameter *_last_switch;
256 
257  bool _parse_error;
258  bool _pack_error;
259  bool _range_error;
260 };
261 
262 #include "dcPacker.I"
263 
264 #endif
This is a block of data that receives the results of DCPacker.
Definition: dcPackData.h:25
A single field of a Distributed Class, either atomic or molecular.
Definition: dcField.h:40
This represents a switch object used as a parameter itself, which packs the appropriate fields of the...
Defines a particular DistributedClass as read from an input .dc file.
Definition: dcClass.h:47
This class can be used for packing a series of numeric and string data into a binary stream...
Definition: dcPacker.h:38
This object contains the names of all of the nested fields available within a particular field...
This defines the internal interface for packing values into a DCField.