various refinements

This commit is contained in:
David Rose 2004-07-02 16:47:55 +00:00
parent 842dd7bf26
commit 836cc8224d
7 changed files with 479 additions and 362 deletions

View File

@ -482,6 +482,14 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
string field_name = field->get_name();
if (!PyObject_HasAttrString(distobj, (char *)field_name.c_str())) {
// If the attribute is not defined, but the field has a default
// value specified, quietly pack the default value.
if (field->has_default_value()) {
packer.pack_default_value();
return true;
}
// If there is no default value specified, it's an error.
ostringstream strm;
strm << "Data element " << field_name
<< ", required by dc file for dclass " << get_name()
@ -503,7 +511,7 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
const DCAtomicField *atom = field->as_atomic_field();
if (atom == (DCAtomicField *)NULL) {
ostringstream strm;
strm << "Cannot pack non-atomic field " << field->get_name()
strm << "Cannot pack molecular field " << field->get_name()
<< " for generate";
nassert_raise(strm.str());
return false;
@ -547,6 +555,14 @@ pack_required_field(DCPacker &packer, PyObject *distobj,
// Now we have to look up the getter on the distributed object
// and call it.
if (!PyObject_HasAttrString(distobj, (char *)getter_name.c_str())) {
// As above, if there's no getter but the field has a default
// value specified, quietly pack the default value.
if (field->has_default_value()) {
packer.pack_default_value();
return true;
}
// Otherwise, with no default value it's an error.
ostringstream strm;
strm << "Distributed class " << get_name()
<< " doesn't have getter named " << getter_name
@ -671,10 +687,9 @@ ai_format_generate(PyObject *distobj, int do_id,
int num_fields = get_num_inherited_fields();
for (int i = 0; i < num_fields; i++) {
DCField *field = get_inherited_field(i);
DCAtomicField *atom = field->as_atomic_field();
if (atom != (DCAtomicField *)NULL && atom->is_required()) {
packer.begin_pack(atom);
if (!pack_required_field(packer, distobj, atom)) {
if (field->is_required() && field->as_molecular_field() == NULL) {
packer.begin_pack(field);
if (!pack_required_field(packer, distobj, field)) {
return Datagram();
}
packer.end_pack();

View File

@ -464,7 +464,6 @@ push() {
length = DCPackerInterface::do_unpack_uint32
(_unpack_data + _unpack_p);
_unpack_p += 4;
_pop_marker = _unpack_p + length;
} else {
length = DCPackerInterface::do_unpack_uint16
(_unpack_data + _unpack_p);
@ -1122,17 +1121,12 @@ clear() {
void DCPacker::
pack_class_object(const DCClass *dclass, PyObject *object) {
PyObject *str = PyObject_Str(object);
cerr << "pack_class_object(" << dclass->get_name() << ", "
<< PyString_AsString(str) << ")\n";
Py_DECREF(str);
push();
while (more_nested_fields()) {
while (more_nested_fields() && !_pack_error) {
const DCField *field = get_current_field()->as_field();
nassertv(field != (DCField *)NULL);
if (!dclass->pack_required_field(*this, object, field)) {
break;
}
get_class_element(dclass, object, field);
}
pop();
}
@ -1257,3 +1251,50 @@ set_class_element(PyObject *class_def, PyObject *&object,
}
}
#endif // HAVE_PYTHON
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: DCPacker::get_class_element
// Access: Private
// Description: Gets the current element from the Python object and
// packs it.
////////////////////////////////////////////////////////////////////
void DCPacker::
get_class_element(const DCClass *dclass, PyObject *object,
const DCField *field) {
string field_name = field->get_name();
DCPackType pack_type = get_pack_type();
if (field_name.empty()) {
switch (pack_type) {
case PT_class:
case PT_switch:
// If the field has no name, but it is one of these container
// objects, we want to get its nested objects directly from
// the class.
push();
while (more_nested_fields() && !_pack_error) {
const DCField *field = get_current_field()->as_field();
nassertv(field != (DCField *)NULL);
get_class_element(dclass, object, field);
}
pop();
break;
default:
// Otherwise, we just pack the default value.
pack_default_value();
}
} else {
// If the field does have a name, we will want to get it from the
// class and pack it. It just so happens that there's already a
// method that does this on DCClass.
if (!dclass->pack_required_field(*this, object, field)) {
_pack_error = true;
}
}
}
#endif // HAVE_PYTHON

View File

@ -183,6 +183,8 @@ private:
PyObject *unpack_class_object(const DCClass *dclass);
void set_class_element(PyObject *class_def, PyObject *&object,
const DCField *field);
void get_class_element(const DCClass *dclass, PyObject *object,
const DCField *field);
#endif
private:

View File

@ -328,7 +328,13 @@ update_switch_fields(const DCSwitchParameter *switch_parameter,
// because we must have come across the DCSwitch when building the
// catalog the first time.
SwitchPrefixes::const_iterator pi = _switch_prefixes.find(switch_parameter);
nassertr(pi != _switch_prefixes.end(), NULL);
if (pi == _switch_prefixes.end()) {
// If it's not stored in the record, the switch must be hidden
// within some non-seekable object, like an array; in this case,
// never mind.
return this;
}
string name_prefix = (*pi).second;
// Start by creating a new DCPackerCatalog object that contains all

View File

@ -350,12 +350,36 @@ bool DCPackerInterface::
unpack_skip(const char *data, size_t length, size_t &p,
bool &pack_error) const {
if (_has_fixed_byte_size) {
// If this field has a fixed byte size, it's easy to skip.
p += _fixed_byte_size;
if (p > length) {
pack_error = true;
}
return true;
}
if (_has_nested_fields && _num_length_bytes != 0) {
// If we have a length prefix, use that for skipping.
if (p + _num_length_bytes > length) {
pack_error = true;
} else {
if (_num_length_bytes == 4) {
size_t this_length = do_unpack_uint32(data + p);
p += this_length + 4;
} else {
size_t this_length = do_unpack_uint16(data + p);
p += this_length + 2;
}
if (p > length) {
pack_error = true;
}
}
return true;
}
// Otherwise, we don't know how to skip this field (presumably it
// can be skipped by skipping over its nested fields individually).
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -116,6 +116,7 @@ dc_cleanup_parser() {
%type <u.atomic> atomic_name
%type <u.s_int> server_flags
%type <u.s_int> no_server_flags
%type <u.dclass> dclass_or_struct
%type <u.dclass> dclass_name
%type <u.dclass> dclass
@ -303,6 +304,8 @@ dclass_fields:
{
if (!current_class->add_field($2)) {
yyerror("Duplicate field name: " + $2->get_name());
} else if ($2->get_number() < 0) {
yyerror("A non-network field cannot be stored on a dclass");
}
}
;
@ -313,9 +316,10 @@ dclass_field:
$$ = $1;
$$->set_flags($2);
}
| molecular_field
| molecular_field no_server_flags
| unnamed_parameter_with_default server_flags ';'
{
yyerror("Unnamed parameters are not allowed on a dclass");
$$ = $1;
$$->set_flags($2);
}
@ -388,13 +392,13 @@ struct_fields:
;
struct_field:
atomic_field
| molecular_field
| unnamed_parameter_with_default ';'
atomic_field no_server_flags
| molecular_field no_server_flags
| unnamed_parameter_with_default no_server_flags ';'
{
$$ = $1;
}
| named_parameter_with_default
| named_parameter_with_default no_server_flags
{
$$ = $1;
}
@ -987,6 +991,16 @@ server_flags:
}
;
no_server_flags:
server_flags
{
if ($1 != 0) {
yyerror("Server flags are not allowed here.");
}
$$ = $1;
}
;
molecular_field:
IDENTIFIER ':'
{