Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

direct/src/dcparser/dcAtomicField.cxx

Go to the documentation of this file.
00001 // Filename: dcAtomicField.cxx
00002 // Created by:  drose (05Oct00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "dcAtomicField.h"
00020 #include "hashGenerator.h"
00021 #include "dcindent.h"
00022 
00023 #include <math.h>
00024 
00025 ostream &
00026 operator << (ostream &out, const DCAtomicField::ElementType &et) {
00027   out << et._type;
00028   if (et._divisor != 1) {
00029     out << " / " << et._divisor;
00030   }
00031   if (!et._name.empty()) {
00032     out << " " << et._name;
00033   }
00034   if (et._has_default_value) {
00035     out << " = <" << hex;
00036     string::const_iterator si;
00037     for (si = et._default_value.begin(); si != et._default_value.end(); ++si) {
00038       out << setw(2) << setfill('0') << (int)(unsigned char)(*si);
00039     }
00040     out << dec << ">";
00041   }
00042   return out;
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: DCAtomicField::ElementType::Constructor
00047 //       Access: Public
00048 //  Description:
00049 ////////////////////////////////////////////////////////////////////
00050 DCAtomicField::ElementType::
00051 ElementType() {
00052   _type = ST_invalid;
00053   _divisor = 1;
00054   _has_default_value = false;
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: DCAtomicField::ElementType::set_default_value
00059 //       Access: Public
00060 //  Description: Stores the indicated value as the default value for
00061 //               this element.
00062 //
00063 //               Returns true if the element type reasonably accepts a
00064 //               default value of numeric type, false otherwise.
00065 ////////////////////////////////////////////////////////////////////
00066 bool DCAtomicField::ElementType::
00067 set_default_value(double num) {
00068   switch (_type) {
00069     // Only fields of these types accept numbers.
00070   case ST_int8:
00071   case ST_int16:
00072   case ST_int32:
00073   case ST_uint8:
00074   case ST_uint16:
00075   case ST_uint32:
00076   case ST_float64:
00077     break;
00078 
00079   default:
00080     return false;
00081   }
00082 
00083   string formatted;
00084   if (!format_default_value(num, formatted)) {
00085     return false;
00086   }
00087 
00088   _default_value = formatted;
00089   _has_default_value = true;
00090   return true;
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: DCAtomicField::ElementType::set_default_value
00095 //       Access: Public
00096 //  Description: Stores the indicated value as the default value for
00097 //               this element.
00098 //
00099 //               Returns true if the element type reasonably accepts a
00100 //               default value of string type, false otherwise.
00101 ////////////////////////////////////////////////////////////////////
00102 bool DCAtomicField::ElementType::
00103 set_default_value(const string &str) {
00104   if (_type != ST_string && _type != ST_blob) {
00105     // Only fields of type string or blob accept quoted strings.
00106     return false;
00107   }
00108 
00109   _default_value = str;
00110   _has_default_value = true;
00111   return true;
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: DCAtomicField::ElementType::set_default_value_literal
00116 //       Access: Public
00117 //  Description: Explicitly sets the default value to the given
00118 //               pre-formatted string.
00119 ////////////////////////////////////////////////////////////////////
00120 bool DCAtomicField::ElementType::
00121 set_default_value_literal(const string &str) {
00122   _default_value = str;
00123   _has_default_value = true;
00124   return true;
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: DCAtomicField::ElementType::add_default_value
00129 //       Access: Public
00130 //  Description: Appends the indicated value as the next array element
00131 //               value for the default value for this type.
00132 //
00133 //               Returns true if the element type reasonably accepts a
00134 //               default value of numeric type, false otherwise.
00135 ////////////////////////////////////////////////////////////////////
00136 bool DCAtomicField::ElementType::
00137 add_default_value(double num) {
00138   string formatted;
00139   if (!format_default_value(num, formatted)) {
00140     return false;
00141   }
00142 
00143   _default_value += formatted;
00144   return true;
00145 }
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 //     Function: DCAtomicField::ElementType::add_default_value
00149 //       Access: Public
00150 //  Description: Appends the indicated value as the next array element
00151 //               value for the default value for this type.
00152 //
00153 //               Returns true if the element type reasonably accepts a
00154 //               default value of numeric type, false otherwise.
00155 ////////////////////////////////////////////////////////////////////
00156 bool DCAtomicField::ElementType::
00157 add_default_value(const string &str) {
00158   string formatted;
00159   if (!format_default_value(str, formatted)) {
00160     return false;
00161   }
00162 
00163   _default_value += formatted;
00164   return true;
00165 }
00166 
00167 ////////////////////////////////////////////////////////////////////
00168 //     Function: DCAtomicField::ElementType::add_default_value_literal
00169 //       Access: Public
00170 //  Description: Appends the indicated value as the next array element
00171 //               value for the default value for this type.
00172 //
00173 //               Returns true if the element type reasonably accepts a
00174 //               default value of numeric type, false otherwise.
00175 ////////////////////////////////////////////////////////////////////
00176 bool DCAtomicField::ElementType::
00177 add_default_value_literal(const string &str) {
00178   if (_type != ST_blob) {
00179     // Only blobs can have literal hex strings nested within arrays.
00180     return false;
00181   }
00182 
00183   _default_value += str;
00184   return true;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: DCAtomicField::ElementType::end_array
00189 //       Access: Public
00190 //  Description: Called by the parser after a number of calls to
00191 //               add_default_value(), to indicate the array has been
00192 //               completed.
00193 ////////////////////////////////////////////////////////////////////
00194 bool DCAtomicField::ElementType::
00195 end_array() {
00196   switch (_type) {
00197   case ST_int8array:
00198   case ST_int16array:
00199   case ST_int32array:
00200   case ST_uint8array:
00201   case ST_uint16array:
00202   case ST_uint32array:
00203   case ST_blob:
00204     // These types accept arrays.
00205     return true;
00206 
00207   case ST_uint32uint8array:
00208     {
00209       // In this special case type, we collapse every other 32-bit
00210       // value down to an 8-bit value after formatting.
00211       string new_value;
00212       size_t p = 0;
00213       while (p < _default_value.size()) {
00214         // We should have at least 8 bytes for each two elements.  If
00215         // we don't, maybe the user gave us an odd number of elements.
00216         if (p + 8 > _default_value.size()) {
00217           return false;
00218         }
00219         new_value += _default_value.substr(p, 5);
00220         p += 8;
00221       }
00222 
00223       _default_value = new_value;
00224       return true;
00225     }
00226 
00227   default:
00228     return false;
00229   }
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: DCAtomicField::ElementType::format_default_value
00234 //       Access: Private
00235 //  Description: Formats the indicated default value to a sequence of
00236 //               bytes, according to the element type.  Returns true
00237 //               if the element type reasonably accepts a number,
00238 //               false otherwise.
00239 ////////////////////////////////////////////////////////////////////
00240 bool DCAtomicField::ElementType::
00241 format_default_value(double num, string &formatted) const {
00242   double real_value = num * _divisor;
00243   int int_value = (int)cfloor(real_value + 0.5);
00244 
00245   switch (_type) {
00246   case ST_int8:
00247   case ST_uint8:
00248   case ST_int8array:
00249   case ST_uint8array:
00250   case ST_blob:
00251     formatted = string(1, (char)(int_value & 0xff));
00252     break;
00253 
00254   case ST_int16:
00255   case ST_uint16:
00256   case ST_int16array:
00257   case ST_uint16array:
00258     formatted =
00259       string(1, (char)(int_value & 0xff)) +
00260       string(1, (char)((int_value >> 8) & 0xff));
00261     break;
00262 
00263   case ST_int32:
00264   case ST_uint32:
00265   case ST_int32array:
00266   case ST_uint32array:
00267   case ST_uint32uint8array:
00268     formatted =
00269       string(1, (char)(int_value & 0xff)) +
00270       string(1, (char)((int_value >> 8) & 0xff)) +
00271       string(1, (char)((int_value >> 16) & 0xff)) +
00272       string(1, (char)((int_value >> 24) & 0xff));
00273     break;
00274 
00275   case ST_int64:
00276     // We don't fully support default values for int64.  The
00277     // high-order 32 bits cannot be specified.
00278     formatted =
00279       string(1, (char)(int_value & 0xff)) +
00280       string(1, (char)((int_value >> 8) & 0xff)) +
00281       string(1, (char)((int_value >> 16) & 0xff)) +
00282       string(1, (char)((int_value >> 24) & 0xff)) +
00283       ((int_value & 0x80000000) != 0 ? string(4, '\xff') : string(4, '\0'));
00284     break;
00285 
00286   case ST_uint64:
00287     // We don't fully support default values for int64.  The
00288     // high-order 32 bits cannot be specified.
00289     formatted =
00290       string(1, (char)(int_value & 0xff)) +
00291       string(1, (char)((int_value >> 8) & 0xff)) +
00292       string(1, (char)((int_value >> 16) & 0xff)) +
00293       string(1, (char)((int_value >> 24) & 0xff)) +
00294       string(4, '\0');
00295     break;
00296 
00297   case ST_float64:
00298     // This may not be fully portable.
00299     formatted = string((char *)&real_value, 8);
00300 #ifdef WORDS_BIGENDIAN
00301     {
00302       // Reverse the byte ordering for big-endian machines.
00303       string str;
00304       str.reserve(8);
00305 
00306       int length = str.length();
00307       for (size_t i = 0; i < 8; i++) {
00308         str += formatted[length - 1 - i];
00309       }
00310       formatted = str;
00311     }
00312 #endif
00313     break;
00314 
00315   case ST_string:
00316     // It doesn't make sense to assign a numeric default value to a
00317     // string.
00318     return false;
00319 
00320   case ST_invalid:
00321     break;
00322   }
00323 
00324   return true;
00325 }
00326 
00327 ////////////////////////////////////////////////////////////////////
00328 //     Function: DCAtomicField::ElementType::format_default_value
00329 //       Access: Private
00330 //  Description: Formats the indicated default value to a sequence of
00331 //               bytes, according to the element type.  Returns true
00332 //               if the element type reasonably accepts a string,
00333 //               false otherwise.
00334 ////////////////////////////////////////////////////////////////////
00335 bool DCAtomicField::ElementType::
00336 format_default_value(const string &str, string &formatted) const {
00337   switch (_type) {
00338   case ST_string:
00339   case ST_blob:
00340     {
00341       int length = str.length();
00342       formatted =
00343         string(1, (char)(length & 0xff)) +
00344         string(1, (char)((length >> 8) & 0xff)) +
00345         str;
00346     }
00347     break;
00348 
00349   default:
00350     // It doesn't make sense to assign a string default to a number.
00351     return false;
00352   }
00353 
00354   return true;
00355 }
00356 
00357 ////////////////////////////////////////////////////////////////////
00358 //     Function: DCAtomicField::as_atomic_field
00359 //       Access: Public, Virtual
00360 //  Description: Returns the same field pointer converted to an atomic
00361 //               field pointer, if this is in fact an atomic field;
00362 //               otherwise, returns NULL.
00363 ////////////////////////////////////////////////////////////////////
00364 DCAtomicField *DCAtomicField::
00365 as_atomic_field() {
00366   return this;
00367 }
00368 
00369 ////////////////////////////////////////////////////////////////////
00370 //     Function: DCAtomicField::get_num_elements
00371 //       Access: Public
00372 //  Description: Returns the number of elements of the atomic field.
00373 ////////////////////////////////////////////////////////////////////
00374 int DCAtomicField::
00375 get_num_elements() const {
00376   return _elements.size();
00377 }
00378 
00379 ////////////////////////////////////////////////////////////////////
00380 //     Function: DCAtomicField::get_element_type
00381 //       Access: Public
00382 //  Description: Returns the numeric type of the nth element of the
00383 //               field.
00384 ////////////////////////////////////////////////////////////////////
00385 DCSubatomicType DCAtomicField::
00386 get_element_type(int n) const {
00387   nassertr(n >= 0 && n < (int)_elements.size(), ST_invalid);
00388   return _elements[n]._type;
00389 }
00390 
00391 ////////////////////////////////////////////////////////////////////
00392 //     Function: DCAtomicField::get_element_name
00393 //       Access: Public
00394 //  Description: Returns the name of the nth element of the field.
00395 //               This name is strictly for documentary purposes; it
00396 //               does not generally affect operation.  If a name is
00397 //               not specified, this will be the empty string.
00398 ////////////////////////////////////////////////////////////////////
00399 string DCAtomicField::
00400 get_element_name(int n) const {
00401   nassertr(n >= 0 && n < (int)_elements.size(), string());
00402   return _elements[n]._name;
00403 }
00404 
00405 ////////////////////////////////////////////////////////////////////
00406 //     Function: DCAtomicField::get_element_divisor
00407 //       Access: Public
00408 //  Description: Returns the divisor associated with the nth element
00409 //               of the field.  This implements an implicit
00410 //               fixed-point system; floating-point values are to be
00411 //               multiplied by this value before encoding into a
00412 //               packet, and divided by this number after decoding.
00413 ////////////////////////////////////////////////////////////////////
00414 int DCAtomicField::
00415 get_element_divisor(int n) const {
00416   nassertr(n >= 0 && n < (int)_elements.size(), 1);
00417   return _elements[n]._divisor;
00418 }
00419 
00420 ////////////////////////////////////////////////////////////////////
00421 //     Function: DCAtomicField::get_element_default
00422 //       Access: Public
00423 //  Description: Returns the pre-formatted default value associated
00424 //               with the nth element of the field.  This is only
00425 //               valid if has_element_default() returns true, in which
00426 //               case this string represents the bytes that should be
00427 //               assigned to the field as a default value.
00428 //
00429 //               If the element is an array-type element, the returned
00430 //               value will include the two-byte length preceding the
00431 //               array data.
00432 ////////////////////////////////////////////////////////////////////
00433 string DCAtomicField::
00434 get_element_default(int n) const {
00435   nassertr(has_element_default(n), string());
00436   nassertr(n >= 0 && n < (int)_elements.size(), string());
00437 
00438   string default_value = _elements[n]._default_value;
00439 
00440   switch (_elements[n]._type) {
00441   case ST_int8array:
00442   case ST_int16array:
00443   case ST_int32array:
00444   case ST_uint8array:
00445   case ST_uint16array:
00446   case ST_uint32array:
00447   case ST_uint32uint8array:
00448   case ST_blob:
00449   case ST_string:
00450     // These array types also want an implicit length.
00451     {
00452       int length = default_value.length();
00453       default_value =
00454         string(1, (char)(length & 0xff)) +
00455         string(1, (char)((length >> 8) & 0xff)) +
00456         default_value;
00457     }
00458     break;
00459 
00460   default:
00461     break;
00462   }
00463 
00464   return default_value;
00465 }
00466 
00467 ////////////////////////////////////////////////////////////////////
00468 //     Function: DCAtomicField::has_element_default
00469 //       Access: Public
00470 //  Description: Returns true if the nth element of the field has a
00471 //               default value specified, false otherwise.
00472 ////////////////////////////////////////////////////////////////////
00473 bool DCAtomicField::
00474 has_element_default(int n) const {
00475   nassertr(n >= 0 && n < (int)_elements.size(), false);
00476   return _elements[n]._has_default_value;
00477 }
00478 
00479 ////////////////////////////////////////////////////////////////////
00480 //     Function: DCAtomicField::is_required
00481 //       Access: Public
00482 //  Description: Returns true if the "required" flag is set for this
00483 //               field, false otherwise.
00484 ////////////////////////////////////////////////////////////////////
00485 bool DCAtomicField::
00486 is_required() const {
00487   return (_flags & F_required) != 0;
00488 }
00489 
00490 ////////////////////////////////////////////////////////////////////
00491 //     Function: DCAtomicField::is_broadcast
00492 //       Access: Public
00493 //  Description: Returns true if the "broadcast" flag is set for this
00494 //               field, false otherwise.
00495 ////////////////////////////////////////////////////////////////////
00496 bool DCAtomicField::
00497 is_broadcast() const {
00498   return (_flags & F_broadcast) != 0;
00499 }
00500 
00501 ////////////////////////////////////////////////////////////////////
00502 //     Function: DCAtomicField::is_p2p
00503 //       Access: Public
00504 //  Description: Returns true if the "p2p" flag is set for this
00505 //               field, false otherwise.
00506 ////////////////////////////////////////////////////////////////////
00507 bool DCAtomicField::
00508 is_p2p() const {
00509   return (_flags & F_p2p) != 0;
00510 }
00511 
00512 ////////////////////////////////////////////////////////////////////
00513 //     Function: DCAtomicField::is_ram
00514 //       Access: Public
00515 //  Description: Returns true if the "ram" flag is set for this
00516 //               field, false otherwise.
00517 ////////////////////////////////////////////////////////////////////
00518 bool DCAtomicField::
00519 is_ram() const {
00520   return (_flags & F_ram) != 0;
00521 }
00522 
00523 ////////////////////////////////////////////////////////////////////
00524 //     Function: DCAtomicField::is_db
00525 //       Access: Public
00526 //  Description: Returns true if the "db" flag is set for this
00527 //               field, false otherwise.
00528 ////////////////////////////////////////////////////////////////////
00529 bool DCAtomicField::
00530 is_db() const {
00531   return (_flags & F_db) != 0;
00532 }
00533 
00534 ////////////////////////////////////////////////////////////////////
00535 //     Function: DCAtomicField::is_clsend
00536 //       Access: Public
00537 //  Description: Returns true if the "clsend" flag is set for this
00538 //               field, false otherwise.
00539 ////////////////////////////////////////////////////////////////////
00540 bool DCAtomicField::
00541 is_clsend() const {
00542   return (_flags & F_clsend) != 0;
00543 }
00544 
00545 ////////////////////////////////////////////////////////////////////
00546 //     Function: DCAtomicField::is_clrecv
00547 //       Access: Public
00548 //  Description: Returns true if the "clrecv" flag is set for this
00549 //               field, false otherwise.
00550 ////////////////////////////////////////////////////////////////////
00551 bool DCAtomicField::
00552 is_clrecv() const {
00553   return (_flags & F_clrecv) != 0;
00554 }
00555 
00556 ////////////////////////////////////////////////////////////////////
00557 //     Function: DCAtomicField::is_ownsend
00558 //       Access: Public
00559 //  Description: Returns true if the "ownsend" flag is set for this
00560 //               field, false otherwise.
00561 ////////////////////////////////////////////////////////////////////
00562 bool DCAtomicField::
00563 is_ownsend() const {
00564   return (_flags & F_ownsend) != 0;
00565 }
00566 
00567 ////////////////////////////////////////////////////////////////////
00568 //     Function: DCAtomicField::Constructor
00569 //       Access: Public
00570 //  Description:
00571 ////////////////////////////////////////////////////////////////////
00572 DCAtomicField::
00573 DCAtomicField() {
00574   _number = 0;
00575   _flags = 0;
00576 }
00577 
00578 ////////////////////////////////////////////////////////////////////
00579 //     Function: DCAtomicField::write
00580 //       Access: Public, Virtual
00581 //  Description: Generates a parseable description of the object to
00582 //               the indicated output stream.
00583 ////////////////////////////////////////////////////////////////////
00584 void DCAtomicField::
00585 write(ostream &out, int indent_level) const {
00586   indent(out, indent_level)
00587     << _name << "(";
00588 
00589   if (!_elements.empty()) {
00590     Elements::const_iterator ei = _elements.begin();
00591     out << (*ei);
00592     ++ei;
00593     while (ei != _elements.end()) {
00594       out << ", " << (*ei);
00595       ++ei;
00596     }
00597   }
00598   out << ")";
00599 
00600   if ((_flags & F_required) != 0) {
00601     out << " required";
00602   }
00603   if ((_flags & F_broadcast) != 0) {
00604     out << " broadcast";
00605   }
00606   if ((_flags & F_p2p) != 0) {
00607     out << " p2p";
00608   }
00609   if ((_flags & F_ram) != 0) {
00610     out << " ram";
00611   }
00612   if ((_flags & F_db) != 0) {
00613     out << " db";
00614   }
00615   if ((_flags & F_clsend) != 0) {
00616     out << " clsend";
00617   }
00618   if ((_flags & F_clrecv) != 0) {
00619     out << " clrecv";
00620   }
00621   if ((_flags & F_ownsend) != 0) {
00622     out << " ownsend";
00623   }
00624 
00625   out << ";  // field " << _number << "\n";
00626 }
00627 
00628 ////////////////////////////////////////////////////////////////////
00629 //     Function: DCAtomicField::generate_hash
00630 //       Access: Public, Virtual
00631 //  Description: Accumulates the properties of this field into the
00632 //               hash.
00633 ////////////////////////////////////////////////////////////////////
00634 void DCAtomicField::
00635 generate_hash(HashGenerator &hashgen) const {
00636   DCField::generate_hash(hashgen);
00637 
00638   hashgen.add_int(_elements.size());
00639   Elements::const_iterator ei;
00640   for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
00641     const ElementType &element = (*ei);
00642     hashgen.add_int(element._type);
00643     hashgen.add_int(element._divisor);
00644   }
00645   hashgen.add_int(_flags);
00646 }

Generated on Fri May 2 01:36:57 2003 for Direct by doxygen1.3