|
@@ -35,6 +35,8 @@ DCSwitch(const string &name, DCParameter *key_parameter) :
|
|
|
_name(name),
|
|
_name(name),
|
|
|
_key_parameter(key_parameter)
|
|
_key_parameter(key_parameter)
|
|
|
{
|
|
{
|
|
|
|
|
+ _default_case = NULL;
|
|
|
|
|
+ _fields_added = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
@@ -44,13 +46,26 @@ DCSwitch(const string &name, DCParameter *key_parameter) :
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
DCSwitch::
|
|
DCSwitch::
|
|
|
~DCSwitch() {
|
|
~DCSwitch() {
|
|
|
|
|
+ nassertv(_key_parameter != (DCParameter *)NULL);
|
|
|
delete _key_parameter;
|
|
delete _key_parameter;
|
|
|
|
|
|
|
|
Cases::iterator ci;
|
|
Cases::iterator ci;
|
|
|
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
|
|
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
|
|
|
- const SwitchCase *dcase = (*ci);
|
|
|
|
|
|
|
+ SwitchCase *dcase = (*ci);
|
|
|
delete dcase;
|
|
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::
|
|
DCPackerInterface *DCSwitch::
|
|
|
get_case(int n) const {
|
|
get_case(int n) const {
|
|
|
nassertr(n >= 0 && n < (int)_cases.size(), NULL);
|
|
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::
|
|
int DCSwitch::
|
|
|
get_num_fields(int case_index) const {
|
|
get_num_fields(int case_index) const {
|
|
|
nassertr(case_index >= 0 && case_index < (int)_cases.size(), 0);
|
|
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::
|
|
DCField *DCSwitch::
|
|
|
get_field(int case_index, int n) const {
|
|
get_field(int case_index, int n) const {
|
|
|
nassertr(case_index >= 0 && case_index < (int)_cases.size(), NULL);
|
|
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 {
|
|
get_field_by_name(int case_index, const string &name) const {
|
|
|
nassertr(case_index >= 0 && case_index < (int)_cases.size(), NULL);
|
|
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;
|
|
FieldsByName::const_iterator ni;
|
|
|
ni = fields_by_name.find(name);
|
|
ni = fields_by_name.find(name);
|
|
|
if (ni != fields_by_name.end()) {
|
|
if (ni != fields_by_name.end()) {
|
|
@@ -192,6 +207,18 @@ get_field_by_name(int case_index, const string &name) const {
|
|
|
return NULL;
|
|
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
|
|
// Function: DCSwitch::add_case
|
|
|
// Access: Public
|
|
// Access: Public
|
|
@@ -207,30 +234,71 @@ add_case(const string &value) {
|
|
|
return -1;
|
|
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);
|
|
_cases.push_back(dcase);
|
|
|
return case_index;
|
|
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
|
|
// Function: DCSwitch::add_field
|
|
|
// Access: Public
|
|
// 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::
|
|
bool DCSwitch::
|
|
|
add_field(DCField *field) {
|
|
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;
|
|
CasesByValue::const_iterator vi;
|
|
|
vi = _cases_by_value.find(string(value_data, length));
|
|
vi = _cases_by_value.find(string(value_data, length));
|
|
|
if (vi != _cases_by_value.end()) {
|
|
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;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -292,22 +365,29 @@ output_instance(ostream &out, bool brief, const string &prename,
|
|
|
_key_parameter->output(out, brief);
|
|
_key_parameter->output(out, brief);
|
|
|
out << ") {";
|
|
out << ") {";
|
|
|
|
|
|
|
|
|
|
+ const SwitchFields *last_fields = NULL;
|
|
|
|
|
+
|
|
|
Cases::const_iterator ci;
|
|
Cases::const_iterator ci;
|
|
|
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
|
|
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
|
|
|
const SwitchCase *dcase = (*ci);
|
|
const SwitchCase *dcase = (*ci);
|
|
|
|
|
+ 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) << ": ";
|
|
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 (_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 << "}";
|
|
out << "}";
|
|
|
if (!prename.empty() || !name.empty() || !postname.empty()) {
|
|
if (!prename.empty() || !name.empty() || !postname.empty()) {
|
|
|
out << " " << prename << name << postname;
|
|
out << " " << prename << name << postname;
|
|
@@ -333,22 +413,31 @@ write_instance(ostream &out, bool brief, int indent_level,
|
|
|
_key_parameter->output(out, brief);
|
|
_key_parameter->output(out, brief);
|
|
|
out << ") {\n";
|
|
out << ") {\n";
|
|
|
|
|
|
|
|
|
|
+ const SwitchFields *last_fields = NULL;
|
|
|
|
|
+
|
|
|
Cases::const_iterator ci;
|
|
Cases::const_iterator ci;
|
|
|
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
|
|
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
|
|
|
const SwitchCase *dcase = (*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)
|
|
indent(out, indent_level)
|
|
|
<< "case " << _key_parameter->format_data(dcase->_value) << ":\n";
|
|
<< "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)
|
|
indent(out, indent_level)
|
|
|
<< "}";
|
|
<< "}";
|
|
|
if (!prename.empty() || !name.empty() || !postname.empty()) {
|
|
if (!prename.empty() || !name.empty() || !postname.empty()) {
|
|
@@ -375,9 +464,19 @@ generate_hash(HashGenerator &hashgen) const {
|
|
|
const SwitchCase *dcase = (*ci);
|
|
const SwitchCase *dcase = (*ci);
|
|
|
hashgen.add_string(dcase->_value);
|
|
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;
|
|
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);
|
|
(*fi)->generate_hash(hashgen);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -386,36 +485,49 @@ generate_hash(HashGenerator &hashgen) const {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: DCSwitch::pack_default_value
|
|
// Function: DCSwitch::pack_default_value
|
|
|
// Access: Public
|
|
// 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::
|
|
bool DCSwitch::
|
|
|
pack_default_value(DCPackData &pack_data, bool &pack_error) const {
|
|
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;
|
|
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()) {
|
|
if (!packer.end_pack()) {
|
|
|
pack_error = true;
|
|
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());
|
|
pack_data.append_data(packer.get_data(), packer.get_length());
|
|
|
|
|
|
|
|
return true;
|
|
return true;
|
|
@@ -425,8 +537,9 @@ pack_default_value(DCPackData &pack_data, bool &pack_error) const {
|
|
|
// Function: DCSwitch::do_check_match_switch
|
|
// Function: DCSwitch::do_check_match_switch
|
|
|
// Access: Public
|
|
// Access: Public
|
|
|
// Description: Returns true if this switch matches the indicated
|
|
// 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().
|
|
// DCSwitchParameter::do_check_match_switch_parameter().
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool DCSwitch::
|
|
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
|
|
// Access: Public
|
|
|
// Description:
|
|
// 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;
|
|
_has_nested_fields = true;
|
|
|
_num_nested_fields = 0;
|
|
_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
|
|
// Access: Public
|
|
|
// Description:
|
|
// 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
|
|
// Access: Public, Virtual
|
|
|
// Description: Returns the DCPackerInterface object that represents
|
|
// Description: Returns the DCPackerInterface object that represents
|
|
|
// the nth nested field. This may return NULL if there
|
|
// the nth nested field. This may return NULL if there
|
|
|
// is no such field (but it shouldn't do this if n is in
|
|
// is no such field (but it shouldn't do this if n is in
|
|
|
// the range 0 <= n < get_num_nested_fields()).
|
|
// the range 0 <= n < get_num_nested_fields()).
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-DCPackerInterface *DCSwitch::SwitchCase::
|
|
|
|
|
|
|
+DCPackerInterface *DCSwitch::SwitchFields::
|
|
|
get_nested_field(int n) const {
|
|
get_nested_field(int n) const {
|
|
|
nassertr(n >= 0 && n < (int)_fields.size(), NULL);
|
|
nassertr(n >= 0 && n < (int)_fields.size(), NULL);
|
|
|
return _fields[n];
|
|
return _fields[n];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: DCSwitch::SwitchCase::add_field
|
|
|
|
|
|
|
+// Function: DCSwitch::SwitchFields::add_field
|
|
|
// Access: Public
|
|
// Access: Public
|
|
|
// Description: Adds a field to this case. Returns true if
|
|
// Description: Adds a field to this case. Returns true if
|
|
|
// successful, false if the field duplicates a field
|
|
// successful, false if the field duplicates a field
|
|
|
// already named within this case. This is normally
|
|
// already named within this case. This is normally
|
|
|
// called only by the parser.
|
|
// called only by the parser.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-bool DCSwitch::SwitchCase::
|
|
|
|
|
|
|
+bool DCSwitch::SwitchFields::
|
|
|
add_field(DCField *field) {
|
|
add_field(DCField *field) {
|
|
|
if (!field->get_name().empty()) {
|
|
if (!field->get_name().empty()) {
|
|
|
bool inserted = _fields_by_name.insert
|
|
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
|
|
// Access: Public
|
|
|
// Description: Returns true if this case matches the indicated
|
|
// Description: Returns true if this case matches the indicated
|
|
|
// case, false otherwise. This is only intended to be
|
|
// case, false otherwise. This is only intended to be
|
|
|
// called internally from
|
|
// called internally from
|
|
|
// DCSwitch::do_check_match_switch().
|
|
// 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()) {
|
|
if (_fields.size() != other->_fields.size()) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -578,18 +714,92 @@ do_check_match_switch_case(const DCSwitch::SwitchCase *other) const {
|
|
|
|
|
|
|
|
return true;
|
|
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
|
|
// Access: Protected, Virtual
|
|
|
// Description: Returns true if the other interface is bitwise the
|
|
// Description: Returns true if the other interface is bitwise the
|
|
|
// same as this one--that is, a uint32 only matches a
|
|
// same as this one--that is, a uint32 only matches a
|
|
|
// uint32, etc. Names of components, and range limits,
|
|
// uint32, etc. Names of components, and range limits,
|
|
|
// are not compared.
|
|
// are not compared.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-bool DCSwitch::SwitchCase::
|
|
|
|
|
|
|
+bool DCSwitch::SwitchFields::
|
|
|
do_check_match(const DCPackerInterface *) const {
|
|
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);
|
|
nassertr(false, false);
|
|
|
return 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);
|
|
|
|
|
+}
|