17 #include "dcAtomicField.h" 18 #include "hashGenerator.h" 20 #include "dcmsgtypes.h" 22 #include "dcClassParameter.h" 30 #include "pStatTimer.h" 33 PStatCollector DCClass::_update_pcollector(
"App:Show code:readerPollTask:Update");
34 PStatCollector DCClass::_generate_pcollector(
"App:Show code:readerPollTask:Generate");
38 (
"dc-multiple-inheritance",
true,
39 PRC_DESC(
"Set this true to support multiple inheritance in the dc file. " 40 "If this is false, the old way, multiple inheritance is not " 41 "supported, but field numbers will be numbered sequentially, " 42 "which may be required to support old code that assumed this."));
45 (
"dc-virtual-inheritance",
true,
46 PRC_DESC(
"Set this true to support proper virtual inheritance in the " 47 "dc file, so that diamond-of-death type constructs can be used. " 48 "This also enables shadowing (overloading) of inherited method " 49 "names from a base class."));
52 (
"dc-sort-inheritance-by-file",
true,
53 PRC_DESC(
"This is a temporary hack. This should be true if you are using " 54 "version 1.42 of the otp_server.exe binary, which sorted inherited " 55 "fields based on the order of the classes within the DC file, " 56 "rather than based on the order in which the references are made " 57 "within the class."));
60 #endif // WITHIN_PANDA 64 inline bool operator ()(
const DCField *a,
const DCField *b)
const {
75 DCClass(
DCFile *dc_file,
const string &name,
bool is_struct,
bool bogus_class) :
77 _class_update_pcollector(_update_pcollector, name),
78 _class_generate_pcollector(_generate_pcollector, name),
82 _is_struct(is_struct),
83 _bogus_class(bogus_class)
90 _owner_class_def = NULL;
101 if (_constructor != (
DCField *)NULL) {
106 for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
111 Py_XDECREF(_class_def);
112 Py_XDECREF(_owner_class_def);
144 return _parents.size();
155 nassertr(n >= 0 && n < (
int)_parents.size(), NULL);
167 return (_constructor != (
DCField *)NULL);
190 return _fields.size();
204 if (n < 0 || n >= (
int)_fields.size()) {
206 <<
"n:" << n <<
" _fields.size():" 207 << (int)_fields.size() << endl;
211 nassertr_always(n >= 0 && n < (
int)_fields.size(), NULL);
227 FieldsByName::const_iterator ni;
228 ni = _fields_by_name.find(name);
229 if (ni != _fields_by_name.end()) {
234 Parents::const_iterator pi;
235 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
236 DCField *result = (*pi)->get_field_by_name(name);
237 if (result != (
DCField *)NULL) {
258 FieldsByIndex::const_iterator ni;
259 ni = _fields_by_index.find(index_number);
260 if (ni != _fields_by_index.end()) {
265 Parents::const_iterator pi;
266 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
267 DCField *result = (*pi)->get_field_by_index(index_number);
268 if (result != (
DCField *)NULL) {
270 ((
DCClass *)
this)->_fields_by_index[index_number] = result;
287 if (dc_multiple_inheritance && dc_virtual_inheritance &&
288 _dc_file != (
DCFile *)NULL) {
289 _dc_file->check_inherited_fields();
290 if (_inherited_fields.empty()) {
291 ((
DCClass *)
this)->rebuild_inherited_fields();
297 return (
int)_inherited_fields.size();
300 int num_fields = get_num_fields();
302 Parents::const_iterator pi;
303 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
304 num_fields += (*pi)->get_num_inherited_fields();
325 if (dc_multiple_inheritance && dc_virtual_inheritance &&
326 _dc_file != (
DCFile *)NULL) {
327 _dc_file->check_inherited_fields();
328 if (_inherited_fields.empty()) {
329 ((
DCClass *)
this)->rebuild_inherited_fields();
331 nassertr(n >= 0 && n < (
int)_inherited_fields.size(), NULL);
332 return _inherited_fields[n];
335 Parents::const_iterator pi;
336 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
337 int psize = (*pi)->get_num_inherited_fields();
339 return (*pi)->get_inherited_field(n);
359 if (is_bogus_class()) {
363 Parents::const_iterator pi;
364 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
365 if ((*pi)->inherits_from_bogus_class()) {
386 if (!_name.empty()) {
399 has_class_def()
const {
400 return (_class_def != NULL);
402 #endif // HAVE_PYTHON 413 set_class_def(PyObject *class_def) {
414 Py_XINCREF(class_def);
415 Py_XDECREF(_class_def);
416 _class_def = class_def;
418 #endif // HAVE_PYTHON 429 get_class_def()
const {
430 if (_class_def == NULL) {
435 Py_INCREF(_class_def);
438 #endif // HAVE_PYTHON 448 has_owner_class_def()
const {
449 return (_owner_class_def != NULL);
451 #endif // HAVE_PYTHON 462 set_owner_class_def(PyObject *owner_class_def) {
463 Py_XINCREF(owner_class_def);
464 Py_XDECREF(_owner_class_def);
465 _owner_class_def = owner_class_def;
467 #endif // HAVE_PYTHON 478 get_owner_class_def()
const {
479 if (_owner_class_def == NULL) {
484 Py_INCREF(_owner_class_def);
485 return _owner_class_def;
487 #endif // HAVE_PYTHON 508 DCField *field = get_field_by_index(field_id);
509 if (field == (
DCField *)NULL) {
512 <<
"Received update for field " << field_id <<
", not in class " 514 nassert_raise(strm.str());
519 field->receive_update(packer, distobj);
525 #endif // HAVE_PYTHON 537 receive_update_broadcast_required(PyObject *distobj,
DatagramIterator &di)
const {
546 int num_fields = get_num_inherited_fields();
547 for (
int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {
548 DCField *field = get_inherited_field(i);
552 field->receive_update(packer, distobj);
561 #endif // HAVE_PYTHON 574 receive_update_broadcast_required_owner(PyObject *distobj,
584 int num_fields = get_num_inherited_fields();
585 for (
int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {
586 DCField *field = get_inherited_field(i);
591 field->receive_update(packer, distobj);
605 #endif // HAVE_PYTHON 617 receive_update_all_required(PyObject *distobj,
DatagramIterator &di)
const {
626 int num_fields = get_num_inherited_fields();
627 for (
int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {
628 DCField *field = get_inherited_field(i);
632 field->receive_update(packer, distobj);
641 #endif // HAVE_PYTHON 656 for (
int i = 0; i < num_fields && !PyErr_Occurred(); ++i) {
657 receive_update(distobj, di);
660 #endif // HAVE_PYTHON 670 direct_update(PyObject *distobj,
const string &field_name,
671 const string &value_blob) {
672 DCField *field = get_field_by_name(field_name);
673 nassertv_always(field != NULL);
678 field->receive_update(packer, distobj);
681 #endif // HAVE_PYTHON 691 direct_update(PyObject *distobj,
const string &field_name,
693 direct_update(distobj, field_name, datagram.
get_message());
695 #endif // HAVE_PYTHON 711 pack_required_field(
Datagram &datagram, PyObject *distobj,
715 if (!pack_required_field(packer, distobj, field)) {
725 #endif // HAVE_PYTHON 741 pack_required_field(
DCPacker &packer, PyObject *distobj,
743 const DCParameter *parameter = field->as_parameter();
747 string field_name = field->
get_name();
749 if (!PyObject_HasAttrString(distobj, (
char *)field_name.c_str())) {
759 strm <<
"Data element " << field_name
760 <<
", required by dc file for dclass " << get_name()
761 <<
", not defined on object";
762 nassert_raise(strm.str());
766 PyObject_GetAttrString(distobj, (
char *)field_name.c_str());
767 nassertr(result != (PyObject *)NULL,
false);
770 bool pack_ok = parameter->pack_args(packer, result);
778 strm <<
"Cannot pack molecular field " << field->
get_name()
780 nassert_raise(strm.str());
791 string setter_name = atom->
get_name();
793 if (setter_name.empty()) {
795 strm <<
"Required field is unnamed!";
796 nassert_raise(strm.str());
804 strm <<
"Required field " << setter_name <<
" has no parameters!";
805 nassert_raise(strm.str());
809 string getter_name = setter_name;
810 if (setter_name.substr(0, 3) ==
"set") {
813 getter_name[0] =
'g';
818 getter_name =
"get" + setter_name;
819 getter_name[3] = toupper(getter_name[3]);
824 if (!PyObject_HasAttrString(distobj, (
char *)getter_name.c_str())) {
834 strm <<
"Distributed class " << get_name()
835 <<
" doesn't have getter named " << getter_name
836 <<
" to match required field " << setter_name;
837 nassert_raise(strm.str());
841 PyObject_GetAttrString(distobj, (
char *)getter_name.c_str());
842 nassertr(func != (PyObject *)NULL,
false);
844 PyObject *empty_args = PyTuple_New(0);
845 PyObject *result = PyObject_CallObject(func, empty_args);
846 Py_DECREF(empty_args);
848 if (result == (PyObject *)NULL) {
851 cerr <<
"Error when calling " << getter_name <<
"\n";
858 PyObject *tuple = PyTuple_New(1);
859 PyTuple_SET_ITEM(tuple, 0, result);
865 if (!PySequence_Check(result)) {
867 strm <<
"Since dclass " << get_name() <<
" method " << setter_name
868 <<
" is declared to have multiple parameters, Python function " 869 << getter_name <<
" must return a list or tuple.\n";
870 nassert_raise(strm.str());
876 bool pack_ok = atom->pack_args(packer, result);
881 #endif // HAVE_PYTHON 892 client_format_update(
const string &field_name, DOID_TYPE do_id,
893 PyObject *args)
const {
894 DCField *field = get_field_by_name(field_name);
895 if (field == (
DCField *)NULL) {
897 strm <<
"No field named " << field_name <<
" in class " << get_name()
899 nassert_raise(strm.str());
903 return field->client_format_update(do_id, args);
905 #endif // HAVE_PYTHON 916 ai_format_update(
const string &field_name, DOID_TYPE do_id,
917 CHANNEL_TYPE to_id, CHANNEL_TYPE from_id, PyObject *args)
const {
918 DCField *field = get_field_by_name(field_name);
919 if (field == (
DCField *)NULL) {
921 strm <<
"No field named " << field_name <<
" in class " << get_name()
923 nassert_raise(strm.str());
927 return field->ai_format_update(do_id, to_id, from_id, args);
929 #endif // HAVE_PYTHON 941 ai_format_update_msg_type(
const string &field_name, DOID_TYPE do_id,
942 CHANNEL_TYPE to_id, CHANNEL_TYPE from_id,
int msg_type, PyObject *args)
const {
943 DCField *field = get_field_by_name(field_name);
944 if (field == (
DCField *)NULL) {
946 strm <<
"No field named " << field_name <<
" in class " << get_name()
948 nassert_raise(strm.str());
952 return field->ai_format_update_msg_type(do_id, to_id, from_id, msg_type, args);
954 #endif // HAVE_PYTHON 971 client_format_generate_CMU(PyObject *distobj, DOID_TYPE do_id,
973 PyObject *optional_fields)
const {
983 int num_fields = get_num_inherited_fields();
984 for (
int i = 0; i < num_fields; ++i) {
985 DCField *field = get_inherited_field(i);
988 if (!pack_required_field(packer, distobj, field)) {
996 int num_optional_fields = 0;
997 if (PyObject_IsTrue(optional_fields)) {
998 num_optional_fields = PySequence_Size(optional_fields);
1002 for (
int i = 0; i < num_optional_fields; i++) {
1003 PyObject *py_field_name = PySequence_GetItem(optional_fields, i);
1004 #if PY_MAJOR_VERSION >= 3 1005 string field_name = PyUnicode_AsUTF8(py_field_name);
1007 string field_name = PyString_AsString(py_field_name);
1009 Py_XDECREF(py_field_name);
1011 DCField *field = get_field_by_name(field_name);
1012 if (field == (
DCField *)NULL) {
1014 strm <<
"No field named " << field_name <<
" in class " << get_name()
1016 nassert_raise(strm.str());
1021 if (!pack_required_field(packer, distobj, field)) {
1029 #endif // HAVE_PYTHON 1044 ai_format_generate(PyObject *distobj, DOID_TYPE do_id,
1045 DOID_TYPE parent_id, ZONEID_TYPE zone_id,
1046 CHANNEL_TYPE district_channel_id, CHANNEL_TYPE from_channel_id,
1047 PyObject *optional_fields)
const {
1051 packer.RAW_PACK_CHANNEL(district_channel_id);
1052 packer.RAW_PACK_CHANNEL(from_channel_id);
1055 bool has_optional_fields = (PyObject_IsTrue(optional_fields) != 0);
1057 if (has_optional_fields) {
1058 packer.
raw_pack_uint16(STATESERVER_OBJECT_GENERATE_WITH_REQUIRED_OTHER);
1074 int num_fields = get_num_inherited_fields();
1075 for (
int i = 0; i < num_fields; ++i) {
1076 DCField *field = get_inherited_field(i);
1079 if (!pack_required_field(packer, distobj, field)) {
1087 if (has_optional_fields) {
1088 int num_optional_fields = PySequence_Size(optional_fields);
1091 for (
int i = 0; i < num_optional_fields; ++i) {
1092 PyObject *py_field_name = PySequence_GetItem(optional_fields, i);
1093 #if PY_MAJOR_VERSION >= 3 1094 string field_name = PyUnicode_AsUTF8(py_field_name);
1096 string field_name = PyString_AsString(py_field_name);
1098 Py_XDECREF(py_field_name);
1100 DCField *field = get_field_by_name(field_name);
1101 if (field == (
DCField *)NULL) {
1103 strm <<
"No field named " << field_name <<
" in class " << get_name()
1105 nassert_raise(strm.str());
1112 if (!pack_required_field(packer, distobj, field)) {
1121 #endif // HAVE_PYTHON 1133 ai_database_generate_context(
1134 unsigned int context_id, DOID_TYPE parent_id, ZONEID_TYPE zone_id,
1135 CHANNEL_TYPE owner_channel,
1136 CHANNEL_TYPE database_server_id, CHANNEL_TYPE from_channel_id)
const 1140 packer.RAW_PACK_CHANNEL(database_server_id);
1141 packer.RAW_PACK_CHANNEL(from_channel_id);
1143 packer.
raw_pack_uint16(STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT);
1146 packer.RAW_PACK_CHANNEL(owner_channel);
1151 int num_fields = get_num_inherited_fields();
1152 for (
int i = 0; i < num_fields; ++i) {
1153 DCField *field = get_inherited_field(i);
1163 #endif // HAVE_PYTHON 1177 ai_database_generate_context_old(
1178 unsigned int context_id, DOID_TYPE parent_id, ZONEID_TYPE zone_id,
1179 CHANNEL_TYPE database_server_id, CHANNEL_TYPE from_channel_id)
const 1183 packer.RAW_PACK_CHANNEL(database_server_id);
1184 packer.RAW_PACK_CHANNEL(from_channel_id);
1186 packer.
raw_pack_uint16(STATESERVER_OBJECT_CREATE_WITH_REQUIRED_CONTEXT);
1193 int num_fields = get_num_inherited_fields();
1194 for (
int i = 0; i < num_fields; ++i) {
1195 DCField *field = get_inherited_field(i);
1205 #endif // HAVE_PYTHON 1215 output_instance(out, brief,
"",
"",
"");
1225 write(ostream &out,
bool brief,
int indent_level)
const {
1226 indent(out, indent_level);
1232 if (!_name.empty()) {
1233 out <<
" " << _name;
1236 if (!_parents.empty()) {
1237 Parents::const_iterator pi = _parents.begin();
1238 out <<
" : " << (*pi)->_name;
1240 while (pi != _parents.end()) {
1241 out <<
", " << (*pi)->_name;
1247 if (!brief && _number >= 0) {
1248 out <<
" // index " << _number;
1252 if (_constructor != (
DCField *)NULL) {
1253 _constructor->write(out, brief, indent_level + 2);
1256 Fields::const_iterator fi;
1257 for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
1258 if (!(*fi)->is_bogus_field()) {
1259 (*fi)->write(out, brief, indent_level + 2);
1277 indent(out, indent_level) <<
"};\n";
1288 const string &name,
const string &postname)
const {
1294 if (!_name.empty()) {
1295 out <<
" " << _name;
1298 if (!_parents.empty()) {
1299 Parents::const_iterator pi = _parents.begin();
1300 out <<
" : " << (*pi)->_name;
1302 while (pi != _parents.end()) {
1303 out <<
", " << (*pi)->_name;
1310 if (_constructor != (
DCField *)NULL) {
1311 _constructor->output(out, brief);
1315 Fields::const_iterator fi;
1316 for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
1317 if (!(*fi)->is_bogus_field()) {
1318 (*fi)->output(out, brief);
1324 if (!prename.empty() || !name.empty() || !postname.empty()) {
1325 out <<
" " << prename << name << postname;
1343 hashgen.
add_int(_parents.size());
1344 Parents::const_iterator pi;
1345 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
1346 hashgen.
add_int((*pi)->get_number());
1349 if (_constructor != (
DCField *)NULL) {
1350 _constructor->generate_hash(hashgen);
1353 hashgen.
add_int(_fields.size());
1354 Fields::const_iterator fi;
1355 for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
1356 (*fi)->generate_hash(hashgen);
1369 _inherited_fields.clear();
1382 _inherited_fields.clear();
1386 Parents::const_iterator pi;
1387 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
1388 const DCClass *parent = (*pi);
1390 for (
int i = 0; i < num_inherited_fields; ++i) {
1394 if (!dc_sort_inheritance_by_file) {
1395 _inherited_fields.push_back(field);
1399 bool inserted = names.insert(field->
get_name()).second;
1402 _inherited_fields.push_back(field);
1412 Fields::const_iterator fi;
1413 for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
1417 _inherited_fields.push_back(field);
1420 bool inserted = names.insert(field->
get_name()).second;
1424 shadow_inherited_field(field->
get_name());
1428 _inherited_fields.push_back(field);
1432 if (dc_sort_inheritance_by_file) {
1447 shadow_inherited_field(
const string &name) {
1448 Fields::iterator fi;
1449 for (fi = _inherited_fields.begin(); fi != _inherited_fields.end(); ++fi) {
1452 _inherited_fields.erase(fi);
1474 if (_dc_file != (
DCFile *)NULL) {
1475 _dc_file->mark_inherited_fields_stale();
1481 if (_constructor != (
DCField *)NULL) {
1489 _constructor = field;
1490 _fields_by_name.insert
1491 (FieldsByName::value_type(field->
get_name(), field));
1495 bool inserted = _fields_by_name.insert
1496 (FieldsByName::value_type(field->
get_name(), field)).second;
1503 if (_dc_file != (
DCFile *)NULL &&
1504 ((dc_virtual_inheritance && dc_sort_inheritance_by_file) || !is_struct())) {
1505 if (dc_multiple_inheritance) {
1506 _dc_file->set_new_index_number(field);
1508 field->
set_number(get_num_inherited_fields());
1511 bool inserted = _fields_by_index.insert
1512 (FieldsByIndex::value_type(field->
get_number(), field)).second;
1515 nassertr(inserted,
false);
1518 _fields.push_back(field);
1530 _parents.push_back(parent);
1531 _dc_file->mark_inherited_fields_stale();
void add_string(const string &str)
Adds a string to the hash, by breaking it down into a sequence of integers.
int get_number() const
Returns a unique index number associated with this field.
void generate_hash(HashGenerator &hashgen) const
Accumulates the properties of this class into the hash.
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
DCClass * get_class() const
Returns the DCClass pointer for the class that contains this field.
void clear_inherited_fields()
Empties the list of inherited fields for the class, so that it may be rebuilt.
DCField * get_field_by_name(const string &name) const
Returns a pointer to the DCField that shares the indicated name.
void add_int(int num)
Adds another integer to the hash so far.
DCClass * get_parent(int n) const
Returns the nth parent class this class inherits from.
size_t get_num_unpacked_bytes() const
Returns the number of bytes that have been unpacked so far, or after unpack_end(), the total number of bytes that were unpacked at all.
A single field of a Distributed Class, either atomic or molecular.
This is a convenience class to specialize ConfigVariable as a boolean type.
const Datagram & get_datagram() const
Return the datagram of this iterator.
unsigned int raw_unpack_uint16()
Unpacks the data from the buffer between unpacking sessions.
void raw_pack_uint8(unsigned int value)
Packs the data into the buffer between packing sessions.
void set_class(DCClass *dclass)
Assigns the class pointer to this field.
const string & get_name() const
Returns the name of this field, or empty string if the field is unnamed.
void set_number(int number)
Assigns the unique number to this field.
virtual DCAtomicField * as_atomic_field()
Returns the same field pointer converted to an atomic field pointer, if this is in fact an atomic fie...
bool is_broadcast() const
Returns true if the "broadcast" flag is set for this field, false otherwise.
Defines a particular DistributedClass as read from an input .dc file.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
bool inherits_from_bogus_class() const
Returns true if this class, or any class in the inheritance heirarchy for this class, is a "bogus" class–a forward reference to an as-yet-undefined class.
bool is_required() const
Returns true if the "required" flag is set for this field, false otherwise.
size_t get_length() const
Returns the current length of the buffer.
A single atomic field of a Distributed Class, as read from a .dc file.
virtual DCMolecularField * as_molecular_field()
Returns the same field pointer converted to a molecular field pointer, if this is in fact a molecular...
Represents the complete list of Distributed Class descriptions as read from a .dc file...
virtual void write(ostream &out, bool brief, int indent_level) const
Generates a parseable description of the object to the indicated output stream.
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
void raw_pack_uint32(unsigned int value)
Packs the data into the buffer between packing sessions.
DCField * get_field_by_index(int index_number) const
Returns a pointer to the DCField that has the indicated index number.
void output_instance(ostream &out, bool brief, const string &prename, const string &name, const string &postname) const
Generates a parseable description of the object to the indicated output stream.
int get_num_elements() const
Returns the number of elements (parameters) of the atomic field.
DCField * get_inherited_field(int n) const
Returns the nth field field in the class and all of its ancestors.
A lightweight class that represents a single element that may be timed and/or counted via stats...
Represents the type specification for a single parameter within a field specification.
virtual void output(ostream &out) const
Write a string representation of this instance to <out>.
void pack_default_value()
Adds the default value for the current element into the stream.
size_t get_current_index() const
Returns the current position within the datagram of the next piece of data to extract.
void raw_pack_uint16(unsigned int value)
Packs the data into the buffer between packing sessions.
int get_remaining_size() const
Return the bytes left in the datagram.
void skip_bytes(size_t size)
Skips over the indicated number of bytes in the datagram.
void add_parent(DCClass *parent)
Adds a new parent to the inheritance hierarchy of the class.
bool has_default_value() const
Returns true if a default value has been explicitly established for this field, false otherwise...
const char * get_data() const
Returns the beginning of the data buffer.
int get_num_parents() const
Returns the number of base classes this class inherits from.
This class generates an arbitrary hash number from a sequence of ints.
bool is_ownrecv() const
Returns true if the "ownrecv" flag is set for this field, false otherwise.
DCField * get_constructor() const
Returns the constructor method for this class if it is defined, or NULL if the class uses the default...
int get_num_inherited_fields() const
Returns the total number of field fields defined in this class and all ancestor classes.
void begin_pack(const DCPackerInterface *root)
Begins a packing session.
This class can be used for packing a series of numeric and string data into a binary stream...
bool has_constructor() const
Returns true if this class has a constructor method, false if it just uses the default constructor...
void unpack_skip()
Skips the current field without unpacking it and advances to the next field.
A class to retrieve the individual data elements previously stored in a Datagram. ...
bool add_field(DCField *field)
Adds the newly-allocated field to the class.
bool end_pack()
Finishes a packing session.
void set_unpack_data(const string &data)
Sets up the unpack_data pointer.
string get_message() const
Returns the datagram's data as a string.
int get_num_fields() const
Returns the number of fields defined directly in this class, ignoring inheritance.
A single molecular field of a Distributed Class, as read from a .dc file.
void rebuild_inherited_fields()
Recomputes the list of inherited fields for the class.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
DCField * get_field(int n) const
Returns the nth field in the class.
void begin_unpack(const DCPackerInterface *root)
Begins an unpacking session.
bool end_unpack()
Finishes the unpacking session.
const void * get_data() const
Returns a pointer to the beginning of the datagram's data.
void set_number(int number)
Assigns the unique number to this class.