00001 // Filename: dcPackerInterface.cxx 00002 // Created by: drose (15Jun04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "dcPackerInterface.h" 00016 #include "dcPackerCatalog.h" 00017 #include "dcField.h" 00018 #include "dcParserDefs.h" 00019 #include "dcLexerDefs.h" 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: DCPackerInterface::Constructor 00023 // Access: Public 00024 // Description: 00025 //////////////////////////////////////////////////////////////////// 00026 DCPackerInterface:: 00027 DCPackerInterface(const string &name) : 00028 _name(name) 00029 { 00030 _has_fixed_byte_size = false; 00031 _fixed_byte_size = 0; 00032 _has_fixed_structure = false; 00033 _has_range_limits = false; 00034 _num_length_bytes = 0; 00035 _has_nested_fields = false; 00036 _num_nested_fields = -1; 00037 _pack_type = PT_invalid; 00038 _catalog = NULL; 00039 } 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Function: DCPackerInterface::Copy Constructor 00043 // Access: Public 00044 // Description: 00045 //////////////////////////////////////////////////////////////////// 00046 DCPackerInterface:: 00047 DCPackerInterface(const DCPackerInterface ©) : 00048 _name(copy._name), 00049 _has_fixed_byte_size(copy._has_fixed_byte_size), 00050 _fixed_byte_size(copy._fixed_byte_size), 00051 _has_fixed_structure(copy._has_fixed_structure), 00052 _has_range_limits(copy._has_range_limits), 00053 _num_length_bytes(copy._num_length_bytes), 00054 _has_nested_fields(copy._has_nested_fields), 00055 _num_nested_fields(copy._num_nested_fields), 00056 _pack_type(copy._pack_type) 00057 { 00058 _catalog = NULL; 00059 } 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Function: DCPackerInterface::Destructor 00063 // Access: Public, Virtual 00064 // Description: 00065 //////////////////////////////////////////////////////////////////// 00066 DCPackerInterface:: 00067 ~DCPackerInterface() { 00068 if (_catalog != (DCPackerCatalog *)NULL) { 00069 delete _catalog; 00070 } 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: DCPackerInterface::find_seek_index 00075 // Access: Published 00076 // Description: Returns the index number to be passed to a future 00077 // call to DCPacker::seek() to seek directly to the 00078 // named field without having to look up the field name 00079 // in a table later, or -1 if the named field cannot be 00080 // found. 00081 // 00082 // If the named field is nested within a switch or some 00083 // similar dynamic structure that reveals different 00084 // fields based on the contents of the data, this 00085 // mechanism cannot be used to pre-fetch the field index 00086 // number--you must seek for the field by name. 00087 //////////////////////////////////////////////////////////////////// 00088 int DCPackerInterface:: 00089 find_seek_index(const string &name) const { 00090 return get_catalog()->find_entry_by_name(name); 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: DCPackerInterface::as_field 00095 // Access: Published, Virtual 00096 // Description: 00097 //////////////////////////////////////////////////////////////////// 00098 DCField *DCPackerInterface:: 00099 as_field() { 00100 return (DCField *)NULL; 00101 } 00102 00103 //////////////////////////////////////////////////////////////////// 00104 // Function: DCPackerInterface::as_field 00105 // Access: Published, Virtual 00106 // Description: 00107 //////////////////////////////////////////////////////////////////// 00108 const DCField *DCPackerInterface:: 00109 as_field() const { 00110 return (DCField *)NULL; 00111 } 00112 00113 //////////////////////////////////////////////////////////////////// 00114 // Function: DCPackerInterface::as_switch_parameter 00115 // Access: Published, Virtual 00116 // Description: 00117 //////////////////////////////////////////////////////////////////// 00118 DCSwitchParameter *DCPackerInterface:: 00119 as_switch_parameter() { 00120 return (DCSwitchParameter *)NULL; 00121 } 00122 00123 //////////////////////////////////////////////////////////////////// 00124 // Function: DCPackerInterface::as_switch_parameter 00125 // Access: Published, Virtual 00126 // Description: 00127 //////////////////////////////////////////////////////////////////// 00128 const DCSwitchParameter *DCPackerInterface:: 00129 as_switch_parameter() const { 00130 return (DCSwitchParameter *)NULL; 00131 } 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function: DCPackerInterface::as_class_parameter 00135 // Access: Published, Virtual 00136 // Description: 00137 //////////////////////////////////////////////////////////////////// 00138 DCClassParameter *DCPackerInterface:: 00139 as_class_parameter() { 00140 return (DCClassParameter *)NULL; 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: DCPackerInterface::as_class_parameter 00145 // Access: Published, Virtual 00146 // Description: 00147 //////////////////////////////////////////////////////////////////// 00148 const DCClassParameter *DCPackerInterface:: 00149 as_class_parameter() const { 00150 return (DCClassParameter *)NULL; 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: DCPackerInterface::check_match 00155 // Access: Published 00156 // Description: Returns true if this interface is bitwise the same as 00157 // the interface described with the indicated formatted 00158 // string, e.g. "(uint8, uint8, int16)", or false 00159 // otherwise. 00160 // 00161 // If DCFile is not NULL, it specifies the DCFile that 00162 // was previously loaded, from which some predefined 00163 // structs and typedefs may be referenced in the 00164 // description string. 00165 //////////////////////////////////////////////////////////////////// 00166 bool DCPackerInterface:: 00167 check_match(const string &description, DCFile *dcfile) const { 00168 bool match = false; 00169 00170 istringstream strm(description); 00171 dc_init_parser_parameter_description(strm, "check_match", dcfile); 00172 dcyyparse(); 00173 dc_cleanup_parser(); 00174 00175 DCField *field = dc_get_parameter_description(); 00176 if (field != NULL) { 00177 match = check_match(field); 00178 delete field; 00179 } 00180 00181 if (dc_error_count() == 0) { 00182 return match; 00183 } 00184 00185 // Parse error: no match is allowed. 00186 return false; 00187 } 00188 00189 //////////////////////////////////////////////////////////////////// 00190 // Function: DCPackerInterface::set_name 00191 // Access: Public, Virtual 00192 // Description: Sets the name of this field. 00193 //////////////////////////////////////////////////////////////////// 00194 void DCPackerInterface:: 00195 set_name(const string &name) { 00196 _name = name; 00197 } 00198 00199 //////////////////////////////////////////////////////////////////// 00200 // Function: DCPackerInterface::calc_num_nested_fields 00201 // Access: Public, Virtual 00202 // Description: This flavor of get_num_nested_fields is used during 00203 // unpacking. It returns the number of nested fields to 00204 // expect, given a certain length in bytes (as read from 00205 // the _num_length_bytes stored in the stream on the 00206 // push). This will only be called if _num_length_bytes 00207 // is nonzero. 00208 //////////////////////////////////////////////////////////////////// 00209 int DCPackerInterface:: 00210 calc_num_nested_fields(size_t) const { 00211 return 0; 00212 } 00213 00214 //////////////////////////////////////////////////////////////////// 00215 // Function: DCPackerInterface::get_nested_field 00216 // Access: Public, Virtual 00217 // Description: Returns the DCPackerInterface object that represents 00218 // the nth nested field. This may return NULL if there 00219 // is no such field (but it shouldn't do this if n is in 00220 // the range 0 <= n < get_num_nested_fields()). 00221 //////////////////////////////////////////////////////////////////// 00222 DCPackerInterface *DCPackerInterface:: 00223 get_nested_field(int) const { 00224 return NULL; 00225 } 00226 00227 //////////////////////////////////////////////////////////////////// 00228 // Function: DCPackerInterface::validate_num_nested_fields 00229 // Access: Public, Virtual 00230 // Description: After a number of fields have been packed via push() 00231 // .. pack_*() .. pop(), this is called to confirm that 00232 // the number of nested fields that were added is valid 00233 // for this type. This is primarily useful for array 00234 // types with dynamic ranges that can't validate the 00235 // number of fields any other way. 00236 //////////////////////////////////////////////////////////////////// 00237 bool DCPackerInterface:: 00238 validate_num_nested_fields(int) const { 00239 return true; 00240 } 00241 00242 //////////////////////////////////////////////////////////////////// 00243 // Function: DCPackerInterface::pack_double 00244 // Access: Public, Virtual 00245 // Description: Packs the indicated numeric or string value into the 00246 // stream. 00247 //////////////////////////////////////////////////////////////////// 00248 void DCPackerInterface:: 00249 pack_double(DCPackData &, double, bool &pack_error, bool &) const { 00250 pack_error = true; 00251 } 00252 00253 //////////////////////////////////////////////////////////////////// 00254 // Function: DCPackerInterface::pack_int 00255 // Access: Public, Virtual 00256 // Description: Packs the indicated numeric or string value into the 00257 // stream. 00258 //////////////////////////////////////////////////////////////////// 00259 void DCPackerInterface:: 00260 pack_int(DCPackData &, int, bool &pack_error, bool &) const { 00261 pack_error = true; 00262 } 00263 00264 //////////////////////////////////////////////////////////////////// 00265 // Function: DCPackerInterface::pack_uint 00266 // Access: Public, Virtual 00267 // Description: Packs the indicated numeric or string value into the 00268 // stream. 00269 //////////////////////////////////////////////////////////////////// 00270 void DCPackerInterface:: 00271 pack_uint(DCPackData &, unsigned int, bool &pack_error, bool &) const { 00272 pack_error = true; 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: DCPackerInterface::pack_int64 00277 // Access: Public, Virtual 00278 // Description: Packs the indicated numeric or string value into the 00279 // stream. 00280 //////////////////////////////////////////////////////////////////// 00281 void DCPackerInterface:: 00282 pack_int64(DCPackData &, PN_int64, bool &pack_error, bool &) const { 00283 pack_error = true; 00284 } 00285 00286 //////////////////////////////////////////////////////////////////// 00287 // Function: DCPackerInterface::pack_uint64 00288 // Access: Public, Virtual 00289 // Description: Packs the indicated numeric or string value into the 00290 // stream. 00291 //////////////////////////////////////////////////////////////////// 00292 void DCPackerInterface:: 00293 pack_uint64(DCPackData &, PN_uint64, bool &pack_error, bool &) const { 00294 pack_error = true; 00295 } 00296 00297 //////////////////////////////////////////////////////////////////// 00298 // Function: DCPackerInterface::pack_string 00299 // Access: Public, Virtual 00300 // Description: Packs the indicated numeric or string value into the 00301 // stream. 00302 //////////////////////////////////////////////////////////////////// 00303 void DCPackerInterface:: 00304 pack_string(DCPackData &, const string &, bool &pack_error, bool &) const { 00305 pack_error = true; 00306 } 00307 00308 //////////////////////////////////////////////////////////////////// 00309 // Function: DCPackerInterface::pack_default_value 00310 // Access: Public, Virtual 00311 // Description: Packs the field's specified default value (or a 00312 // sensible default if no value is specified) into the 00313 // stream. Returns true if the default value is packed, 00314 // false if the field doesn't know how to pack its 00315 // default value. 00316 //////////////////////////////////////////////////////////////////// 00317 bool DCPackerInterface:: 00318 pack_default_value(DCPackData &, bool &) const { 00319 return false; 00320 } 00321 00322 //////////////////////////////////////////////////////////////////// 00323 // Function: DCPackerInterface::unpack_double 00324 // Access: Public, Virtual 00325 // Description: Unpacks the current numeric or string value from the 00326 // stream. 00327 //////////////////////////////////////////////////////////////////// 00328 void DCPackerInterface:: 00329 unpack_double(const char *, size_t, size_t &, double &, bool &pack_error, bool &) const { 00330 pack_error = true; 00331 } 00332 00333 //////////////////////////////////////////////////////////////////// 00334 // Function: DCPackerInterface::unpack_int 00335 // Access: Public, Virtual 00336 // Description: Unpacks the current numeric or string value from the 00337 // stream. 00338 //////////////////////////////////////////////////////////////////// 00339 void DCPackerInterface:: 00340 unpack_int(const char *, size_t, size_t &, int &, bool &pack_error, bool &) const { 00341 pack_error = true; 00342 } 00343 00344 //////////////////////////////////////////////////////////////////// 00345 // Function: DCPackerInterface::unpack_uint 00346 // Access: Public, Virtual 00347 // Description: Unpacks the current numeric or string value from the 00348 // stream. 00349 //////////////////////////////////////////////////////////////////// 00350 void DCPackerInterface:: 00351 unpack_uint(const char *, size_t, size_t &, unsigned int &, bool &pack_error, bool &) const { 00352 pack_error = true; 00353 } 00354 00355 //////////////////////////////////////////////////////////////////// 00356 // Function: DCPackerInterface::unpack_int64 00357 // Access: Public, Virtual 00358 // Description: Unpacks the current numeric or string value from the 00359 // stream. 00360 //////////////////////////////////////////////////////////////////// 00361 void DCPackerInterface:: 00362 unpack_int64(const char *, size_t, size_t &, PN_int64 &, bool &pack_error, bool &) const { 00363 pack_error = true; 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: DCPackerInterface::unpack_uint64 00368 // Access: Public, Virtual 00369 // Description: Unpacks the current numeric or string value from the 00370 // stream. 00371 //////////////////////////////////////////////////////////////////// 00372 void DCPackerInterface:: 00373 unpack_uint64(const char *, size_t, size_t &, PN_uint64 &, bool &pack_error, bool &) const { 00374 pack_error = true; 00375 } 00376 00377 //////////////////////////////////////////////////////////////////// 00378 // Function: DCPackerInterface::unpack_string 00379 // Access: Public, Virtual 00380 // Description: Unpacks the current numeric or string value from the 00381 // stream. 00382 //////////////////////////////////////////////////////////////////// 00383 void DCPackerInterface:: 00384 unpack_string(const char *, size_t, size_t &, string &, bool &pack_error, bool &) const { 00385 pack_error = true; 00386 } 00387 00388 //////////////////////////////////////////////////////////////////// 00389 // Function: DCPackerInterface::unpack_validate 00390 // Access: Public, Virtual 00391 // Description: Internally unpacks the current numeric or string 00392 // value and validates it against the type range limits, 00393 // but does not return the value. Returns true on 00394 // success, false on failure (e.g. we don't know how to 00395 // validate this field). 00396 //////////////////////////////////////////////////////////////////// 00397 bool DCPackerInterface:: 00398 unpack_validate(const char *data, size_t length, size_t &p, 00399 bool &pack_error, bool &) const { 00400 if (!_has_range_limits) { 00401 return unpack_skip(data, length, p, pack_error); 00402 } 00403 return false; 00404 } 00405 00406 //////////////////////////////////////////////////////////////////// 00407 // Function: DCPackerInterface::unpack_skip 00408 // Access: Public, Virtual 00409 // Description: Increments p to the end of the current field without 00410 // actually unpacking any data or performing any range 00411 // validation. Returns true on success, false on 00412 // failure (e.g. we don't know how to skip this field). 00413 //////////////////////////////////////////////////////////////////// 00414 bool DCPackerInterface:: 00415 unpack_skip(const char *data, size_t length, size_t &p, 00416 bool &pack_error) const { 00417 if (_has_fixed_byte_size) { 00418 // If this field has a fixed byte size, it's easy to skip. 00419 p += _fixed_byte_size; 00420 if (p > length) { 00421 pack_error = true; 00422 } 00423 return true; 00424 } 00425 00426 if (_has_nested_fields && _num_length_bytes != 0) { 00427 // If we have a length prefix, use that for skipping. 00428 if (p + _num_length_bytes > length) { 00429 pack_error = true; 00430 00431 } else { 00432 if (_num_length_bytes == 4) { 00433 size_t this_length = do_unpack_uint32(data + p); 00434 p += this_length + 4; 00435 } else { 00436 size_t this_length = do_unpack_uint16(data + p); 00437 p += this_length + 2; 00438 } 00439 if (p > length) { 00440 pack_error = true; 00441 } 00442 } 00443 return true; 00444 } 00445 00446 // Otherwise, we don't know how to skip this field (presumably it 00447 // can be skipped by skipping over its nested fields individually). 00448 return false; 00449 } 00450 00451 //////////////////////////////////////////////////////////////////// 00452 // Function: DCPackerInterface::get_catalog 00453 // Access: Public 00454 // Description: Returns the DCPackerCatalog associated with this 00455 // field, listing all of the nested fields by name. 00456 //////////////////////////////////////////////////////////////////// 00457 const DCPackerCatalog *DCPackerInterface:: 00458 get_catalog() const { 00459 if (_catalog == (DCPackerCatalog *)NULL) { 00460 ((DCPackerInterface *)this)->make_catalog(); 00461 } 00462 return _catalog; 00463 } 00464 00465 //////////////////////////////////////////////////////////////////// 00466 // Function: DCPackerInterface::do_check_match_simple_parameter 00467 // Access: Protected, Virtual 00468 // Description: Returns true if this field matches the indicated 00469 // simple parameter, false otherwise. 00470 //////////////////////////////////////////////////////////////////// 00471 bool DCPackerInterface:: 00472 do_check_match_simple_parameter(const DCSimpleParameter *) const { 00473 return false; 00474 } 00475 00476 //////////////////////////////////////////////////////////////////// 00477 // Function: DCPackerInterface::do_check_match_class_parameter 00478 // Access: Protected, Virtual 00479 // Description: Returns true if this field matches the indicated 00480 // class parameter, false otherwise. 00481 //////////////////////////////////////////////////////////////////// 00482 bool DCPackerInterface:: 00483 do_check_match_class_parameter(const DCClassParameter *) const { 00484 return false; 00485 } 00486 00487 //////////////////////////////////////////////////////////////////// 00488 // Function: DCPackerInterface::do_check_match_switch_parameter 00489 // Access: Protected, Virtual 00490 // Description: Returns true if this field matches the indicated 00491 // switch parameter, false otherwise. 00492 //////////////////////////////////////////////////////////////////// 00493 bool DCPackerInterface:: 00494 do_check_match_switch_parameter(const DCSwitchParameter *) const { 00495 return false; 00496 } 00497 00498 //////////////////////////////////////////////////////////////////// 00499 // Function: DCPackerInterface::do_check_match_array_parameter 00500 // Access: Protected, Virtual 00501 // Description: Returns true if this field matches the indicated 00502 // array parameter, false otherwise. 00503 //////////////////////////////////////////////////////////////////// 00504 bool DCPackerInterface:: 00505 do_check_match_array_parameter(const DCArrayParameter *) const { 00506 return false; 00507 } 00508 00509 //////////////////////////////////////////////////////////////////// 00510 // Function: DCPackerInterface::do_check_match_atomic_field 00511 // Access: Protected, Virtual 00512 // Description: Returns true if this field matches the indicated 00513 // atomic field, false otherwise. 00514 //////////////////////////////////////////////////////////////////// 00515 bool DCPackerInterface:: 00516 do_check_match_atomic_field(const DCAtomicField *) const { 00517 return false; 00518 } 00519 00520 //////////////////////////////////////////////////////////////////// 00521 // Function: DCPackerInterface::do_check_match_molecular_field 00522 // Access: Protected, Virtual 00523 // Description: Returns true if this field matches the indicated 00524 // molecular field, false otherwise. 00525 //////////////////////////////////////////////////////////////////// 00526 bool DCPackerInterface:: 00527 do_check_match_molecular_field(const DCMolecularField *) const { 00528 return false; 00529 } 00530 00531 //////////////////////////////////////////////////////////////////// 00532 // Function: DCPackerInterface::make_catalog 00533 // Access: Private 00534 // Description: Called internally to create a new DCPackerCatalog 00535 // object. 00536 //////////////////////////////////////////////////////////////////// 00537 void DCPackerInterface:: 00538 make_catalog() { 00539 nassertv(_catalog == (DCPackerCatalog *)NULL); 00540 _catalog = new DCPackerCatalog(this); 00541 00542 _catalog->r_fill_catalog("", this, NULL, 0); 00543 }