00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "xFileDataDef.h"
00016 #include "indent.h"
00017 #include "xLexerDefs.h"
00018 #include "xFileParseData.h"
00019 #include "xFileDataObjectInteger.h"
00020 #include "xFileDataObjectDouble.h"
00021 #include "xFileDataObjectString.h"
00022 #include "xFileDataNodeTemplate.h"
00023 #include "xFileDataObjectArray.h"
00024 #include "string_utils.h"
00025
00026 TypeHandle XFileDataDef::_type_handle;
00027
00028
00029
00030
00031
00032
00033 XFileDataDef::
00034 ~XFileDataDef() {
00035 clear();
00036 }
00037
00038
00039
00040
00041
00042
00043 void XFileDataDef::
00044 clear() {
00045 XFileNode::clear();
00046 _array_def.clear();
00047 }
00048
00049
00050
00051
00052
00053
00054
00055 void XFileDataDef::
00056 add_array_def(const XFileArrayDef &array_def) {
00057 _array_def.push_back(array_def);
00058 }
00059
00060
00061
00062
00063
00064
00065
00066 void XFileDataDef::
00067 write_text(ostream &out, int indent_level) const {
00068 indent(out, indent_level);
00069
00070 if (!_array_def.empty()) {
00071 out << "array ";
00072 }
00073
00074 switch (_type) {
00075 case T_word:
00076 out << "WORD";
00077 break;
00078
00079 case T_dword:
00080 out << "DWORD";
00081 break;
00082
00083 case T_float:
00084 out << "FLOAT";
00085 break;
00086
00087 case T_double:
00088 out << "DOUBLE";
00089 break;
00090
00091 case T_char:
00092 out << "CHAR";
00093 break;
00094
00095 case T_uchar:
00096 out << "UCHAR";
00097 break;
00098
00099 case T_sword:
00100 out << "SWORD";
00101 break;
00102
00103 case T_sdword:
00104 out << "SDWORD";
00105 break;
00106
00107 case T_string:
00108 out << "STRING";
00109 break;
00110
00111 case T_cstring:
00112 out << "CSTRING";
00113 break;
00114
00115 case T_unicode:
00116 out << "UNICODE";
00117 break;
00118
00119 case T_template:
00120 out << _template->get_name();
00121 break;
00122 }
00123
00124 if (has_name()) {
00125 out << " " << get_name();
00126 }
00127
00128 ArrayDef::const_iterator ai;
00129 for (ai = _array_def.begin(); ai != _array_def.end(); ++ai) {
00130 (*ai).output(out);
00131 }
00132
00133 out << ";\n";
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 bool XFileDataDef::
00150 repack_data(XFileDataObject *object,
00151 const XFileParseDataList &parse_data_list,
00152 XFileDataDef::PrevData &prev_data,
00153 size_t &index, size_t &sub_index) const {
00154
00155 PT(XFileDataObject) data_value;
00156
00157
00158 switch (_type) {
00159 case T_word:
00160 case T_dword:
00161 case T_char:
00162 case T_uchar:
00163 case T_sword:
00164 case T_sdword:
00165
00166 data_value = unpack_value(parse_data_list, 0,
00167 prev_data, index, sub_index,
00168 &XFileDataDef::unpack_integer_value);
00169 break;
00170
00171 case T_float:
00172 case T_double:
00173 data_value = unpack_value(parse_data_list, 0,
00174 prev_data, index, sub_index,
00175 &XFileDataDef::unpack_double_value);
00176 break;
00177
00178 case T_string:
00179 case T_cstring:
00180 case T_unicode:
00181 data_value = unpack_value(parse_data_list, 0,
00182 prev_data, index, sub_index,
00183 &XFileDataDef::unpack_string_value);
00184 break;
00185
00186 case T_template:
00187 data_value = unpack_value(parse_data_list, 0,
00188 prev_data, index, sub_index,
00189 &XFileDataDef::unpack_template_value);
00190 break;
00191 }
00192
00193 if (data_value != (XFileDataObject *)NULL) {
00194 object->add_element(data_value);
00195 prev_data[this] = data_value;
00196 }
00197
00198 return XFileNode::repack_data(object, parse_data_list,
00199 prev_data, index, sub_index);
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209 bool XFileDataDef::
00210 fill_zero_data(XFileDataObject *object) const {
00211 PT(XFileDataObject) data_value;
00212
00213
00214 switch (_type) {
00215 case T_word:
00216 case T_dword:
00217 case T_char:
00218 case T_uchar:
00219 case T_sword:
00220 case T_sdword:
00221 data_value = zero_fill_value(0, &XFileDataDef::zero_fill_integer_value);
00222 break;
00223
00224 case T_float:
00225 case T_double:
00226 data_value = zero_fill_value(0, &XFileDataDef::zero_fill_double_value);
00227 break;
00228
00229 case T_string:
00230 case T_cstring:
00231 case T_unicode:
00232 data_value = zero_fill_value(0, &XFileDataDef::zero_fill_string_value);
00233 break;
00234
00235 case T_template:
00236 data_value = zero_fill_value(0, &XFileDataDef::zero_fill_template_value);
00237 break;
00238 }
00239
00240 if (data_value != (XFileDataObject *)NULL) {
00241 object->add_element(data_value);
00242 }
00243
00244 return XFileNode::fill_zero_data(object);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 bool XFileDataDef::
00257 matches(const XFileNode *other) const {
00258 if (!XFileNode::matches(other)) {
00259 return false;
00260 }
00261
00262 const XFileDataDef *data_def = DCAST(XFileDataDef, other);
00263 if (data_def->get_data_type() != get_data_type()) {
00264 return false;
00265 }
00266
00267 if (get_data_type() == T_template &&
00268 !get_template()->matches(data_def->get_template())) {
00269 return false;
00270 }
00271
00272 if (data_def->get_num_array_defs() != get_num_array_defs()) {
00273 return false;
00274 }
00275
00276 for (int i = 0; i < get_num_array_defs(); i++) {
00277 if (!get_array_def(i).matches(data_def->get_array_def(i),
00278 this, data_def)) {
00279 return false;
00280 }
00281 }
00282
00283 return true;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293 PT(XFileDataObject) XFileDataDef::
00294 unpack_integer_value(const XFileParseDataList &parse_data_list,
00295 const XFileDataDef::PrevData &prev_data,
00296 size_t &index, size_t &sub_index) const {
00297 nassertr(index < parse_data_list._list.size(), NULL);
00298 const XFileParseData &parse_data = parse_data_list._list[index];
00299
00300 PT(XFileDataObject) data_value;
00301
00302 if ((parse_data._parse_flags & XFileParseData::PF_int) != 0) {
00303 nassertr(sub_index < parse_data._int_list.size(), NULL);
00304 int value = parse_data._int_list[sub_index];
00305 data_value = new XFileDataObjectInteger(this, value);
00306
00307 sub_index++;
00308 if (sub_index >= parse_data._int_list.size()) {
00309 index++;
00310 sub_index = 0;
00311 }
00312
00313 } else {
00314 parse_data.yyerror("Expected integer data for " + get_name());
00315 }
00316
00317 return data_value;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326 PT(XFileDataObject) XFileDataDef::
00327 unpack_double_value(const XFileParseDataList &parse_data_list,
00328 const XFileDataDef::PrevData &prev_data,
00329 size_t &index, size_t &sub_index) const {
00330 nassertr(index < parse_data_list._list.size(), NULL);
00331 const XFileParseData &parse_data = parse_data_list._list[index];
00332
00333 PT(XFileDataObject) data_value;
00334
00335 if ((parse_data._parse_flags & XFileParseData::PF_double) != 0) {
00336 nassertr(sub_index < parse_data._double_list.size(), NULL);
00337 double value = parse_data._double_list[sub_index];
00338 data_value = new XFileDataObjectDouble(this, value);
00339
00340 sub_index++;
00341 if (sub_index >= parse_data._double_list.size()) {
00342 index++;
00343 sub_index = 0;
00344 }
00345
00346 } else if ((parse_data._parse_flags & XFileParseData::PF_int) != 0) {
00347 nassertr(sub_index < parse_data._int_list.size(), NULL);
00348 int value = parse_data._int_list[sub_index];
00349 data_value = new XFileDataObjectDouble(this, value);
00350
00351 sub_index++;
00352 if (sub_index >= parse_data._int_list.size()) {
00353 index++;
00354 sub_index = 0;
00355 }
00356
00357 } else {
00358 parse_data.yyerror("Expected floating-point data for " + get_name());
00359 }
00360
00361 return data_value;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370 PT(XFileDataObject) XFileDataDef::
00371 unpack_string_value(const XFileParseDataList &parse_data_list,
00372 const XFileDataDef::PrevData &prev_data,
00373 size_t &index, size_t &sub_index) const {
00374 nassertr(index < parse_data_list._list.size(), NULL);
00375 const XFileParseData &parse_data = parse_data_list._list[index];
00376
00377 PT(XFileDataObject) data_value;
00378
00379 if ((parse_data._parse_flags & XFileParseData::PF_string) != 0) {
00380 data_value = new XFileDataObjectString(this, parse_data._string);
00381 index++;
00382 sub_index = 0;
00383
00384 } else {
00385 parse_data.yyerror("Expected string data for " + get_name());
00386 }
00387
00388 return data_value;
00389 }
00390
00391
00392
00393
00394
00395
00396 PT(XFileDataObject) XFileDataDef::
00397 unpack_template_value(const XFileParseDataList &parse_data_list,
00398 const XFileDataDef::PrevData &prev_data,
00399 size_t &index, size_t &sub_index) const {
00400 PT(XFileDataNodeTemplate) data_value =
00401 new XFileDataNodeTemplate(get_x_file(), get_name(), _template);
00402
00403 PrevData nested_prev_data(prev_data);
00404 if (!_template->repack_data(data_value, parse_data_list,
00405 nested_prev_data, index, sub_index)) {
00406 return NULL;
00407 }
00408
00409 return data_value.p();
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 PT(XFileDataObject) XFileDataDef::
00421 unpack_value(const XFileParseDataList &parse_data_list, int array_index,
00422 const XFileDataDef::PrevData &prev_data,
00423 size_t &index, size_t &sub_index,
00424 XFileDataDef::UnpackMethod unpack_method) const {
00425 PT(XFileDataObject) data_value;
00426
00427 if (array_index == (int)_array_def.size()) {
00428 if (index >= parse_data_list._list.size()) {
00429 xyyerror("Not enough data elements in structure at " + get_name());
00430 return NULL;
00431 }
00432 data_value = (this->*unpack_method)(parse_data_list, prev_data,
00433 index, sub_index);
00434
00435 } else {
00436 data_value = new XFileDataObjectArray(this);
00437 int array_size = _array_def[array_index].get_size(prev_data);
00438
00439 for (int i = 0; i < array_size; i++) {
00440 if (index >= parse_data_list._list.size()) {
00441 xyyerror(string("Expected ") + format_string(array_size)
00442 + " array elements, found " + format_string(i));
00443 return data_value;
00444 }
00445
00446 PT(XFileDataObject) array_element =
00447 unpack_value(parse_data_list, array_index + 1,
00448 prev_data, index, sub_index,
00449 unpack_method);
00450 if (array_element == (XFileDataObject *)NULL) {
00451 return data_value;
00452 }
00453 data_value->add_element(array_element);
00454 }
00455 }
00456
00457 return data_value;
00458 }
00459
00460
00461
00462
00463
00464
00465 PT(XFileDataObject) XFileDataDef::
00466 zero_fill_integer_value() const {
00467 return new XFileDataObjectInteger(this, 0);
00468 }
00469
00470
00471
00472
00473
00474
00475 PT(XFileDataObject) XFileDataDef::
00476 zero_fill_double_value() const {
00477 return new XFileDataObjectDouble(this, 0.0);
00478 }
00479
00480
00481
00482
00483
00484
00485 PT(XFileDataObject) XFileDataDef::
00486 zero_fill_string_value() const {
00487 return new XFileDataObjectString(this, "");
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 PT(XFileDataObject) XFileDataDef::
00497 zero_fill_template_value() const {
00498 PT(XFileDataObject) data_value =
00499 new XFileDataNodeTemplate(get_x_file(), get_name(), _template);
00500 if (!_template->fill_zero_data(data_value)) {
00501 return NULL;
00502 }
00503
00504 return data_value;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 PT(XFileDataObject) XFileDataDef::
00516 zero_fill_value(int array_index,
00517 XFileDataDef::ZeroFillMethod zero_fill_method) const {
00518 PT(XFileDataObject) data_value;
00519
00520 if (array_index == (int)_array_def.size()) {
00521 data_value = (this->*zero_fill_method)();
00522
00523 } else {
00524 data_value = new XFileDataObjectArray(this);
00525 int array_size = 0;
00526 if (_array_def[array_index].is_fixed_size()) {
00527 array_size = _array_def[array_index].get_fixed_size();
00528 }
00529
00530 for (int i = 0; i < array_size; i++) {
00531 PT(XFileDataObject) array_element =
00532 zero_fill_value(array_index + 1, zero_fill_method);
00533 if (array_element == (XFileDataObject *)NULL) {
00534 return NULL;
00535 }
00536 data_value->add_element(array_element);
00537 }
00538 }
00539
00540 return data_value;
00541 }