mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
various refinements
This commit is contained in:
parent
842dd7bf26
commit
836cc8224d
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
@ -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 ':'
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user