Panda3D

dcSwitch.cxx

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 }
 All Classes Functions Variables Enumerations