diff --git a/direct/src/dcparser/dcLexer.lxx b/direct/src/dcparser/dcLexer.lxx index 907f23fd68..d1155ca21f 100644 --- a/direct/src/dcparser/dcLexer.lxx +++ b/direct/src/dcparser/dcLexer.lxx @@ -479,6 +479,16 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) return KW_CASE; } +"default" { + accept(); + return KW_DEFAULT; +} + +"break" { + accept(); + return KW_BREAK; +} + "int8" { accept(); return KW_INT8; diff --git a/direct/src/dcparser/dcParser.yxx b/direct/src/dcparser/dcParser.yxx index 3039c877ef..62b86106a6 100644 --- a/direct/src/dcparser/dcParser.yxx +++ b/direct/src/dcparser/dcParser.yxx @@ -91,6 +91,8 @@ dc_cleanup_parser() { %token KW_TYPEDEF %token KW_SWITCH %token KW_CASE +%token KW_DEFAULT +%token KW_BREAK %token KW_INT8 %token KW_INT16 @@ -1226,9 +1228,11 @@ switch_fields: empty | switch_fields ';' | switch_fields switch_case + | switch_fields switch_default + | switch_fields switch_break | switch_fields switch_field { - if (current_switch->get_num_cases() == 0) { + if (!current_switch->is_field_valid()) { yyerror("case declaration required before first element"); } else if ($2 != (DCField *)NULL) { if (!current_switch->add_field($2)) { @@ -1250,11 +1254,30 @@ switch_case: if (!current_packer->end_pack()) { yyerror("Invalid value for switch parameter"); } else { - current_switch->add_case(current_packer->get_string()); + int case_index = current_switch->add_case(current_packer->get_string()); + if (case_index == -1) { + yyerror("Duplicate case value"); + } } } ; +switch_default: + KW_DEFAULT ':' +{ + if (!current_switch->add_default()) { + yyerror("Default case already defined"); + } +} + ; + +switch_break: + KW_BREAK ';' +{ + current_switch->add_break(); +} + ; + switch_field: unnamed_parameter_with_default ';' { diff --git a/direct/src/dcparser/dcSwitch.cxx b/direct/src/dcparser/dcSwitch.cxx index 909f4d009e..666939dbe5 100644 --- a/direct/src/dcparser/dcSwitch.cxx +++ b/direct/src/dcparser/dcSwitch.cxx @@ -35,6 +35,8 @@ DCSwitch(const string &name, DCParameter *key_parameter) : _name(name), _key_parameter(key_parameter) { + _default_case = NULL; + _fields_added = false; } //////////////////////////////////////////////////////////////////// @@ -44,13 +46,26 @@ DCSwitch(const string &name, DCParameter *key_parameter) : //////////////////////////////////////////////////////////////////// DCSwitch:: ~DCSwitch() { + nassertv(_key_parameter != (DCParameter *)NULL); delete _key_parameter; Cases::iterator ci; for (ci = _cases.begin(); ci != _cases.end(); ++ci) { - const SwitchCase *dcase = (*ci); + SwitchCase *dcase = (*ci); delete dcase; } + + CaseFields::iterator fi; + for (fi = _case_fields.begin(); fi != _case_fields.end(); ++fi) { + SwitchFields *fields = (*fi); + delete fields; + } + + Fields::iterator ni; + for (ni = _nested_fields.begin(); ni != _nested_fields.end(); ++ni) { + DCField *field = (*ni); + delete field; + } } //////////////////////////////////////////////////////////////////// @@ -134,7 +149,7 @@ get_case_by_value(const string &case_value) const { DCPackerInterface *DCSwitch:: get_case(int n) const { nassertr(n >= 0 && n < (int)_cases.size(), NULL); - return _cases[n]; + return _cases[n]->_fields; } //////////////////////////////////////////////////////////////////// @@ -157,7 +172,7 @@ get_value(int case_index) const { int DCSwitch:: get_num_fields(int case_index) const { nassertr(case_index >= 0 && case_index < (int)_cases.size(), 0); - return _cases[case_index]->_fields.size(); + return _cases[case_index]->_fields->_fields.size(); } //////////////////////////////////////////////////////////////////// @@ -168,8 +183,8 @@ get_num_fields(int case_index) const { DCField *DCSwitch:: get_field(int case_index, int n) const { nassertr(case_index >= 0 && case_index < (int)_cases.size(), NULL); - nassertr(n >= 0 && n < (int)_cases[case_index]->_fields.size(), NULL); - return _cases[case_index]->_fields[n]; + nassertr(n >= 0 && n < (int)_cases[case_index]->_fields->_fields.size(), NULL); + return _cases[case_index]->_fields->_fields[n]; } //////////////////////////////////////////////////////////////////// @@ -182,7 +197,7 @@ DCField *DCSwitch:: get_field_by_name(int case_index, const string &name) const { nassertr(case_index >= 0 && case_index < (int)_cases.size(), NULL); - const FieldsByName &fields_by_name = _cases[case_index]->_fields_by_name; + const FieldsByName &fields_by_name = _cases[case_index]->_fields->_fields_by_name; FieldsByName::const_iterator ni; ni = fields_by_name.find(name); if (ni != fields_by_name.end()) { @@ -192,6 +207,18 @@ get_field_by_name(int case_index, const string &name) const { return NULL; } +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::is_field_valid +// Access: Public +// Description: Returns true if it is valid to add a new field at +// this point (implying that a case or default has been +// added already), or false if not. +//////////////////////////////////////////////////////////////////// +bool DCSwitch:: +is_field_valid() const { + return !_current_fields.empty(); +} + //////////////////////////////////////////////////////////////////// // Function: DCSwitch::add_case // Access: Public @@ -207,30 +234,71 @@ add_case(const string &value) { return -1; } - SwitchCase *dcase = new SwitchCase(_name, value); - dcase->add_field(_key_parameter); + SwitchFields *fields = start_new_case(); + SwitchCase *dcase = new SwitchCase(value, fields); _cases.push_back(dcase); return case_index; } +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::add_default +// Access: Public +// Description: Adds a default case to the switch. Returns true if +// the case is successfully added, or false if it had +// already been added. This is normally called only by +// the parser. +//////////////////////////////////////////////////////////////////// +bool DCSwitch:: +add_default() { + if (_default_case != (SwitchFields *)NULL) { + return false; + } + + _default_case = start_new_case(); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: DCSwitch::add_field // Access: Public -// Description: Adds a field to the case most recently added via -// add_case(). Returns true if successful, false if the -// field duplicates a field already named within this -// case. It is an error to call this before calling -// add_case(). This is normally called only by the -// parser. +// Description: Adds a field to the currently active cases (those +// that have been added via add_case() or add_default(), +// since the last call to add_break()). Returns true if +// successful, false if the field duplicates a field +// already named within this case. It is an error to +// call this before calling add_case() or add_default(). +// This is normally called only by the parser. //////////////////////////////////////////////////////////////////// bool DCSwitch:: add_field(DCField *field) { - nassertr(!_cases.empty(), false); + nassertr(!_current_fields.empty(), false); - if (!_cases.back()->add_field(field)) { - return false; + bool all_ok = true; + + CaseFields::iterator fi; + for (fi = _current_fields.begin(); fi != _current_fields.end(); ++fi) { + SwitchFields *fields = (*fi); + if (!fields->add_field(field)) { + all_ok = false; + } } - return true; + _nested_fields.push_back(field); + _fields_added = true; + + return all_ok; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::add_break +// Access: Public +// Description: Adds a break statement to the switch. This closes +// the currently open cases and prepares for a new, +// unrelated case. +//////////////////////////////////////////////////////////////////// +void DCSwitch:: +add_break() { + _current_fields.clear(); + _fields_added = false; } //////////////////////////////////////////////////////////////////// @@ -246,10 +314,15 @@ apply_switch(const char *value_data, size_t length) const { CasesByValue::const_iterator vi; vi = _cases_by_value.find(string(value_data, length)); if (vi != _cases_by_value.end()) { - return _cases[(*vi).second]; + return _cases[(*vi).second]->_fields; } - // Invalid value. + // Unexpected value--use the default. + if (_default_case != (SwitchFields *)NULL) { + return _default_case; + } + + // No default. return NULL; } @@ -292,22 +365,29 @@ output_instance(ostream &out, bool brief, const string &prename, _key_parameter->output(out, brief); out << ") {"; + const SwitchFields *last_fields = NULL; + Cases::const_iterator ci; for (ci = _cases.begin(); ci != _cases.end(); ++ci) { const SwitchCase *dcase = (*ci); - out << "case " << _key_parameter->format_data(dcase->_value) << ": "; - - Fields::const_iterator fi; - if (!dcase->_fields.empty()) { - fi = dcase->_fields.begin(); - ++fi; - while (fi != dcase->_fields.end()) { - (*fi)->output(out, brief); - out << "; "; - ++fi; - } + if (dcase->_fields != last_fields && last_fields != (SwitchFields *)NULL) { + last_fields->output(out, brief); } + last_fields = dcase->_fields; + out << "case " << _key_parameter->format_data(dcase->_value) << ": "; } + + if (_default_case != (SwitchFields *)NULL) { + if (_default_case != last_fields && last_fields != (SwitchFields *)NULL) { + last_fields->output(out, brief); + } + last_fields = _default_case; + out << "default: "; + } + if (last_fields != (SwitchFields *)NULL) { + last_fields->output(out, brief); + } + out << "}"; if (!prename.empty() || !name.empty() || !postname.empty()) { out << " " << prename << name << postname; @@ -333,22 +413,31 @@ write_instance(ostream &out, bool brief, int indent_level, _key_parameter->output(out, brief); out << ") {\n"; + const SwitchFields *last_fields = NULL; + Cases::const_iterator ci; for (ci = _cases.begin(); ci != _cases.end(); ++ci) { const SwitchCase *dcase = (*ci); + if (dcase->_fields != last_fields && last_fields != (SwitchFields *)NULL) { + last_fields->write(out, brief, indent_level + 2); + } + last_fields = dcase->_fields; indent(out, indent_level) << "case " << _key_parameter->format_data(dcase->_value) << ":\n"; - - Fields::const_iterator fi; - if (!dcase->_fields.empty()) { - fi = dcase->_fields.begin(); - ++fi; - while (fi != dcase->_fields.end()) { - (*fi)->write(out, brief, indent_level + 2); - ++fi; - } - } } + + if (_default_case != (SwitchFields *)NULL) { + if (_default_case != last_fields && last_fields != (SwitchFields *)NULL) { + last_fields->write(out, brief, indent_level + 2); + } + last_fields = _default_case; + indent(out, indent_level) + << "default:\n"; + } + if (last_fields != (SwitchFields *)NULL) { + last_fields->write(out, brief, indent_level + 2); + } + indent(out, indent_level) << "}"; if (!prename.empty() || !name.empty() || !postname.empty()) { @@ -375,9 +464,19 @@ generate_hash(HashGenerator &hashgen) const { const SwitchCase *dcase = (*ci); hashgen.add_string(dcase->_value); - hashgen.add_int(dcase->_fields.size()); + const SwitchFields *fields = dcase->_fields; + hashgen.add_int(fields->_fields.size()); Fields::const_iterator fi; - for (fi = dcase->_fields.begin(); fi != dcase->_fields.end(); ++fi) { + for (fi = fields->_fields.begin(); fi != fields->_fields.end(); ++fi) { + (*fi)->generate_hash(hashgen); + } + } + + if (_default_case != (SwitchFields *)NULL) { + const SwitchFields *fields = _default_case; + hashgen.add_int(fields->_fields.size()); + Fields::const_iterator fi; + for (fi = fields->_fields.begin(); fi != fields->_fields.end(); ++fi) { (*fi)->generate_hash(hashgen); } } @@ -386,36 +485,49 @@ generate_hash(HashGenerator &hashgen) const { //////////////////////////////////////////////////////////////////// // Function: DCSwitch::pack_default_value // Access: Public -// Description: Packs the switchParameter's specified default value (or a -// sensible default if no value is specified) into the -// stream. Returns true if the default value is packed, -// false if the switchParameter doesn't know how to pack its -// default value. +// Description: Packs the switchParameter's specified default value +// (or a sensible default if no value is specified) into +// the stream. Returns true if the default value is +// packed, false if the switchParameter doesn't know how +// to pack its default value. //////////////////////////////////////////////////////////////////// bool DCSwitch:: pack_default_value(DCPackData &pack_data, bool &pack_error) const { - if (_cases.empty()) { - pack_error = true; - return true; - } - - // The default value for a switch is the first case. - + SwitchFields *fields = NULL; DCPacker packer; - packer.begin_pack(_cases[0]); - packer.pack_literal_value(_cases[0]->_value); + packer.begin_pack(_key_parameter); + if (!_cases.empty()) { + // If we have any cases, the first case is always the default + // case, regardless of the default value specified by the key + // parameter. That's just the easiest to code. + packer.pack_literal_value(_cases[0]->_value); + fields = _cases[0]->_fields; + + } else { + // If we don't have any cases, just pack the key parameter's + // default. + packer.pack_default_value(); + fields = _default_case; + } + if (!packer.end_pack()) { pack_error = true; } - // Then everything within the case gets its normal default. - for (size_t i = 1; i < _cases[0]->_fields.size(); i++) { - packer.begin_pack(_cases[0]->_fields[i]); - packer.pack_default_value(); - if (!packer.end_pack()) { - pack_error = true; + if (fields == (SwitchFields *)NULL) { + pack_error = true; + + } else { + // Then everything within the case gets its normal default. + for (size_t i = 1; i < fields->_fields.size(); i++) { + packer.begin_pack(fields->_fields[i]); + packer.pack_default_value(); + if (!packer.end_pack()) { + pack_error = true; + } } } + pack_data.append_data(packer.get_data(), packer.get_length()); return true; @@ -425,8 +537,9 @@ pack_default_value(DCPackData &pack_data, bool &pack_error) const { // Function: DCSwitch::do_check_match_switch // Access: Public // Description: Returns true if this switch matches the indicated -// switch, false otherwise. This is only intended to be -// called internally from +// other switch--that is, the two switches are bitwise +// equivalent--false otherwise. This is only intended +// to be called internally from // DCSwitchParameter::do_check_match_switch_parameter(). //////////////////////////////////////////////////////////////////// bool DCSwitch:: @@ -461,14 +574,47 @@ do_check_match_switch(const DCSwitch *other) const { } //////////////////////////////////////////////////////////////////// -// Function: DCSwitch::SwitchCase::Constructor +// Function: DCSwitch::start_new_case +// Access: Private +// Description: Creates a new field set for the new case, or shares +// the field set with the previous case, as appropriate. +// Returns the appropriate field set. +//////////////////////////////////////////////////////////////////// +DCSwitch::SwitchFields *DCSwitch:: +start_new_case() { + SwitchFields *fields = NULL; + + if (_current_fields.empty() || _fields_added) { + // If we have recently encountered a break (which removes all of + // the current field sets) or if we have already added at least + // one field to the previous case without an intervening break, + // then we can't share the field set with the previous case. + // Create a new one. + fields = new SwitchFields(_name); + fields->add_field(_key_parameter); + + _case_fields.push_back(fields); + _current_fields.push_back(fields); + + } else { + // Otherwise, we can share the field set with the previous case. + fields = _current_fields.back(); + } + + _fields_added = false; + + return fields; +} + + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::SwitchFields::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -DCSwitch::SwitchCase:: -SwitchCase(const string &name, const string &value) : - DCPackerInterface(name), - _value(value) +DCSwitch::SwitchFields:: +SwitchFields(const string &name) : + DCPackerInterface(name) { _has_nested_fields = true; _num_nested_fields = 0; @@ -482,50 +628,40 @@ SwitchCase(const string &name, const string &value) : } //////////////////////////////////////////////////////////////////// -// Function: DCSwitch::SwitchCase::Destructor +// Function: DCSwitch::SwitchFields::Destructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// -DCSwitch::SwitchCase:: -~SwitchCase() { - Fields::iterator fi = _fields.begin(); - - // Be careful not to delete the _key_parameter, which is added to - // the beginning of each case. - nassertv(fi != _fields.end()); - ++fi; - - // But we do want to delete all of the other fields. - while (fi != _fields.end()) { - delete (*fi); - ++fi; - } - _fields.clear(); +DCSwitch::SwitchFields:: +~SwitchFields() { + // We don't delete any of the nested fields here, since they might + // be shared by multiple SwitchFields objects. Instead, we delete + // them in the DCSwitch destructor. } //////////////////////////////////////////////////////////////////// -// Function: DCSwitch::SwitchCase::get_nested_field +// Function: DCSwitch::SwitchFields::get_nested_field // Access: Public, Virtual // Description: Returns the DCPackerInterface object that represents // the nth nested field. This may return NULL if there // is no such field (but it shouldn't do this if n is in // the range 0 <= n < get_num_nested_fields()). //////////////////////////////////////////////////////////////////// -DCPackerInterface *DCSwitch::SwitchCase:: +DCPackerInterface *DCSwitch::SwitchFields:: get_nested_field(int n) const { nassertr(n >= 0 && n < (int)_fields.size(), NULL); return _fields[n]; } //////////////////////////////////////////////////////////////////// -// Function: DCSwitch::SwitchCase::add_field +// Function: DCSwitch::SwitchFields::add_field // Access: Public // Description: Adds a field to this case. Returns true if // successful, false if the field duplicates a field // already named within this case. This is normally // called only by the parser. //////////////////////////////////////////////////////////////////// -bool DCSwitch::SwitchCase:: +bool DCSwitch::SwitchFields:: add_field(DCField *field) { if (!field->get_name().empty()) { bool inserted = _fields_by_name.insert @@ -558,15 +694,15 @@ add_field(DCField *field) { } //////////////////////////////////////////////////////////////////// -// Function: DCSwitch::SwitchCase::do_check_match_switch_case +// Function: DCSwitch::SwitchFields::do_check_match_switch_case // Access: Public // Description: Returns true if this case matches the indicated // case, false otherwise. This is only intended to be // called internally from // DCSwitch::do_check_match_switch(). //////////////////////////////////////////////////////////////////// -bool DCSwitch::SwitchCase:: -do_check_match_switch_case(const DCSwitch::SwitchCase *other) const { +bool DCSwitch::SwitchFields:: +do_check_match_switch_case(const DCSwitch::SwitchFields *other) const { if (_fields.size() != other->_fields.size()) { return false; } @@ -578,18 +714,92 @@ do_check_match_switch_case(const DCSwitch::SwitchCase *other) const { return true; } + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::SwitchFields::output +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void DCSwitch::SwitchFields:: +output(ostream &out, bool brief) const { + Fields::const_iterator fi; + if (!_fields.empty()) { + fi = _fields.begin(); + ++fi; + while (fi != _fields.end()) { + (*fi)->output(out, brief); + out << "; "; + ++fi; + } + } + out << "break; "; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::SwitchFields::write +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void DCSwitch::SwitchFields:: +write(ostream &out, bool brief, int indent_level) const { + Fields::const_iterator fi; + if (!_fields.empty()) { + fi = _fields.begin(); + ++fi; + while (fi != _fields.end()) { + (*fi)->write(out, brief, indent_level); + ++fi; + } + } + indent(out, indent_level) + << "break;\n"; +} //////////////////////////////////////////////////////////////////// -// Function: DCSwitch::SwitchCase::do_check_match +// Function: DCSwitch::SwitchFields::do_check_match // Access: Protected, Virtual // Description: Returns true if the other interface is bitwise the // same as this one--that is, a uint32 only matches a // uint32, etc. Names of components, and range limits, // are not compared. //////////////////////////////////////////////////////////////////// -bool DCSwitch::SwitchCase:: +bool DCSwitch::SwitchFields:: do_check_match(const DCPackerInterface *) const { - // This should never be called on a SwitchCase. + // This should never be called on a SwitchFields. nassertr(false, false); return false; } + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::SwitchCase::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +DCSwitch::SwitchCase:: +SwitchCase(const string &value, DCSwitch::SwitchFields *fields) : + _value(value), + _fields(fields) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::SwitchCase::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +DCSwitch::SwitchCase:: +~SwitchCase() { +} + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitch::SwitchCase::do_check_match_switch_case +// Access: Public +// Description: Returns true if this case matches the indicated +// case, false otherwise. This is only intended to be +// called internally from +// DCSwitch::do_check_match_switch(). +//////////////////////////////////////////////////////////////////// +bool DCSwitch::SwitchCase:: +do_check_match_switch_case(const DCSwitch::SwitchCase *other) const { + return _fields->do_check_match_switch_case(other->_fields); +} diff --git a/direct/src/dcparser/dcSwitch.h b/direct/src/dcparser/dcSwitch.h index 7d1e638337..3e413f23b3 100644 --- a/direct/src/dcparser/dcSwitch.h +++ b/direct/src/dcparser/dcSwitch.h @@ -56,8 +56,11 @@ PUBLISHED: DCField *get_field_by_name(int case_index, const string &name) const; public: + bool is_field_valid() const; int add_case(const string &value); + bool add_default(); bool add_field(DCField *field); + void add_break(); const DCPackerInterface *apply_switch(const char *value_data, size_t length) const; @@ -77,32 +80,68 @@ public: typedef pvector Fields; typedef pmap FieldsByName; - class SwitchCase : public DCPackerInterface { + class SwitchFields : public DCPackerInterface { public: - SwitchCase(const string &name, const string &value); - ~SwitchCase(); + SwitchFields(const string &name); + ~SwitchFields(); virtual DCPackerInterface *get_nested_field(int n) const; bool add_field(DCField *field); - bool do_check_match_switch_case(const SwitchCase *other) const; + bool do_check_match_switch_case(const SwitchFields *other) const; + + void output(ostream &out, bool brief) const; + void write(ostream &out, bool brief, int indent_level) const; protected: virtual bool do_check_match(const DCPackerInterface *other) const; public: - string _value; Fields _fields; FieldsByName _fields_by_name; bool _has_default_value; }; + class SwitchCase { + public: + SwitchCase(const string &value, SwitchFields *fields); + ~SwitchCase(); + + bool do_check_match_switch_case(const SwitchCase *other) const; + + public: + string _value; + SwitchFields *_fields; + }; + +private: + SwitchFields *start_new_case(); + private: string _name; DCParameter *_key_parameter; typedef pvector Cases; Cases _cases; + SwitchFields *_default_case; + // All SwitchFields created and used by the DCSwitch object are also + // stored here; this is the vector that "owns" the pointers. + typedef pvector CaseFields; + CaseFields _case_fields; + + // All nested DCField objects that have been added to one or more of + // the above SwitchFields are also recorded here; this is the vector + // that "owns" these pointers. + Fields _nested_fields; + + // These are the SwitchFields that are currently being filled up + // during this stage of the parser. There might be more than one at + // a time, if we have multiple cases being introduced in the middle + // of a series of fields (without a break statement intervening). + CaseFields _current_fields; + bool _fields_added; + + // This map indexes into the _cases vector, above. typedef pmap CasesByValue; CasesByValue _cases_by_value; }; diff --git a/direct/src/dcparser/dcSwitchParameter.cxx b/direct/src/dcparser/dcSwitchParameter.cxx index 9350d431d7..6bbe980a58 100755 --- a/direct/src/dcparser/dcSwitchParameter.cxx +++ b/direct/src/dcparser/dcSwitchParameter.cxx @@ -54,16 +54,18 @@ DCSwitchParameter(const DCSwitch *dswitch) : _fixed_byte_size = _dswitch->get_case(0)->get_fixed_byte_size(); for (int i = 0; i < num_cases; i++) { - const DCSwitch::SwitchCase *dcase = (const DCSwitch::SwitchCase *)_dswitch->get_case(i); - if (!dcase->has_fixed_byte_size() || - dcase->get_fixed_byte_size() != _fixed_byte_size) { + const DCSwitch::SwitchFields *fields = + (const DCSwitch::SwitchFields *)_dswitch->get_case(i); + + if (!fields->has_fixed_byte_size() || + fields->get_fixed_byte_size() != _fixed_byte_size) { // Nope, we have a variable byte size. _has_fixed_byte_size = false; } - _has_range_limits = _has_range_limits || dcase->has_range_limits(); - _has_default_value = _has_default_value || dcase->_has_default_value; + _has_range_limits = _has_range_limits || fields->has_range_limits(); + _has_default_value = _has_default_value || fields->_has_default_value; } } diff --git a/direct/src/doc/sample.dc b/direct/src/doc/sample.dc index 06ac737362..63d78b9e7e 100644 --- a/direct/src/doc/sample.dc +++ b/direct/src/doc/sample.dc @@ -105,6 +105,7 @@ struct AvatarDNA { DNAColor shirtColor; uint8(0-25) skirtIndex; DNAColor skirtColor; + break; case 0: // Boy clothes @@ -112,6 +113,7 @@ struct AvatarDNA { DNAColor shirtColor; uint8(0-15) shortsIndex; DNAColor shortsColor; + break; }; // Nested structure references.