From 68bdff57eb842ae2897515cb65644f2855de52d7 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 10 Jan 2006 17:10:50 +0000 Subject: [PATCH] add virtual inheritance --- direct/src/dcparser/Sources.pp | 3 +- direct/src/dcparser/dcClass.I | 22 +++ direct/src/dcparser/dcClass.cxx | 186 +++++++++++++----- direct/src/dcparser/dcClass.h | 15 +- direct/src/dcparser/dcField.I | 226 ++++++++++++++++++++++ direct/src/dcparser/dcField.cxx | 198 ++----------------- direct/src/dcparser/dcField.h | 38 ++-- direct/src/dcparser/dcFile.I | 58 ++++++ direct/src/dcparser/dcFile.cxx | 41 ++-- direct/src/dcparser/dcFile.h | 8 +- direct/src/dcparser/dcPackerInterface.I | 10 - direct/src/dcparser/dcPackerInterface.cxx | 10 + direct/src/dcparser/dcPackerInterface.h | 2 +- 13 files changed, 537 insertions(+), 280 deletions(-) create mode 100644 direct/src/dcparser/dcField.I create mode 100644 direct/src/dcparser/dcFile.I diff --git a/direct/src/dcparser/Sources.pp b/direct/src/dcparser/Sources.pp index 8b0003cba2..60117c4ef8 100644 --- a/direct/src/dcparser/Sources.pp +++ b/direct/src/dcparser/Sources.pp @@ -18,7 +18,8 @@ #define SOURCES \ dcAtomicField.h dcClass.h dcClass.I \ dcDeclaration.h \ - dcField.h dcFile.h \ + dcField.h dcField.I \ + dcFile.h dcFile.I \ dcKeyword.h dcKeywordList.h \ dcLexer.lxx \ dcLexerDefs.h dcMolecularField.h dcParser.yxx dcParserDefs.h \ diff --git a/direct/src/dcparser/dcClass.I b/direct/src/dcparser/dcClass.I index a9e579cf41..b70e913bdd 100644 --- a/direct/src/dcparser/dcClass.I +++ b/direct/src/dcparser/dcClass.I @@ -27,6 +27,28 @@ get_dc_file() const { return _dc_file; } +//////////////////////////////////////////////////////////////////// +// Function: DCClass::get_name +// Access: Published +// Description: Returns the name of this class. +//////////////////////////////////////////////////////////////////// +INLINE const string &DCClass:: +get_name() const { + return _name; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCClass::get_number +// Access: Published +// Description: Returns a unique index number associated with this +// class. This is defined implicitly when the .dc +// file(s) are read. +//////////////////////////////////////////////////////////////////// +INLINE int DCClass:: +get_number() const { + return _number; +} + //////////////////////////////////////////////////////////////////// // Function: DCClass::is_struct // Access: Published diff --git a/direct/src/dcparser/dcClass.cxx b/direct/src/dcparser/dcClass.cxx index 756ca27bea..34c7824972 100644 --- a/direct/src/dcparser/dcClass.cxx +++ b/direct/src/dcparser/dcClass.cxx @@ -40,8 +40,22 @@ ConfigVariableBool dc_multiple_inheritance "supported, but field numbers will be numbered sequentially, " "which may be required to support old code that assumed this.")); +ConfigVariableBool dc_virtual_inheritance +("dc-virtual-inheritance", false, + PRC_DESC("Set this true to support proper virtual inheritance in the " + "dc file, so that diamond-of-death type constructs can be used. " + "This also enables shadowing (overloading) of inherited method " + "names from a base class.")); + #endif // WITHIN_PANDA +class SortFieldsByIndex { +public: + inline bool operator ()(const DCField *a, const DCField *b) const { + return a->get_number() < b->get_number(); + } +}; + //////////////////////////////////////////////////////////////////// // Function: DCClass::Constructor // Access: Public @@ -110,49 +124,26 @@ as_class() const { } //////////////////////////////////////////////////////////////////// -// Function: DCClass::get_name +// Function: DCClass::get_num_parents // Access: Published -// Description: Returns the name of this class. -//////////////////////////////////////////////////////////////////// -const string &DCClass:: -get_name() const { - return _name; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCClass::get_number -// Access: Published -// Description: Returns a unique index number associated with this -// class. This is defined implicitly when the .dc -// file(s) are read. +// Description: Returns the number of base classes this class +// inherits from. //////////////////////////////////////////////////////////////////// int DCClass:: -get_number() const { - return _number; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCClass::has_parent -// Access: Published -// Description: Returns true if this class inherits from some other -// class, false if it does not. -//////////////////////////////////////////////////////////////////// -bool DCClass:: -has_parent() const { - return !_parents.empty(); +get_num_parents() const { + return _parents.size(); } //////////////////////////////////////////////////////////////////// // Function: DCClass::get_parent // Access: Published -// Description: Returns the parent class this class inherits from, if -// any. It is an error to call this unless has_parent() -// returned true. +// Description: Returns the nth parent class this class inherits +// from. //////////////////////////////////////////////////////////////////// DCClass *DCClass:: -get_parent() const { - nassertr(has_parent(), NULL); - return _parents.front(); +get_parent(int n) const { + nassertr(n >= 0 && n < (int)_parents.size(), NULL); + return _parents[n]; } //////////////////////////////////////////////////////////////////// @@ -283,14 +274,25 @@ get_field_by_index(int index_number) const { //////////////////////////////////////////////////////////////////// int DCClass:: get_num_inherited_fields() const { - int num_fields = get_num_fields(); + if (dc_virtual_inheritance) { + if (_dc_file != (DCFile *)NULL) { + _dc_file->check_inherited_fields(); + } + if (_inherited_fields.empty()) { + ((DCClass *)this)->rebuild_inherited_fields(); + } + return (int)_inherited_fields.size(); - Parents::const_iterator pi; - for (pi = _parents.begin(); pi != _parents.end(); ++pi) { - num_fields += (*pi)->get_num_inherited_fields(); + } else { + int num_fields = get_num_fields(); + + Parents::const_iterator pi; + for (pi = _parents.begin(); pi != _parents.end(); ++pi) { + num_fields += (*pi)->get_num_inherited_fields(); + } + + return num_fields; } - - return num_fields; } //////////////////////////////////////////////////////////////////// @@ -307,17 +309,29 @@ get_num_inherited_fields() const { //////////////////////////////////////////////////////////////////// DCField *DCClass:: get_inherited_field(int n) const { - Parents::const_iterator pi; - for (pi = _parents.begin(); pi != _parents.end(); ++pi) { - int psize = (*pi)->get_num_inherited_fields(); - if (n < psize) { - return (*pi)->get_inherited_field(n); + if (dc_virtual_inheritance) { + if (_dc_file != (DCFile *)NULL) { + _dc_file->check_inherited_fields(); } + if (_inherited_fields.empty()) { + ((DCClass *)this)->rebuild_inherited_fields(); + } + nassertr(n >= 0 && n < (int)_inherited_fields.size(), NULL); + return _inherited_fields[n]; - n -= psize; + } else { + Parents::const_iterator pi; + for (pi = _parents.begin(); pi != _parents.end(); ++pi) { + int psize = (*pi)->get_num_inherited_fields(); + if (n < psize) { + return (*pi)->get_inherited_field(n); + } + + n -= psize; + } + + return get_field(n); } - - return get_field(n); } //////////////////////////////////////////////////////////////////// @@ -1263,6 +1277,75 @@ generate_hash(HashGenerator &hashgen) const { } } +//////////////////////////////////////////////////////////////////// +// Function: DCClass::clear_inherited_fields +// Access: Public +// Description: Empties the list of inherited fields for the class, +// so that it may be rebuilt. This is normally only +// called by DCFile::rebuild_inherited_fields(). +//////////////////////////////////////////////////////////////////// +void DCClass:: +clear_inherited_fields() { + _inherited_fields.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCClass::rebuild_inherited_fields +// Access: Public +// Description: Recomputes the list of inherited fields for the class. +//////////////////////////////////////////////////////////////////// +void DCClass:: +rebuild_inherited_fields() { + typedef pset Names; + Names names; + + _inherited_fields.clear(); + + // First, get a list of all of the inherited field names. + Parents::const_iterator pi; + for (pi = _parents.begin(); pi != _parents.end(); ++pi) { + const DCClass *parent = (*pi); + int num_inherited_fields = parent->get_num_inherited_fields(); + for (int i = 0; i < num_inherited_fields; ++i) { + const DCField *field = parent->get_inherited_field(i); + names.insert(field->get_name()); + } + } + + // Also get the local field names. Any local unnamed fields are + // immediately added to the _inherited_fields list, since the + // unnamed fields are not inherited. + Fields::const_iterator fi; + for (fi = _fields.begin(); fi != _fields.end(); ++fi) { + DCField *field = (*fi); + if (field->get_name().empty()) { + _inherited_fields.push_back(field); + } else { + names.insert(field->get_name()); + } + } + + // And now build up the table. We use get_field_by_name() to + // extract each one, to guarantee that the index we build exactly + // matches the return value of get_field_by_name(). + + Names::const_iterator ni; + for (ni = names.begin(); ni != names.end(); ++ni) { + // Note that we only list the named fields in the inherited field + // list. Thus, the unnamed fields, if any, are not inherited. + if (!(*ni).empty()) { + DCField *field = get_field_by_name(*ni); + nassertv(field != (DCField *)NULL); + _inherited_fields.push_back(field); + } + } + + // Finally, sort the list in global field index order. This will + // put the inherited fields at the top of the list. + ::sort(_inherited_fields.begin(), _inherited_fields.end(), + SortFieldsByIndex()); +} + //////////////////////////////////////////////////////////////////// // Function: DCClass::add_field // Access: Public @@ -1270,10 +1353,16 @@ generate_hash(HashGenerator &hashgen) const { // class becomes the owner of the pointer and will // delete it when it destructs. Returns true if the // field is successfully added, or false if there was a -// name conflict. +// name conflict or some other problem. //////////////////////////////////////////////////////////////////// bool DCClass:: add_field(DCField *field) { + nassertr(field->get_class() == this || field->get_class() == NULL, false); + field->set_class(this); + if (_dc_file != (DCFile *)NULL) { + _dc_file->mark_inherited_fields_stale(); + } + if (!field->get_name().empty()) { if (field->get_name() == _name) { // This field is a constructor. @@ -1326,6 +1415,7 @@ add_field(DCField *field) { void DCClass:: add_parent(DCClass *parent) { _parents.push_back(parent); + _dc_file->mark_inherited_fields_stale(); } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcClass.h b/direct/src/dcparser/dcClass.h index f23d6637b4..92c6bacb5b 100644 --- a/direct/src/dcparser/dcClass.h +++ b/direct/src/dcparser/dcClass.h @@ -29,10 +29,12 @@ #include "configVariableBool.h" extern ConfigVariableBool dc_multiple_inheritance; +extern ConfigVariableBool dc_virtual_inheritance; #else // WITHIN_PANDA static const bool dc_multiple_inheritance = true; +static const bool dc_virtual_inheritance = true; #endif // WITHIN_PANDA @@ -56,17 +58,18 @@ PUBLISHED: INLINE DCFile *get_dc_file() const; - const string &get_name() const; - int get_number() const; + INLINE const string &get_name() const; + INLINE int get_number() const; - bool has_parent() const; - DCClass *get_parent() const; + int get_num_parents() const; + DCClass *get_parent(int n) const; bool has_constructor() const; DCField *get_constructor() const; int get_num_fields() const; DCField *get_field(int n) const; + DCField *get_field_by_name(const string &name) const; DCField *get_field_by_index(int index_number) const; @@ -129,6 +132,8 @@ public: void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const; void generate_hash(HashGenerator &hashgen) const; + void clear_inherited_fields(); + void rebuild_inherited_fields(); bool add_field(DCField *field); void add_parent(DCClass *parent); @@ -155,7 +160,7 @@ private: DCField *_constructor; typedef pvector Fields; - Fields _fields; + Fields _fields, _inherited_fields; typedef pmap FieldsByName; FieldsByName _fields_by_name; diff --git a/direct/src/dcparser/dcField.I b/direct/src/dcparser/dcField.I new file mode 100644 index 0000000000..89d37d04e2 --- /dev/null +++ b/direct/src/dcparser/dcField.I @@ -0,0 +1,226 @@ +// Filename: dcField.I +// Created by: drose (10Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// 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 . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: DCField::get_number +// Access: Published +// Description: Returns a unique index number associated with this +// field. This is defined implicitly when the .dc +// file(s) are read. +//////////////////////////////////////////////////////////////////// +INLINE int DCField:: +get_number() const { + return _number; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::get_class +// Access: Published +// Description: Returns the DCClass pointer for the class that +// contains this field. +//////////////////////////////////////////////////////////////////// +INLINE DCClass *DCField:: +get_class() const { + return _dclass; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::has_default_value +// Access: Published +// Description: Returns true if a default value has been explicitly +// established for this field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +has_default_value() const { + return _has_default_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::get_default_value +// Access: Published +// Description: Returns the default value for this field. If a +// default value has been explicitly set +// (e.g. has_default_value() returns true), returns that +// value; otherwise, returns an implicit default for the +// field. +//////////////////////////////////////////////////////////////////// +INLINE const string &DCField:: +get_default_value() const { + if (_default_value_stale) { + ((DCField *)this)->refresh_default_value(); + } + return _default_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_required +// Access: Published +// Description: Returns true if the "required" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_required() const { + return has_keyword("required"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_broadcast +// Access: Published +// Description: Returns true if the "broadcast" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_broadcast() const { + return has_keyword("broadcast"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_ram +// Access: Published +// Description: Returns true if the "ram" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_ram() const { + return has_keyword("ram"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_db +// Access: Published +// Description: Returns true if the "db" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_db() const { + return has_keyword("db"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_clsend +// Access: Published +// Description: Returns true if the "clsend" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_clsend() const { + return has_keyword("clsend"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_clrecv +// Access: Published +// Description: Returns true if the "clrecv" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_clrecv() const { + return has_keyword("clrecv"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_ownsend +// Access: Published +// Description: Returns true if the "ownsend" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_ownsend() const { + return has_keyword("ownsend"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_ownrecv +// Access: Published +// Description: Returns true if the "ownrecv" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_ownrecv() const { + return has_keyword("ownrecv"); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::is_airecv +// Access: Published +// Description: Returns true if the "airecv" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool DCField:: +is_airecv() const { + return has_keyword("airecv"); +} + +//////////////////////////////////////////////////////////////////// +// Function : DCField::output +// Access : Published +// Description : Write a string representation of this instance to +// . +//////////////////////////////////////////////////////////////////// +INLINE void DCField:: +output(ostream &out) const { + output(out, true); +} + +//////////////////////////////////////////////////////////////////// +// Function : DCField:: +// Access : Published +// Description : Write a string representation of this instance to +// . +//////////////////////////////////////////////////////////////////// +INLINE void DCField:: +write(ostream &out, int indent_level) const { + write(out, false, indent_level); +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::set_number +// Access: Public +// Description: Assigns the unique number to this field. This is +// normally called only by the DCClass interface as the +// field is added. +//////////////////////////////////////////////////////////////////// +INLINE void DCField:: +set_number(int number) { + _number = number; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::set_class +// Access: Public +// Description: Assigns the class pointer to this field. This is +// normally called only by the DCClass interface as the +// field is added. +//////////////////////////////////////////////////////////////////// +INLINE void DCField:: +set_class(DCClass *dclass) { + _dclass = dclass; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::set_default_value +// Access: Public +// Description: Establishes a default value for this field. +//////////////////////////////////////////////////////////////////// +INLINE void DCField:: +set_default_value(const string &default_value) { + _default_value = default_value; + _has_default_value = true; + _default_value_stale = false; +} diff --git a/direct/src/dcparser/dcField.cxx b/direct/src/dcparser/dcField.cxx index 9e8353e8ae..e178dd4626 100644 --- a/direct/src/dcparser/dcField.cxx +++ b/direct/src/dcparser/dcField.cxx @@ -32,9 +32,11 @@ // Description: //////////////////////////////////////////////////////////////////// DCField:: -DCField() +DCField() : + _dclass(NULL) #ifdef WITHIN_PANDA - : _field_update_pcollector("DCField") + , + _field_update_pcollector("DCField") #endif { _number = -1; @@ -57,7 +59,8 @@ DCField() //////////////////////////////////////////////////////////////////// DCField:: DCField(const string &name, DCClass *dclass) : - DCPackerInterface(name) + DCPackerInterface(name), + _dclass(dclass) #ifdef WITHIN_PANDA , _field_update_pcollector(dclass->_class_update_pcollector, name) @@ -85,18 +88,6 @@ DCField:: ~DCField() { } -//////////////////////////////////////////////////////////////////// -// Function: DCField::get_number -// Access: Published -// Description: Returns a unique index number associated with this -// field. This is defined implicitly when the .dc -// file(s) are read. -//////////////////////////////////////////////////////////////////// -int DCField:: -get_number() const { - return _number; -} - //////////////////////////////////////////////////////////////////// // Function: DCField::as_field // Access: Published, Virtual @@ -250,155 +241,6 @@ validate_ranges(const string &packed_data) const { return (packer.get_num_unpacked_bytes() == packed_data.length()); } -//////////////////////////////////////////////////////////////////// -// Function: DCField::has_default_value -// Access: Published -// Description: Returns true if a default value has been explicitly -// established for this field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -has_default_value() const { - return _has_default_value; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::get_default_value -// Access: Published -// Description: Returns the default value for this field. If a -// default value has been explicitly set -// (e.g. has_default_value() returns true), returns that -// value; otherwise, returns an implicit default for the -// field. -//////////////////////////////////////////////////////////////////// -const string &DCField:: -get_default_value() const { - if (_default_value_stale) { - ((DCField *)this)->refresh_default_value(); - } - return _default_value; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_required -// Access: Published -// Description: Returns true if the "required" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_required() const { - return has_keyword("required"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_broadcast -// Access: Published -// Description: Returns true if the "broadcast" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_broadcast() const { - return has_keyword("broadcast"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_ram -// Access: Published -// Description: Returns true if the "ram" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_ram() const { - return has_keyword("ram"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_db -// Access: Published -// Description: Returns true if the "db" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_db() const { - return has_keyword("db"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_clsend -// Access: Published -// Description: Returns true if the "clsend" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_clsend() const { - return has_keyword("clsend"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_clrecv -// Access: Published -// Description: Returns true if the "clrecv" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_clrecv() const { - return has_keyword("clrecv"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_ownsend -// Access: Published -// Description: Returns true if the "ownsend" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_ownsend() const { - return has_keyword("ownsend"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_ownrecv -// Access: Published -// Description: Returns true if the "ownrecv" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_ownrecv() const { - return has_keyword("ownrecv"); -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::is_airecv -// Access: Published -// Description: Returns true if the "airecv" flag is set for this -// field, false otherwise. -//////////////////////////////////////////////////////////////////// -bool DCField:: -is_airecv() const { - return has_keyword("airecv"); -} - -//////////////////////////////////////////////////////////////////// -// Function : DCField::output -// Access : Published -// Description : Write a string representation of this instance to -// . -//////////////////////////////////////////////////////////////////// -void DCField:: -output(ostream &out) const { - output(out, true); -} - -//////////////////////////////////////////////////////////////////// -// Function : DCField:: -// Access : Published -// Description : Write a string representation of this instance to -// . -//////////////////////////////////////////////////////////////////// -void DCField:: -write(ostream &out, int indent_level) const { - write(out, false, indent_level); -} - #ifdef HAVE_PYTHON //////////////////////////////////////////////////////////////////// // Function: DCField::pack_args @@ -623,7 +465,6 @@ ai_format_update(int do_id, CHANNEL_TYPE to_id, CHANNEL_TYPE from_id, PyObject * packer.raw_pack_uint8(1); packer.RAW_PACK_CHANNEL(to_id); packer.RAW_PACK_CHANNEL(from_id); - //packer.raw_pack_uint8('A'); packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD); packer.raw_pack_uint32(do_id); packer.raw_pack_uint16(_number); @@ -683,27 +524,16 @@ pack_default_value(DCPackData &pack_data, bool &) const { } //////////////////////////////////////////////////////////////////// -// Function: DCField::set_number -// Access: Public -// Description: Assigns the unique number to this field. This is -// normally called only by the DCClass interface as the -// field is added. +// Function: DCField::set_name +// Access: Public, Virtual +// Description: Sets the name of this field. //////////////////////////////////////////////////////////////////// void DCField:: -set_number(int number) { - _number = number; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCField::set_default_value -// Access: Public -// Description: Establishes a default value for this field. -//////////////////////////////////////////////////////////////////// -void DCField:: -set_default_value(const string &default_value) { - _default_value = default_value; - _has_default_value = true; - _default_value_stale = false; +set_name(const string &name) { + DCPackerInterface::set_name(name); + if (_dclass != (DCClass *)NULL) { + _dclass->_dc_file->mark_inherited_fields_stale(); + } } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcField.h b/direct/src/dcparser/dcField.h index f08910de4e..1c86e0f833 100644 --- a/direct/src/dcparser/dcField.h +++ b/direct/src/dcparser/dcField.h @@ -48,7 +48,8 @@ public: virtual ~DCField(); PUBLISHED: - int get_number() const; + INLINE int get_number() const; + INLINE DCClass *get_class() const; virtual DCField *as_field(); virtual const DCField *as_field() const; @@ -64,21 +65,21 @@ PUBLISHED: bool validate_ranges(const string &packed_data) const; - bool has_default_value() const; - const string &get_default_value() const; + INLINE bool has_default_value() const; + INLINE const string &get_default_value() const; - bool is_required() const; - bool is_broadcast() const; - bool is_ram() const; - bool is_db() const; - bool is_clsend() const; - bool is_clrecv() const; - bool is_ownsend() const; - bool is_ownrecv() const; - bool is_airecv() const; + INLINE bool is_required() const; + INLINE bool is_broadcast() const; + INLINE bool is_ram() const; + INLINE bool is_db() const; + INLINE bool is_clsend() const; + INLINE bool is_clrecv() const; + INLINE bool is_ownsend() const; + INLINE bool is_ownrecv() const; + INLINE bool is_airecv() const; - void output(ostream &out) const; - void write(ostream &out, int indent_level) const; + INLINE void output(ostream &out) const; + INLINE void write(ostream &out, int indent_level) const; #ifdef HAVE_PYTHON bool pack_args(DCPacker &packer, PyObject *sequence) const; @@ -96,14 +97,17 @@ public: virtual void write(ostream &out, bool brief, int indent_level) const=0; virtual void generate_hash(HashGenerator &hashgen) const; virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; + virtual void set_name(const string &name); - void set_number(int number); - void set_default_value(const string &default_value); + INLINE void set_number(int number); + INLINE void set_class(DCClass *dclass); + INLINE void set_default_value(const string &default_value); protected: void refresh_default_value(); protected: + DCClass *_dclass; int _number; bool _default_value_stale; bool _has_default_value; @@ -121,4 +125,6 @@ INLINE ostream &operator << (ostream &out, const DCField &field) { return out; } +#include "dcField.I" + #endif diff --git a/direct/src/dcparser/dcFile.I b/direct/src/dcparser/dcFile.I new file mode 100644 index 0000000000..ef59fe2c79 --- /dev/null +++ b/direct/src/dcparser/dcFile.I @@ -0,0 +1,58 @@ +// Filename: dcFile.I +// Created by: drose (10Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// 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 . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: DCFile::all_objects_valid +// Access: Published +// Description: Returns true if all of the classes read from the DC +// file were defined and valid, or false if any of them +// were undefined ("bogus classes"). If this is true, +// we might have read a partial file. +//////////////////////////////////////////////////////////////////// +INLINE bool DCFile:: +all_objects_valid() const { + return _all_objects_valid; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCFile::check_inherited_fields +// Access: Public +// Description: Rebuilds all of the inherited fields tables, if +// necessary. +//////////////////////////////////////////////////////////////////// +INLINE void DCFile:: +check_inherited_fields() { + if (_inherited_fields_stale) { + rebuild_inherited_fields(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DCFile::mark_inherited_fields_stale +// Access: Public +// Description: Indicates that something has changed in one or more +// of the inheritance chains or the set of fields; the +// next time check_inherited_fields() is called, the +// inherited fields tables of all classes will be +// rebuilt. +//////////////////////////////////////////////////////////////////// +INLINE void DCFile:: +mark_inherited_fields_stale() { + _inherited_fields_stale = true; +} diff --git a/direct/src/dcparser/dcFile.cxx b/direct/src/dcparser/dcFile.cxx index 429e3a2c8a..f28c777223 100644 --- a/direct/src/dcparser/dcFile.cxx +++ b/direct/src/dcparser/dcFile.cxx @@ -42,6 +42,7 @@ DCFile:: DCFile() { _all_objects_valid = true; + _inherited_fields_stale = false; setup_default_keywords(); } @@ -83,6 +84,7 @@ clear() { setup_default_keywords(); _all_objects_valid = true; + _inherited_fields_stale = false; } #ifdef WITHIN_PANDA @@ -342,19 +344,6 @@ get_field_by_index(int index_number) const { return NULL; } -//////////////////////////////////////////////////////////////////// -// Function: DCFile::all_objects_valid -// Access: Published -// Description: Returns true if all of the classes read from the DC -// file were defined and valid, or false if any of them -// were undefined ("bogus classes"). If this is true, -// we might have read a partial file. -//////////////////////////////////////////////////////////////////// -bool DCFile:: -all_objects_valid() const { - return _all_objects_valid; -} - //////////////////////////////////////////////////////////////////// // Function: DCFile::get_num_import_modules // Access: Published @@ -510,6 +499,11 @@ get_hash() const { //////////////////////////////////////////////////////////////////// void DCFile:: generate_hash(HashGenerator &hashgen) const { + if (dc_virtual_inheritance) { + // Just to make the hash number change in this case. + hashgen.add_int(1); + } + hashgen.add_int(_classes.size()); Classes::const_iterator ci; for (ci = _classes.begin(); ci != _classes.end(); ++ci) { @@ -696,7 +690,7 @@ set_new_index_number(DCField *field) { //////////////////////////////////////////////////////////////////// // Function: DCFile::setup_default_keywords -// Access: Public +// Access: Private // Description: Adds an entry for each of the default keywords that // are defined for every DCFile for legacy reasons. //////////////////////////////////////////////////////////////////// @@ -729,3 +723,22 @@ setup_default_keywords() { _things_to_delete.push_back(keyword); } } + +//////////////////////////////////////////////////////////////////// +// Function: DCFile::rebuild_inherited_fields +// Access: Private +// Description: Reconstructs the inherited fields table of all +// classes. +//////////////////////////////////////////////////////////////////// +void DCFile:: +rebuild_inherited_fields() { + _inherited_fields_stale = false; + + Classes::iterator ci; + for (ci = _classes.begin(); ci != _classes.end(); ++ci) { + (*ci)->clear_inherited_fields(); + } + for (ci = _classes.begin(); ci != _classes.end(); ++ci) { + (*ci)->rebuild_inherited_fields(); + } +} diff --git a/direct/src/dcparser/dcFile.h b/direct/src/dcparser/dcFile.h index 93ddcdf942..45374a95c0 100644 --- a/direct/src/dcparser/dcFile.h +++ b/direct/src/dcparser/dcFile.h @@ -59,7 +59,7 @@ PUBLISHED: DCField *get_field_by_index(int index_number) const; - bool all_objects_valid() const; + INLINE bool all_objects_valid() const; int get_num_import_modules() const; string get_import_module(int n) const; @@ -87,9 +87,12 @@ public: void add_thing_to_delete(DCDeclaration *decl); void set_new_index_number(DCField *field); + INLINE void check_inherited_fields(); + INLINE void mark_inherited_fields_stale(); private: void setup_default_keywords(); + void rebuild_inherited_fields(); typedef pvector Classes; Classes _classes; @@ -124,8 +127,11 @@ private: FieldsByIndex _fields_by_index; bool _all_objects_valid; + bool _inherited_fields_stale; }; +#include "dcFile.I" + #endif diff --git a/direct/src/dcparser/dcPackerInterface.I b/direct/src/dcparser/dcPackerInterface.I index 3c34112c42..8cd0b98a22 100644 --- a/direct/src/dcparser/dcPackerInterface.I +++ b/direct/src/dcparser/dcPackerInterface.I @@ -41,16 +41,6 @@ check_match(const DCPackerInterface *other) const { return do_check_match(other); } -//////////////////////////////////////////////////////////////////// -// Function: DCPackerInterface::set_name -// Access: Public -// Description: Sets the name of this field. -//////////////////////////////////////////////////////////////////// -INLINE void DCPackerInterface:: -set_name(const string &name) { - _name = name; -} - //////////////////////////////////////////////////////////////////// // Function: DCPackerInterface::has_fixed_byte_size // Access: Public diff --git a/direct/src/dcparser/dcPackerInterface.cxx b/direct/src/dcparser/dcPackerInterface.cxx index 4653a7e2e6..09c53a1da1 100755 --- a/direct/src/dcparser/dcPackerInterface.cxx +++ b/direct/src/dcparser/dcPackerInterface.cxx @@ -190,6 +190,16 @@ check_match(const string &description, DCFile *dcfile) const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: DCPackerInterface::set_name +// Access: Public, Virtual +// Description: Sets the name of this field. +//////////////////////////////////////////////////////////////////// +void DCPackerInterface:: +set_name(const string &name) { + _name = name; +} + //////////////////////////////////////////////////////////////////// // Function: DCPackerInterface::calc_num_nested_fields // Access: Public, Virtual diff --git a/direct/src/dcparser/dcPackerInterface.h b/direct/src/dcparser/dcPackerInterface.h index 939bdfeda0..d4c74d48fa 100755 --- a/direct/src/dcparser/dcPackerInterface.h +++ b/direct/src/dcparser/dcPackerInterface.h @@ -93,7 +93,7 @@ PUBLISHED: bool check_match(const string &description, DCFile *dcfile = NULL) const; public: - INLINE void set_name(const string &name); + virtual void set_name(const string &name); INLINE bool has_fixed_byte_size() const; INLINE size_t get_fixed_byte_size() const; INLINE bool has_fixed_structure() const;