00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00047
00048
00049
00050 DCAtomicField::ElementType::
00051 ElementType() {
00052 _type = ST_invalid;
00053 _divisor = 1;
00054 _has_default_value = false;
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 bool DCAtomicField::ElementType::
00067 set_default_value(double num) {
00068 switch (_type) {
00069
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
00095
00096
00097
00098
00099
00100
00101
00102 bool DCAtomicField::ElementType::
00103 set_default_value(const string &str) {
00104 if (_type != ST_string && _type != ST_blob) {
00105
00106 return false;
00107 }
00108
00109 _default_value = str;
00110 _has_default_value = true;
00111 return true;
00112 }
00113
00114
00115
00116
00117
00118
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
00129
00130
00131
00132
00133
00134
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
00149
00150
00151
00152
00153
00154
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
00169
00170
00171
00172
00173
00174
00175
00176 bool DCAtomicField::ElementType::
00177 add_default_value_literal(const string &str) {
00178 if (_type != ST_blob) {
00179
00180 return false;
00181 }
00182
00183 _default_value += str;
00184 return true;
00185 }
00186
00187
00188
00189
00190
00191
00192
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
00205 return true;
00206
00207 case ST_uint32uint8array:
00208 {
00209
00210
00211 string new_value;
00212 size_t p = 0;
00213 while (p < _default_value.size()) {
00214
00215
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
00234
00235
00236
00237
00238
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
00277
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
00288
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
00299 formatted = string((char *)&real_value, 8);
00300 #ifdef WORDS_BIGENDIAN
00301 {
00302
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
00317
00318 return false;
00319
00320 case ST_invalid:
00321 break;
00322 }
00323
00324 return true;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
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
00351 return false;
00352 }
00353
00354 return true;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364 DCAtomicField *DCAtomicField::
00365 as_atomic_field() {
00366 return this;
00367 }
00368
00369
00370
00371
00372
00373
00374 int DCAtomicField::
00375 get_num_elements() const {
00376 return _elements.size();
00377 }
00378
00379
00380
00381
00382
00383
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
00393
00394
00395
00396
00397
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
00407
00408
00409
00410
00411
00412
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
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
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
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
00469
00470
00471
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
00481
00482
00483
00484
00485 bool DCAtomicField::
00486 is_required() const {
00487 return (_flags & F_required) != 0;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 bool DCAtomicField::
00497 is_broadcast() const {
00498 return (_flags & F_broadcast) != 0;
00499 }
00500
00501
00502
00503
00504
00505
00506
00507 bool DCAtomicField::
00508 is_p2p() const {
00509 return (_flags & F_p2p) != 0;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518 bool DCAtomicField::
00519 is_ram() const {
00520 return (_flags & F_ram) != 0;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529 bool DCAtomicField::
00530 is_db() const {
00531 return (_flags & F_db) != 0;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 bool DCAtomicField::
00541 is_clsend() const {
00542 return (_flags & F_clsend) != 0;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551 bool DCAtomicField::
00552 is_clrecv() const {
00553 return (_flags & F_clrecv) != 0;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562 bool DCAtomicField::
00563 is_ownsend() const {
00564 return (_flags & F_ownsend) != 0;
00565 }
00566
00567
00568
00569
00570
00571
00572 DCAtomicField::
00573 DCAtomicField() {
00574 _number = 0;
00575 _flags = 0;
00576 }
00577
00578
00579
00580
00581
00582
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
00630
00631
00632
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 }