diff --git a/direct/src/dcparser/dcArrayParameter.cxx b/direct/src/dcparser/dcArrayParameter.cxx index 7a26e6b0ed..7d81d6ca6f 100644 --- a/direct/src/dcparser/dcArrayParameter.cxx +++ b/direct/src/dcparser/dcArrayParameter.cxx @@ -54,6 +54,10 @@ DCArrayParameter(DCParameter *element_type, const DCUnsignedIntRange &size) : _has_range_limits = true; } + if (_element_type->has_default_value()) { + _has_default_value = true; + } + _has_nested_fields = true; _num_nested_fields = _array_size; _pack_type = PT_array; @@ -223,3 +227,42 @@ generate_hash(HashGenerator &hashgen) const { _element_type->generate_hash(hashgen); _array_size_range.generate_hash(hashgen); } + +//////////////////////////////////////////////////////////////////// +// Function: DCArrayParameter::pack_default_value +// Access: Public, Virtual +// Description: Packs the arrayParameter'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 arrayParameter doesn't know how to pack its +// default value. +//////////////////////////////////////////////////////////////////// +bool DCArrayParameter:: +pack_default_value(DCPackData &pack_data, bool &pack_error) const { + if (has_default_value()) { + return DCField::pack_default_value(pack_data, pack_error); + } + + // If a default value is not specified for a variable-length array, + // the default is the minimum array. + unsigned int minimum_length = 0; + if (!_array_size_range.is_empty()) { + minimum_length = _array_size_range.get_min(0); + } + + DCPacker packer; + packer.begin_pack(this); + packer.push(); + for (unsigned int i = 0; i < minimum_length; i++) { + packer.pack_default_value(); + } + packer.pop(); + if (!packer.end_pack()) { + pack_error = true; + + } else { + pack_data.append_data(packer.get_data(), packer.get_length()); + } + + return true; +} diff --git a/direct/src/dcparser/dcArrayParameter.h b/direct/src/dcparser/dcArrayParameter.h index b27455226a..ad176b8011 100644 --- a/direct/src/dcparser/dcArrayParameter.h +++ b/direct/src/dcparser/dcArrayParameter.h @@ -53,6 +53,7 @@ public: virtual void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; + virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; private: DCParameter *_element_type; diff --git a/direct/src/dcparser/dcAtomicField.cxx b/direct/src/dcparser/dcAtomicField.cxx index 81d9ee72eb..ff7acb902f 100644 --- a/direct/src/dcparser/dcAtomicField.cxx +++ b/direct/src/dcparser/dcAtomicField.cxx @@ -33,6 +33,20 @@ DCAtomicField:: DCAtomicField(const string &name) : DCField(name) { } +//////////////////////////////////////////////////////////////////// +// Function: DCAtomicField::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DCAtomicField:: +~DCAtomicField() { + Elements::iterator ei; + for (ei = _elements.begin(); ei != _elements.end(); ++ei) { + delete (*ei); + } + _elements.clear(); +} + //////////////////////////////////////////////////////////////////// // Function: DCAtomicField::as_atomic_field // Access: Published, Virtual @@ -65,7 +79,7 @@ get_num_elements() const { DCParameter *DCAtomicField:: get_element(int n) const { nassertr(n >= 0 && n < (int)_elements.size(), NULL); - return _elements[n]._param; + return _elements[n]; } //////////////////////////////////////////////////////////////////// @@ -80,13 +94,13 @@ get_element(int n) const { // If the element is an array-type element, the returned // value will include the two-byte length preceding the // array data. +// +// This is deprecated; use get_element() instead. //////////////////////////////////////////////////////////////////// string DCAtomicField:: get_element_default(int n) const { - nassertr(has_element_default(n), string()); nassertr(n >= 0 && n < (int)_elements.size(), string()); - - return _elements[n]._default_value; + return _elements[n]->get_default_value(); } //////////////////////////////////////////////////////////////////// @@ -94,11 +108,13 @@ get_element_default(int n) const { // Access: Published // Description: Returns true if the nth element of the field has a // default value specified, false otherwise. +// +// This is deprecated; use get_element() instead. //////////////////////////////////////////////////////////////////// bool DCAtomicField:: has_element_default(int n) const { nassertr(n >= 0 && n < (int)_elements.size(), false); - return _elements[n]._has_default_value; + return _elements[n]->has_default_value(); } //////////////////////////////////////////////////////////////////// @@ -115,7 +131,7 @@ has_element_default(int n) const { string DCAtomicField:: get_element_name(int n) const { nassertr(n >= 0 && n < (int)_elements.size(), string()); - return _elements[n]._param->get_name(); + return _elements[n]->get_name(); } //////////////////////////////////////////////////////////////////// @@ -128,7 +144,7 @@ get_element_name(int n) const { DCSubatomicType DCAtomicField:: get_element_type(int n) const { nassertr(n >= 0 && n < (int)_elements.size(), ST_invalid); - DCSimpleParameter *simple_parameter = _elements[n]._param->as_simple_parameter(); + DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter(); nassertr(simple_parameter != (DCSimpleParameter *)NULL, ST_invalid); return simple_parameter->get_type(); } @@ -148,7 +164,7 @@ get_element_type(int n) const { int DCAtomicField:: get_element_divisor(int n) const { nassertr(n >= 0 && n < (int)_elements.size(), 1); - DCSimpleParameter *simple_parameter = _elements[n]._param->as_simple_parameter(); + DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter(); nassertr(simple_parameter != (DCSimpleParameter *)NULL, 1); return simple_parameter->get_divisor(); } @@ -164,11 +180,11 @@ output(ostream &out, bool brief) const { if (!_elements.empty()) { Elements::const_iterator ei = _elements.begin(); - (*ei).output(out, brief); + output_element(out, brief, *ei); ++ei; while (ei != _elements.end()) { out << ", "; - (*ei).output(out, brief); + output_element(out, brief, *ei); ++ei; } } @@ -207,8 +223,7 @@ generate_hash(HashGenerator &hashgen) const { hashgen.add_int(_elements.size()); Elements::const_iterator ei; for (ei = _elements.begin(); ei != _elements.end(); ++ei) { - const ElementType &element = (*ei); - element._param->generate_hash(hashgen); + (*ei)->generate_hash(hashgen); } hashgen.add_int(get_flags()); } @@ -224,107 +239,53 @@ generate_hash(HashGenerator &hashgen) const { DCPackerInterface *DCAtomicField:: get_nested_field(int n) const { nassertr(n >= 0 && n < (int)_elements.size(), NULL); - return _elements[n]._param; + return _elements[n]; } //////////////////////////////////////////////////////////////////// // Function: DCAtomicField::add_element // Access: Public // Description: Adds a new element (parameter) to the field. -// Normally this is called only during parsing. +// Normally this is called only during parsing. The +// DCAtomicField object becomes the owner of the new +// pointer and will delete it upon destruction. //////////////////////////////////////////////////////////////////// void DCAtomicField:: -add_element(const DCAtomicField::ElementType &element) { +add_element(DCParameter *element) { _elements.push_back(element); _num_nested_fields = (int)_elements.size(); // See if we still have a fixed byte size. if (_has_fixed_byte_size) { - _has_fixed_byte_size = element._param->has_fixed_byte_size(); - _fixed_byte_size += element._param->get_fixed_byte_size(); + _has_fixed_byte_size = element->has_fixed_byte_size(); + _fixed_byte_size += element->get_fixed_byte_size(); } if (_has_fixed_structure) { - _has_fixed_structure = element._param->has_fixed_structure(); + _has_fixed_structure = element->has_fixed_structure(); } if (!_has_range_limits) { - _has_range_limits = element._param->has_range_limits(); + _has_range_limits = element->has_range_limits(); } + if (!_has_default_value) { + _has_default_value = element->has_default_value(); + } + _default_value_stale = true; } //////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::ElementType::Constructor -// Access: Public -// Description: The type parameter should be a newly-allocated DCParameter -// object; it will eventually be freed with delete when -// this object destructs. -//////////////////////////////////////////////////////////////////// -DCAtomicField::ElementType:: -ElementType(DCParameter *param) { - _param = param; - _has_default_value = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::ElementType::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -DCAtomicField::ElementType:: -ElementType(const DCAtomicField::ElementType ©) : - _param(copy._param->make_copy()), - _default_value(copy._default_value), - _has_default_value(copy._has_default_value) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::ElementType::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void DCAtomicField::ElementType:: -operator = (const DCAtomicField::ElementType ©) { - delete _param; - _param = copy._param->make_copy(); - _default_value = copy._default_value; - _has_default_value = copy._has_default_value; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::ElementType::Destructor -// Access: Public +// Function: DCAtomicField::output_element +// Access: Private // Description: //////////////////////////////////////////////////////////////////// -DCAtomicField::ElementType:: -~ElementType() { - delete _param; -} +void DCAtomicField:: +output_element(ostream &out, bool brief, DCParameter *element) const { + element->output(out, brief); -//////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::ElementType::set_default_value -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void DCAtomicField::ElementType:: -set_default_value(const string &default_value) { - _default_value = default_value; - _has_default_value = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: DCAtomicField::ElementType::output -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void DCAtomicField::ElementType:: -output(ostream &out, bool brief) const { - _param->output(out, brief); - - if (!brief && _has_default_value) { + if (!brief && element->has_default_value()) { out << " = "; DCPacker packer; - packer.set_unpack_data(_default_value); - packer.begin_unpack(_param); + packer.set_unpack_data(element->get_default_value()); + packer.begin_unpack(element); packer.unpack_and_format(out); packer.end_unpack(); } diff --git a/direct/src/dcparser/dcAtomicField.h b/direct/src/dcparser/dcAtomicField.h index 3bf2abf47f..83930ee341 100644 --- a/direct/src/dcparser/dcAtomicField.h +++ b/direct/src/dcparser/dcAtomicField.h @@ -38,48 +38,34 @@ class EXPCL_DIRECT DCAtomicField : public DCField { public: DCAtomicField(const string &name); + virtual ~DCAtomicField(); PUBLISHED: virtual DCAtomicField *as_atomic_field(); int get_num_elements() const; DCParameter *get_element(int n) const; + + // These five methods are deprecated and will be removed soon. string get_element_default(int n) const; bool has_element_default(int n) const; - - // These three methods are deprecated and will be removed soon. string get_element_name(int n) const; DCSubatomicType get_element_type(int n) const; int get_element_divisor(int n) const; public: + void add_element(DCParameter *element); + virtual void output(ostream &out, bool brief) const; virtual void write(ostream &out, bool brief, int indent_level) const; virtual void generate_hash(HashGenerator &hashgen) const; virtual DCPackerInterface *get_nested_field(int n) const; -public: - class ElementType { - public: - ElementType(DCParameter *param); - ElementType(const ElementType ©); - void operator = (const ElementType ©); - ~ElementType(); - - void set_default_value(const string &default_value); - - void output(ostream &out, bool brief) const; - - DCParameter *_param; - string _default_value; - bool _has_default_value; - }; - - void add_element(const ElementType &element); - private: - typedef pvector Elements; + void output_element(ostream &out, bool brief, DCParameter *element) const; + + typedef pvector Elements; Elements _elements; }; diff --git a/direct/src/dcparser/dcClassParameter.cxx b/direct/src/dcparser/dcClassParameter.cxx index e0cafb43cc..2e61db003b 100644 --- a/direct/src/dcparser/dcClassParameter.cxx +++ b/direct/src/dcparser/dcClassParameter.cxx @@ -42,11 +42,15 @@ DCClassParameter(const DCClass *dclass) : _nested_fields.reserve(_num_nested_fields); if (_dclass->has_constructor()) { - _nested_fields.push_back(_dclass->get_constructor()); + DCField *field = _dclass->get_constructor(); + _nested_fields.push_back(field); + _has_default_value = _has_default_value || field->has_default_value(); } int i; for (i = 0 ; i < num_fields; i++) { - _nested_fields.push_back(_dclass->get_inherited_field(i)); + DCField *field = _dclass->get_inherited_field(i); + _nested_fields.push_back(field); + _has_default_value = _has_default_value || field->has_default_value(); } // If all of the nested fields have a fixed byte size, then so does diff --git a/direct/src/dcparser/dcField.cxx b/direct/src/dcparser/dcField.cxx index 91260d5949..fedf0354c5 100644 --- a/direct/src/dcparser/dcField.cxx +++ b/direct/src/dcparser/dcField.cxx @@ -30,6 +30,8 @@ DCField:: DCField(const string &name) : DCPackerInterface(name) { _number = -1; _flags = 0; + _has_default_value = false; + _default_value_stale = true; _has_nested_fields = true; _num_nested_fields = 0; @@ -180,6 +182,34 @@ validate_ranges(const string &packed_data) const { return (packer.get_num_unpacked_bytes() == packed_data.length()); } +//////////////////////////////////////////////////////////////////// +// Function: DCField::has_default_value +// Access: Published +// Description: Returns true if a default value has been explicitly +// established for this field, false otherwise. +//////////////////////////////////////////////////////////////////// +bool DCField:: +has_default_value() const { + return _has_default_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: DCField::get_default_value +// Access: Published +// Description: Returns the default value for this field. If a +// default value has been explicitly set +// (e.g. has_default_value() returns true), returns that +// value; otherwise, returns an implicit default for the +// field. +//////////////////////////////////////////////////////////////////// +const string &DCField:: +get_default_value() const { + if (_default_value_stale) { + ((DCField *)this)->refresh_default_value(); + } + return _default_value; +} + //////////////////////////////////////////////////////////////////// // Function: DCField::is_required // Access: Published @@ -488,6 +518,28 @@ generate_hash(HashGenerator &hashgen) const { hashgen.add_string(_name); } +//////////////////////////////////////////////////////////////////// +// Function: DCField::pack_default_value +// Access: Public, Virtual +// Description: Packs the field'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 field doesn't know how to pack its +// default value. +//////////////////////////////////////////////////////////////////// +bool DCField:: +pack_default_value(DCPackData &pack_data, bool &) const { + // The default behavior is to pack the default value if we got it; + // otherwise, to return false and let the packer visit our nested + // elements. + if (!_default_value_stale) { + pack_data.append_data(_default_value.data(), _default_value.length()); + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: DCField::set_number // Access: Public @@ -500,6 +552,18 @@ set_number(int number) { _number = number; } +//////////////////////////////////////////////////////////////////// +// Function: DCField::set_default_value +// Access: Public +// Description: Establishes a default value for this field. +//////////////////////////////////////////////////////////////////// +void DCField:: +set_default_value(const string &default_value) { + _default_value = default_value; + _has_default_value = true; + _default_value_stale = false; +} + //////////////////////////////////////////////////////////////////// // Function: DCField::add_flag // Access: Public @@ -530,6 +594,25 @@ get_flags() const { return _flags; } +//////////////////////////////////////////////////////////////////// +// Function: DCField::refresh_default_value +// Access: Protected +// Description: Recomputes the default value of the field by +// repacking it. +//////////////////////////////////////////////////////////////////// +void DCField:: +refresh_default_value() { + DCPacker packer; + packer.begin_pack(this); + packer.pack_default_value(); + if (!packer.end_pack()) { + cerr << "Error while packing default value for " << get_name() << "\n"; + } else { + _default_value.assign(packer.get_data(), packer.get_length()); + } + _default_value_stale = false; +} + //////////////////////////////////////////////////////////////////// // Function: DCField::output_flags // Access: Protected diff --git a/direct/src/dcparser/dcField.h b/direct/src/dcparser/dcField.h index eaa0f87a87..e0b3988eb4 100644 --- a/direct/src/dcparser/dcField.h +++ b/direct/src/dcparser/dcField.h @@ -54,6 +54,9 @@ PUBLISHED: bool validate_ranges(const string &packed_data) const; + bool has_default_value() const; + const string &get_default_value() const; + bool is_required() const; bool is_broadcast() const; bool is_p2p() const; @@ -81,8 +84,10 @@ public: virtual void output(ostream &out, bool brief) const=0; virtual void write(ostream &out, bool brief, int indent_level) const=0; virtual void generate_hash(HashGenerator &hashgen) const; + virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; void set_number(int number); + void set_default_value(const string &default_value); enum Flags { F_required = 0x0001, @@ -100,13 +105,18 @@ public: int get_flags() const; protected: + void refresh_default_value(); void output_flags(ostream &out) const; protected: int _number; + bool _default_value_stale; + bool _has_default_value; private: int _flags; // A bitmask union of any of the above values. + + string _default_value; }; #endif diff --git a/direct/src/dcparser/dcMolecularField.cxx b/direct/src/dcparser/dcMolecularField.cxx index ffc0e1b64e..c655454c4d 100644 --- a/direct/src/dcparser/dcMolecularField.cxx +++ b/direct/src/dcparser/dcMolecularField.cxx @@ -105,6 +105,10 @@ add_atomic(DCAtomicField *atomic) { if (!_has_range_limits) { _has_range_limits = atomic->has_range_limits(); } + if (!_has_default_value) { + _has_default_value = atomic->has_default_value(); + } + _default_value_stale = true; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/dcparser/dcPacker.cxx b/direct/src/dcparser/dcPacker.cxx index b516ec7150..a85ef7515a 100755 --- a/direct/src/dcparser/dcPacker.cxx +++ b/direct/src/dcparser/dcPacker.cxx @@ -560,6 +560,34 @@ pop() { advance(); } +//////////////////////////////////////////////////////////////////// +// Function: DCPacker::pack_default_value +// Access: Published +// Description: Adds the default value for the current element into +// the stream. If no default has been set for the +// current element, creates a sensible default. +//////////////////////////////////////////////////////////////////// +void DCPacker:: +pack_default_value() { + nassertv(_mode == M_pack || _mode == M_repack); + if (_current_field == NULL) { + _pack_error = true; + } else { + if (_current_field->pack_default_value(_pack_data, _pack_error)) { + advance(); + + } else { + // If the single field didn't know how to pack a default value, + // try packing nested fields. + push(); + while (more_nested_fields()) { + pack_default_value(); + } + pop(); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: DCPacker::unpack_validate // Access: Published @@ -938,7 +966,7 @@ unpack_and_format(ostream &out) { } push(); - while (more_nested_fields()) { + while (more_nested_fields() && !had_pack_error()) { unpack_and_format(out); if (more_nested_fields()) { diff --git a/direct/src/dcparser/dcPacker.h b/direct/src/dcparser/dcPacker.h index ccffcb3431..ae43f82e5f 100755 --- a/direct/src/dcparser/dcPacker.h +++ b/direct/src/dcparser/dcPacker.h @@ -82,6 +82,7 @@ PUBLISHED: INLINE void pack_uint64(PN_uint64 value); INLINE void pack_string(const string &value); INLINE void pack_literal_value(const string &value); + void pack_default_value(); INLINE double unpack_double(); INLINE int unpack_int(); diff --git a/direct/src/dcparser/dcPackerInterface.cxx b/direct/src/dcparser/dcPackerInterface.cxx index f9b1c3fa9e..9df651d86a 100755 --- a/direct/src/dcparser/dcPackerInterface.cxx +++ b/direct/src/dcparser/dcPackerInterface.cxx @@ -210,6 +210,20 @@ pack_string(DCPackData &, const string &, bool &pack_error, bool &) const { pack_error = true; } +//////////////////////////////////////////////////////////////////// +// Function: DCPackerInterface::pack_default_value +// Access: Public, Virtual +// Description: Packs the field'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 field doesn't know how to pack its +// default value. +//////////////////////////////////////////////////////////////////// +bool DCPackerInterface:: +pack_default_value(DCPackData &, bool &) const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: DCPackerInterface::unpack_double // Access: Public, Virtual diff --git a/direct/src/dcparser/dcPackerInterface.h b/direct/src/dcparser/dcPackerInterface.h index 1c3ac9c549..4da81364b5 100755 --- a/direct/src/dcparser/dcPackerInterface.h +++ b/direct/src/dcparser/dcPackerInterface.h @@ -109,6 +109,7 @@ public: bool &pack_error, bool &range_error) const; virtual void pack_string(DCPackData &pack_data, const string &value, bool &pack_error, bool &range_error) const; + virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; virtual void unpack_double(const char *data, size_t length, size_t &p, double &value, bool &pack_error, bool &range_error) const; diff --git a/direct/src/dcparser/dcParameter.cxx b/direct/src/dcparser/dcParameter.cxx index 827d73d715..edfe9705cd 100644 --- a/direct/src/dcparser/dcParameter.cxx +++ b/direct/src/dcparser/dcParameter.cxx @@ -120,7 +120,7 @@ get_typedef() const { //////////////////////////////////////////////////////////////////// // Function: DCParameter::set_typedef -// Access: Published +// Access: Public // Description: Records the DCTypedef object that generated this // parameter. This is normally called only from // DCTypedef::make_new_parameter(). diff --git a/direct/src/dcparser/dcParser.yxx b/direct/src/dcparser/dcParser.yxx index 84dae1fc20..67d8ef516f 100644 --- a/direct/src/dcparser/dcParser.yxx +++ b/direct/src/dcparser/dcParser.yxx @@ -32,7 +32,6 @@ static DCClass *current_class = (DCClass *)NULL; static DCSwitch *current_switch = (DCSwitch *)NULL; static DCAtomicField *current_atomic = (DCAtomicField *)NULL; static DCMolecularField *current_molecular = (DCMolecularField *)NULL; -static DCAtomicField::ElementType atomic_element(new DCSimpleParameter(ST_invalid)); static DCParameter *current_parameter = (DCParameter *)NULL; static DCPacker default_packer; static DCPacker *current_packer; @@ -424,8 +423,7 @@ nonempty_parameter_list: atomic_element: parameter { - atomic_element = DCAtomicField::ElementType($1); - current_atomic->add_element(atomic_element); + current_atomic->add_element($1); } | parameter '=' { @@ -436,9 +434,8 @@ atomic_element: parameter_value { bool is_valid = $1->is_valid(); - atomic_element = DCAtomicField::ElementType($1); if (current_packer->end_pack()) { - atomic_element.set_default_value(current_packer->get_string()); + $1->set_default_value(current_packer->get_string()); } else { if (is_valid) { @@ -448,7 +445,7 @@ atomic_element: // error (there's no way for us to validate the syntax). So we'll // just ignore the default value in this case. } - current_atomic->add_element(atomic_element); + current_atomic->add_element($1); } ; diff --git a/direct/src/dcparser/dcSimpleParameter.cxx b/direct/src/dcparser/dcSimpleParameter.cxx index 0eaa464393..063519bb22 100644 --- a/direct/src/dcparser/dcSimpleParameter.cxx +++ b/direct/src/dcparser/dcSimpleParameter.cxx @@ -666,7 +666,7 @@ pack_int(DCPackData &pack_data, int value, //////////////////////////////////////////////////////////////////// void DCSimpleParameter:: pack_uint(DCPackData &pack_data, unsigned int value, - bool &pack_error, bool &range_error) const { + bool &pack_error, bool &range_error) const { unsigned int int_value = value * _divisor; switch (_type) { @@ -912,6 +912,103 @@ pack_string(DCPackData &pack_data, const string &value, } } +//////////////////////////////////////////////////////////////////// +// Function: DCSimpleParameter::pack_default_value +// Access: Public, Virtual +// Description: Packs the simpleParameter'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 simpleParameter doesn't know how to pack its +// default value. +//////////////////////////////////////////////////////////////////// +bool DCSimpleParameter:: +pack_default_value(DCPackData &pack_data, bool &pack_error) const { + if (has_default_value()) { + return DCField::pack_default_value(pack_data, pack_error); + } + + if (_has_nested_fields) { + // If the simple type is an array (or string) type, pack the + // appropriate length array, with code similar to + // DCArrayParameter::pack_default_value(). + + unsigned int minimum_length = 0; + if (!_uint_range.is_empty()) { + minimum_length = _uint_range.get_min(0); + } + + DCPacker packer; + packer.begin_pack(this); + packer.push(); + for (unsigned int i = 0; i < minimum_length; i++) { + packer.pack_default_value(); + } + packer.pop(); + if (!packer.end_pack()) { + pack_error = true; + + } else { + pack_data.append_data(packer.get_data(), packer.get_length()); + } + + } else { + // Otherwise, if it's just a simple numeric type, pack a zero or + // the minimum value. + switch (_type) { + case ST_int8: + case ST_int16: + case ST_int32: + if (_int_range.is_in_range(0)) { + pack_int(pack_data, 0, pack_error, pack_error); + } else { + pack_int(pack_data, _int_range.get_min(0), pack_error, pack_error); + } + break; + + case ST_int64: + if (_int64_range.is_in_range(0)) { + pack_int64(pack_data, 0, pack_error, pack_error); + } else { + pack_int64(pack_data, _int64_range.get_min(0), pack_error, pack_error); + } + break; + + case ST_char: + case ST_uint8: + case ST_uint16: + case ST_uint32: + if (_uint_range.is_in_range(0)) { + pack_uint(pack_data, 0, pack_error, pack_error); + } else { + pack_uint(pack_data, _uint_range.get_min(0), pack_error, pack_error); + } + break; + + case ST_uint64: + if (_uint64_range.is_in_range(0)) { + pack_uint64(pack_data, 0, pack_error, pack_error); + } else { + pack_uint64(pack_data, _uint64_range.get_min(0), pack_error, pack_error); + } + break; + + case ST_float64: + if (_double_range.is_in_range(0.0)) { + pack_double(pack_data, 0.0, pack_error, pack_error); + } else { + pack_double(pack_data, _double_range.get_min(0), pack_error, pack_error); + } + break; + + default: + pack_error = true; + } + } + return true; +} + + + //////////////////////////////////////////////////////////////////// // Function: DCSimpleParameter::unpack_double // Access: Public, Virtual diff --git a/direct/src/dcparser/dcSimpleParameter.h b/direct/src/dcparser/dcSimpleParameter.h index bcef313aae..8fe3c78150 100644 --- a/direct/src/dcparser/dcSimpleParameter.h +++ b/direct/src/dcparser/dcSimpleParameter.h @@ -65,6 +65,7 @@ public: bool &pack_error, bool &range_error) const; virtual void pack_string(DCPackData &pack_data, const string &value, bool &pack_error, bool &range_error) const; + virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; virtual void unpack_double(const char *data, size_t length, size_t &p, double &value, bool &pack_error, bool &range_error) const; diff --git a/direct/src/dcparser/dcSwitch.cxx b/direct/src/dcparser/dcSwitch.cxx index c970aeb987..4282586f51 100644 --- a/direct/src/dcparser/dcSwitch.cxx +++ b/direct/src/dcparser/dcSwitch.cxx @@ -361,6 +361,44 @@ 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. +//////////////////////////////////////////////////////////////////// +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. + + DCPacker packer; + packer.begin_pack(_cases[0]); + packer.pack_literal_value(_cases[0]->_value); + 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; + } + } + pack_data.append_data(packer.get_data(), packer.get_length()); + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: DCSwitch::SwitchCase::Constructor // Access: Public @@ -379,6 +417,7 @@ SwitchCase(const string &name, const string &value) : _fixed_byte_size = 0; _has_fixed_structure = true; _has_range_limits = false; + _has_default_value = false; } //////////////////////////////////////////////////////////////////// @@ -449,5 +488,8 @@ add_field(DCField *field) { if (!_has_range_limits) { _has_range_limits = field->has_range_limits(); } + if (!_has_default_value) { + _has_default_value = field->has_default_value(); + } return true; } diff --git a/direct/src/dcparser/dcSwitch.h b/direct/src/dcparser/dcSwitch.h index 192f1f3697..c80083079b 100644 --- a/direct/src/dcparser/dcSwitch.h +++ b/direct/src/dcparser/dcSwitch.h @@ -67,11 +67,9 @@ public: const string &prename, const string &name, const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; + virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; -private: - string _name; - DCParameter *_key_parameter; - +public: typedef pvector Fields; typedef pmap FieldsByName; @@ -86,8 +84,13 @@ private: string _value; Fields _fields; FieldsByName _fields_by_name; + bool _has_default_value; }; +private: + string _name; + DCParameter *_key_parameter; + typedef pvector Cases; Cases _cases; diff --git a/direct/src/dcparser/dcSwitchParameter.cxx b/direct/src/dcparser/dcSwitchParameter.cxx index 7054819b6b..723a89bd0c 100755 --- a/direct/src/dcparser/dcSwitchParameter.cxx +++ b/direct/src/dcparser/dcSwitchParameter.cxx @@ -47,13 +47,14 @@ DCSwitchParameter(const DCSwitch *dswitch) : DCParameter *key_parameter = dswitch->get_key_parameter(); _has_fixed_byte_size = _has_fixed_byte_size && key_parameter->has_fixed_byte_size(); _has_range_limits = _has_range_limits || key_parameter->has_range_limits(); + _has_default_value = _has_default_value || key_parameter->has_default_value(); int num_cases = _dswitch->get_num_cases(); if (num_cases > 0) { _fixed_byte_size = _dswitch->get_case(0)->get_fixed_byte_size(); for (int i = 0; i < num_cases; i++) { - const DCPackerInterface *dcase = _dswitch->get_case(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) { @@ -62,6 +63,7 @@ DCSwitchParameter(const DCSwitch *dswitch) : } _has_range_limits = _has_range_limits || dcase->has_range_limits(); + _has_default_value = _has_default_value || dcase->_has_default_value; } } @@ -194,3 +196,21 @@ generate_hash(HashGenerator &hashgen) const { DCParameter::generate_hash(hashgen); _dswitch->generate_hash(hashgen); } + +//////////////////////////////////////////////////////////////////// +// Function: DCSwitchParameter::pack_default_value +// Access: Public, Virtual +// 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 DCSwitchParameter:: +pack_default_value(DCPackData &pack_data, bool &pack_error) const { + if (has_default_value()) { + return DCField::pack_default_value(pack_data, pack_error); + } + + return _dswitch->pack_default_value(pack_data, pack_error); +} diff --git a/direct/src/dcparser/dcSwitchParameter.h b/direct/src/dcparser/dcSwitchParameter.h index 190c4d885c..4bb835b36f 100755 --- a/direct/src/dcparser/dcSwitchParameter.h +++ b/direct/src/dcparser/dcSwitchParameter.h @@ -53,6 +53,7 @@ public: const string &prename, const string &name, const string &postname) const; virtual void generate_hash(HashGenerator &hashgen) const; + virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const; private: const DCSwitch *_dswitch;