Panda3D
|
00001 // Filename: dcSwitch.cxx 00002 // Created by: drose (23Jun04) 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 "dcSwitch.h" 00016 #include "dcField.h" 00017 #include "dcParameter.h" 00018 #include "hashGenerator.h" 00019 #include "dcindent.h" 00020 #include "dcPacker.h" 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: DCSwitch::Constructor 00024 // Access: Public 00025 // Description: The key_parameter must be recently allocated via 00026 // new; it will be deleted via delete when the switch 00027 // destructs. 00028 //////////////////////////////////////////////////////////////////// 00029 DCSwitch:: 00030 DCSwitch(const string &name, DCField *key_parameter) : 00031 _name(name), 00032 _key_parameter(key_parameter) 00033 { 00034 _default_case = NULL; 00035 _fields_added = false; 00036 } 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: DCSwitch::Destructor 00040 // Access: Public, Virtual 00041 // Description: 00042 //////////////////////////////////////////////////////////////////// 00043 DCSwitch:: 00044 ~DCSwitch() { 00045 nassertv(_key_parameter != (DCField *)NULL); 00046 delete _key_parameter; 00047 00048 Cases::iterator ci; 00049 for (ci = _cases.begin(); ci != _cases.end(); ++ci) { 00050 SwitchCase *dcase = (*ci); 00051 delete dcase; 00052 } 00053 00054 CaseFields::iterator fi; 00055 for (fi = _case_fields.begin(); fi != _case_fields.end(); ++fi) { 00056 SwitchFields *fields = (*fi); 00057 delete fields; 00058 } 00059 00060 Fields::iterator ni; 00061 for (ni = _nested_fields.begin(); ni != _nested_fields.end(); ++ni) { 00062 DCField *field = (*ni); 00063 delete field; 00064 } 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: DCSwitch::as_switch 00069 // Access: Published, Virtual 00070 // Description: 00071 //////////////////////////////////////////////////////////////////// 00072 DCSwitch *DCSwitch:: 00073 as_switch() { 00074 return this; 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: DCSwitch::as_switch 00079 // Access: Published, Virtual 00080 // Description: 00081 //////////////////////////////////////////////////////////////////// 00082 const DCSwitch *DCSwitch:: 00083 as_switch() const { 00084 return this; 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: DCSwitch::get_name 00089 // Access: Published 00090 // Description: Returns the name of this switch. 00091 //////////////////////////////////////////////////////////////////// 00092 const string &DCSwitch:: 00093 get_name() const { 00094 return _name; 00095 } 00096 00097 //////////////////////////////////////////////////////////////////// 00098 // Function: DCSwitch::get_key_parameter 00099 // Access: Published 00100 // Description: Returns the key parameter on which the switch is 00101 // based. The value of this parameter in the record 00102 // determines which one of the several cases within the 00103 // switch will be used. 00104 //////////////////////////////////////////////////////////////////// 00105 DCField *DCSwitch:: 00106 get_key_parameter() const { 00107 return _key_parameter; 00108 } 00109 00110 //////////////////////////////////////////////////////////////////// 00111 // Function: DCSwitch::get_num_cases 00112 // Access: Published 00113 // Description: Returns the number of different cases within the 00114 // switch. The legal values for case_index range from 0 00115 // to get_num_cases() - 1. 00116 //////////////////////////////////////////////////////////////////// 00117 int DCSwitch:: 00118 get_num_cases() const { 00119 return _cases.size(); 00120 } 00121 00122 //////////////////////////////////////////////////////////////////// 00123 // Function: DCSwitch::get_case_by_value 00124 // Access: Published 00125 // Description: Returns the index number of the case with the 00126 // indicated packed value, or -1 if no case has this 00127 // value. 00128 //////////////////////////////////////////////////////////////////// 00129 int DCSwitch:: 00130 get_case_by_value(const string &case_value) const { 00131 CasesByValue::const_iterator vi; 00132 vi = _cases_by_value.find(case_value); 00133 if (vi != _cases_by_value.end()) { 00134 return (*vi).second; 00135 } 00136 00137 return -1; 00138 } 00139 00140 //////////////////////////////////////////////////////////////////// 00141 // Function: DCSwitch::get_case 00142 // Access: Published 00143 // Description: Returns the DCPackerInterface that packs the nth case. 00144 //////////////////////////////////////////////////////////////////// 00145 DCPackerInterface *DCSwitch:: 00146 get_case(int n) const { 00147 nassertr(n >= 0 && n < (int)_cases.size(), NULL); 00148 return _cases[n]->_fields; 00149 } 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: DCSwitch::get_default_case 00153 // Access: Published 00154 // Description: Returns the DCPackerInterface that packs the default 00155 // case, or NULL if there is no default case. 00156 //////////////////////////////////////////////////////////////////// 00157 DCPackerInterface *DCSwitch:: 00158 get_default_case() const { 00159 return _default_case; 00160 } 00161 00162 //////////////////////////////////////////////////////////////////// 00163 // Function: DCSwitch::get_value 00164 // Access: Published 00165 // Description: Returns the packed value associated with the 00166 // indicated case. 00167 //////////////////////////////////////////////////////////////////// 00168 string DCSwitch:: 00169 get_value(int case_index) const { 00170 nassertr(case_index >= 0 && case_index < (int)_cases.size(), string()); 00171 return _cases[case_index]->_value; 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: DCSwitch::get_num_fields 00176 // Access: Published 00177 // Description: Returns the number of fields in the indicated case. 00178 //////////////////////////////////////////////////////////////////// 00179 int DCSwitch:: 00180 get_num_fields(int case_index) const { 00181 nassertr(case_index >= 0 && case_index < (int)_cases.size(), 0); 00182 return _cases[case_index]->_fields->_fields.size(); 00183 } 00184 00185 //////////////////////////////////////////////////////////////////// 00186 // Function: DCSwitch::get_num_fields 00187 // Access: Published 00188 // Description: Returns the nth field in the indicated case. 00189 //////////////////////////////////////////////////////////////////// 00190 DCField *DCSwitch:: 00191 get_field(int case_index, int n) const { 00192 nassertr(case_index >= 0 && case_index < (int)_cases.size(), NULL); 00193 nassertr(n >= 0 && n < (int)_cases[case_index]->_fields->_fields.size(), NULL); 00194 return _cases[case_index]->_fields->_fields[n]; 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: DCSwitch::get_field_by_name 00199 // Access: Published 00200 // Description: Returns the field with the given name from the 00201 // indicated case, or NULL if no field has this name. 00202 //////////////////////////////////////////////////////////////////// 00203 DCField *DCSwitch:: 00204 get_field_by_name(int case_index, const string &name) const { 00205 nassertr(case_index >= 0 && case_index < (int)_cases.size(), NULL); 00206 00207 const FieldsByName &fields_by_name = _cases[case_index]->_fields->_fields_by_name; 00208 FieldsByName::const_iterator ni; 00209 ni = fields_by_name.find(name); 00210 if (ni != fields_by_name.end()) { 00211 return (*ni).second; 00212 } 00213 00214 return NULL; 00215 } 00216 00217 //////////////////////////////////////////////////////////////////// 00218 // Function: DCSwitch::is_field_valid 00219 // Access: Public 00220 // Description: Returns true if it is valid to add a new field at 00221 // this point (implying that a case or default has been 00222 // added already), or false if not. 00223 //////////////////////////////////////////////////////////////////// 00224 bool DCSwitch:: 00225 is_field_valid() const { 00226 return !_current_fields.empty(); 00227 } 00228 00229 //////////////////////////////////////////////////////////////////// 00230 // Function: DCSwitch::add_case 00231 // Access: Public 00232 // Description: Adds a new case to the switch with the indicated 00233 // value, and returns the new case_index. If the value 00234 // has already been used for another case, returns -1. 00235 // This is normally called only by the parser. 00236 //////////////////////////////////////////////////////////////////// 00237 int DCSwitch:: 00238 add_case(const string &value) { 00239 int case_index = (int)_cases.size(); 00240 if (!_cases_by_value.insert(CasesByValue::value_type(value, case_index)).second) { 00241 add_invalid_case(); 00242 return -1; 00243 } 00244 00245 SwitchFields *fields = start_new_case(); 00246 SwitchCase *dcase = new SwitchCase(value, fields); 00247 _cases.push_back(dcase); 00248 return case_index; 00249 } 00250 00251 //////////////////////////////////////////////////////////////////// 00252 // Function: DCSwitch::add_invalid_case 00253 // Access: Public 00254 // Description: Adds a new case to the switch that will never be 00255 // matched. This is only used by the parser, to handle 00256 // an error condition more gracefully without bitching 00257 // the parsing (which behaves differently according to 00258 // whether a case has been encountered or not). 00259 //////////////////////////////////////////////////////////////////// 00260 void DCSwitch:: 00261 add_invalid_case() { 00262 start_new_case(); 00263 } 00264 00265 //////////////////////////////////////////////////////////////////// 00266 // Function: DCSwitch::add_default 00267 // Access: Public 00268 // Description: Adds a default case to the switch. Returns true if 00269 // the case is successfully added, or false if it had 00270 // already been added. This is normally called only by 00271 // the parser. 00272 //////////////////////////////////////////////////////////////////// 00273 bool DCSwitch:: 00274 add_default() { 00275 if (_default_case != (SwitchFields *)NULL) { 00276 add_invalid_case(); 00277 return false; 00278 } 00279 00280 SwitchFields *fields = start_new_case(); 00281 _default_case = fields; 00282 return true; 00283 } 00284 00285 //////////////////////////////////////////////////////////////////// 00286 // Function: DCSwitch::add_field 00287 // Access: Public 00288 // Description: Adds a field to the currently active cases (those 00289 // that have been added via add_case() or add_default(), 00290 // since the last call to add_break()). Returns true if 00291 // successful, false if the field duplicates a field 00292 // already named within this case. It is an error to 00293 // call this before calling add_case() or add_default(). 00294 // This is normally called only by the parser. 00295 //////////////////////////////////////////////////////////////////// 00296 bool DCSwitch:: 00297 add_field(DCField *field) { 00298 nassertr(!_current_fields.empty(), false); 00299 00300 bool all_ok = true; 00301 00302 CaseFields::iterator fi; 00303 for (fi = _current_fields.begin(); fi != _current_fields.end(); ++fi) { 00304 SwitchFields *fields = (*fi); 00305 if (!fields->add_field(field)) { 00306 all_ok = false; 00307 } 00308 } 00309 _nested_fields.push_back(field); 00310 _fields_added = true; 00311 00312 return all_ok; 00313 } 00314 00315 //////////////////////////////////////////////////////////////////// 00316 // Function: DCSwitch::add_break 00317 // Access: Public 00318 // Description: Adds a break statement to the switch. This closes 00319 // the currently open cases and prepares for a new, 00320 // unrelated case. 00321 //////////////////////////////////////////////////////////////////// 00322 void DCSwitch:: 00323 add_break() { 00324 _current_fields.clear(); 00325 _fields_added = false; 00326 } 00327 00328 //////////////////////////////////////////////////////////////////// 00329 // Function: DCSwitch::apply_switch 00330 // Access: Public 00331 // Description: Returns the DCPackerInterface that presents the 00332 // alternative fields for the case indicated by the 00333 // given packed value string, or NULL if the value 00334 // string does not match one of the expected cases. 00335 //////////////////////////////////////////////////////////////////// 00336 const DCPackerInterface *DCSwitch:: 00337 apply_switch(const char *value_data, size_t length) const { 00338 CasesByValue::const_iterator vi; 00339 vi = _cases_by_value.find(string(value_data, length)); 00340 if (vi != _cases_by_value.end()) { 00341 return _cases[(*vi).second]->_fields; 00342 } 00343 00344 // Unexpected value--use the default. 00345 if (_default_case != (SwitchFields *)NULL) { 00346 return _default_case; 00347 } 00348 00349 // No default. 00350 return NULL; 00351 } 00352 00353 //////////////////////////////////////////////////////////////////// 00354 // Function : DCSwitch::output 00355 // Access : Public, Virtual 00356 // Description : Write a string representation of this instance to 00357 // <out>. 00358 //////////////////////////////////////////////////////////////////// 00359 void DCSwitch:: 00360 output(ostream &out, bool brief) const { 00361 output_instance(out, brief, "", "", ""); 00362 } 00363 00364 //////////////////////////////////////////////////////////////////// 00365 // Function: DCSwitch::write 00366 // Access: Public, Virtual 00367 // Description: Generates a parseable description of the object to 00368 // the indicated output stream. 00369 //////////////////////////////////////////////////////////////////// 00370 void DCSwitch:: 00371 write(ostream &out, bool brief, int indent_level) const { 00372 write_instance(out, brief, indent_level, "", "", ""); 00373 } 00374 00375 //////////////////////////////////////////////////////////////////// 00376 // Function: DCSwitch::output_instance 00377 // Access: Public 00378 // Description: Generates a parseable description of the object to 00379 // the indicated output stream. 00380 //////////////////////////////////////////////////////////////////// 00381 void DCSwitch:: 00382 output_instance(ostream &out, bool brief, const string &prename, 00383 const string &name, const string &postname) const { 00384 out << "switch"; 00385 if (!_name.empty()) { 00386 out << " " << _name; 00387 } 00388 out << " ("; 00389 _key_parameter->output(out, brief); 00390 out << ") {"; 00391 00392 const SwitchFields *last_fields = NULL; 00393 00394 Cases::const_iterator ci; 00395 for (ci = _cases.begin(); ci != _cases.end(); ++ci) { 00396 const SwitchCase *dcase = (*ci); 00397 if (dcase->_fields != last_fields && last_fields != (SwitchFields *)NULL) { 00398 last_fields->output(out, brief); 00399 } 00400 last_fields = dcase->_fields; 00401 out << "case " << _key_parameter->format_data(dcase->_value, false) << ": "; 00402 } 00403 00404 if (_default_case != (SwitchFields *)NULL) { 00405 if (_default_case != last_fields && last_fields != (SwitchFields *)NULL) { 00406 last_fields->output(out, brief); 00407 } 00408 last_fields = _default_case; 00409 out << "default: "; 00410 } 00411 if (last_fields != (SwitchFields *)NULL) { 00412 last_fields->output(out, brief); 00413 } 00414 00415 out << "}"; 00416 if (!prename.empty() || !name.empty() || !postname.empty()) { 00417 out << " " << prename << name << postname; 00418 } 00419 } 00420 00421 //////////////////////////////////////////////////////////////////// 00422 // Function: DCSwitch::write_instance 00423 // Access: Public, Virtual 00424 // Description: Generates a parseable description of the object to 00425 // the indicated output stream. 00426 //////////////////////////////////////////////////////////////////// 00427 void DCSwitch:: 00428 write_instance(ostream &out, bool brief, int indent_level, 00429 const string &prename, const string &name, 00430 const string &postname) const { 00431 indent(out, indent_level) 00432 << "switch"; 00433 if (!_name.empty()) { 00434 out << " " << _name; 00435 } 00436 out << " ("; 00437 _key_parameter->output(out, brief); 00438 out << ") {\n"; 00439 00440 const SwitchFields *last_fields = NULL; 00441 00442 Cases::const_iterator ci; 00443 for (ci = _cases.begin(); ci != _cases.end(); ++ci) { 00444 const SwitchCase *dcase = (*ci); 00445 if (dcase->_fields != last_fields && last_fields != (SwitchFields *)NULL) { 00446 last_fields->write(out, brief, indent_level + 2); 00447 } 00448 last_fields = dcase->_fields; 00449 indent(out, indent_level) 00450 << "case " << _key_parameter->format_data(dcase->_value, false) << ":\n"; 00451 } 00452 00453 if (_default_case != (SwitchFields *)NULL) { 00454 if (_default_case != last_fields && last_fields != (SwitchFields *)NULL) { 00455 last_fields->write(out, brief, indent_level + 2); 00456 } 00457 last_fields = _default_case; 00458 indent(out, indent_level) 00459 << "default:\n"; 00460 } 00461 if (last_fields != (SwitchFields *)NULL) { 00462 last_fields->write(out, brief, indent_level + 2); 00463 } 00464 00465 indent(out, indent_level) 00466 << "}"; 00467 if (!prename.empty() || !name.empty() || !postname.empty()) { 00468 out << " " << prename << name << postname; 00469 } 00470 out << ";\n"; 00471 } 00472 00473 //////////////////////////////////////////////////////////////////// 00474 // Function: DCSwitch::generate_hash 00475 // Access: Public, Virtual 00476 // Description: Accumulates the properties of this switch into the 00477 // hash. 00478 //////////////////////////////////////////////////////////////////// 00479 void DCSwitch:: 00480 generate_hash(HashGenerator &hashgen) const { 00481 hashgen.add_string(_name); 00482 00483 _key_parameter->generate_hash(hashgen); 00484 00485 hashgen.add_int(_cases.size()); 00486 Cases::const_iterator ci; 00487 for (ci = _cases.begin(); ci != _cases.end(); ++ci) { 00488 const SwitchCase *dcase = (*ci); 00489 hashgen.add_string(dcase->_value); 00490 00491 const SwitchFields *fields = dcase->_fields; 00492 hashgen.add_int(fields->_fields.size()); 00493 Fields::const_iterator fi; 00494 for (fi = fields->_fields.begin(); fi != fields->_fields.end(); ++fi) { 00495 (*fi)->generate_hash(hashgen); 00496 } 00497 } 00498 00499 if (_default_case != (SwitchFields *)NULL) { 00500 const SwitchFields *fields = _default_case; 00501 hashgen.add_int(fields->_fields.size()); 00502 Fields::const_iterator fi; 00503 for (fi = fields->_fields.begin(); fi != fields->_fields.end(); ++fi) { 00504 (*fi)->generate_hash(hashgen); 00505 } 00506 } 00507 } 00508 00509 //////////////////////////////////////////////////////////////////// 00510 // Function: DCSwitch::pack_default_value 00511 // Access: Public 00512 // Description: Packs the switchParameter's specified default value 00513 // (or a sensible default if no value is specified) into 00514 // the stream. Returns true if the default value is 00515 // packed, false if the switchParameter doesn't know how 00516 // to pack its default value. 00517 //////////////////////////////////////////////////////////////////// 00518 bool DCSwitch:: 00519 pack_default_value(DCPackData &pack_data, bool &pack_error) const { 00520 SwitchFields *fields = NULL; 00521 DCPacker packer; 00522 packer.begin_pack(_key_parameter); 00523 if (!_cases.empty()) { 00524 // If we have any cases, the first case is always the default 00525 // case, regardless of the default value specified by the key 00526 // parameter. That's just the easiest to code. 00527 packer.pack_literal_value(_cases[0]->_value); 00528 fields = _cases[0]->_fields; 00529 00530 } else { 00531 // If we don't have any cases, just pack the key parameter's 00532 // default. 00533 packer.pack_default_value(); 00534 fields = _default_case; 00535 } 00536 00537 if (!packer.end_pack()) { 00538 pack_error = true; 00539 } 00540 00541 if (fields == (SwitchFields *)NULL) { 00542 pack_error = true; 00543 00544 } else { 00545 // Then everything within the case gets its normal default. 00546 for (size_t i = 1; i < fields->_fields.size(); i++) { 00547 packer.begin_pack(fields->_fields[i]); 00548 packer.pack_default_value(); 00549 if (!packer.end_pack()) { 00550 pack_error = true; 00551 } 00552 } 00553 } 00554 00555 pack_data.append_data(packer.get_data(), packer.get_length()); 00556 00557 return true; 00558 } 00559 00560 //////////////////////////////////////////////////////////////////// 00561 // Function: DCSwitch::do_check_match_switch 00562 // Access: Public 00563 // Description: Returns true if this switch matches the indicated 00564 // other switch--that is, the two switches are bitwise 00565 // equivalent--false otherwise. This is only intended 00566 // to be called internally from 00567 // DCSwitchParameter::do_check_match_switch_parameter(). 00568 //////////////////////////////////////////////////////////////////// 00569 bool DCSwitch:: 00570 do_check_match_switch(const DCSwitch *other) const { 00571 if (!_key_parameter->check_match(other->_key_parameter)) { 00572 return false; 00573 } 00574 00575 if (_cases.size() != other->_cases.size()) { 00576 return false; 00577 } 00578 00579 Cases::const_iterator ci; 00580 for (ci = _cases.begin(); ci != _cases.end(); ++ci) { 00581 const SwitchCase *c1 = (*ci); 00582 CasesByValue::const_iterator vi; 00583 vi = other->_cases_by_value.find(c1->_value); 00584 if (vi == other->_cases_by_value.end()) { 00585 // No matching value. 00586 return false; 00587 } 00588 int c2_index = (*vi).second; 00589 nassertr(c2_index >= 0 && c2_index < (int)other->_cases.size(), false); 00590 const SwitchCase *c2 = other->_cases[c2_index]; 00591 00592 if (!c1->do_check_match_switch_case(c2)) { 00593 return false; 00594 } 00595 } 00596 00597 return true; 00598 } 00599 00600 //////////////////////////////////////////////////////////////////// 00601 // Function: DCSwitch::start_new_case 00602 // Access: Private 00603 // Description: Creates a new field set for the new case, or shares 00604 // the field set with the previous case, as appropriate. 00605 // Returns the appropriate field set. 00606 //////////////////////////////////////////////////////////////////// 00607 DCSwitch::SwitchFields *DCSwitch:: 00608 start_new_case() { 00609 SwitchFields *fields = NULL; 00610 00611 if (_current_fields.empty() || _fields_added) { 00612 // If we have recently encountered a break (which removes all of 00613 // the current field sets) or if we have already added at least 00614 // one field to the previous case without an intervening break, 00615 // then we can't share the field set with the previous case. 00616 // Create a new one. 00617 fields = new SwitchFields(_name); 00618 fields->add_field(_key_parameter); 00619 00620 _case_fields.push_back(fields); 00621 _current_fields.push_back(fields); 00622 00623 } else { 00624 // Otherwise, we can share the field set with the previous case. 00625 fields = _current_fields.back(); 00626 } 00627 00628 _fields_added = false; 00629 00630 return fields; 00631 } 00632 00633 00634 //////////////////////////////////////////////////////////////////// 00635 // Function: DCSwitch::SwitchFields::Constructor 00636 // Access: Public 00637 // Description: 00638 //////////////////////////////////////////////////////////////////// 00639 DCSwitch::SwitchFields:: 00640 SwitchFields(const string &name) : 00641 DCPackerInterface(name) 00642 { 00643 _has_nested_fields = true; 00644 _num_nested_fields = 0; 00645 _pack_type = PT_switch; 00646 00647 _has_fixed_byte_size = true; 00648 _fixed_byte_size = 0; 00649 _has_fixed_structure = true; 00650 _has_range_limits = false; 00651 _has_default_value = false; 00652 } 00653 00654 //////////////////////////////////////////////////////////////////// 00655 // Function: DCSwitch::SwitchFields::Destructor 00656 // Access: Public 00657 // Description: 00658 //////////////////////////////////////////////////////////////////// 00659 DCSwitch::SwitchFields:: 00660 ~SwitchFields() { 00661 // We don't delete any of the nested fields here, since they might 00662 // be shared by multiple SwitchFields objects. Instead, we delete 00663 // them in the DCSwitch destructor. 00664 } 00665 00666 //////////////////////////////////////////////////////////////////// 00667 // Function: DCSwitch::SwitchFields::get_nested_field 00668 // Access: Public, Virtual 00669 // Description: Returns the DCPackerInterface object that represents 00670 // the nth nested field. This may return NULL if there 00671 // is no such field (but it shouldn't do this if n is in 00672 // the range 0 <= n < get_num_nested_fields()). 00673 //////////////////////////////////////////////////////////////////// 00674 DCPackerInterface *DCSwitch::SwitchFields:: 00675 get_nested_field(int n) const { 00676 nassertr(n >= 0 && n < (int)_fields.size(), NULL); 00677 return _fields[n]; 00678 } 00679 00680 //////////////////////////////////////////////////////////////////// 00681 // Function: DCSwitch::SwitchFields::add_field 00682 // Access: Public 00683 // Description: Adds a field to this case. Returns true if 00684 // successful, false if the field duplicates a field 00685 // already named within this case. This is normally 00686 // called only by the parser. 00687 //////////////////////////////////////////////////////////////////// 00688 bool DCSwitch::SwitchFields:: 00689 add_field(DCField *field) { 00690 if (!field->get_name().empty()) { 00691 bool inserted = _fields_by_name.insert 00692 (FieldsByName::value_type(field->get_name(), field)).second; 00693 00694 if (!inserted) { 00695 return false; 00696 } 00697 } 00698 00699 _fields.push_back(field); 00700 00701 _num_nested_fields = (int)_fields.size(); 00702 00703 // See if we still have a fixed byte size. 00704 if (_has_fixed_byte_size) { 00705 _has_fixed_byte_size = field->has_fixed_byte_size(); 00706 _fixed_byte_size += field->get_fixed_byte_size(); 00707 } 00708 if (_has_fixed_structure) { 00709 _has_fixed_structure = field->has_fixed_structure(); 00710 } 00711 if (!_has_range_limits) { 00712 _has_range_limits = field->has_range_limits(); 00713 } 00714 if (!_has_default_value) { 00715 _has_default_value = field->has_default_value(); 00716 } 00717 return true; 00718 } 00719 00720 //////////////////////////////////////////////////////////////////// 00721 // Function: DCSwitch::SwitchFields::do_check_match_switch_case 00722 // Access: Public 00723 // Description: Returns true if this case matches the indicated 00724 // case, false otherwise. This is only intended to be 00725 // called internally from 00726 // DCSwitch::do_check_match_switch(). 00727 //////////////////////////////////////////////////////////////////// 00728 bool DCSwitch::SwitchFields:: 00729 do_check_match_switch_case(const DCSwitch::SwitchFields *other) const { 00730 if (_fields.size() != other->_fields.size()) { 00731 return false; 00732 } 00733 for (size_t i = 0; i < _fields.size(); i++) { 00734 if (!_fields[i]->check_match(other->_fields[i])) { 00735 return false; 00736 } 00737 } 00738 00739 return true; 00740 } 00741 00742 //////////////////////////////////////////////////////////////////// 00743 // Function: DCSwitch::SwitchFields::output 00744 // Access: Public 00745 // Description: 00746 //////////////////////////////////////////////////////////////////// 00747 void DCSwitch::SwitchFields:: 00748 output(ostream &out, bool brief) const { 00749 Fields::const_iterator fi; 00750 if (!_fields.empty()) { 00751 fi = _fields.begin(); 00752 ++fi; 00753 while (fi != _fields.end()) { 00754 (*fi)->output(out, brief); 00755 out << "; "; 00756 ++fi; 00757 } 00758 } 00759 out << "break; "; 00760 } 00761 00762 //////////////////////////////////////////////////////////////////// 00763 // Function: DCSwitch::SwitchFields::write 00764 // Access: Public 00765 // Description: 00766 //////////////////////////////////////////////////////////////////// 00767 void DCSwitch::SwitchFields:: 00768 write(ostream &out, bool brief, int indent_level) const { 00769 Fields::const_iterator fi; 00770 if (!_fields.empty()) { 00771 fi = _fields.begin(); 00772 ++fi; 00773 while (fi != _fields.end()) { 00774 (*fi)->write(out, brief, indent_level); 00775 ++fi; 00776 } 00777 } 00778 indent(out, indent_level) 00779 << "break;\n"; 00780 } 00781 00782 //////////////////////////////////////////////////////////////////// 00783 // Function: DCSwitch::SwitchFields::do_check_match 00784 // Access: Protected, Virtual 00785 // Description: Returns true if the other interface is bitwise the 00786 // same as this one--that is, a uint32 only matches a 00787 // uint32, etc. Names of components, and range limits, 00788 // are not compared. 00789 //////////////////////////////////////////////////////////////////// 00790 bool DCSwitch::SwitchFields:: 00791 do_check_match(const DCPackerInterface *) const { 00792 // This should never be called on a SwitchFields. 00793 nassertr(false, false); 00794 return false; 00795 } 00796 00797 //////////////////////////////////////////////////////////////////// 00798 // Function: DCSwitch::SwitchCase::Constructor 00799 // Access: Public 00800 // Description: 00801 //////////////////////////////////////////////////////////////////// 00802 DCSwitch::SwitchCase:: 00803 SwitchCase(const string &value, DCSwitch::SwitchFields *fields) : 00804 _value(value), 00805 _fields(fields) 00806 { 00807 } 00808 00809 //////////////////////////////////////////////////////////////////// 00810 // Function: DCSwitch::SwitchCase::Destructor 00811 // Access: Public 00812 // Description: 00813 //////////////////////////////////////////////////////////////////// 00814 DCSwitch::SwitchCase:: 00815 ~SwitchCase() { 00816 } 00817 00818 //////////////////////////////////////////////////////////////////// 00819 // Function: DCSwitch::SwitchCase::do_check_match_switch_case 00820 // Access: Public 00821 // Description: Returns true if this case matches the indicated 00822 // case, false otherwise. This is only intended to be 00823 // called internally from 00824 // DCSwitch::do_check_match_switch(). 00825 //////////////////////////////////////////////////////////////////// 00826 bool DCSwitch::SwitchCase:: 00827 do_check_match_switch_case(const DCSwitch::SwitchCase *other) const { 00828 return _fields->do_check_match_switch_case(other->_fields); 00829 }