00001 // Filename: dcClass.cxx 00002 // Created by: drose (05Oct00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "dcClass.h" 00020 #include "hashGenerator.h" 00021 #include "dcindent.h" 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: DCClass::get_number 00025 // Access: Public 00026 // Description: Returns a unique index number associated with this 00027 // class. This is defined implicitly when the .dc 00028 // file(s) are read. 00029 //////////////////////////////////////////////////////////////////// 00030 int DCClass:: 00031 get_number() const { 00032 return _number; 00033 } 00034 00035 //////////////////////////////////////////////////////////////////// 00036 // Function: DCClass::get_name 00037 // Access: Public 00038 // Description: Returns the name of this class. 00039 //////////////////////////////////////////////////////////////////// 00040 string DCClass:: 00041 get_name() const { 00042 return _name; 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: DCClass::has_parent 00047 // Access: Public 00048 // Description: Returns true if this class inherits from some other 00049 // class, false if it does not. 00050 //////////////////////////////////////////////////////////////////// 00051 bool DCClass:: 00052 has_parent() const { 00053 return !_parents.empty(); 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: DCClass::get_parent 00058 // Access: Public 00059 // Description: Returns the parent class this class inherits from, if 00060 // any. It is an error to call this unless has_parent() 00061 // returned true. 00062 //////////////////////////////////////////////////////////////////// 00063 DCClass *DCClass:: 00064 get_parent() const { 00065 nassertr(has_parent(), NULL); 00066 return _parents.front(); 00067 } 00068 00069 //////////////////////////////////////////////////////////////////// 00070 // Function: DCClass::get_num_fields 00071 // Access: Public 00072 // Description: Returns the number of fields defined directly in this 00073 // class, ignoring inheritance. 00074 //////////////////////////////////////////////////////////////////// 00075 int DCClass:: 00076 get_num_fields() { 00077 return _fields.size(); 00078 } 00079 00080 //////////////////////////////////////////////////////////////////// 00081 // Function: DCClass::get_field 00082 // Access: Public 00083 // Description: Returns the nth field in the class. This is not 00084 // necessarily the field with index n; this is the nth 00085 // field defined in the class directly, ignoring 00086 // inheritance. 00087 //////////////////////////////////////////////////////////////////// 00088 DCField *DCClass:: 00089 get_field(int n) { 00090 nassertr(n >= 0 && n < (int)_fields.size(), NULL); 00091 return _fields[n]; 00092 } 00093 00094 //////////////////////////////////////////////////////////////////// 00095 // Function: DCClass::get_field_by_name 00096 // Access: Public 00097 // Description: Returns a pointer to the DCField that shares the 00098 // indicated name. If the named field is not found in 00099 // the current class, the parent classes will be 00100 // searched, so the value returned may not actually be a 00101 // field within this class. Returns NULL if there is no 00102 // such field defined. 00103 //////////////////////////////////////////////////////////////////// 00104 DCField *DCClass:: 00105 get_field_by_name(const string &name) { 00106 FieldsByName::const_iterator ni; 00107 ni = _fields_by_name.find(name); 00108 if (ni != _fields_by_name.end()) { 00109 return (*ni).second; 00110 } 00111 00112 // We didn't have such a field, so check our parents. 00113 Parents::iterator pi; 00114 for (pi = _parents.begin(); pi != _parents.end(); ++pi) { 00115 DCField *result = (*pi)->get_field_by_name(name); 00116 if (result != (DCField *)NULL) { 00117 return result; 00118 } 00119 } 00120 00121 // Nobody knew what this field is. 00122 return (DCField *)NULL; 00123 } 00124 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: DCClass::get_num_inherited_fields 00127 // Access: Public 00128 // Description: Returns the total number of field fields defined in 00129 // this class and all ancestor classes. 00130 //////////////////////////////////////////////////////////////////// 00131 int DCClass:: 00132 get_num_inherited_fields() { 00133 if (!_parents.empty()) { 00134 // This won't work for multiple dclass inheritance. 00135 return _parents.front()->get_num_inherited_fields() + get_num_fields(); 00136 } 00137 return get_num_fields(); 00138 } 00139 00140 //////////////////////////////////////////////////////////////////// 00141 // Function: DCClass::get_inherited_field 00142 // Access: Public 00143 // Description: Returns the nth field field in the class and all of 00144 // its ancestors. This *is* the field corresponding to 00145 // the given index number, since the fields are ordered 00146 // consecutively beginning at the earliest inherited 00147 // fields. 00148 //////////////////////////////////////////////////////////////////// 00149 DCField *DCClass:: 00150 get_inherited_field(int n) { 00151 if (!_parents.empty()) { 00152 // This won't work for multiple dclass inheritance. 00153 int psize = _parents.front()->get_num_inherited_fields(); 00154 if (n < psize) { 00155 return _parents.front()->get_inherited_field(n); 00156 } 00157 00158 n -= psize; 00159 } 00160 return get_field(n); 00161 } 00162 00163 //////////////////////////////////////////////////////////////////// 00164 // Function: DCClass::Constructor 00165 // Access: Public 00166 // Description: 00167 //////////////////////////////////////////////////////////////////// 00168 DCClass:: 00169 DCClass() { 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: DCClass::Destructor 00174 // Access: Public 00175 // Description: 00176 //////////////////////////////////////////////////////////////////// 00177 DCClass:: 00178 ~DCClass() { 00179 Fields::iterator fi; 00180 for (fi = _fields.begin(); fi != _fields.end(); ++fi) { 00181 delete (*fi); 00182 } 00183 } 00184 00185 //////////////////////////////////////////////////////////////////// 00186 // Function: DCClass::write 00187 // Access: Public 00188 // Description: Generates a parseable description of the object to 00189 // the indicated output stream. 00190 //////////////////////////////////////////////////////////////////// 00191 void DCClass:: 00192 write(ostream &out, int indent_level) const { 00193 indent(out, indent_level) 00194 << "dclass " << _name; 00195 00196 if (!_parents.empty()) { 00197 Parents::const_iterator pi = _parents.begin(); 00198 out << " : " << (*pi)->_name; 00199 ++pi; 00200 while (pi != _parents.end()) { 00201 out << ", " << (*pi)->_name; 00202 ++pi; 00203 } 00204 } 00205 out << " { // index " << _number << "\n"; 00206 00207 Fields::const_iterator fi; 00208 for (fi = _fields.begin(); fi != _fields.end(); ++fi) { 00209 (*fi)->write(out, indent_level + 2); 00210 } 00211 00212 indent(out, indent_level) << "};\n"; 00213 } 00214 00215 //////////////////////////////////////////////////////////////////// 00216 // Function: DCClass::generate_hash 00217 // Access: Public, Virtual 00218 // Description: Accumulates the properties of this class into the 00219 // hash. 00220 //////////////////////////////////////////////////////////////////// 00221 void DCClass:: 00222 generate_hash(HashGenerator &hashgen) const { 00223 hashgen.add_string(_name); 00224 00225 hashgen.add_int(_parents.size()); 00226 Parents::const_iterator pi; 00227 for (pi = _parents.begin(); pi != _parents.end(); ++pi) { 00228 hashgen.add_int((*pi)->get_number()); 00229 } 00230 00231 hashgen.add_int(_fields.size()); 00232 Fields::const_iterator fi; 00233 for (fi = _fields.begin(); fi != _fields.end(); ++fi) { 00234 (*fi)->generate_hash(hashgen); 00235 } 00236 } 00237 00238 //////////////////////////////////////////////////////////////////// 00239 // Function: DCClass::add_field 00240 // Access: Public 00241 // Description: Adds the newly-allocated field to the class. The 00242 // class becomes the owner of the pointer and will 00243 // delete it when it destructs. Returns true if the 00244 // field is successfully added, or false if there was a 00245 // name conflict. 00246 //////////////////////////////////////////////////////////////////// 00247 bool DCClass:: 00248 add_field(DCField *field) { 00249 bool inserted = _fields_by_name.insert 00250 (FieldsByName::value_type(field->_name, field)).second; 00251 00252 if (!inserted) { 00253 return false; 00254 } 00255 00256 field->_number = get_num_inherited_fields(); 00257 _fields.push_back(field); 00258 return true; 00259 }