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