Panda3D
dcPackerInterface.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file dcPackerInterface.cxx
10  * @author drose
11  * @date 2004-06-15
12  */
13 
14 #include "dcPackerInterface.h"
15 #include "dcPackerCatalog.h"
16 #include "dcField.h"
17 #include "dcParserDefs.h"
18 #include "dcLexerDefs.h"
19 
20 using std::string;
21 
22 /**
23  *
24  */
25 DCPackerInterface::
26 DCPackerInterface(const string &name) :
27  _name(name)
28 {
29  _has_fixed_byte_size = false;
30  _fixed_byte_size = 0;
31  _has_fixed_structure = false;
32  _has_range_limits = false;
33  _num_length_bytes = 0;
34  _has_nested_fields = false;
35  _num_nested_fields = -1;
36  _pack_type = PT_invalid;
37  _catalog = nullptr;
38 }
39 
40 /**
41  *
42  */
43 DCPackerInterface::
44 DCPackerInterface(const DCPackerInterface &copy) :
45  _name(copy._name),
46  _has_fixed_byte_size(copy._has_fixed_byte_size),
47  _fixed_byte_size(copy._fixed_byte_size),
48  _has_fixed_structure(copy._has_fixed_structure),
49  _has_range_limits(copy._has_range_limits),
50  _num_length_bytes(copy._num_length_bytes),
51  _has_nested_fields(copy._has_nested_fields),
52  _num_nested_fields(copy._num_nested_fields),
53  _pack_type(copy._pack_type)
54 {
55  _catalog = nullptr;
56 }
57 
58 /**
59  *
60  */
61 DCPackerInterface::
62 ~DCPackerInterface() {
63  if (_catalog != nullptr) {
64  delete _catalog;
65  }
66 }
67 
68 /**
69  * Returns the index number to be passed to a future call to DCPacker::seek()
70  * to seek directly to the named field without having to look up the field
71  * name in a table later, or -1 if the named field cannot be found.
72  *
73  * If the named field is nested within a switch or some similar dynamic
74  * structure that reveals different fields based on the contents of the data,
75  * this mechanism cannot be used to pre-fetch the field index number--you must
76  * seek for the field by name.
77  */
79 find_seek_index(const string &name) const {
80  return get_catalog()->find_entry_by_name(name);
81 }
82 
83 /**
84  *
85  */
86 DCField *DCPackerInterface::
87 as_field() {
88  return nullptr;
89 }
90 
91 /**
92  *
93  */
94 const DCField *DCPackerInterface::
95 as_field() const {
96  return nullptr;
97 }
98 
99 /**
100  *
101  */
102 DCSwitchParameter *DCPackerInterface::
103 as_switch_parameter() {
104  return nullptr;
105 }
106 
107 /**
108  *
109  */
110 const DCSwitchParameter *DCPackerInterface::
111 as_switch_parameter() const {
112  return nullptr;
113 }
114 
115 /**
116  *
117  */
118 DCClassParameter *DCPackerInterface::
119 as_class_parameter() {
120  return nullptr;
121 }
122 
123 /**
124  *
125  */
126 const DCClassParameter *DCPackerInterface::
127 as_class_parameter() const {
128  return nullptr;
129 }
130 
131 /**
132  * Returns true if this interface is bitwise the same as the interface
133  * described with the indicated formatted string, e.g. "(uint8, uint8,
134  * int16)", or false otherwise.
135  *
136  * If DCFile is not NULL, it specifies the DCFile that was previously loaded,
137  * from which some predefined structs and typedefs may be referenced in the
138  * description string.
139  */
141 check_match(const string &description, DCFile *dcfile) const {
142  bool match = false;
143 
144  std::istringstream strm(description);
145  dc_init_parser_parameter_description(strm, "check_match", dcfile);
146  dcyyparse();
147  dc_cleanup_parser();
148 
149  DCField *field = dc_get_parameter_description();
150  if (field != nullptr) {
151  match = check_match(field);
152  delete field;
153  }
154 
155  if (dc_error_count() == 0) {
156  return match;
157  }
158 
159  // Parse error: no match is allowed.
160  return false;
161 }
162 
163 /**
164  * Sets the name of this field.
165  */
167 set_name(const string &name) {
168  _name = name;
169 }
170 
171 /**
172  * This flavor of get_num_nested_fields is used during unpacking. It returns
173  * the number of nested fields to expect, given a certain length in bytes (as
174  * read from the _num_length_bytes stored in the stream on the push). This
175  * will only be called if _num_length_bytes is nonzero.
176  */
178 calc_num_nested_fields(size_t) const {
179  return 0;
180 }
181 
182 /**
183  * Returns the DCPackerInterface object that represents the nth nested field.
184  * This may return NULL if there is no such field (but it shouldn't do this if
185  * n is in the range 0 <= n < get_num_nested_fields()).
186  */
188 get_nested_field(int) const {
189  return nullptr;
190 }
191 
192 /**
193  * After a number of fields have been packed via push() .. pack_*() .. pop(),
194  * this is called to confirm that the number of nested fields that were added
195  * is valid for this type. This is primarily useful for array types with
196  * dynamic ranges that can't validate the number of fields any other way.
197  */
200  return true;
201 }
202 
203 /**
204  * Packs the indicated numeric or string value into the stream.
205  */
207 pack_double(DCPackData &, double, bool &pack_error, bool &) const {
208  pack_error = true;
209 }
210 
211 /**
212  * Packs the indicated numeric or string value into the stream.
213  */
215 pack_int(DCPackData &, int, bool &pack_error, bool &) const {
216  pack_error = true;
217 }
218 
219 /**
220  * Packs the indicated numeric or string value into the stream.
221  */
223 pack_uint(DCPackData &, unsigned int, bool &pack_error, bool &) const {
224  pack_error = true;
225 }
226 
227 /**
228  * Packs the indicated numeric or string value into the stream.
229  */
231 pack_int64(DCPackData &, int64_t, bool &pack_error, bool &) const {
232  pack_error = true;
233 }
234 
235 /**
236  * Packs the indicated numeric or string value into the stream.
237  */
239 pack_uint64(DCPackData &, uint64_t, bool &pack_error, bool &) const {
240  pack_error = true;
241 }
242 
243 /**
244  * Packs the indicated numeric or string value into the stream.
245  */
247 pack_string(DCPackData &, const string &, bool &pack_error, bool &) const {
248  pack_error = true;
249 }
250 
251 /**
252  * Packs the indicated numeric or string value into the stream.
253  */
255 pack_blob(DCPackData &, const vector_uchar &, bool &pack_error, bool &) const {
256  pack_error = true;
257 }
258 
259 /**
260  * Packs the field's specified default value (or a sensible default if no
261  * value is specified) into the stream. Returns true if the default value is
262  * packed, false if the field doesn't know how to pack its default value.
263  */
265 pack_default_value(DCPackData &, bool &) const {
266  return false;
267 }
268 
269 /**
270  * Unpacks the current numeric or string value from the stream.
271  */
273 unpack_double(const char *, size_t, size_t &, double &, bool &pack_error, bool &) const {
274  pack_error = true;
275 }
276 
277 /**
278  * Unpacks the current numeric or string value from the stream.
279  */
281 unpack_int(const char *, size_t, size_t &, int &, bool &pack_error, bool &) const {
282  pack_error = true;
283 }
284 
285 /**
286  * Unpacks the current numeric or string value from the stream.
287  */
289 unpack_uint(const char *, size_t, size_t &, unsigned int &, bool &pack_error, bool &) const {
290  pack_error = true;
291 }
292 
293 /**
294  * Unpacks the current numeric or string value from the stream.
295  */
297 unpack_int64(const char *, size_t, size_t &, int64_t &, bool &pack_error, bool &) const {
298  pack_error = true;
299 }
300 
301 /**
302  * Unpacks the current numeric or string value from the stream.
303  */
305 unpack_uint64(const char *, size_t, size_t &, uint64_t &, bool &pack_error, bool &) const {
306  pack_error = true;
307 }
308 
309 /**
310  * Unpacks the current numeric or string value from the stream.
311  */
313 unpack_string(const char *, size_t, size_t &, string &, bool &pack_error, bool &) const {
314  pack_error = true;
315 }
316 
317 /**
318  * Unpacks the current numeric or string value from the stream.
319  */
321 unpack_blob(const char *, size_t, size_t &, vector_uchar &, bool &pack_error, bool &) const {
322  pack_error = true;
323 }
324 
325 /**
326  * Internally unpacks the current numeric or string value and validates it
327  * against the type range limits, but does not return the value. Returns true
328  * on success, false on failure (e.g. we don't know how to validate this
329  * field).
330  */
332 unpack_validate(const char *data, size_t length, size_t &p,
333  bool &pack_error, bool &) const {
334  if (!_has_range_limits) {
335  return unpack_skip(data, length, p, pack_error);
336  }
337  return false;
338 }
339 
340 /**
341  * Increments p to the end of the current field without actually unpacking any
342  * data or performing any range validation. Returns true on success, false on
343  * failure (e.g. we don't know how to skip this field).
344  */
346 unpack_skip(const char *data, size_t length, size_t &p,
347  bool &pack_error) const {
348  if (_has_fixed_byte_size) {
349  // If this field has a fixed byte size, it's easy to skip.
350  p += _fixed_byte_size;
351  if (p > length) {
352  pack_error = true;
353  }
354  return true;
355  }
356 
357  if (_has_nested_fields && _num_length_bytes != 0) {
358  // If we have a length prefix, use that for skipping.
359  if (p + _num_length_bytes > length) {
360  pack_error = true;
361 
362  } else {
363  if (_num_length_bytes == 4) {
364  size_t this_length = do_unpack_uint32(data + p);
365  p += this_length + 4;
366  } else {
367  size_t this_length = do_unpack_uint16(data + p);
368  p += this_length + 2;
369  }
370  if (p > length) {
371  pack_error = true;
372  }
373  }
374  return true;
375  }
376 
377  // Otherwise, we don't know how to skip this field (presumably it can be
378  // skipped by skipping over its nested fields individually).
379  return false;
380 }
381 
382 /**
383  * Returns the DCPackerCatalog associated with this field, listing all of the
384  * nested fields by name.
385  */
387 get_catalog() const {
388  if (_catalog == nullptr) {
389  ((DCPackerInterface *)this)->make_catalog();
390  }
391  return _catalog;
392 }
393 
394 /**
395  * Returns true if this field matches the indicated simple parameter, false
396  * otherwise.
397  */
400  return false;
401 }
402 
403 /**
404  * Returns true if this field matches the indicated class parameter, false
405  * otherwise.
406  */
409  return false;
410 }
411 
412 /**
413  * Returns true if this field matches the indicated switch parameter, false
414  * otherwise.
415  */
418  return false;
419 }
420 
421 /**
422  * Returns true if this field matches the indicated array parameter, false
423  * otherwise.
424  */
427  return false;
428 }
429 
430 /**
431  * Returns true if this field matches the indicated atomic field, false
432  * otherwise.
433  */
436  return false;
437 }
438 
439 /**
440  * Returns true if this field matches the indicated molecular field, false
441  * otherwise.
442  */
445  return false;
446 }
447 
448 /**
449  * Called internally to create a new DCPackerCatalog object.
450  */
451 void DCPackerInterface::
452 make_catalog() {
453  nassertv(_catalog == nullptr);
454  _catalog = new DCPackerCatalog(this);
455 
456  _catalog->r_fill_catalog("", this, nullptr, 0);
457 }
This is a block of data that receives the results of DCPacker.
Definition: dcPackData.h:22
int find_entry_by_name(const std::string &name) const
Returns the index number of the entry with the indicated name, or -1 if no entry has the indicated na...
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...
virtual bool do_check_match_array_parameter(const DCArrayParameter *other) const
Returns true if this field matches the indicated array parameter, false otherwise.
virtual void pack_uint(DCPackData &pack_data, unsigned int value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
This represents a class (or struct) object used as a parameter itself.
A single field of a Distributed Class, either atomic or molecular.
Definition: dcField.h:37
This is the most fundamental kind of parameter type: a single number or string, one of the DCSubatomi...
virtual void unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
This represents a switch object used as a parameter itself, which packs the appropriate fields of the...
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void set_name(const std::string &name)
Sets the name of this field.
virtual bool do_check_match_simple_parameter(const DCSimpleParameter *other) const
Returns true if this field matches the indicated simple parameter, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A single atomic field of a Distributed Class, as read from a .dc file.
Definition: dcAtomicField.h:30
Represents the complete list of Distributed Class descriptions as read from a .dc file.
Definition: dcFile.h:32
virtual void pack_uint64(DCPackData &pack_data, uint64_t value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool unpack_validate(const char *data, size_t length, size_t &p, bool &pack_error, bool &range_error) const
Internally unpacks the current numeric or string value and validates it against the type range limits...
virtual void pack_int64(DCPackData &pack_data, int64_t value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
This represents an array of some other kind of object, meaning this parameter type accepts an arbitra...
bool check_match(const DCPackerInterface *other) const
Returns true if the other interface is bitwise the same as this oneā€“that is, a uint32 only matches a ...
const DCPackerCatalog * get_catalog() const
Returns the DCPackerCatalog associated with this field, listing all of the nested fields by name.
virtual void unpack_uint(const char *data, size_t length, size_t &p, unsigned int &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
virtual bool unpack_skip(const char *data, size_t length, size_t &p, bool &pack_error) const
Increments p to the end of the current field without actually unpacking any data or performing any ra...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool do_check_match_atomic_field(const DCAtomicField *other) const
Returns true if this field matches the indicated atomic field, false otherwise.
virtual bool do_check_match_class_parameter(const DCClassParameter *other) const
Returns true if this field matches the indicated class parameter, false otherwise.
virtual void unpack_int(const char *data, size_t length, size_t &p, int &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
virtual void unpack_string(const char *data, size_t length, size_t &p, std::string &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
virtual int calc_num_nested_fields(size_t length_bytes) const
This flavor of get_num_nested_fields is used during unpacking.
virtual void pack_string(DCPackData &pack_data, const std::string &value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
virtual bool do_check_match_switch_parameter(const DCSwitchParameter *other) const
Returns true if this field matches the indicated switch parameter, false otherwise.
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
virtual bool do_check_match_molecular_field(const DCMolecularField *other) const
Returns true if this field matches the indicated molecular field, false otherwise.
virtual void unpack_double(const char *data, size_t length, size_t &p, double &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
This object contains the names of all of the nested fields available within a particular field.
virtual bool validate_num_nested_fields(int num_nested_fields) const
After a number of fields have been packed via push() .
virtual void unpack_int64(const char *data, size_t length, size_t &p, int64_t &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
A single molecular field of a Distributed Class, as read from a .dc file.
virtual void pack_double(DCPackData &pack_data, double value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines the internal interface for packing values into a DCField.
virtual void pack_int(DCPackData &pack_data, int value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
virtual void unpack_uint64(const char *data, size_t length, size_t &p, uint64_t &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
int find_seek_index(const std::string &name) const
Returns the index number to be passed to a future call to DCPacker::seek() to seek directly to the na...