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  */
199 validate_num_nested_fields(int) const {
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 represents an array of some other kind of object, meaning this parameter type accepts an arbitra...
A single atomic field of a Distributed Class, as read from a .dc file.
Definition: dcAtomicField.h:30
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
Represents the complete list of Distributed Class descriptions as read from a .dc file.
Definition: dcFile.h:32
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.
Definition: dcPackData.h:22
This object contains the names of all of the nested fields available within a particular field.
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...
This defines the internal interface for packing values into a DCField.
const DCPackerCatalog * get_catalog() const
Returns the DCPackerCatalog associated with this field, listing all of the nested fields by name.
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.
virtual void unpack_blob(const char *data, size_t length, size_t &p, std::vector< unsigned char > &value, bool &pack_error, bool &range_error) const
Unpacks the current numeric or string value from the stream.
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.
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.
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.
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.
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 int calc_num_nested_fields(size_t length_bytes) const
This flavor of get_num_nested_fields is used during unpacking.
virtual bool do_check_match_simple_parameter(const DCSimpleParameter *other) const
Returns true if this field matches the indicated simple parameter, false otherwise.
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 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 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 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 bool do_check_match_atomic_field(const DCAtomicField *other) const
Returns true if this field matches the indicated atomic field, false otherwise.
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 bool validate_num_nested_fields(int num_nested_fields) const
After a number of fields have been packed via push() .
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 ...
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_double(DCPackData &pack_data, double value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into the stream.
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.
virtual DCPackerInterface * get_nested_field(int n) const
Returns the DCPackerInterface object that represents the nth nested field.
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 set_name(const std::string &name)
Sets the name of this field.
virtual bool do_check_match_molecular_field(const DCMolecularField *other) const
Returns true if this field matches the indicated molecular field, false otherwise.
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_blob(DCPackData &pack_data, const std::vector< unsigned char > &value, bool &pack_error, bool &range_error) const
Packs the indicated numeric or string value into 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...
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...
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...
This is the most fundamental kind of parameter type: a single number or string, one of the DCSubatomi...
This represents a switch object used as a parameter itself, which packs the appropriate fields of the...
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.