260 lines
8.5 KiB
C++
260 lines
8.5 KiB
C++
// Filename: dcClass.cxx
|
|
// Created by: drose (05Oct00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "dcClass.h"
|
|
#include "hashGenerator.h"
|
|
#include "dcindent.h"
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_number
|
|
// Access: Public
|
|
// Description: Returns a unique index number associated with this
|
|
// class. This is defined implicitly when the .dc
|
|
// file(s) are read.
|
|
////////////////////////////////////////////////////////////////////
|
|
int DCClass::
|
|
get_number() const {
|
|
return _number;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_name
|
|
// Access: Public
|
|
// Description: Returns the name of this class.
|
|
////////////////////////////////////////////////////////////////////
|
|
string DCClass::
|
|
get_name() const {
|
|
return _name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::has_parent
|
|
// Access: Public
|
|
// Description: Returns true if this class inherits from some other
|
|
// class, false if it does not.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool DCClass::
|
|
has_parent() const {
|
|
return !_parents.empty();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_parent
|
|
// Access: Public
|
|
// Description: Returns the parent class this class inherits from, if
|
|
// any. It is an error to call this unless has_parent()
|
|
// returned true.
|
|
////////////////////////////////////////////////////////////////////
|
|
DCClass *DCClass::
|
|
get_parent() const {
|
|
nassertr(has_parent(), NULL);
|
|
return _parents.front();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_num_fields
|
|
// Access: Public
|
|
// Description: Returns the number of fields defined directly in this
|
|
// class, ignoring inheritance.
|
|
////////////////////////////////////////////////////////////////////
|
|
int DCClass::
|
|
get_num_fields() {
|
|
return _fields.size();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_field
|
|
// Access: Public
|
|
// Description: Returns the nth field in the class. This is not
|
|
// necessarily the field with index n; this is the nth
|
|
// field defined in the class directly, ignoring
|
|
// inheritance.
|
|
////////////////////////////////////////////////////////////////////
|
|
DCField *DCClass::
|
|
get_field(int n) {
|
|
nassertr(n >= 0 && n < (int)_fields.size(), NULL);
|
|
return _fields[n];
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_field_by_name
|
|
// Access: Public
|
|
// Description: Returns a pointer to the DCField that shares the
|
|
// indicated name. If the named field is not found in
|
|
// the current class, the parent classes will be
|
|
// searched, so the value returned may not actually be a
|
|
// field within this class. Returns NULL if there is no
|
|
// such field defined.
|
|
////////////////////////////////////////////////////////////////////
|
|
DCField *DCClass::
|
|
get_field_by_name(const string &name) {
|
|
FieldsByName::const_iterator ni;
|
|
ni = _fields_by_name.find(name);
|
|
if (ni != _fields_by_name.end()) {
|
|
return (*ni).second;
|
|
}
|
|
|
|
// We didn't have such a field, so check our parents.
|
|
Parents::iterator pi;
|
|
for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
|
|
DCField *result = (*pi)->get_field_by_name(name);
|
|
if (result != (DCField *)NULL) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// Nobody knew what this field is.
|
|
return (DCField *)NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_num_inherited_fields
|
|
// Access: Public
|
|
// Description: Returns the total number of field fields defined in
|
|
// this class and all ancestor classes.
|
|
////////////////////////////////////////////////////////////////////
|
|
int DCClass::
|
|
get_num_inherited_fields() {
|
|
if (!_parents.empty()) {
|
|
// This won't work for multiple dclass inheritance.
|
|
return _parents.front()->get_num_inherited_fields() + get_num_fields();
|
|
}
|
|
return get_num_fields();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::get_inherited_field
|
|
// Access: Public
|
|
// Description: Returns the nth field field in the class and all of
|
|
// its ancestors. This *is* the field corresponding to
|
|
// the given index number, since the fields are ordered
|
|
// consecutively beginning at the earliest inherited
|
|
// fields.
|
|
////////////////////////////////////////////////////////////////////
|
|
DCField *DCClass::
|
|
get_inherited_field(int n) {
|
|
if (!_parents.empty()) {
|
|
// This won't work for multiple dclass inheritance.
|
|
int psize = _parents.front()->get_num_inherited_fields();
|
|
if (n < psize) {
|
|
return _parents.front()->get_inherited_field(n);
|
|
}
|
|
|
|
n -= psize;
|
|
}
|
|
return get_field(n);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
DCClass::
|
|
DCClass() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::Destructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
DCClass::
|
|
~DCClass() {
|
|
Fields::iterator fi;
|
|
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
|
|
delete (*fi);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::write
|
|
// Access: Public
|
|
// Description: Generates a parseable description of the object to
|
|
// the indicated output stream.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DCClass::
|
|
write(ostream &out, int indent_level) const {
|
|
indent(out, indent_level)
|
|
<< "dclass " << _name;
|
|
|
|
if (!_parents.empty()) {
|
|
Parents::const_iterator pi = _parents.begin();
|
|
out << " : " << (*pi)->_name;
|
|
++pi;
|
|
while (pi != _parents.end()) {
|
|
out << ", " << (*pi)->_name;
|
|
++pi;
|
|
}
|
|
}
|
|
out << " { // index " << _number << "\n";
|
|
|
|
Fields::const_iterator fi;
|
|
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
|
|
(*fi)->write(out, indent_level + 2);
|
|
}
|
|
|
|
indent(out, indent_level) << "};\n";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::generate_hash
|
|
// Access: Public, Virtual
|
|
// Description: Accumulates the properties of this class into the
|
|
// hash.
|
|
////////////////////////////////////////////////////////////////////
|
|
void DCClass::
|
|
generate_hash(HashGenerator &hashgen) const {
|
|
hashgen.add_string(_name);
|
|
|
|
hashgen.add_int(_parents.size());
|
|
Parents::const_iterator pi;
|
|
for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
|
|
hashgen.add_int((*pi)->get_number());
|
|
}
|
|
|
|
hashgen.add_int(_fields.size());
|
|
Fields::const_iterator fi;
|
|
for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
|
|
(*fi)->generate_hash(hashgen);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: DCClass::add_field
|
|
// Access: Public
|
|
// Description: Adds the newly-allocated field to the class. The
|
|
// 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.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool DCClass::
|
|
add_field(DCField *field) {
|
|
bool inserted = _fields_by_name.insert
|
|
(FieldsByName::value_type(field->_name, field)).second;
|
|
|
|
if (!inserted) {
|
|
return false;
|
|
}
|
|
|
|
field->_number = get_num_inherited_fields();
|
|
_fields.push_back(field);
|
|
return true;
|
|
}
|