From 932359216f257bf2cc057742ec8b96e918fe0245 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 30 Jun 2004 00:50:25 +0000 Subject: [PATCH] struct and switch are now inline --- direct/src/dcparser/Sources.pp | 7 +- direct/src/dcparser/dcArrayParameter.cxx | 9 +- direct/src/dcparser/dcArrayParameter.h | 2 +- direct/src/dcparser/dcAtomicField.cxx | 22 ++- direct/src/dcparser/dcAtomicField.h | 1 + direct/src/dcparser/dcClass.cxx | 63 ++++++- direct/src/dcparser/dcClass.h | 4 + direct/src/dcparser/dcClassParameter.cxx | 11 +- direct/src/dcparser/dcClassParameter.h | 2 +- direct/src/dcparser/dcDeclaration.cxx | 20 ++ direct/src/dcparser/dcDeclaration.h | 9 + direct/src/dcparser/dcField.h | 1 + direct/src/dcparser/dcFile.cxx | 66 ++++++- direct/src/dcparser/dcFile.h | 9 +- direct/src/dcparser/dcMolecularField.cxx | 21 ++- direct/src/dcparser/dcMolecularField.h | 1 + direct/src/dcparser/dcPacker.I | 8 +- direct/src/dcparser/dcPacker.cxx | 34 ++-- direct/src/dcparser/dcPacker.h | 8 +- direct/src/dcparser/dcPackerCatalog.cxx | 19 +- direct/src/dcparser/dcPackerCatalog.h | 8 +- direct/src/dcparser/dcPackerInterface.cxx | 20 +- direct/src/dcparser/dcPackerInterface.h | 9 +- direct/src/dcparser/dcParameter.cxx | 48 ++++- direct/src/dcparser/dcParameter.h | 12 +- direct/src/dcparser/dcParser.yxx | 60 ++++-- direct/src/dcparser/dcParserDefs.h | 2 + direct/src/dcparser/dcSimpleParameter.cxx | 6 +- direct/src/dcparser/dcSimpleParameter.h | 2 +- direct/src/dcparser/dcSwitch.cxx | 132 ++++++++----- direct/src/dcparser/dcSwitch.h | 14 +- direct/src/dcparser/dcSwitchParameter.cxx | 198 ++++++++++++++++++++ direct/src/dcparser/dcSwitchParameter.h | 61 ++++++ direct/src/dcparser/dcparser_composite2.cxx | 1 + 34 files changed, 703 insertions(+), 187 deletions(-) create mode 100755 direct/src/dcparser/dcSwitchParameter.cxx create mode 100755 direct/src/dcparser/dcSwitchParameter.h diff --git a/direct/src/dcparser/Sources.pp b/direct/src/dcparser/Sources.pp index c20b00a595..9b14c1e4de 100644 --- a/direct/src/dcparser/Sources.pp +++ b/direct/src/dcparser/Sources.pp @@ -24,7 +24,8 @@ dcPacker.h dcPacker.I \ dcPackerCatalog.h dcPackerCatalog.I \ dcPackerInterface.h dcPackerInterface.I \ - dcParameter.h dcClassParameter.h dcArrayParameter.h dcSimpleParameter.h \ + dcParameter.h dcClassParameter.h dcArrayParameter.h \ + dcSimpleParameter.h dcSwitchParameter.h \ dcNumericRange.h dcNumericRange.I \ dcSwitch.h \ dcTypedef.h \ @@ -41,8 +42,8 @@ dcPacker.cxx \ dcPackerCatalog.cxx \ dcPackerInterface.cxx \ - dcParameter.cxx dcClassParameter.cxx \ - dcArrayParameter.cxx dcSimpleParameter.cxx \ + dcParameter.cxx dcClassParameter.cxx dcArrayParameter.cxx \ + dcSimpleParameter.cxx dcSwitchParameter.cxx \ dcSwitch.cxx \ dcTypedef.cxx \ dcindent.cxx \ diff --git a/direct/src/dcparser/dcArrayParameter.cxx b/direct/src/dcparser/dcArrayParameter.cxx index 467ac5cbab..90677a6a7a 100644 --- a/direct/src/dcparser/dcArrayParameter.cxx +++ b/direct/src/dcparser/dcArrayParameter.cxx @@ -188,10 +188,10 @@ validate_num_nested_fields(int num_nested_fields) const { // typename and identifier. //////////////////////////////////////////////////////////////////// void DCArrayParameter:: -output_instance(ostream &out, const string &prename, const string &name, - const string &postname) const { +output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const { if (get_typedef() != (DCTypedef *)NULL) { - output_typedef_name(out, prename, name, postname); + output_typedef_name(out, brief, prename, name, postname); } else { ostringstream strm; @@ -200,7 +200,8 @@ output_instance(ostream &out, const string &prename, const string &name, _array_size_range.output(strm); strm << "]"; - _element_type->output_instance(out, prename, name, strm.str() + postname); + _element_type->output_instance(out, brief, prename, name, + strm.str() + postname); } } diff --git a/direct/src/dcparser/dcArrayParameter.h b/direct/src/dcparser/dcArrayParameter.h index 2063f80110..b27455226a 100644 --- a/direct/src/dcparser/dcArrayParameter.h +++ b/direct/src/dcparser/dcArrayParameter.h @@ -50,7 +50,7 @@ public: virtual DCPackerInterface *get_nested_field(int n) const; virtual bool validate_num_nested_fields(int num_nested_fields) const; - virtual void output_instance(ostream &out, const string &prename, + virtual void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; diff --git a/direct/src/dcparser/dcAtomicField.cxx b/direct/src/dcparser/dcAtomicField.cxx index f43c117f2e..3d609a2656 100644 --- a/direct/src/dcparser/dcAtomicField.cxx +++ b/direct/src/dcparser/dcAtomicField.cxx @@ -266,15 +266,13 @@ compare_flags(const DCAtomicField &other) const { } //////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::write +// Function: DCAtomicField::output // Access: Public, Virtual -// Description: Generates a parseable description of the object to -// the indicated output stream. +// Description: //////////////////////////////////////////////////////////////////// void DCAtomicField:: -write(ostream &out, bool brief, int indent_level) const { - indent(out, indent_level) - << _name << "("; +output(ostream &out, bool brief) const { + out << _name << "("; if (!_elements.empty()) { Elements::const_iterator ei = _elements.begin(); @@ -317,6 +315,18 @@ write(ostream &out, bool brief, int indent_level) const { } out << ";"; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCAtomicField::write +// Access: Public, Virtual +// Description: Generates a parseable description of the object to +// the indicated output stream. +//////////////////////////////////////////////////////////////////// +void DCAtomicField:: +write(ostream &out, bool brief, int indent_level) const { + indent(out, indent_level); + output(out, brief); if (!brief && _number >= 0) { out << " // field " << _number; } diff --git a/direct/src/dcparser/dcAtomicField.h b/direct/src/dcparser/dcAtomicField.h index d261985366..305c818001 100644 --- a/direct/src/dcparser/dcAtomicField.h +++ b/direct/src/dcparser/dcAtomicField.h @@ -65,6 +65,7 @@ PUBLISHED: bool compare_flags(const DCAtomicField &other) const; public: + virtual void output(ostream &out, bool brief) const; virtual void write(ostream &out, bool brief, int indent_level) const; virtual void generate_hash(HashGenerator &hashgen) const; diff --git a/direct/src/dcparser/dcClass.cxx b/direct/src/dcparser/dcClass.cxx index 0d6fa6deac..72c6bde831 100644 --- a/direct/src/dcparser/dcClass.cxx +++ b/direct/src/dcparser/dcClass.cxx @@ -57,6 +57,16 @@ DCClass:: #endif } +//////////////////////////////////////////////////////////////////// +// Function: DCClass::as_class +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DCClass *DCClass:: +as_class() { + return this; +} + //////////////////////////////////////////////////////////////////// // Function: DCClass::get_name // Access: Published @@ -263,7 +273,7 @@ set_class_def(PyObject *class_def) { PyObject *DCClass:: get_class_def() const { if (_class_def == NULL) { - return Py_BuildValue(""); + return Py_None; } Py_INCREF(_class_def); @@ -435,7 +445,7 @@ pack_required_field(DCPacker &packer, PyObject *distobj, ostringstream strm; strm << "Data element " << field_name << ", required by dc file for dclass " << get_name() - << ", not defined on object."; + << ", not defined on object"; nassert_raise(strm.str()); return false; } @@ -661,9 +671,12 @@ void DCClass:: write(ostream &out, bool brief, int indent_level) const { indent(out, indent_level); if (_is_struct) { - out << "struct " << _name; + out << "struct"; } else { - out << "dclass " << _name; + out << "dclass"; + } + if (!_name.empty()) { + out << " " << _name; } if (!_parents.empty()) { @@ -690,6 +703,48 @@ write(ostream &out, bool brief, int indent_level) const { indent(out, indent_level) << "};\n"; } +//////////////////////////////////////////////////////////////////// +// Function: DCClass::output_instance +// Access: Public +// Description: Generates a parseable description of the object to +// the indicated output stream. +//////////////////////////////////////////////////////////////////// +void DCClass:: +output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const { + if (_is_struct) { + out << "struct"; + } else { + out << "dclass"; + } + if (!_name.empty()) { + out << " " << _name; + } + + if (!_parents.empty()) { + Parents::const_iterator pi = _parents.begin(); + out << " : " << (*pi)->_name; + ++pi; + while (pi != _parents.end()) { + out << ", " << (*pi)->_name; + ++pi; + } + } + + out << " {"; + + Fields::const_iterator fi; + for (fi = _fields.begin(); fi != _fields.end(); ++fi) { + (*fi)->output(out, brief); + out << "; "; + } + + out << "}"; + if (!prename.empty() || !name.empty() || !postname.empty()) { + out << " " << prename << name << postname; + } +} + //////////////////////////////////////////////////////////////////// // Function: DCClass::generate_hash // Access: Public, Virtual diff --git a/direct/src/dcparser/dcClass.h b/direct/src/dcparser/dcClass.h index d097d6dc6a..16f070c8bf 100644 --- a/direct/src/dcparser/dcClass.h +++ b/direct/src/dcparser/dcClass.h @@ -38,6 +38,8 @@ public: ~DCClass(); PUBLISHED: + virtual DCClass *as_class(); + const string &get_name() const; int get_number() const; @@ -83,6 +85,8 @@ PUBLISHED: public: virtual void write(ostream &out, bool brief, int indent_level) const; + void output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const; void generate_hash(HashGenerator &hashgen) const; bool add_field(DCField *field); diff --git a/direct/src/dcparser/dcClassParameter.cxx b/direct/src/dcparser/dcClassParameter.cxx index a8c3585344..3d48652431 100644 --- a/direct/src/dcparser/dcClassParameter.cxx +++ b/direct/src/dcparser/dcClassParameter.cxx @@ -123,16 +123,13 @@ get_nested_field(int n) const { // typename and identifier. //////////////////////////////////////////////////////////////////// void DCClassParameter:: -output_instance(ostream &out, const string &prename, const string &name, - const string &postname) const { +output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const { if (get_typedef() != (DCTypedef *)NULL) { - output_typedef_name(out, prename, name, postname); + output_typedef_name(out, brief, prename, name, postname); } else { - out << get_name(); - if (!prename.empty() || !name.empty() || !postname.empty()) { - out << " " << prename << name << postname; - } + _dclass->output_instance(out, brief, prename, name, postname); } } diff --git a/direct/src/dcparser/dcClassParameter.h b/direct/src/dcparser/dcClassParameter.h index 2d2a4665ad..25ad590523 100644 --- a/direct/src/dcparser/dcClassParameter.h +++ b/direct/src/dcparser/dcClassParameter.h @@ -45,7 +45,7 @@ PUBLISHED: public: virtual DCPackerInterface *get_nested_field(int n) const; - virtual void output_instance(ostream &out, const string &prename, + virtual void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; diff --git a/direct/src/dcparser/dcDeclaration.cxx b/direct/src/dcparser/dcDeclaration.cxx index f625a3a6f1..5e80ec7022 100644 --- a/direct/src/dcparser/dcDeclaration.cxx +++ b/direct/src/dcparser/dcDeclaration.cxx @@ -27,3 +27,23 @@ DCDeclaration:: ~DCDeclaration() { } + +//////////////////////////////////////////////////////////////////// +// Function: DCDeclaration::as_class +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DCClass *DCDeclaration:: +as_class() { + return (DCClass *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCDeclaration::as_switch +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DCSwitch *DCDeclaration:: +as_switch() { + return (DCSwitch *)NULL; +} diff --git a/direct/src/dcparser/dcDeclaration.h b/direct/src/dcparser/dcDeclaration.h index 600fad07f9..93bf9c385b 100644 --- a/direct/src/dcparser/dcDeclaration.h +++ b/direct/src/dcparser/dcDeclaration.h @@ -21,6 +21,9 @@ #include "dcbase.h" +class DCClass; +class DCSwitch; + //////////////////////////////////////////////////////////////////// // Class : DCDeclaration // Description : This is a common interface for a declaration in a DC @@ -34,6 +37,12 @@ class EXPCL_DIRECT DCDeclaration { public: virtual ~DCDeclaration(); + +PUBLISHED: + virtual DCClass *as_class(); + virtual DCSwitch *as_switch(); + +public: virtual void write(ostream &out, bool brief, int indent_level) const=0; }; diff --git a/direct/src/dcparser/dcField.h b/direct/src/dcparser/dcField.h index 486105de1c..88975c39f4 100644 --- a/direct/src/dcparser/dcField.h +++ b/direct/src/dcparser/dcField.h @@ -66,6 +66,7 @@ PUBLISHED: #endif public: + virtual void output(ostream &out, bool brief) const=0; virtual void write(ostream &out, bool brief, int indent_level) const=0; virtual void generate_hash(HashGenerator &hashgen) const; diff --git a/direct/src/dcparser/dcFile.cxx b/direct/src/dcparser/dcFile.cxx index a2c98002ea..7bd71e5e5e 100644 --- a/direct/src/dcparser/dcFile.cxx +++ b/direct/src/dcparser/dcFile.cxx @@ -17,6 +17,8 @@ //////////////////////////////////////////////////////////////////// #include "dcFile.h" +#include "dcClass.h" +#include "dcSwitch.h" #include "dcParserDefs.h" #include "dcLexerDefs.h" #include "dcTypedef.h" @@ -65,7 +67,7 @@ clear() { _classes.clear(); _imports.clear(); - _classes_by_name.clear(); + _things_by_name.clear(); } #ifdef WITHIN_PANDA @@ -273,15 +275,32 @@ get_class(int n) const { //////////////////////////////////////////////////////////////////// DCClass *DCFile:: get_class_by_name(const string &name) const { - ClassesByName::const_iterator ni; - ni = _classes_by_name.find(name); - if (ni != _classes_by_name.end()) { - return (*ni).second; + ThingsByName::const_iterator ni; + ni = _things_by_name.find(name); + if (ni != _things_by_name.end()) { + return (*ni).second->as_class(); } return (DCClass *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: DCFile::get_switch_by_name +// Access: Published +// Description: Returns the switch that has the indicated name, or +// NULL if there is no such switch. +//////////////////////////////////////////////////////////////////// +DCSwitch *DCFile:: +get_switch_by_name(const string &name) const { + ThingsByName::const_iterator ni; + ni = _things_by_name.find(name); + if (ni != _things_by_name.end()) { + return (*ni).second->as_switch(); + } + + return (DCSwitch *)NULL; +} + //////////////////////////////////////////////////////////////////// // Function: DCFile::all_objects_valid // Access: Published @@ -426,11 +445,13 @@ generate_hash(HashGenerator &hashgen) const { //////////////////////////////////////////////////////////////////// bool DCFile:: add_class(DCClass *dclass) { - bool inserted = _classes_by_name.insert - (ClassesByName::value_type(dclass->get_name(), dclass)).second; - - if (!inserted) { - return false; + if (!dclass->get_name().empty()) { + bool inserted = _things_by_name.insert + (ThingsByName::value_type(dclass->get_name(), dclass)).second; + + if (!inserted) { + return false; + } } dclass->set_number(get_num_classes()); @@ -447,6 +468,31 @@ add_class(DCClass *dclass) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: DCFile::add_switch +// Access: Public +// Description: Adds the newly-allocated switch definition +// to the file. The DCFile becomes the owner of the +// pointer and will delete it when it destructs. +// Returns true if the switch is successfully added, or +// false if there was a name conflict. +//////////////////////////////////////////////////////////////////// +bool DCFile:: +add_switch(DCSwitch *dswitch) { + if (!dswitch->get_name().empty()) { + bool inserted = _things_by_name.insert + (ThingsByName::value_type(dswitch->get_name(), dswitch)).second; + + if (!inserted) { + return false; + } + } + + _declarations.push_back(dswitch); + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: DCFile::add_import_module // Access: Public diff --git a/direct/src/dcparser/dcFile.h b/direct/src/dcparser/dcFile.h index c276124355..2cb2e638c2 100644 --- a/direct/src/dcparser/dcFile.h +++ b/direct/src/dcparser/dcFile.h @@ -20,8 +20,9 @@ #define DCFILE_H #include "dcbase.h" -#include "dcClass.h" +class DCClass; +class DCSwitch; class HashGenerator; class DCTypedef; class DCDeclaration; @@ -51,6 +52,7 @@ PUBLISHED: int get_num_classes() const; DCClass *get_class(int n) const; DCClass *get_class_by_name(const string &name) const; + DCSwitch *get_switch_by_name(const string &name) const; bool all_objects_valid() const; @@ -68,6 +70,7 @@ PUBLISHED: public: void generate_hash(HashGenerator &hashgen) const; bool add_class(DCClass *dclass); + bool add_switch(DCSwitch *dswitch); void add_import_module(const string &import_module); void add_import_symbol(const string &import_symbol); bool add_typedef(DCTypedef *dtypedef); @@ -76,8 +79,8 @@ private: typedef pvector Classes; Classes _classes; - typedef pmap ClassesByName; - ClassesByName _classes_by_name; + typedef pmap ThingsByName; + ThingsByName _things_by_name; typedef pvector ImportSymbols; class Import { diff --git a/direct/src/dcparser/dcMolecularField.cxx b/direct/src/dcparser/dcMolecularField.cxx index 1a0b6740a3..bc9d7e11d8 100644 --- a/direct/src/dcparser/dcMolecularField.cxx +++ b/direct/src/dcparser/dcMolecularField.cxx @@ -102,14 +102,13 @@ add_atomic(DCAtomicField *atomic) { } //////////////////////////////////////////////////////////////////// -// Function: DCMolecularField::write +// Function: DCMolecularField::output // Access: Public, Virtual -// Description: Generates a parseable description of the object to -// the indicated output stream. +// Description: //////////////////////////////////////////////////////////////////// void DCMolecularField:: -write(ostream &out, bool brief, int indent_level) const { - indent(out, indent_level) << _name; +output(ostream &out, bool brief) const { + out << _name; if (!_fields.empty()) { Fields::const_iterator fi = _fields.begin(); @@ -122,6 +121,18 @@ write(ostream &out, bool brief, int indent_level) const { } out << ";"; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCMolecularField::write +// Access: Public, Virtual +// Description: Generates a parseable description of the object to +// the indicated output stream. +//////////////////////////////////////////////////////////////////// +void DCMolecularField:: +write(ostream &out, bool brief, int indent_level) const { + indent(out, indent_level); + output(out, brief); if (!brief) { out << " // field " << _number; } diff --git a/direct/src/dcparser/dcMolecularField.h b/direct/src/dcparser/dcMolecularField.h index e8a82ca4eb..967743654b 100644 --- a/direct/src/dcparser/dcMolecularField.h +++ b/direct/src/dcparser/dcMolecularField.h @@ -45,6 +45,7 @@ PUBLISHED: public: void add_atomic(DCAtomicField *atomic); + virtual void output(ostream &out, bool brief) const; virtual void write(ostream &out, bool brief, int indent_level) const; virtual void generate_hash(HashGenerator &hashgen) const; diff --git a/direct/src/dcparser/dcPacker.I b/direct/src/dcparser/dcPacker.I index 83af1f5157..2c79001532 100755 --- a/direct/src/dcparser/dcPacker.I +++ b/direct/src/dcparser/dcPacker.I @@ -127,7 +127,7 @@ get_current_field() const { // get_current_parent() will contain the particular // SwitchCase that was selected by the switch. //////////////////////////////////////////////////////////////////// -INLINE const DCSwitch *DCPacker:: +INLINE const DCSwitchParameter *DCPacker:: get_last_switch() const { return _last_switch; } @@ -1122,9 +1122,9 @@ advance() { // But if the parent is a switch record, we make a special case so // we can get the alternate fields. if (_current_parent != (DCPackerInterface *)NULL) { - const DCSwitch *dswitch = ((DCPackerInterface *)_current_parent)->as_switch(); - if (dswitch != (DCSwitch *)NULL) { - handle_switch(dswitch); + const DCSwitchParameter *switch_parameter = ((DCPackerInterface *)_current_parent)->as_switch_parameter(); + if (switch_parameter != (DCSwitchParameter *)NULL) { + handle_switch(switch_parameter); } } diff --git a/direct/src/dcparser/dcPacker.cxx b/direct/src/dcparser/dcPacker.cxx index 6dfeb89cbc..597b8d6ec1 100755 --- a/direct/src/dcparser/dcPacker.cxx +++ b/direct/src/dcparser/dcPacker.cxx @@ -21,6 +21,7 @@ #include "dcParserDefs.h" #include "dcLexerDefs.h" #include "dcClassParameter.h" +#include "dcSwitchParameter.h" #include "dcClass.h" //////////////////////////////////////////////////////////////////// @@ -351,7 +352,7 @@ seek(const string &field_name) { const DCPackerCatalog::Entry &entry = _live_catalog->get_entry(entry_index); - if (((DCPackerInterface *)entry._parent)->as_switch() != (DCSwitch *)NULL) { + if (((DCPackerInterface *)entry._parent)->as_switch_parameter() != (DCSwitchParameter *)NULL) { // If the parent is a DCSwitch, that can only mean that the // seeked field is a switch parameter. We can't support seeking // to a switch parameter and modifying it directly--what would @@ -653,13 +654,20 @@ pack_object(PyObject *object) { } } else { + int size = PySequence_Size(object); + bool is_instance = false; + DCClass *dclass = NULL; const DCClassParameter *class_param = ((DCPackerInterface *)get_current_field())->as_class_parameter(); if (class_param != (DCClassParameter *)NULL) { dclass = class_param->get_class(); - } - int size = PySequence_Size(object); + if (dclass->has_class_def()) { + PyObject *class_def = dclass->get_class_def(); + is_instance = (PyObject_IsInstance(object, dclass->get_class_def()) != 0); + Py_DECREF(class_def); + } + } // If dclass is not NULL, the packer is expecting a class object. // There are then two cases: (1) the user has supplied a matching @@ -678,10 +686,7 @@ pack_object(PyObject *object) { // (3) Otherwise, it is considered to be a class object. - if (dclass != (DCClass *)NULL && - ((dclass->get_class_def() != (PyObject *)NULL && - PyObject_IsInstance(object, dclass->get_class_def())) || - size < 0)) { + if (dclass != (DCClass *)NULL && (is_instance || size < 0)) { // The supplied object is either an instance of the expected // class object, or the size is less than 0--this is case (1) or // (3). @@ -689,7 +694,7 @@ pack_object(PyObject *object) { } else if (size >= 0) { // The supplied object is not an instance of the expected class - // object, and it does return a valid size. This is case (2). + // object, but it does have a size. This is case (2). push(); int size = PySequence_Size(object); for (int i = 0; i < size; i++) { @@ -1021,20 +1026,19 @@ output_hex_string(ostream &out, const string &str) { // appropriate case of the switch record. //////////////////////////////////////////////////////////////////// void DCPacker:: -handle_switch(const DCSwitch *dswitch) { +handle_switch(const DCSwitchParameter *switch_parameter) { // First, get the value from the key. This is either found in the // unpack or the pack data, depending on what mode we're in. const DCPackerInterface *new_parent = NULL; if (_mode == M_pack || _mode == M_repack) { const char *data = _pack_data.get_data(); - new_parent = dswitch->apply_switch(data + _push_marker, - _pack_data.get_length() - _push_marker); + new_parent = switch_parameter->apply_switch + (data + _push_marker, _pack_data.get_length() - _push_marker); } else if (_mode == M_unpack) { - new_parent = dswitch->apply_switch(_unpack_data + _push_marker, - _unpack_p - _push_marker); - + new_parent = switch_parameter->apply_switch + (_unpack_data + _push_marker, _unpack_p - _push_marker); } if (new_parent == (DCPackerInterface *)NULL) { @@ -1043,7 +1047,7 @@ handle_switch(const DCSwitch *dswitch) { return; } - _last_switch = dswitch; + _last_switch = switch_parameter; // Now substitute in the switch case for the previous parent (which // replaces the switch node itself). This will suddenly make a slew diff --git a/direct/src/dcparser/dcPacker.h b/direct/src/dcparser/dcPacker.h index bef814f319..e665f3fc71 100755 --- a/direct/src/dcparser/dcPacker.h +++ b/direct/src/dcparser/dcPacker.h @@ -27,7 +27,7 @@ #include "dcPython.h" class DCClass; -class DCSwitch; +class DCSwitchParametera; //////////////////////////////////////////////////////////////////// // Class : DCPacker @@ -69,7 +69,7 @@ PUBLISHED: INLINE const DCPackerInterface *get_current_parent() const; INLINE const DCPackerInterface *get_current_field() const; - INLINE const DCSwitch *get_last_switch() const; + INLINE const DCSwitchParameter *get_last_switch() const; INLINE DCPackType get_pack_type() const; void push(); @@ -174,7 +174,7 @@ public: private: INLINE void advance(); - void handle_switch(const DCSwitch *dswitch); + void handle_switch(const DCSwitchParameter *switch_parameter); void clear(); #ifdef HAVE_PYTHON @@ -226,7 +226,7 @@ private: // use. size_t _pop_marker; int _num_nested_fields; - const DCSwitch *_last_switch; + const DCSwitchParameter *_last_switch; bool _pack_error; bool _range_error; diff --git a/direct/src/dcparser/dcPackerCatalog.cxx b/direct/src/dcparser/dcPackerCatalog.cxx index c1401ed708..900f285fae 100644 --- a/direct/src/dcparser/dcPackerCatalog.cxx +++ b/direct/src/dcparser/dcPackerCatalog.cxx @@ -19,7 +19,7 @@ #include "dcPackerCatalog.h" #include "dcPackerInterface.h" #include "dcPacker.h" -#include "dcSwitch.h" +#include "dcSwitchParameter.h" //////////////////////////////////////////////////////////////////// // Function: DCPackerCatalog::Constructor @@ -135,7 +135,7 @@ get_live_catalog(const char *data, size_t length) const { DCPacker packer; packer.set_unpack_data(data, length, false); packer.begin_unpack(_root); - const DCSwitch *last_switch = NULL; + const DCSwitchParameter *last_switch = NULL; r_fill_live_catalog(live_catalog, packer, last_switch); bool okflag = packer.end_unpack(); @@ -207,7 +207,7 @@ r_fill_catalog(const string &name_prefix, const DCPackerInterface *field, const DCPackerInterface *parent, int field_index) { string next_name_prefix = name_prefix; - if (!field->get_name().empty()) { + if (parent != (const DCPackerInterface *)NULL && !field->get_name().empty()) { // Record this entry in the catalog. next_name_prefix += field->get_name(); add_entry(next_name_prefix, field, parent, field_index); @@ -215,14 +215,14 @@ r_fill_catalog(const string &name_prefix, const DCPackerInterface *field, next_name_prefix += "."; } - const DCSwitch *dswitch = ((DCPackerInterface *)field)->as_switch(); - if (dswitch != (DCSwitch *)NULL) { + const DCSwitchParameter *switch_parameter = ((DCPackerInterface *)field)->as_switch_parameter(); + if (switch_parameter != (DCSwitchParameter *)NULL) { // If we come upon a DCSwitch while building the catalog, save the // name_prefix at this point so we'll have it again when we later // encounter the switch while unpacking a live record (and so we // can return to this point in the recursion from // update_switch_fields). - _switch_prefixes[dswitch] = next_name_prefix; + _switch_prefixes[switch_parameter] = next_name_prefix; } // Add any children. @@ -247,7 +247,7 @@ r_fill_catalog(const string &name_prefix, const DCPackerInterface *field, //////////////////////////////////////////////////////////////////// void DCPackerCatalog:: r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer, - const DCSwitch *&last_switch) const { + const DCSwitchParameter *&last_switch) const { const DCPackerInterface *current_field = packer.get_current_field(); int field_index = live_catalog->find_entry_by_field(current_field); @@ -281,6 +281,7 @@ r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer, nassertv(switch_case != (DCPackerInterface *)NULL); const DCPackerCatalog *switch_catalog = live_catalog->_catalog->update_switch_fields(last_switch, switch_case); + nassertv(switch_catalog != (DCPackerCatalog *)NULL); live_catalog->_catalog = switch_catalog; // And we also have to expand the live catalog to hold the new @@ -315,7 +316,7 @@ r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer, // pointer is kept by this object. //////////////////////////////////////////////////////////////////// const DCPackerCatalog *DCPackerCatalog:: -update_switch_fields(const DCSwitch *dswitch, +update_switch_fields(const DCSwitchParameter *switch_parameter, const DCPackerInterface *switch_case) const { SwitchCatalogs::const_iterator si = _switch_catalogs.find(switch_case); if (si != _switch_catalogs.end()) { @@ -326,7 +327,7 @@ update_switch_fields(const DCSwitch *dswitch, // descend from this switch. This should be stored in this record // because we must have come across the DCSwitch when building the // catalog the first time. - SwitchPrefixes::const_iterator pi = _switch_prefixes.find(dswitch); + SwitchPrefixes::const_iterator pi = _switch_prefixes.find(switch_parameter); nassertr(pi != _switch_prefixes.end(), NULL); string name_prefix = (*pi).second; diff --git a/direct/src/dcparser/dcPackerCatalog.h b/direct/src/dcparser/dcPackerCatalog.h index 7de471b940..0cb2d30012 100644 --- a/direct/src/dcparser/dcPackerCatalog.h +++ b/direct/src/dcparser/dcPackerCatalog.h @@ -23,7 +23,7 @@ class DCPackerInterface; class DCPacker; -class DCSwitch; +class DCSwitchParameter; //////////////////////////////////////////////////////////////////// // Class : DCPackerCatalog @@ -92,9 +92,9 @@ private: void r_fill_catalog(const string &name_prefix, const DCPackerInterface *field, const DCPackerInterface *parent, int field_index); void r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer, - const DCSwitch *&last_switch) const; + const DCSwitchParameter *&last_switch) const; - const DCPackerCatalog *update_switch_fields(const DCSwitch *dswitch, + const DCPackerCatalog *update_switch_fields(const DCSwitchParameter *dswitch, const DCPackerInterface *switch_case) const; @@ -113,7 +113,7 @@ private: typedef pmap SwitchCatalogs; SwitchCatalogs _switch_catalogs; - typedef pmap SwitchPrefixes; + typedef pmap SwitchPrefixes; SwitchPrefixes _switch_prefixes; friend class DCPackerInterface; diff --git a/direct/src/dcparser/dcPackerInterface.cxx b/direct/src/dcparser/dcPackerInterface.cxx index 5c5dac71df..6347721f9a 100755 --- a/direct/src/dcparser/dcPackerInterface.cxx +++ b/direct/src/dcparser/dcPackerInterface.cxx @@ -84,9 +84,9 @@ as_field() { // Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// -DCSwitch *DCPackerInterface:: -as_switch() { - return (DCSwitch *)NULL; +DCSwitchParameter *DCPackerInterface:: +as_switch_parameter() { + return (DCSwitchParameter *)NULL; } //////////////////////////////////////////////////////////////////// @@ -326,17 +326,5 @@ make_catalog() { nassertv(_catalog == (DCPackerCatalog *)NULL); _catalog = new DCPackerCatalog(this); - if (has_nested_fields()) { - int num_nested = get_num_nested_fields(); - // num_nested might be -1, indicating there are a dynamic number - // of fields (e.g. an array). But in that case, none of the - // fields will be named anyway, so we don't care about them, so - // it's ok that the following loop will not visit any fields. - for (int i = 0; i < num_nested; i++) { - DCPackerInterface *nested = get_nested_field(i); - if (nested != (DCPackerInterface *)NULL) { - _catalog->r_fill_catalog("", nested, this, i); - } - } - } + _catalog->r_fill_catalog("", this, NULL, 0); } diff --git a/direct/src/dcparser/dcPackerInterface.h b/direct/src/dcparser/dcPackerInterface.h index 2fb1f7e4a6..bf611df915 100755 --- a/direct/src/dcparser/dcPackerInterface.h +++ b/direct/src/dcparser/dcPackerInterface.h @@ -23,7 +23,7 @@ #include "dcSubatomicType.h" class DCField; -class DCSwitch; +class DCSwitchParameter; class DCClassParameter; class DCPackData; class DCPackerCatalog; @@ -77,7 +77,7 @@ PUBLISHED: INLINE const string &get_name() const; virtual DCField *as_field(); - virtual DCSwitch *as_switch(); + virtual DCSwitchParameter *as_switch_parameter(); virtual DCClassParameter *as_class_parameter(); public: @@ -159,6 +159,9 @@ public: const DCPackerCatalog *get_catalog() const; +private: + void make_catalog(); + protected: string _name; bool _has_fixed_byte_size; @@ -170,8 +173,6 @@ protected: DCPackType _pack_type; private: - void make_catalog(); - DCPackerCatalog *_catalog; }; diff --git a/direct/src/dcparser/dcParameter.cxx b/direct/src/dcparser/dcParameter.cxx index 500a8d1006..d5e677e50c 100644 --- a/direct/src/dcparser/dcParameter.cxx +++ b/direct/src/dcparser/dcParameter.cxx @@ -122,7 +122,7 @@ set_typedef(const DCTypedef *dtypedef) { //////////////////////////////////////////////////////////////////// // Function: DCParameter::output -// Access: Public +// Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// void DCParameter:: @@ -131,21 +131,34 @@ output(ostream &out, bool brief) const { if (!brief) { name = get_name(); } - output_instance(out, "", name, ""); + output_instance(out, brief, "", name, ""); } //////////////////////////////////////////////////////////////////// // Function: DCParameter::write -// Access: Public +// Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// void DCParameter:: -write(ostream &out, bool, int indent_level) const { +write(ostream &out, bool brief, int indent_level) const { // we must always output the name when the parameter occurs by - // itself within a class, so we ignore brief and pass false up to - // output(). + // itself within a class, so we pass get_name() even if brief is + // true. + write_instance(out, brief, indent_level, "", get_name(), ""); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCParameter::write_instance +// Access: Public, Virtual +// Description: Formats the parameter in the C++-like dc syntax as a +// typename and identifier. +//////////////////////////////////////////////////////////////////// +void DCParameter:: +write_instance(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const { indent(out, indent_level); - output(out, false); + output_instance(out, brief, prename, name, postname); out << ";\n"; } @@ -156,14 +169,31 @@ write(ostream &out, bool, int indent_level) const { // the typedef name instead. //////////////////////////////////////////////////////////////////// void DCParameter:: -output_typedef_name(ostream &out, const string &prename, const string &name, - const string &postname) const { +output_typedef_name(ostream &out, bool, const string &prename, + const string &name, const string &postname) const { out << get_typedef()->get_name(); if (!prename.empty() || !name.empty() || !postname.empty()) { out << " " << prename << name << postname; } } +//////////////////////////////////////////////////////////////////// +// Function: DCParameter::write_typedef_name +// Access: Public +// Description: Formats the instance like write_instance, but uses +// the typedef name instead. +//////////////////////////////////////////////////////////////////// +void DCParameter:: +write_typedef_name(ostream &out, bool, int indent_level, const string &prename, + const string &name, const string &postname) const { + indent(out, indent_level) + << get_typedef()->get_name(); + if (!prename.empty() || !name.empty() || !postname.empty()) { + out << " " << prename << name << postname; + } + out << ";\n"; +} + //////////////////////////////////////////////////////////////////// // Function: DCParameter::generate_hash // Access: Public, Virtual diff --git a/direct/src/dcparser/dcParameter.h b/direct/src/dcparser/dcParameter.h index 6b719b78c6..645710ea59 100644 --- a/direct/src/dcparser/dcParameter.h +++ b/direct/src/dcparser/dcParameter.h @@ -60,12 +60,18 @@ PUBLISHED: public: void set_typedef(const DCTypedef *dtypedef); - void output(ostream &out, bool brief) const; + virtual void output(ostream &out, bool brief) const; virtual void write(ostream &out, bool brief, int indent_level) const; - virtual void output_instance(ostream &out, const string &prename, + virtual void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const=0; - void output_typedef_name(ostream &out, const string &prename, + virtual void write_instance(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const; + void output_typedef_name(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const; + void write_typedef_name(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; private: diff --git a/direct/src/dcparser/dcParser.yxx b/direct/src/dcparser/dcParser.yxx index 93570de706..4dec372889 100644 --- a/direct/src/dcparser/dcParser.yxx +++ b/direct/src/dcparser/dcParser.yxx @@ -12,6 +12,7 @@ #include "dcAtomicField.h" #include "dcMolecularField.h" #include "dcClassParameter.h" +#include "dcSwitchParameter.h" #include "dcArrayParameter.h" #include "dcSimpleParameter.h" #include "dcTypedef.h" @@ -116,12 +117,13 @@ dc_cleanup_parser() { %type kw_struct_or_kw_dclass %type dclass_name +%type dclass +%type switch %type atomic_name %type dclass_field %type switch_field %type atomic_field %type molecular_field -%type switch %type type_token %type type_name %type type_definition @@ -150,24 +152,37 @@ dc: empty | dc ';' | dc dclass +{ + if (!dc_file->add_class($2)) { + DCClass *old_class = dc_file->get_class_by_name($2->get_name()); + if (old_class != (DCClass *)NULL && old_class->is_bogus_class()) { + yyerror("Base class defined after its first reference: " + $2->get_name()); + } else { + yyerror("Duplicate class name: " + $2->get_name()); + } + } +} + | dc switch +{ + if (!dc_file->add_switch($2)) { + yyerror("Duplicate class name: " + $2->get_name()); + } +} | dc import | dc typedef_decl ; dclass: - kw_struct_or_kw_dclass IDENTIFIER + kw_struct_or_kw_dclass optional_name { + $$ = current_class; current_class = new DCClass($2, $1, false); - if (!dc_file->add_class(current_class)) { - DCClass *old_class = dc_file->get_class_by_name(current_class->get_name()); - if (old_class->is_bogus_class()) { - yyerror("Base class defined after its first reference: " + current_class->get_name()); - } else { - yyerror("Duplicate class name: " + current_class->get_name()); - } - } } dclass_derivation '{' dclass_fields '}' +{ + $$ = current_class; + current_class = $3; +} ; kw_struct_or_kw_dclass: @@ -291,7 +306,6 @@ dclass_fields: dclass_field: atomic_field | molecular_field - | switch | unnamed_parameter ';' { $$ = $1; @@ -332,6 +346,7 @@ atomic_element: | parameter '=' { current_packer = &default_packer; + current_packer->clear_data(); current_packer->begin_pack($1); } parameter_value @@ -435,14 +450,29 @@ type_name: // Create an implicit typedef for this. dtypedef = new DCTypedef(new DCClassParameter(dclass), true); } else { - // It's an undefined typedef. Create a bogus forward reference. - dtypedef = new DCTypedef($1); + // Maybe it's a switch name. + DCSwitch *dswitch = dc_file->get_switch_by_name($1); + if (dswitch != (DCSwitch *)NULL) { + // This also gets an implicit typedef. + dtypedef = new DCTypedef(new DCSwitchParameter(dswitch), true); + } else { + // It's an undefined typedef. Create a bogus forward reference. + dtypedef = new DCTypedef($1); + } } dc_file->add_typedef(dtypedef); } $$ = dtypedef->make_new_parameter(); +} + | dclass +{ + $$ = new DCClassParameter($1); +} + | switch +{ + $$ = new DCSwitchParameter($1); } ; @@ -917,6 +947,7 @@ switch_case: KW_CASE { current_packer = &default_packer; + current_packer->clear_data(); current_packer->begin_pack(current_switch->get_key_parameter()); } parameter_value ':' @@ -930,8 +961,7 @@ switch_case: ; switch_field: - switch - | unnamed_parameter ';' + unnamed_parameter ';' { $$ = $1; } diff --git a/direct/src/dcparser/dcParserDefs.h b/direct/src/dcparser/dcParserDefs.h index d344b00963..0ebf5b4e88 100644 --- a/direct/src/dcparser/dcParserDefs.h +++ b/direct/src/dcparser/dcParserDefs.h @@ -24,6 +24,7 @@ class DCFile; class DCClass; +class DCSwitch; class DCField; class DCAtomicField; class DCParameter; @@ -52,6 +53,7 @@ public: double real; bool flag; DCClass *dclass; + DCSwitch *dswitch; DCField *field; DCAtomicField *atomic; DCSubatomicType subatomic; diff --git a/direct/src/dcparser/dcSimpleParameter.cxx b/direct/src/dcparser/dcSimpleParameter.cxx index 5e5b69fcf2..016bdc32f8 100644 --- a/direct/src/dcparser/dcSimpleParameter.cxx +++ b/direct/src/dcparser/dcSimpleParameter.cxx @@ -1942,10 +1942,10 @@ unpack_skip(const char *data, size_t length, size_t &p) const { // typename and identifier. //////////////////////////////////////////////////////////////////// void DCSimpleParameter:: -output_instance(ostream &out, const string &prename, const string &name, - const string &postname) const { +output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const { if (get_typedef() != (DCTypedef *)NULL) { - output_typedef_name(out, prename, name, postname); + output_typedef_name(out, brief, prename, name, postname); } else { out << _type; diff --git a/direct/src/dcparser/dcSimpleParameter.h b/direct/src/dcparser/dcSimpleParameter.h index 584e578860..bdb6498ba7 100644 --- a/direct/src/dcparser/dcSimpleParameter.h +++ b/direct/src/dcparser/dcSimpleParameter.h @@ -82,7 +82,7 @@ public: bool &pack_error, bool &range_error) const; virtual bool unpack_skip(const char *data, size_t length, size_t &p) const; - virtual void output_instance(ostream &out, const string &prename, + virtual void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; diff --git a/direct/src/dcparser/dcSwitch.cxx b/direct/src/dcparser/dcSwitch.cxx index 5e781d2e4a..3def86aac1 100644 --- a/direct/src/dcparser/dcSwitch.cxx +++ b/direct/src/dcparser/dcSwitch.cxx @@ -29,21 +29,9 @@ //////////////////////////////////////////////////////////////////// DCSwitch:: DCSwitch(const string &name, DCParameter *key_parameter) : - DCField(name), + _name(name), _key_parameter(key_parameter) { - _has_fixed_byte_size = _key_parameter->has_fixed_byte_size(); - _fixed_byte_size = _key_parameter->get_fixed_byte_size(); - _has_fixed_structure = false; - - // The DCSwitch presents just one nested field initially, which is - // the key parameter. When we pack or unpack that, the DCPacker - // calls apply_switch(), which returns a new record that presents - // the remaining nested fields. - _has_nested_fields = true; - _num_nested_fields = 1; - - _pack_type = PT_switch; } //////////////////////////////////////////////////////////////////// @@ -72,6 +60,16 @@ as_switch() { return this; } +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::get_name +// Access: Published +// Description: Returns the name of this switch. +//////////////////////////////////////////////////////////////////// +const string &DCSwitch:: +get_name() const { + return _name; +} + //////////////////////////////////////////////////////////////////// // Function: DCSwitch::get_key_parameter // Access: Published @@ -115,6 +113,17 @@ get_case_by_value(const string &case_value) const { return -1; } +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::get_case +// Access: Published +// Description: Returns the DCPackerInterface that packs the nth case. +//////////////////////////////////////////////////////////////////// +DCPackerInterface *DCSwitch:: +get_case(int n) const { + nassertr(n >= 0 && n < (int)_cases.size(), NULL); + return _cases[n]; +} + //////////////////////////////////////////////////////////////////// // Function: DCSwitch::get_value // Access: Published @@ -170,23 +179,6 @@ get_field_by_name(int case_index, const string &name) const { return NULL; } -//////////////////////////////////////////////////////////////////// -// Function: DCSwitch::get_nested_field -// Access: Public, Virtual -// Description: Returns the DCPackerInterface object that represents -// the nth nested field. This may return NULL if there -// is no such field (but it shouldn't do this if n is in -// the range 0 <= n < get_num_nested_fields()). -//////////////////////////////////////////////////////////////////// -DCPackerInterface *DCSwitch:: -get_nested_field(int) const { - // The DCSwitch presents just one nested field initially, which is - // the key parameter. When we pack or unpack that, the DCPacker - // calls apply_switch(), which returns a new record that presents - // the remaining nested fields. - return _key_parameter; -} - //////////////////////////////////////////////////////////////////// // Function: DCSwitch::add_case // Access: Public @@ -225,26 +217,6 @@ add_field(DCField *field) { if (!_cases.back()->add_field(field)) { return false; } - - // See if we now have a fixed byte size for the overall switch. - // This will be true only if all of the individual cases have the - // same fixed byte size. - _fixed_byte_size = _cases.back()->get_fixed_byte_size(); - - Cases::const_iterator ci; - for (ci = _cases.begin(); ci != _cases.end(); ++ci) { - const SwitchCase *dcase = (*ci); - if (!dcase->has_fixed_byte_size() || - dcase->get_fixed_byte_size() != _fixed_byte_size) { - - // Nope, we have a variable byte size. - _has_fixed_byte_size = false; - return true; - } - } - - // Sonofagun, we do have a fixed byte size. - _has_fixed_byte_size = true; return true; } @@ -276,6 +248,58 @@ apply_switch(const char *value_data, size_t length) const { //////////////////////////////////////////////////////////////////// void DCSwitch:: write(ostream &out, bool brief, int indent_level) const { + write_instance(out, brief, indent_level, "", "", ""); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCClass::output_instance +// Access: Public +// Description: Generates a parseable description of the object to +// the indicated output stream. +//////////////////////////////////////////////////////////////////// +void DCSwitch:: +output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const { + out << "switch"; + if (!_name.empty()) { + out << " " << _name; + } + out << " ("; + _key_parameter->output(out, brief); + out << ") {"; + + Cases::const_iterator ci; + for (ci = _cases.begin(); ci != _cases.end(); ++ci) { + const SwitchCase *dcase = (*ci); + out << "case " << _key_parameter->format_data(dcase->_value) << ": "; + + Fields::const_iterator fi; + if (!dcase->_fields.empty()) { + fi = dcase->_fields.begin(); + ++fi; + while (fi != dcase->_fields.end()) { + (*fi)->output(out, brief); + out << "; "; + ++fi; + } + } + } + out << "}"; + if (!prename.empty() || !name.empty() || !postname.empty()) { + out << " " << prename << name << postname; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::write_instance +// Access: Public, Virtual +// Description: Generates a parseable description of the object to +// the indicated output stream. +//////////////////////////////////////////////////////////////////// +void DCSwitch:: +write_instance(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const { indent(out, indent_level) << "switch"; if (!_name.empty()) { @@ -302,7 +326,11 @@ write(ostream &out, bool brief, int indent_level) const { } } indent(out, indent_level) - << "};\n"; + << "}"; + if (!prename.empty() || !name.empty() || !postname.empty()) { + out << " " << prename << name << postname; + } + out << ";\n"; } //////////////////////////////////////////////////////////////////// @@ -313,7 +341,7 @@ write(ostream &out, bool brief, int indent_level) const { //////////////////////////////////////////////////////////////////// void DCSwitch:: generate_hash(HashGenerator &hashgen) const { - DCField::generate_hash(hashgen); + hashgen.add_string(_name); _key_parameter->generate_hash(hashgen); diff --git a/direct/src/dcparser/dcSwitch.h b/direct/src/dcparser/dcSwitch.h index ee0363dafa..667a5dfd4b 100644 --- a/direct/src/dcparser/dcSwitch.h +++ b/direct/src/dcparser/dcSwitch.h @@ -20,7 +20,7 @@ #define DCSWITCH_H #include "dcbase.h" -#include "dcField.h" +#include "dcDeclaration.h" //////////////////////////////////////////////////////////////////// // Class : DCSwitch @@ -29,7 +29,7 @@ // alternative unpacking schemes based on the first // field read. //////////////////////////////////////////////////////////////////// -class EXPCL_DIRECT DCSwitch : public DCField { +class EXPCL_DIRECT DCSwitch : public DCDeclaration { public: DCSwitch(const string &name, DCParameter *key_parameter); virtual ~DCSwitch(); @@ -37,10 +37,12 @@ public: PUBLISHED: virtual DCSwitch *as_switch(); + const string &get_name() const; DCParameter *get_key_parameter() const; int get_num_cases() const; int get_case_by_value(const string &case_value) const; + DCPackerInterface *get_case(int n) const; string get_value(int case_index) const; int get_num_fields(int case_index) const; @@ -48,17 +50,21 @@ PUBLISHED: DCField *get_field_by_name(int case_index, const string &name) const; public: - virtual DCPackerInterface *get_nested_field(int n) const; - int add_case(const string &value); bool add_field(DCField *field); const DCPackerInterface *apply_switch(const char *value_data, size_t length) const; virtual void write(ostream &out, bool brief, int indent_level) const; + void output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const; + void write_instance(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; private: + string _name; DCParameter *_key_parameter; typedef pvector Fields; diff --git a/direct/src/dcparser/dcSwitchParameter.cxx b/direct/src/dcparser/dcSwitchParameter.cxx new file mode 100755 index 0000000000..c368d844f5 --- /dev/null +++ b/direct/src/dcparser/dcSwitchParameter.cxx @@ -0,0 +1,198 @@ +// Filename: dcSwitchParameter.cxx +// Created by: drose (18Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "dcSwitchParameter.h" +#include "dcSwitch.h" +#include "hashGenerator.h" + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +DCSwitchParameter:: +DCSwitchParameter(DCSwitch *dswitch) : + _dswitch(dswitch) +{ + set_name(dswitch->get_name()); + + _has_fixed_byte_size = false; + _has_fixed_structure = false; + + // The DCSwitch presents just one nested field initially, which is + // the key parameter. When we pack or unpack that, the DCPacker + // calls apply_switch(), which returns a new record that presents + // the remaining nested fields. + _has_nested_fields = true; + _num_nested_fields = 1; + + _pack_type = PT_switch; + + DCParameter *key_parameter = dswitch->get_key_parameter(); + if (key_parameter->has_fixed_byte_size()) { + // See if we have a fixed byte size for the overall switch. This + // will be true only if all of the individual cases have the same + // fixed byte size. + int num_cases = _dswitch->get_num_cases(); + _has_fixed_byte_size = true; + _fixed_byte_size = 0; + + if (num_cases > 0) { + _fixed_byte_size = _dswitch->get_case(0)->get_fixed_byte_size(); + + for (int i = 0; i < num_cases && _has_fixed_byte_size; i++) { + const DCPackerInterface *dcase = _dswitch->get_case(i); + if (!dcase->has_fixed_byte_size() || + dcase->get_fixed_byte_size() != _fixed_byte_size) { + + // Nope, we have a variable byte size. + _has_fixed_byte_size = false; + } + } + } + + _fixed_byte_size += key_parameter->get_fixed_byte_size(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +DCSwitchParameter:: +DCSwitchParameter(const DCSwitchParameter ©) : + DCParameter(copy), + _dswitch(copy._dswitch) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::as_switch_parameter +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DCSwitchParameter *DCSwitchParameter:: +as_switch_parameter() { + return this; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::make_copy +// Access: Published, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DCParameter *DCSwitchParameter:: +make_copy() const { + return new DCSwitchParameter(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::is_valid +// Access: Published, Virtual +// Description: Returns false if the type is an invalid type +// (e.g. declared from an undefined typedef), true if +// it is valid. +//////////////////////////////////////////////////////////////////// +bool DCSwitchParameter:: +is_valid() const { + return true; //_dswitch->is_valid(); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::get_switch +// Access: Published +// Description: Returns the switch object this parameter represents. +//////////////////////////////////////////////////////////////////// +DCSwitch *DCSwitchParameter:: +get_switch() const { + return _dswitch; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::get_nested_field +// Access: Public, Virtual +// Description: Returns the DCPackerInterface object that represents +// the nth nested field. This may return NULL if there +// is no such field (but it shouldn't do this if n is in +// the range 0 <= n < get_num_nested_fields()). +//////////////////////////////////////////////////////////////////// +DCPackerInterface *DCSwitchParameter:: +get_nested_field(int) const { + return _dswitch->get_key_parameter(); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::apply_switch +// Access: Public +// Description: Returns the DCPackerInterface that presents the +// alternative fields for the case indicated by the +// given packed value string, or NULL if the value +// string does not match one of the expected cases. +//////////////////////////////////////////////////////////////////// +const DCPackerInterface *DCSwitchParameter:: +apply_switch(const char *value_data, size_t length) const { + return _dswitch->apply_switch(value_data, length); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::output_instance +// Access: Public, Virtual +// Description: Formats the parameter in the C++-like dc syntax as a +// typename and identifier. +//////////////////////////////////////////////////////////////////// +void DCSwitchParameter:: +output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const { + if (get_typedef() != (DCTypedef *)NULL) { + output_typedef_name(out, brief, prename, name, postname); + + } else { + _dswitch->output_instance(out, brief, prename, name, postname); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::write_instance +// Access: Public, Virtual +// Description: Formats the parameter in the C++-like dc syntax as a +// typename and identifier. +//////////////////////////////////////////////////////////////////// +void DCSwitchParameter:: +write_instance(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const { + if (get_typedef() != (DCTypedef *)NULL) { + write_typedef_name(out, brief, indent_level, prename, name, postname); + + } else { + _dswitch->write_instance(out, brief, indent_level, prename, name, postname); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::generate_hash +// Access: Public, Virtual +// Description: Accumulates the properties of this type into the +// hash. +//////////////////////////////////////////////////////////////////// +void DCSwitchParameter:: +generate_hash(HashGenerator &hashgen) const { + DCParameter::generate_hash(hashgen); + _dswitch->generate_hash(hashgen); +} diff --git a/direct/src/dcparser/dcSwitchParameter.h b/direct/src/dcparser/dcSwitchParameter.h new file mode 100755 index 0000000000..30de81ff59 --- /dev/null +++ b/direct/src/dcparser/dcSwitchParameter.h @@ -0,0 +1,61 @@ +// Filename: dcClassParameter.h +// Created by: drose (29Jun04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef DCSWITCHPARAMETER_H +#define DCSWITCHPARAMETER_H + +#include "dcbase.h" +#include "dcParameter.h" + +class DCSwitch; + +//////////////////////////////////////////////////////////////////// +// Class : DCSwitchParameter +// Description : This represents a switch object used as a +// parameter itself, which packs the appropriate fields +// of the switch into the message. +//////////////////////////////////////////////////////////////////// +class EXPCL_DIRECT DCSwitchParameter : public DCParameter { +public: + DCSwitchParameter(DCSwitch *dswitch); + DCSwitchParameter(const DCSwitchParameter ©); + +PUBLISHED: + virtual DCSwitchParameter *as_switch_parameter(); + virtual DCParameter *make_copy() const; + virtual bool is_valid() const; + + DCSwitch *get_switch() const; + +public: + virtual DCPackerInterface *get_nested_field(int n) const; + + const DCPackerInterface *apply_switch(const char *value_data, size_t length) const; + + virtual void output_instance(ostream &out, bool brief, const string &prename, + const string &name, const string &postname) const; + virtual void write_instance(ostream &out, bool brief, int indent_level, + const string &prename, const string &name, + const string &postname) const; + virtual void generate_hash(HashGenerator &hashgen) const; + +private: + DCSwitch *_dswitch; +}; + +#endif diff --git a/direct/src/dcparser/dcparser_composite2.cxx b/direct/src/dcparser/dcparser_composite2.cxx index 3d13c9d39d..4be8fa3ee0 100644 --- a/direct/src/dcparser/dcparser_composite2.cxx +++ b/direct/src/dcparser/dcparser_composite2.cxx @@ -3,6 +3,7 @@ #include "dcClassParameter.cxx" #include "dcArrayParameter.cxx" #include "dcSimpleParameter.cxx" +#include "dcSwitchParameter.cxx" #include "dcField.cxx" #include "dcFile.cxx" #include "dcMolecularField.cxx"