17 #include "dcParameter.h" 18 #include "hashGenerator.h" 32 _key_parameter(key_parameter)
35 _fields_added =
false;
45 nassertv(_key_parameter != (
DCField *)NULL);
46 delete _key_parameter;
49 for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
54 CaseFields::iterator fi;
55 for (fi = _case_fields.begin(); fi != _case_fields.end(); ++fi) {
61 for (ni = _nested_fields.begin(); ni != _nested_fields.end(); ++ni) {
107 return _key_parameter;
119 return _cases.size();
131 CasesByValue::const_iterator vi;
132 vi = _cases_by_value.find(case_value);
133 if (vi != _cases_by_value.end()) {
147 nassertr(n >= 0 && n < (
int)_cases.size(), NULL);
148 return _cases[n]->_fields;
159 return _default_case;
170 nassertr(case_index >= 0 && case_index < (
int)_cases.size(), string());
171 return _cases[case_index]->_value;
181 nassertr(case_index >= 0 && case_index < (
int)_cases.size(), 0);
182 return _cases[case_index]->_fields->_fields.size();
192 nassertr(case_index >= 0 && case_index < (
int)_cases.size(), NULL);
193 nassertr(n >= 0 && n < (
int)_cases[case_index]->_fields->_fields.size(), NULL);
194 return _cases[case_index]->_fields->_fields[n];
205 nassertr(case_index >= 0 && case_index < (
int)_cases.size(), NULL);
207 const FieldsByName &fields_by_name = _cases[case_index]->_fields->_fields_by_name;
208 FieldsByName::const_iterator ni;
209 ni = fields_by_name.find(name);
210 if (ni != fields_by_name.end()) {
226 return !_current_fields.empty();
239 int case_index = (int)_cases.size();
240 if (!_cases_by_value.insert(CasesByValue::value_type(value, case_index)).second) {
247 _cases.push_back(dcase);
281 _default_case = fields;
298 nassertr(!_current_fields.empty(),
false);
302 CaseFields::iterator fi;
303 for (fi = _current_fields.begin(); fi != _current_fields.end(); ++fi) {
309 _nested_fields.push_back(field);
310 _fields_added =
true;
324 _current_fields.clear();
325 _fields_added =
false;
338 CasesByValue::const_iterator vi;
339 vi = _cases_by_value.find(
string(value_data, length));
340 if (vi != _cases_by_value.end()) {
341 return _cases[(*vi).second]->_fields;
346 return _default_case;
371 write(ostream &out,
bool brief,
int indent_level)
const {
383 const string &name,
const string &postname)
const {
385 if (!_name.empty()) {
389 _key_parameter->
output(out, brief);
394 Cases::const_iterator ci;
395 for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
397 if (dcase->_fields != last_fields && last_fields != (
SwitchFields *)NULL) {
398 last_fields->output(out, brief);
400 last_fields = dcase->_fields;
401 out <<
"case " << _key_parameter->
format_data(dcase->_value,
false) <<
": ";
405 if (_default_case != last_fields && last_fields != (
SwitchFields *)NULL) {
406 last_fields->output(out, brief);
408 last_fields = _default_case;
412 last_fields->output(out, brief);
416 if (!prename.empty() || !name.empty() || !postname.empty()) {
417 out <<
" " << prename << name << postname;
429 const string &prename,
const string &name,
430 const string &postname)
const {
431 indent(out, indent_level)
433 if (!_name.empty()) {
437 _key_parameter->
output(out, brief);
442 Cases::const_iterator ci;
443 for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
445 if (dcase->_fields != last_fields && last_fields != (
SwitchFields *)NULL) {
446 last_fields->write(out, brief, indent_level + 2);
448 last_fields = dcase->_fields;
449 indent(out, indent_level)
450 <<
"case " << _key_parameter->
format_data(dcase->_value,
false) <<
":\n";
454 if (_default_case != last_fields && last_fields != (
SwitchFields *)NULL) {
455 last_fields->write(out, brief, indent_level + 2);
457 last_fields = _default_case;
458 indent(out, indent_level)
462 last_fields->write(out, brief, indent_level + 2);
465 indent(out, indent_level)
467 if (!prename.empty() || !name.empty() || !postname.empty()) {
468 out <<
" " << prename << name << postname;
485 hashgen.
add_int(_cases.size());
486 Cases::const_iterator ci;
487 for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
492 hashgen.
add_int(fields->_fields.size());
493 Fields::const_iterator fi;
494 for (fi = fields->_fields.begin(); fi != fields->_fields.end(); ++fi) {
495 (*fi)->generate_hash(hashgen);
501 hashgen.
add_int(fields->_fields.size());
502 Fields::const_iterator fi;
503 for (fi = fields->_fields.begin(); fi != fields->_fields.end(); ++fi) {
504 (*fi)->generate_hash(hashgen);
523 if (!_cases.empty()) {
528 fields = _cases[0]->_fields;
534 fields = _default_case;
546 for (
size_t i = 1; i < fields->_fields.size(); i++) {
571 if (!_key_parameter->
check_match(other->_key_parameter)) {
575 if (_cases.size() != other->_cases.size()) {
579 Cases::const_iterator ci;
580 for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
582 CasesByValue::const_iterator vi;
583 vi = other->_cases_by_value.find(c1->_value);
584 if (vi == other->_cases_by_value.end()) {
588 int c2_index = (*vi).second;
589 nassertr(c2_index >= 0 && c2_index < (
int)other->_cases.size(),
false);
590 const SwitchCase *c2 = other->_cases[c2_index];
611 if (_current_fields.empty() || _fields_added) {
620 _case_fields.push_back(fields);
621 _current_fields.push_back(fields);
625 fields = _current_fields.back();
628 _fields_added =
false;
639 DCSwitch::SwitchFields::
640 SwitchFields(
const string &name) :
643 _has_nested_fields =
true;
644 _num_nested_fields = 0;
645 _pack_type = PT_switch;
647 _has_fixed_byte_size =
true;
648 _fixed_byte_size = 0;
649 _has_fixed_structure =
true;
650 _has_range_limits =
false;
651 _has_default_value =
false;
659 DCSwitch::SwitchFields::
676 nassertr(n >= 0 && n < (
int)_fields.size(), NULL);
691 bool inserted = _fields_by_name.insert
692 (FieldsByName::value_type(field->
get_name(), field)).second;
699 _fields.push_back(field);
701 _num_nested_fields = (int)_fields.size();
704 if (_has_fixed_byte_size) {
708 if (_has_fixed_structure) {
711 if (!_has_range_limits) {
714 if (!_has_default_value) {
730 if (_fields.size() != other->_fields.size()) {
733 for (
size_t i = 0; i < _fields.size(); i++) {
734 if (!_fields[i]->check_match(other->_fields[i])) {
747 void DCSwitch::SwitchFields::
748 output(ostream &out,
bool brief)
const {
749 Fields::const_iterator fi;
750 if (!_fields.empty()) {
751 fi = _fields.begin();
753 while (fi != _fields.end()) {
754 (*fi)->output(out, brief);
767 void DCSwitch::SwitchFields::
768 write(ostream &out,
bool brief,
int indent_level)
const {
769 Fields::const_iterator fi;
770 if (!_fields.empty()) {
771 fi = _fields.begin();
773 while (fi != _fields.end()) {
774 (*fi)->write(out, brief, indent_level);
778 indent(out, indent_level)
790 bool DCSwitch::SwitchFields::
793 nassertr(
false,
false);
802 DCSwitch::SwitchCase::
814 DCSwitch::SwitchCase::
828 return _fields->do_check_match_switch_case(other->_fields);
void add_string(const string &str)
Adds a string to the hash, by breaking it down into a sequence of integers.
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const
Packs the switchParameter's specified default value (or a sensible default if no value is specified) ...
This is a block of data that receives the results of DCPacker.
string get_value(int case_index) const
Returns the packed value associated with the indicated case.
void append_data(const char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
string format_data(const string &packed_data, bool show_field_names=true)
Given a blob that represents the packed data for this field, returns a string formatting it for human...
DCField * get_key_parameter() const
Returns the key parameter on which the switch is based.
int add_case(const string &value)
Adds a new case to the switch with the indicated value, and returns the new case_index.
void write_instance(ostream &out, bool brief, int indent_level, const string &prename, const string &name, const string &postname) const
Generates a parseable description of the object to the indicated output stream.
bool has_fixed_structure() const
Returns true if this field type always has the same structure regardless of the data in the stream...
void add_int(int num)
Adds another integer to the hash so far.
int get_case_by_value(const string &case_value) const
Returns the index number of the case with the indicated packed value, or -1 if no case has this value...
void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const
Generates a parseable description of the object to the indicated output stream.
A single field of a Distributed Class, either atomic or molecular.
const string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
void add_invalid_case()
Adds a new case to the switch that will never be matched.
bool has_fixed_byte_size() const
Returns true if this field type always packs to the same number of bytes, false if it is variable...
This represents a switch statement, which can appear inside a class body and represents two or more a...
int get_num_cases() const
Returns the number of different cases within the switch.
virtual void output(ostream &out, bool brief) const
Write a string representation of this instance to <out>.
bool do_check_match_switch_case(const SwitchCase *other) const
Returns true if this case matches the indicated case, false otherwise.
bool do_check_match_switch_case(const SwitchFields *other) const
Returns true if this case matches the indicated case, false otherwise.
size_t get_length() const
Returns the current length of the buffer.
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this field into the hash.
void add_break()
Adds a break statement to the switch.
DCField * get_field(int case_index, int n) const
Returns the nth field in the indicated case.
size_t get_fixed_byte_size() const
If has_fixed_byte_size() returns true, this returns the number of bytes this field type will use...
bool has_range_limits() const
Returns true if this field, or any sub-field of this field, has a limit imposed in the DC file on its...
bool add_default()
Adds a default case to the switch.
void pack_default_value()
Adds the default value for the current element into the stream.
bool check_match(const DCPackerInterface *other) const
Returns true if the other interface is bitwise the same as this one–that is, a uint32 only matches a...
bool add_field(DCField *field)
Adds a field to this case.
const DCPackerInterface * apply_switch(const char *value_data, size_t length) const
Returns the DCPackerInterface that presents the alternative fields for the case indicated by the give...
const string & get_name() const
Returns the name of this switch.
void output(ostream &out) const
Write a string representation of this instance to <out>.
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this switch into the hash.
bool has_default_value() const
Returns true if a default value has been explicitly established for this field, false otherwise...
const char * get_data() const
Returns the beginning of the data buffer.
bool do_check_match_switch(const DCSwitch *other) const
Returns true if this switch matches the indicated other switch–that is, the two switches are bitwise...
This class generates an arbitrary hash number from a sequence of ints.
void pack_literal_value(const string &value)
Adds the indicated string value into the stream, representing a single pre-packed field element...
void begin_pack(const DCPackerInterface *root)
Begins a packing session.
bool is_field_valid() const
Returns true if it is valid to add a new field at this point (implying that a case or default has bee...
int get_num_fields(int case_index) const
Returns the number of fields in the indicated case.
DCSwitch(const string &name, DCField *key_parameter)
The key_parameter must be recently allocated via new; it will be deleted via delete when the switch d...
This class can be used for packing a series of numeric and string data into a binary stream...
virtual void write(ostream &out, bool brief, int indent_level) const
Generates a parseable description of the object to the indicated output stream.
bool add_field(DCField *field)
Adds a field to the currently active cases (those that have been added via add_case() or add_default(...
DCPackerInterface * get_default_case() const
Returns the DCPackerInterface that packs the default case, or NULL if there is no default case...
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
DCPackerInterface * get_case(int n) const
Returns the DCPackerInterface that packs the nth case.
bool end_pack()
Finishes a packing session.
This defines the internal interface for packing values into a DCField.
DCField * get_field_by_name(int case_index, const string &name) const
Returns the field with the given name from the indicated case, or NULL if no field has this name...