39 _field_update_pcollector(
"DCField")
43 _default_value_stale =
true;
44 _has_default_value =
false;
48 _has_nested_fields =
true;
49 _num_nested_fields = 0;
50 _pack_type = PT_field;
52 _has_fixed_byte_size =
true;
54 _has_fixed_structure =
true;
61 DCField(
const string &name,
DCClass *dclass) :
66 _field_update_pcollector(dclass->_class_update_pcollector, name)
70 _has_default_value =
false;
71 _default_value_stale =
true;
75 _has_nested_fields =
true;
76 _num_nested_fields = 0;
77 _pack_type = PT_field;
79 _has_fixed_byte_size =
true;
81 _has_fixed_structure =
true;
155 as_parameter()
const {
165 format_data(
const vector_uchar &packed_data,
bool show_field_names) {
187 return vector_uchar();
191 return vector_uchar();
223 pack_args(
DCPacker &packer, PyObject *sequence)
const {
227 packer.pack_object(sequence);
237 std::ostringstream strm;
238 PyObject *exc_type = PyExc_Exception;
240 if (as_parameter() !=
nullptr) {
244 strm <<
"Incorrect arguments to field: " <<
get_name()
245 <<
" = " << get_pystr(sequence);
246 exc_type = PyExc_TypeError;
248 strm <<
"Value out of range on field: " <<
get_name()
249 <<
" = " << get_pystr(sequence);
250 exc_type = PyExc_ValueError;
255 PyObject *tuple = PySequence_Tuple(sequence);
256 if (tuple ==
nullptr) {
257 strm <<
"Value for " <<
get_name() <<
" not a sequence: " \
258 << get_pystr(sequence);
259 exc_type = PyExc_TypeError;
263 strm <<
"Incorrect arguments to field: " <<
get_name()
264 << get_pystr(sequence);
265 exc_type = PyExc_TypeError;
267 strm <<
"Value out of range on field: " <<
get_name()
268 << get_pystr(sequence);
269 exc_type = PyExc_ValueError;
276 string message = strm.str();
277 PyErr_SetString(exc_type, message.c_str());
291 unpack_args(
DCPacker &packer)
const {
296 PyObject *
object = packer.unpack_object();
308 std::ostringstream strm;
309 PyObject *exc_type = PyExc_Exception;
312 strm <<
"Data error unpacking field ";
315 strm <<
"\nGot data (" << (int)length <<
" bytes):\n";
319 strm <<
"Error detected on byte " << error_byte
320 <<
" (" << std::hex << error_byte << std::dec <<
" hex)";
322 exc_type = PyExc_RuntimeError;
324 strm <<
"Value outside specified range when unpacking field "
325 <<
get_name() <<
": " << get_pystr(
object);
326 exc_type = PyExc_ValueError;
329 string message = strm.str();
330 PyErr_SetString(exc_type, message.c_str());
344 receive_update(
DCPacker &packer, PyObject *distobj)
const {
345 if (as_parameter() !=
nullptr) {
347 PyObject *value = unpack_args(packer);
348 if (value !=
nullptr) {
349 PyObject_SetAttrString(distobj, (
char *)_name.c_str(), value);
357 if (!PyObject_HasAttrString(distobj, (
char *)_name.c_str())) {
365 PyObject *args = unpack_args(packer);
367 if (args !=
nullptr) {
368 PyObject *func = PyObject_GetAttrString(distobj, (
char *)_name.c_str());
369 nassertv(func !=
nullptr);
376 result = PyObject_CallObject(func, args);
393 client_format_update(DOID_TYPE do_id, PyObject *args)
const {
401 pack_args(packer, args);
416 ai_format_update(DOID_TYPE do_id, CHANNEL_TYPE to_id, CHANNEL_TYPE from_id, PyObject *args)
const {
420 packer.RAW_PACK_CHANNEL(to_id);
421 packer.RAW_PACK_CHANNEL(from_id);
427 pack_args(packer, args);
442 ai_format_update_msg_type(DOID_TYPE do_id, CHANNEL_TYPE to_id, CHANNEL_TYPE from_id,
int msg_type, PyObject *args)
const {
446 packer.RAW_PACK_CHANNEL(to_id);
447 packer.RAW_PACK_CHANNEL(from_id);
453 pack_args(packer, args);
476 if (dc_multiple_inheritance) {
490 if (!_default_value_stale) {
491 pack_data.
append_data((
const char *)_default_value.data(), _default_value.size());
504 if (_dclass !=
nullptr) {
514 get_pystr(PyObject *value) {
515 if (value ==
nullptr) {
519 PyObject *str = PyObject_Str(value);
520 if (str !=
nullptr) {
521 #if PY_MAJOR_VERSION >= 3
522 string result = PyUnicode_AsUTF8(str);
524 string result = PyString_AsString(str);
530 PyObject *repr = PyObject_Repr(value);
531 if (repr !=
nullptr) {
532 #if PY_MAJOR_VERSION >= 3
533 string result = PyUnicode_AsUTF8(repr);
535 string result = PyString_AsString(repr);
541 if (value->ob_type !=
nullptr) {
542 PyObject *typestr = PyObject_Str((PyObject *)(value->ob_type));
543 if (typestr !=
nullptr) {
544 #if PY_MAJOR_VERSION >= 3
545 string result = PyUnicode_AsUTF8(typestr);
547 string result = PyString_AsString(typestr);
554 return "(invalid object)";
562 refresh_default_value() {
567 std::cerr <<
"Error while packing default value for " <<
get_name() <<
"\n";
569 const unsigned char *data = (
const unsigned char *)packer.
get_data();
570 _default_value = vector_uchar(data, data + packer.
get_length());
572 _default_value_stale =
false;
A single atomic field of a Distributed Class, as read from a .dc file.
Defines a particular DistributedClass as read from an input .dc file.
A single field of a Distributed Class, either atomic or molecular.
std::string format_data(const std::vector< unsigned char > &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...
virtual void set_name(const std::string &name)
Sets the name of this field.
std::vector< unsigned char > parse_string(const std::string &formatted_string)
Given a human-formatted string (for instance, as returned by format_data(), above) that represents th...
virtual void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this field into the hash.
virtual DCAtomicField * as_atomic_field()
Returns the same field pointer converted to an atomic field pointer, if this is in fact an atomic fie...
void output(std::ostream &out) const
Write a string representation of this instance to <out>.
virtual DCMolecularField * as_molecular_field()
Returns the same field pointer converted to a molecular field pointer, if this is in fact a molecular...
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const
Packs the field's specified default value (or a sensible default if no value is specified) into the s...
bool validate_ranges(const std::vector< unsigned char > &packed_data) const
Verifies that all of the packed values in the field data are within the specified ranges and that the...
void mark_inherited_fields_stale()
Indicates that something has changed in one or more of the inheritance chains or the set of fields; t...
A single molecular field of a Distributed Class, as read from a .dc file.
This is a block of data that receives the results of DCPacker.
void append_data(const char *buffer, size_t size)
Adds the indicated bytes to the end of the data.
This defines the internal interface for packing values into a DCField.
const std::string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
virtual void set_name(const std::string &name)
Sets the name of this field.
This class can be used for packing a series of numeric and string data into a binary stream,...
const DCPackerInterface * get_current_field() const
Returns the field that will be referenced by the next call to pack_*() or unpack_*().
std::vector< unsigned char > get_bytes() const
Returns the packed data buffer as a bytes object.
void unpack_validate()
Internally unpacks the current numeric or string value and validates it against the type range limits...
void begin_pack(const DCPackerInterface *root)
Begins a packing session.
void begin_unpack(const DCPackerInterface *root)
Begins an unpacking session.
bool end_unpack()
Finishes the unpacking session.
void raw_pack_uint32(unsigned int value)
Packs the data into the buffer between packing sessions.
bool had_error() const
Returns true if there has been any error (either a pack error or a range error) since the most recent...
void raw_pack_uint16(unsigned int value)
Packs the data into the buffer between packing sessions.
void raw_pack_uint8(unsigned int value)
Packs the data into the buffer between packing sessions.
size_t get_unpack_length() const
Returns the total number of bytes in the unpack data buffer.
bool had_pack_error() const
Returns true if there has been an packing error since the most recent call to begin(); in particular,...
bool end_pack()
Finishes a packing session.
const char * get_data() const
Returns the beginning of the data buffer.
void unpack_skip()
Skips the current field without unpacking it and advances to the next field.
void set_unpack_data(const std::vector< unsigned char > &data)
Sets up the unpack_data pointer.
bool parse_and_pack(const std::string &formatted_object)
Parses an object's value according to the DC file syntax (e.g.
void pack_default_value()
Adds the default value for the current element into the stream.
const char * get_unpack_data() const
Returns a read pointer to the unpack data buffer.
size_t get_num_unpacked_bytes() const
Returns the number of bytes that have been unpacked so far, or after unpack_end(),...
std::string unpack_and_format(bool show_field_names=true)
Unpacks an object and formats its value into a syntax suitable for parsing in the dc file (e....
size_t get_length() const
Returns the current length of the buffer.
Represents the type specification for a single parameter within a field specification.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
This class generates an arbitrary hash number from a sequence of ints.
void add_int(int num)
Adds another integer to the hash so far.
void add_string(const std::string &str)
Adds a string to the hash, by breaking it down into a sequence of integers.
static Notify * ptr()
Returns the pointer to the global Notify object.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.