Panda3D
 All Classes Functions Variables Enumerations
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 }
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_class_parameter(const DCClassParameter *other) const
Returns true if this field matches the indicated class parameter, false otherwise.
This is a block of data that receives the results of DCPacker.
Definition: dcPackData.h:25
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.
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_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 bool do_check_match_switch_parameter(const DCSwitchParameter *other) const
Returns true if this field matches the indicated switch 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.
This represents a switch object used as a parameter itself, which packs the appropriate fields of the...
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 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 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.
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 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 bool do_check_match_array_parameter(const DCArrayParameter *other) const
Returns true if this field matches the indicated array 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...
This represents an array of some other kind of object, meaning this parameter type accepts an arbitra...
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_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.
const DCPackerCatalog * get_catalog() const
Returns the DCPackerCatalog associated with this field, listing all of the nested fields by name...
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 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.
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 ...
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 bool validate_num_nested_fields(int num_nested_fields) const
After a number of fields have been packed via push()
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 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 void set_name(const string &name)
Sets the name of this field.
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 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.
A single molecular field of a Distributed Class, as read from a .dc file.
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_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 defines the internal interface for packing values into a DCField.
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...