default values

This commit is contained in:
David Rose 2004-07-01 23:15:19 +00:00
parent 9082f017d4
commit 9222e02084
20 changed files with 422 additions and 125 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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 &copy) :
_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 &copy) {
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();
}

View File

@ -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 &copy);
void operator = (const ElementType &copy);
~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<ElementType> Elements;
void output_element(ostream &out, bool brief, DCParameter *element) const;
typedef pvector<DCParameter *> Elements;
Elements _elements;
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
////////////////////////////////////////////////////////////////////

View File

@ -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()) {

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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().

View File

@ -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);
}
;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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<DCField *> Fields;
typedef pmap<string, DCField *> 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<SwitchCase *> Cases;
Cases _cases;

View File

@ -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);
}

View File

@ -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;