Panda3D
|
00001 // Filename: dcAtomicField.cxx 00002 // Created by: drose (05Oct00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "dcAtomicField.h" 00016 #include "hashGenerator.h" 00017 #include "dcindent.h" 00018 #include "dcSimpleParameter.h" 00019 #include "dcPacker.h" 00020 00021 #include <math.h> 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: DCAtomicField::Constructor 00025 // Access: Public 00026 // Description: 00027 //////////////////////////////////////////////////////////////////// 00028 DCAtomicField:: 00029 DCAtomicField(const string &name, DCClass *dclass, 00030 bool bogus_field) : 00031 DCField(name, dclass) 00032 { 00033 _bogus_field = bogus_field; 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: DCAtomicField::Destructor 00038 // Access: Public, Virtual 00039 // Description: 00040 //////////////////////////////////////////////////////////////////// 00041 DCAtomicField:: 00042 ~DCAtomicField() { 00043 Elements::iterator ei; 00044 for (ei = _elements.begin(); ei != _elements.end(); ++ei) { 00045 delete (*ei); 00046 } 00047 _elements.clear(); 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: DCAtomicField::as_atomic_field 00052 // Access: Published, Virtual 00053 // Description: Returns the same field pointer converted to an atomic 00054 // field pointer, if this is in fact an atomic field; 00055 // otherwise, returns NULL. 00056 //////////////////////////////////////////////////////////////////// 00057 DCAtomicField *DCAtomicField:: 00058 as_atomic_field() { 00059 return this; 00060 } 00061 00062 //////////////////////////////////////////////////////////////////// 00063 // Function: DCAtomicField::as_atomic_field 00064 // Access: Published, Virtual 00065 // Description: Returns the same field pointer converted to an atomic 00066 // field pointer, if this is in fact an atomic field; 00067 // otherwise, returns NULL. 00068 //////////////////////////////////////////////////////////////////// 00069 const DCAtomicField *DCAtomicField:: 00070 as_atomic_field() const { 00071 return this; 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: DCAtomicField::get_num_elements 00076 // Access: Published 00077 // Description: Returns the number of elements (parameters) of the 00078 // atomic field. 00079 //////////////////////////////////////////////////////////////////// 00080 int DCAtomicField:: 00081 get_num_elements() const { 00082 return _elements.size(); 00083 } 00084 00085 //////////////////////////////////////////////////////////////////// 00086 // Function: DCAtomicField::get_element 00087 // Access: Published 00088 // Description: Returns the parameter object describing the 00089 // nth element. 00090 //////////////////////////////////////////////////////////////////// 00091 DCParameter *DCAtomicField:: 00092 get_element(int n) const { 00093 nassertr(n >= 0 && n < (int)_elements.size(), NULL); 00094 return _elements[n]; 00095 } 00096 00097 //////////////////////////////////////////////////////////////////// 00098 // Function: DCAtomicField::get_element_default 00099 // Access: Published 00100 // Description: Returns the pre-formatted default value associated 00101 // with the nth element of the field. This is only 00102 // valid if has_element_default() returns true, in which 00103 // case this string represents the bytes that should be 00104 // assigned to the field as a default value. 00105 // 00106 // If the element is an array-type element, the returned 00107 // value will include the two-byte length preceding the 00108 // array data. 00109 // 00110 // This is deprecated; use get_element() instead. 00111 //////////////////////////////////////////////////////////////////// 00112 string DCAtomicField:: 00113 get_element_default(int n) const { 00114 nassertr(n >= 0 && n < (int)_elements.size(), string()); 00115 return _elements[n]->get_default_value(); 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: DCAtomicField::has_element_default 00120 // Access: Published 00121 // Description: Returns true if the nth element of the field has a 00122 // default value specified, false otherwise. 00123 // 00124 // This is deprecated; use get_element() instead. 00125 //////////////////////////////////////////////////////////////////// 00126 bool DCAtomicField:: 00127 has_element_default(int n) const { 00128 nassertr(n >= 0 && n < (int)_elements.size(), false); 00129 return _elements[n]->has_default_value(); 00130 } 00131 00132 //////////////////////////////////////////////////////////////////// 00133 // Function: DCAtomicField::get_element_name 00134 // Access: Published 00135 // Description: Returns the name of the nth element of the field. 00136 // This name is strictly for documentary purposes; it 00137 // does not generally affect operation. If a name is 00138 // not specified, this will be the empty string. 00139 // 00140 // This method is deprecated; use 00141 // get_element()->get_name() instead. 00142 //////////////////////////////////////////////////////////////////// 00143 string DCAtomicField:: 00144 get_element_name(int n) const { 00145 nassertr(n >= 0 && n < (int)_elements.size(), string()); 00146 return _elements[n]->get_name(); 00147 } 00148 00149 //////////////////////////////////////////////////////////////////// 00150 // Function: DCAtomicField::get_element_type 00151 // Access: Published 00152 // Description: Returns the numeric type of the nth element of the 00153 // field. This method is deprecated; use 00154 // get_element() instead. 00155 //////////////////////////////////////////////////////////////////// 00156 DCSubatomicType DCAtomicField:: 00157 get_element_type(int n) const { 00158 nassertr(n >= 0 && n < (int)_elements.size(), ST_invalid); 00159 DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter(); 00160 nassertr(simple_parameter != (DCSimpleParameter *)NULL, ST_invalid); 00161 return simple_parameter->get_type(); 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: DCAtomicField::get_element_divisor 00166 // Access: Published 00167 // Description: Returns the divisor associated with the nth element 00168 // of the field. This implements an implicit 00169 // fixed-point system; floating-point values are to be 00170 // multiplied by this value before encoding into a 00171 // packet, and divided by this number after decoding. 00172 // 00173 // This method is deprecated; use 00174 // get_element()->get_divisor() instead. 00175 //////////////////////////////////////////////////////////////////// 00176 int DCAtomicField:: 00177 get_element_divisor(int n) const { 00178 nassertr(n >= 0 && n < (int)_elements.size(), 1); 00179 DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter(); 00180 nassertr(simple_parameter != (DCSimpleParameter *)NULL, 1); 00181 return simple_parameter->get_divisor(); 00182 } 00183 00184 //////////////////////////////////////////////////////////////////// 00185 // Function: DCAtomicField::output 00186 // Access: Public, Virtual 00187 // Description: 00188 //////////////////////////////////////////////////////////////////// 00189 void DCAtomicField:: 00190 output(ostream &out, bool brief) const { 00191 out << _name << "("; 00192 00193 if (!_elements.empty()) { 00194 Elements::const_iterator ei = _elements.begin(); 00195 output_element(out, brief, *ei); 00196 ++ei; 00197 while (ei != _elements.end()) { 00198 out << ", "; 00199 output_element(out, brief, *ei); 00200 ++ei; 00201 } 00202 } 00203 out << ")"; 00204 00205 output_keywords(out); 00206 } 00207 00208 //////////////////////////////////////////////////////////////////// 00209 // Function: DCAtomicField::write 00210 // Access: Public, Virtual 00211 // Description: Generates a parseable description of the object to 00212 // the indicated output stream. 00213 //////////////////////////////////////////////////////////////////// 00214 void DCAtomicField:: 00215 write(ostream &out, bool brief, int indent_level) const { 00216 indent(out, indent_level); 00217 output(out, brief); 00218 out << ";"; 00219 if (!brief && _number >= 0) { 00220 out << " // field " << _number; 00221 } 00222 out << "\n"; 00223 } 00224 00225 //////////////////////////////////////////////////////////////////// 00226 // Function: DCAtomicField::generate_hash 00227 // Access: Public, Virtual 00228 // Description: Accumulates the properties of this field into the 00229 // hash. 00230 //////////////////////////////////////////////////////////////////// 00231 void DCAtomicField:: 00232 generate_hash(HashGenerator &hashgen) const { 00233 DCField::generate_hash(hashgen); 00234 00235 hashgen.add_int(_elements.size()); 00236 Elements::const_iterator ei; 00237 for (ei = _elements.begin(); ei != _elements.end(); ++ei) { 00238 (*ei)->generate_hash(hashgen); 00239 } 00240 00241 DCKeywordList::generate_hash(hashgen); 00242 } 00243 00244 //////////////////////////////////////////////////////////////////// 00245 // Function: DCAtomicField::get_nested_field 00246 // Access: Public, Virtual 00247 // Description: Returns the DCPackerInterface object that represents 00248 // the nth nested field. This may return NULL if there 00249 // is no such field (but it shouldn't do this if n is in 00250 // the range 0 <= n < get_num_nested_fields()). 00251 //////////////////////////////////////////////////////////////////// 00252 DCPackerInterface *DCAtomicField:: 00253 get_nested_field(int n) const { 00254 nassertr(n >= 0 && n < (int)_elements.size(), NULL); 00255 return _elements[n]; 00256 } 00257 00258 //////////////////////////////////////////////////////////////////// 00259 // Function: DCAtomicField::add_element 00260 // Access: Public 00261 // Description: Adds a new element (parameter) to the field. 00262 // Normally this is called only during parsing. The 00263 // DCAtomicField object becomes the owner of the new 00264 // pointer and will delete it upon destruction. 00265 //////////////////////////////////////////////////////////////////// 00266 void DCAtomicField:: 00267 add_element(DCParameter *element) { 00268 _elements.push_back(element); 00269 _num_nested_fields = (int)_elements.size(); 00270 00271 // See if we still have a fixed byte size. 00272 if (_has_fixed_byte_size) { 00273 _has_fixed_byte_size = element->has_fixed_byte_size(); 00274 _fixed_byte_size += element->get_fixed_byte_size(); 00275 } 00276 if (_has_fixed_structure) { 00277 _has_fixed_structure = element->has_fixed_structure(); 00278 } 00279 if (!_has_range_limits) { 00280 _has_range_limits = element->has_range_limits(); 00281 } 00282 if (!_has_default_value) { 00283 _has_default_value = element->has_default_value(); 00284 } 00285 _default_value_stale = true; 00286 } 00287 00288 //////////////////////////////////////////////////////////////////// 00289 // Function: DCAtomicField::do_check_match 00290 // Access: Protected, Virtual 00291 // Description: Returns true if the other interface is bitwise the 00292 // same as this one--that is, a uint32 only matches a 00293 // uint32, etc. Names of components, and range limits, 00294 // are not compared. 00295 //////////////////////////////////////////////////////////////////// 00296 bool DCAtomicField:: 00297 do_check_match(const DCPackerInterface *other) const { 00298 return other->do_check_match_atomic_field(this); 00299 } 00300 00301 //////////////////////////////////////////////////////////////////// 00302 // Function: DCAtomicField::do_check_match_atomic_field 00303 // Access: Protected, Virtual 00304 // Description: Returns true if this field matches the indicated 00305 // atomic field, false otherwise. 00306 //////////////////////////////////////////////////////////////////// 00307 bool DCAtomicField:: 00308 do_check_match_atomic_field(const DCAtomicField *other) const { 00309 if (_elements.size() != other->_elements.size()) { 00310 return false; 00311 } 00312 for (size_t i = 0; i < _elements.size(); i++) { 00313 if (!_elements[i]->check_match(other->_elements[i])) { 00314 return false; 00315 } 00316 } 00317 00318 return true; 00319 } 00320 00321 //////////////////////////////////////////////////////////////////// 00322 // Function: DCAtomicField::output_element 00323 // Access: Private 00324 // Description: 00325 //////////////////////////////////////////////////////////////////// 00326 void DCAtomicField:: 00327 output_element(ostream &out, bool brief, DCParameter *element) const { 00328 element->output(out, brief); 00329 00330 if (!brief && element->has_default_value()) { 00331 out << " = "; 00332 DCPacker packer; 00333 packer.set_unpack_data(element->get_default_value()); 00334 packer.begin_unpack(element); 00335 packer.unpack_and_format(out, false); 00336 packer.end_unpack(); 00337 } 00338 }