Panda3D
|
00001 // Filename: dcPacker.h 00002 // Created by: drose (15Jun04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef DCPACKER_H 00016 #define DCPACKER_H 00017 00018 #include "dcbase.h" 00019 #include "dcPackerInterface.h" 00020 #include "dcSubatomicType.h" 00021 #include "dcPackData.h" 00022 #include "dcPackerCatalog.h" 00023 #include "dcPython.h" 00024 00025 class DCClass; 00026 class DCSwitchParameter; 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Class : DCPacker 00030 // Description : This class can be used for packing a series of 00031 // numeric and string data into a binary stream, 00032 // according to the DC specification. 00033 // 00034 // See also direct/src/doc/dcPacker.txt for a more 00035 // complete description and examples of using this 00036 // class. 00037 //////////////////////////////////////////////////////////////////// 00038 class EXPCL_DIRECT DCPacker { 00039 PUBLISHED: 00040 DCPacker(); 00041 ~DCPacker(); 00042 00043 INLINE void clear_data(); 00044 00045 void begin_pack(const DCPackerInterface *root); 00046 bool end_pack(); 00047 00048 void set_unpack_data(const string &data); 00049 public: 00050 void set_unpack_data(const char *unpack_data, size_t unpack_length, 00051 bool owns_unpack_data); 00052 00053 PUBLISHED: 00054 void begin_unpack(const DCPackerInterface *root); 00055 bool end_unpack(); 00056 00057 void begin_repack(const DCPackerInterface *root); 00058 bool end_repack(); 00059 00060 bool seek(const string &field_name); 00061 bool seek(int seek_index); 00062 00063 INLINE bool has_nested_fields() const; 00064 INLINE int get_num_nested_fields() const; 00065 INLINE bool more_nested_fields() const; 00066 00067 INLINE const DCPackerInterface *get_current_parent() const; 00068 INLINE const DCPackerInterface *get_current_field() const; 00069 INLINE const DCSwitchParameter *get_last_switch() const; 00070 INLINE DCPackType get_pack_type() const; 00071 INLINE string get_current_field_name() const; 00072 00073 void push(); 00074 void pop(); 00075 00076 INLINE void pack_double(double value); 00077 INLINE void pack_int(int value); 00078 INLINE void pack_uint(unsigned int value); 00079 INLINE void pack_int64(PN_int64 value); 00080 INLINE void pack_uint64(PN_uint64 value); 00081 INLINE void pack_string(const string &value); 00082 INLINE void pack_literal_value(const string &value); 00083 void pack_default_value(); 00084 00085 INLINE double unpack_double(); 00086 INLINE int unpack_int(); 00087 INLINE unsigned int unpack_uint(); 00088 INLINE PN_int64 unpack_int64(); 00089 INLINE PN_uint64 unpack_uint64(); 00090 INLINE string unpack_string(); 00091 INLINE string unpack_literal_value(); 00092 void unpack_validate(); 00093 void unpack_skip(); 00094 00095 public: 00096 // The following are variants on the above unpack() calls that pass 00097 // the result back by reference instead of as a return value. 00098 INLINE void unpack_double(double &value); 00099 INLINE void unpack_int(int &value); 00100 INLINE void unpack_uint(unsigned int &value); 00101 INLINE void unpack_int64(PN_int64 &value); 00102 INLINE void unpack_uint64(PN_uint64 &value); 00103 INLINE void unpack_string(string &value); 00104 INLINE void unpack_literal_value(string &value); 00105 00106 PUBLISHED: 00107 00108 #ifdef HAVE_PYTHON 00109 void pack_object(PyObject *object); 00110 PyObject *unpack_object(); 00111 #endif 00112 00113 bool parse_and_pack(const string &formatted_object); 00114 bool parse_and_pack(istream &in); 00115 string unpack_and_format(bool show_field_names = true); 00116 void unpack_and_format(ostream &out, bool show_field_names = true); 00117 00118 INLINE bool had_parse_error() const; 00119 INLINE bool had_pack_error() const; 00120 INLINE bool had_range_error() const; 00121 INLINE bool had_error() const; 00122 INLINE size_t get_num_unpacked_bytes() const; 00123 00124 INLINE size_t get_length() const; 00125 INLINE string get_string() const; 00126 INLINE size_t get_unpack_length() const; 00127 INLINE string get_unpack_string() const; 00128 public: 00129 INLINE void get_string(string &data) const; 00130 INLINE const char *get_data() const; 00131 INLINE char *take_data(); 00132 00133 INLINE void append_data(const char *buffer, size_t size); 00134 INLINE char *get_write_pointer(size_t size); 00135 00136 INLINE const char *get_unpack_data() const; 00137 00138 PUBLISHED: 00139 INLINE static int get_num_stack_elements_ever_allocated(); 00140 00141 // The following methods are used only for packing (or unpacking) 00142 // raw data into the buffer between packing sessions (e.g. between 00143 // calls to end_pack() and the next begin_pack()). 00144 00145 INLINE void raw_pack_int8(int value); 00146 INLINE void raw_pack_int16(int value); 00147 INLINE void raw_pack_int32(int value); 00148 INLINE void raw_pack_int64(PN_int64 value); 00149 INLINE void raw_pack_uint8(unsigned int value); 00150 INLINE void raw_pack_uint16(unsigned int value); 00151 INLINE void raw_pack_uint32(unsigned int value); 00152 INLINE void raw_pack_uint64(PN_uint64 value); 00153 INLINE void raw_pack_float64(double value); 00154 INLINE void raw_pack_string(const string &value); 00155 00156 // this is a hack to allw me to get in and out of 32bit Mode Faster 00157 // need to agree with channel_type in dcbase.h 00158 #define RAW_PACK_CHANNEL(in) raw_pack_uint64(in) 00159 #define RAW_UNPACK_CHANNEL() raw_unpack_uint64() 00160 00161 00162 INLINE int raw_unpack_int8(); 00163 INLINE int raw_unpack_int16(); 00164 INLINE int raw_unpack_int32(); 00165 INLINE PN_int64 raw_unpack_int64(); 00166 INLINE unsigned int raw_unpack_uint8(); 00167 INLINE unsigned int raw_unpack_uint16(); 00168 INLINE unsigned int raw_unpack_uint32(); 00169 INLINE PN_uint64 raw_unpack_uint64(); 00170 INLINE double raw_unpack_float64(); 00171 INLINE string raw_unpack_string(); 00172 00173 public: 00174 INLINE void raw_unpack_int8(int &value); 00175 INLINE void raw_unpack_int16(int &value); 00176 INLINE void raw_unpack_int32(int &value); 00177 INLINE void raw_unpack_int64(PN_int64 &value); 00178 INLINE void raw_unpack_uint8(unsigned int &value); 00179 INLINE void raw_unpack_uint16(unsigned int &value); 00180 INLINE void raw_unpack_uint32(unsigned int &value); 00181 INLINE void raw_unpack_uint64(PN_uint64 &value); 00182 INLINE void raw_unpack_float64(double &value); 00183 INLINE void raw_unpack_string(string &value); 00184 00185 public: 00186 static void enquote_string(ostream &out, char quote_mark, const string &str); 00187 static void output_hex_string(ostream &out, const string &str); 00188 00189 private: 00190 INLINE void advance(); 00191 void handle_switch(const DCSwitchParameter *switch_parameter); 00192 void clear(); 00193 void clear_stack(); 00194 00195 #ifdef HAVE_PYTHON 00196 void pack_class_object(const DCClass *dclass, PyObject *object); 00197 PyObject *unpack_class_object(const DCClass *dclass); 00198 void set_class_element(PyObject *class_def, PyObject *&object, 00199 const DCField *field); 00200 void get_class_element(const DCClass *dclass, PyObject *object, 00201 const DCField *field); 00202 #endif 00203 00204 private: 00205 enum Mode { 00206 M_idle, 00207 M_pack, 00208 M_unpack, 00209 M_repack, 00210 }; 00211 Mode _mode; 00212 00213 DCPackData _pack_data; 00214 const char *_unpack_data; 00215 size_t _unpack_length; 00216 bool _owns_unpack_data; 00217 size_t _unpack_p; 00218 00219 const DCPackerInterface *_root; 00220 const DCPackerCatalog *_catalog; 00221 const DCPackerCatalog::LiveCatalog *_live_catalog; 00222 00223 class StackElement { 00224 public: 00225 // As an optimization, we implement operator new and delete here 00226 // to minimize allocation overhead during push() and pop(). 00227 INLINE void *operator new(size_t size); 00228 INLINE void operator delete(void *ptr); 00229 00230 const DCPackerInterface *_current_parent; 00231 int _current_field_index; 00232 size_t _push_marker; 00233 size_t _pop_marker; 00234 StackElement *_next; 00235 00236 static StackElement *_deleted_chain; 00237 static int _num_ever_allocated; 00238 }; 00239 StackElement *_stack; 00240 00241 const DCPackerInterface *_current_field; 00242 const DCPackerInterface *_current_parent; 00243 int _current_field_index; 00244 00245 // _push_marker marks the beginning of the push record (so we can go 00246 // back and write in the length later, or figure out the switch 00247 // parameter). 00248 size_t _push_marker; 00249 // _pop_marker is used in unpack mode with certain data structures 00250 // (like dynamic arrays) to mark the end of the push record (so we 00251 // know when we've reached the end). It is zero when it is not in 00252 // use. 00253 size_t _pop_marker; 00254 int _num_nested_fields; 00255 const DCSwitchParameter *_last_switch; 00256 00257 bool _parse_error; 00258 bool _pack_error; 00259 bool _range_error; 00260 }; 00261 00262 #include "dcPacker.I" 00263 00264 #endif