Panda3D
 All Classes Functions Variables Enumerations
dcPacker.h
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
 All Classes Functions Variables Enumerations