solparser.c (34899B)
1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com) 2 * Copyright (C) 2016-2018 CNRS 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #define _POSIX_C_SOURCE 200112L /* nextafter support */ 18 19 #include "solparser_c.h" 20 21 #include <rsys/cstr.h> 22 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <yaml.h> 27 28 /******************************************************************************* 29 * Helper functions 30 ******************************************************************************/ 31 static res_T 32 flush_deferred_target_aliases 33 (struct solparser* parser, 34 const yaml_node_t* node, 35 const struct solparser_entity_id entity_id) 36 { 37 const struct solparser_entity* entity; 38 struct darray_char alias; 39 size_t i, n; 40 size_t prefix_len; 41 res_T res = RES_OK; 42 ASSERT(parser); 43 44 darray_char_init(parser->allocator, &alias); 45 46 if(!darray_tgtalias_size_get(&parser->tgtaliases)) 47 goto exit; /* No deferred target alias */ 48 49 /* Retrieve the entity referenced by the 'self' keyword */ 50 entity = solparser_get_entity(parser, entity_id); 51 52 /* Copy the entity name */ 53 prefix_len = strlen(str_cget(&entity->name)); 54 res = darray_char_resize(&alias, prefix_len); 55 if(res != RES_OK) { 56 log_err(parser, node, 57 "could not reserve the prefix of the targeted alias name.\n"); 58 goto error; 59 } 60 strncpy(darray_char_data_get(&alias), str_cget(&entity->name), prefix_len); 61 62 n = darray_tgtalias_size_get(&parser->tgtaliases); 63 FOR_EACH(i, 0, n) { 64 const struct solparser_anchor* anchor; 65 struct solparser_x_pivot* x_pivot; 66 const struct target_alias* tgt; 67 size_t ianchor; 68 size_t len; 69 70 tgt = darray_tgtalias_cdata_get(&parser->tgtaliases) + i; 71 ASSERT(!strncmp((char*)tgt->alias->data.scalar.value, "self.", 5)); 72 73 /* Copy the anchor alias */ 74 len = strlen((char*)tgt->alias->data.scalar.value) 75 - 4/*strlen(self)*/ + 1/*NULL char*/; 76 res = darray_char_resize(&alias, prefix_len + len); 77 if(res != RES_OK) { 78 log_err(parser, node, 79 "could not reserve the suffix of the targeted alias name.\n"); 80 goto error; 81 } 82 strcpy(darray_char_data_get(&alias) + prefix_len, 83 (char*)tgt->alias->data.scalar.value+4); 84 85 /* Retrieve the anchor */ 86 anchor = solparser_find_anchor(parser, darray_char_cdata_get(&alias)); 87 if(!anchor) { 88 log_err(parser, tgt->alias, "undefined anchor `%s'.\n", 89 tgt->alias->data.scalar.value); 90 res = RES_BAD_ARG; 91 goto error; 92 } 93 94 /* Define the targeted anchor of the pivot */ 95 x_pivot = darray_x_pivot_data_get(&parser->x_pivots) + tgt->pivot.i; 96 ASSERT(x_pivot->target.type == SOLPARSER_TARGET_ANCHOR); 97 ianchor = (size_t)(anchor - darray_anchor_cdata_get(&parser->anchors)); 98 ASSERT(ianchor < darray_anchor_size_get(&parser->anchors)); 99 x_pivot->target.data.anchor.i = ianchor; 100 } 101 102 darray_tgtalias_clear(&parser->tgtaliases); 103 104 exit: 105 darray_char_release(&alias); 106 return res; 107 error: 108 goto exit; 109 } 110 111 static res_T 112 parse_item 113 (struct solparser* parser, 114 yaml_document_t* doc, 115 const yaml_node_t* item) 116 { 117 /* Temporary dummy variables */ 118 struct solparser_entity_id entity; 119 struct solparser_geometry_id geometry; 120 struct solparser_material_double_sided_id mtl2; 121 struct solparser_medium_id medium; 122 struct solparser_sun* sun; 123 struct solparser_atmosphere* atmosphere; 124 125 yaml_node_t* key; 126 yaml_node_t* val; 127 intptr_t n; 128 res_T res = RES_OK; 129 ASSERT(doc && item); 130 131 if(item->type != YAML_MAPPING_NODE) { 132 log_err(parser, item, "expect an item definition.\n"); 133 res = RES_BAD_ARG; 134 goto error; 135 } 136 137 n = item->data.mapping.pairs.top - item->data.mapping.pairs.start; 138 if(n != 1) { 139 log_err(parser, item, 140 "expect only one \"key:value\" pair while %li are provided.\n", n); 141 res = RES_BAD_ARG; 142 goto error; 143 } 144 145 key = yaml_document_get_node(doc, item->data.mapping.pairs.start[0].key); 146 val = yaml_document_get_node(doc, item->data.mapping.pairs.start[0].value); 147 if(key->type != YAML_SCALAR_NODE) { 148 log_err(parser, key, "expecting an item name.\n"); 149 res = RES_BAD_ARG; 150 goto error; 151 } 152 153 /* The parsing of the templates/spectra is deferred to their explicit use */ 154 if(!strcmp((char*)key->data.scalar.value, "material")) { 155 res = parse_material(parser, doc, val, &mtl2); 156 } else if(!strcmp((char*)key->data.scalar.value, "medium")) { 157 res = parse_medium(parser, doc, val, &medium); 158 } else if(!strcmp((char*)key->data.scalar.value, "entity")) { 159 res = parse_entity(parser, doc, val, &parser->str2entities, &entity); 160 if(res == RES_OK) { 161 res = flush_deferred_target_aliases(parser, item, entity); 162 } 163 } else if(!strcmp((char*)key->data.scalar.value, "template")) { /* Deferred */ 164 } else if(!strcmp((char*)key->data.scalar.value, "geometry")) { 165 res = parse_geometry(parser, doc, val, &geometry); 166 } else if(!strcmp((char*)key->data.scalar.value, "sun")) { 167 res = parse_sun(parser, doc, val, &sun); 168 } else if (!strcmp((char*)key->data.scalar.value, "atmosphere")) { 169 res = parse_atmosphere(parser, doc, val, &atmosphere); 170 } else if(!strcmp((char*)key->data.scalar.value, "spectrum")) { /* Deferred */ 171 } else { 172 log_err(parser, key, "unknown item `%s'.\n", key->data.scalar.value); 173 res = RES_BAD_ARG; 174 goto error; 175 } 176 if(res != RES_OK) { 177 log_node(parser, key); 178 goto error; 179 } 180 181 exit: 182 return res; 183 error: 184 goto exit; 185 } 186 187 /* Clean up loaded data */ 188 static INLINE void 189 parser_clear(struct solparser* parser) 190 { 191 ASSERT(parser); 192 193 /* Materials */ 194 htable_yaml2sols_clear(&parser->yaml2mtls); 195 darray_image_clear(&parser->images); 196 darray_material_clear(&parser->mtls); 197 darray_material2_clear(&parser->mtls2); 198 darray_dielectric_clear(&parser->dielectrics); 199 darray_matte_clear(&parser->mattes); 200 darray_mirror_clear(&parser->mirrors); 201 darray_thin_dielectric_clear(&parser->thin_dielectrics); 202 203 /* Mediums */ 204 htable_yaml2sols_clear(&parser->yaml2mediums); 205 darray_medium_clear(&parser->mediums); 206 207 /* Deferred targeted anchors */ 208 darray_tgtalias_clear(&parser->tgtaliases); 209 210 /* Shapes */ 211 darray_shape_clear(&parser->shapes); 212 darray_cuboid_clear(&parser->cuboids); 213 darray_cylinder_clear(&parser->cylinders); 214 darray_impgeom_clear(&parser->objs); 215 darray_paraboloid_clear(&parser->parabols); 216 darray_paraboloid_clear(&parser->parabolic_cylinders); 217 darray_hyperboloid_clear(&parser->hyperbols); 218 darray_hemisphere_clear(&parser->hemispheres); 219 darray_plane_clear(&parser->planes); 220 darray_sphere_clear(&parser->spheres); 221 darray_impgeom_clear(&parser->stls); 222 223 /* Geometries */ 224 htable_yaml2sols_clear(&parser->yaml2geoms); 225 darray_object_clear(&parser->objects); 226 darray_geometry_clear(&parser->geometries); 227 228 /* Sun */ 229 solparser_sun_clear(&parser->sun); 230 parser->sun_key = 0; 231 232 /* Atmosphere */ 233 solparser_atmosphere_clear(&parser->atmosphere); 234 parser->atmosphere_key = 0; 235 236 /* Entities */ 237 htable_str2sols_clear(&parser->str2entities); 238 darray_entity_clear(&parser->entities); 239 240 /* Miscellaneous */ 241 darray_anchor_clear(&parser->anchors); 242 darray_x_pivot_clear(&parser->x_pivots); 243 darray_zx_pivot_clear(&parser->zx_pivots); 244 darray_spectrum_clear(&parser->spectra); 245 } 246 247 static void 248 parser_release(ref_T* ref) 249 { 250 struct solparser* parser; 251 ASSERT(ref); 252 253 parser = CONTAINER_OF(ref, struct solparser, ref); 254 if(parser->parser_is_init) yaml_parser_delete(&parser->parser); 255 str_release(&parser->stream_name); 256 257 /* Materials */ 258 htable_yaml2sols_release(&parser->yaml2mtls); 259 darray_image_release(&parser->images); 260 darray_material_release(&parser->mtls); 261 darray_material2_release(&parser->mtls2); 262 darray_dielectric_release(&parser->dielectrics); 263 darray_matte_release(&parser->mattes); 264 darray_mirror_release(&parser->mirrors); 265 darray_thin_dielectric_release(&parser->thin_dielectrics); 266 267 /* Mediums */ 268 htable_yaml2sols_release(&parser->yaml2mediums); 269 darray_medium_release(&parser->mediums); 270 271 /* Deferred targeted anchors */ 272 darray_tgtalias_release(&parser->tgtaliases); 273 274 /* Shapes */ 275 darray_shape_release(&parser->shapes); 276 darray_cuboid_release(&parser->cuboids); 277 darray_cylinder_release(&parser->cylinders); 278 darray_impgeom_release(&parser->objs); 279 darray_paraboloid_release(&parser->parabols); 280 darray_paraboloid_release(&parser->parabolic_cylinders); 281 darray_hyperboloid_release(&parser->hyperbols); 282 darray_hemisphere_release(&parser->hemispheres); 283 darray_plane_release(&parser->planes); 284 darray_sphere_release(&parser->spheres); 285 darray_impgeom_release(&parser->stls); 286 287 /* Geometries */ 288 htable_yaml2sols_release(&parser->yaml2geoms); 289 darray_object_release(&parser->objects); 290 darray_geometry_release(&parser->geometries); 291 292 /* Sun */ 293 solparser_sun_release(&parser->sun); 294 295 /* Atmosphere */ 296 solparser_atmosphere_release(&parser->atmosphere); 297 298 /* Entities */ 299 htable_str2sols_release(&parser->str2entities); 300 darray_entity_release(&parser->entities); 301 302 /* Miscellaneous */ 303 darray_anchor_release(&parser->anchors); 304 darray_x_pivot_release(&parser->x_pivots); 305 darray_zx_pivot_release(&parser->zx_pivots); 306 darray_spectrum_release(&parser->spectra); 307 308 MEM_RM(parser->allocator, parser); 309 } 310 311 /******************************************************************************* 312 * Local functions 313 ******************************************************************************/ 314 void 315 log_err 316 (const struct solparser* parser, 317 const yaml_node_t* node, 318 const char* fmt, 319 ...) 320 { 321 va_list vargs_list; 322 ASSERT(parser && node && fmt); 323 324 fprintf(stderr, "%s:%lu:%lu: ", 325 str_cget(&parser->stream_name), 326 (unsigned long)node->start_mark.line+1, 327 (unsigned long)node->start_mark.column+1); 328 va_start(vargs_list, fmt); 329 vfprintf(stderr, fmt, vargs_list); 330 va_end(vargs_list); 331 } 332 333 void 334 log_node(const struct solparser* parser, const yaml_node_t* node) 335 { 336 fprintf(stderr, "\tby %s:%lu:%lu\n", 337 str_cget(&parser->stream_name), 338 (unsigned long)node->start_mark.line+1, 339 (unsigned long)node->start_mark.column+1); 340 } 341 342 res_T 343 parse_real 344 (struct solparser* parser, 345 const yaml_node_t* real, 346 const double lower_bound, 347 const double upper_bound, 348 double* dst) 349 { 350 res_T res = RES_OK; 351 ASSERT(real && dst && lower_bound < upper_bound); 352 353 if(real->type != YAML_SCALAR_NODE 354 || !strlen((char*)real->data.scalar.value)) { 355 log_err(parser, real, "expect a floating point number.\n"); 356 res = RES_BAD_ARG; 357 goto error; 358 } 359 360 res = cstr_to_double((char*)real->data.scalar.value, dst); 361 if(res != RES_OK) { 362 log_err(parser, real, "invalid floating point number `%s'.\n", 363 real->data.scalar.value); 364 res = RES_BAD_ARG; 365 goto error; 366 } 367 368 if(*dst < lower_bound || *dst > upper_bound) { 369 double l = nextafter(lower_bound, -DBL_MAX); 370 double u = nextafter(upper_bound, DBL_MAX); 371 int l_excluded = (l == (double) (int) l); 372 int u_excluded = (u == (double) (int) u); 373 if(l_excluded && u_excluded) { 374 log_err(parser, real, "%g is not in ]%g, %g[.\n", 375 *dst, l, u); 376 } else if(l_excluded) { 377 log_err(parser, real, "%g is not in ]%g, %g].\n", 378 *dst, l, upper_bound); 379 } else if(u_excluded) { 380 log_err(parser, real, "%g is not in [%g, %g[.\n", 381 *dst, lower_bound, u); 382 } else { 383 log_err(parser, real, "%g is not in [%g, %g].\n", 384 *dst, lower_bound, upper_bound); 385 } 386 res = RES_BAD_ARG; 387 goto error; 388 } 389 390 exit: 391 return res; 392 error: 393 goto exit; 394 } 395 396 res_T 397 parse_realX 398 (struct solparser* parser, 399 yaml_document_t* doc, 400 const yaml_node_t* realX, 401 const double lower_bound, 402 const double upper_bound, 403 const size_t dim, 404 double dst[]) 405 { 406 intptr_t i, n; 407 res_T res = RES_OK; 408 ASSERT(doc && realX && dst && dim > 0); 409 410 if(realX->type != YAML_SEQUENCE_NODE) { 411 log_err(parser, realX, "expect a sequence of %lu reals.\n", 412 (unsigned long)dim); 413 res = RES_BAD_ARG; 414 goto error; 415 } 416 417 n = realX->data.sequence.items.top - realX->data.sequence.items.start; 418 if((size_t)n != dim) { 419 log_err(parser, realX, "expect %lu reals while `%li' %s submitted.\n", 420 (unsigned long)dim, n, n > 1 ? "are" : "is"); 421 res = RES_BAD_ARG; 422 goto error; 423 } 424 425 FOR_EACH(i, 0, n) { 426 yaml_node_t* real; 427 real = yaml_document_get_node(doc, realX->data.sequence.items.start[i]); 428 res = parse_real(parser, real, lower_bound, upper_bound, dst + i); 429 if(res != RES_OK) goto error; 430 } 431 432 exit: 433 return res; 434 error: 435 goto exit; 436 } 437 438 res_T 439 parse_integer 440 (struct solparser* parser, 441 yaml_node_t* integer, 442 const long lower_bound, 443 const long upper_bound, 444 long* dst) 445 { 446 res_T res = RES_OK; 447 ASSERT(integer && dst && lower_bound < upper_bound); 448 449 if(integer->type != YAML_SCALAR_NODE 450 || !strlen((char*)integer->data.scalar.value)) { 451 log_err(parser, integer, "expect an integer.\n"); 452 res = RES_BAD_ARG; 453 goto error; 454 } 455 456 res = cstr_to_long((char*)integer->data.scalar.value, dst); 457 if(res != RES_OK) { 458 log_err(parser, integer, "invalid integer `%s'.\n", 459 integer->data.scalar.value); 460 res = RES_BAD_ARG; 461 goto error; 462 } 463 464 if(*dst < lower_bound || *dst > upper_bound) { 465 log_err(parser, integer, "%li is not in [%li, %li].\n", 466 *dst, lower_bound, upper_bound); 467 res = RES_BAD_ARG; 468 goto error; 469 } 470 exit: 471 return res; 472 error: 473 goto exit; 474 } 475 476 res_T 477 parse_string 478 (struct solparser* parser, 479 yaml_node_t* string, 480 struct str* str) 481 { 482 res_T res = RES_OK; 483 ASSERT(string && str); 484 485 if(string->type != YAML_SCALAR_NODE 486 || !strlen((char*)string->data.scalar.value)) { 487 log_err(parser, string, "expect a character string.\n"); 488 res = RES_BAD_ARG; 489 goto error; 490 } 491 res = str_set(str, (char*)string->data.scalar.value); 492 if(res != RES_OK) { 493 log_err(parser, string, "could not register the string `%s'.\n", 494 string->data.scalar.value); 495 goto error; 496 } 497 498 exit: 499 return res; 500 error: 501 goto exit; 502 } 503 504 res_T 505 parse_transform 506 (struct solparser* parser, 507 yaml_document_t* doc, 508 const yaml_node_t* transform, 509 double translation[3], 510 double rotation[3]) 511 { 512 enum { ROTATION, TRANSLATION }; 513 intptr_t i, n; 514 int mask = 0; /* Register the parsed attributes */ 515 res_T res = RES_OK; 516 ASSERT(doc && translation && rotation && transform); 517 518 d3_splat(translation, 0); 519 d3_splat(rotation, 0); 520 521 if(transform->type != YAML_MAPPING_NODE) { 522 log_err(parser, transform, "expect a mapping of transform parameters.\n"); 523 res = RES_BAD_ARG; 524 goto error; 525 } 526 527 n = transform->data.mapping.pairs.top - transform->data.mapping.pairs.start; 528 FOR_EACH(i, 0, n) { 529 yaml_node_t* key; 530 yaml_node_t* val; 531 532 key = yaml_document_get_node(doc, transform->data.mapping.pairs.start[i].key); 533 val = yaml_document_get_node(doc, transform->data.mapping.pairs.start[i].value); 534 if(key->type != YAML_SCALAR_NODE) { 535 log_err(parser, key, "expect transform parameters.\n"); 536 res = RES_BAD_ARG; 537 goto error; 538 } 539 540 #define SETUP_MASK(Flag, Name) { \ 541 if(mask & BIT(Flag)) { \ 542 log_err(parser, key, "the transform `"Name"' is already defined.\n"); \ 543 res = RES_BAD_ARG; \ 544 goto error; \ 545 } \ 546 mask |= BIT(Flag); \ 547 } (void)0 548 if(!strcmp((char*)key->data.scalar.value, "translation")) { 549 SETUP_MASK(TRANSLATION, "translation"); 550 res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, translation); 551 } else if(!strcmp((char*)key->data.scalar.value, "rotation")) { 552 SETUP_MASK(ROTATION, "rotation"); 553 res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, rotation); 554 } else { 555 log_err(parser, key, "unknown transform parameter `%s'.\n", 556 key->data.scalar.value); 557 res = RES_BAD_ARG; 558 goto error; 559 } 560 if(res != RES_OK) { 561 log_node(parser, key); 562 goto error; 563 } 564 #undef SETUP_MASK 565 } 566 exit: 567 return res; 568 error: 569 goto exit; 570 } 571 572 /******************************************************************************* 573 * Exported functions 574 ******************************************************************************/ 575 res_T 576 solparser_create 577 (struct mem_allocator* allocator, struct solparser** out_parser) 578 { 579 struct solparser* parser = NULL; 580 struct mem_allocator* mem_allocator; 581 res_T res = RES_OK; 582 ASSERT(out_parser); 583 584 mem_allocator = allocator ? allocator : &mem_default_allocator; 585 parser = MEM_CALLOC(mem_allocator, 1, sizeof(struct solparser)); 586 if(!parser) { 587 fprintf(stderr, "Could not allocate the Solstice parser.\n"); 588 res = RES_MEM_ERR; 589 goto error; 590 } 591 parser->allocator = mem_allocator; 592 ref_init(&parser->ref); 593 str_init(mem_allocator, &parser->stream_name); 594 595 /* Materials */ 596 htable_yaml2sols_init(mem_allocator, &parser->yaml2mtls); 597 darray_image_init(mem_allocator, &parser->images); 598 darray_material_init(mem_allocator, &parser->mtls); 599 darray_material2_init(mem_allocator, &parser->mtls2); 600 darray_dielectric_init(mem_allocator, &parser->dielectrics); 601 darray_matte_init(mem_allocator, &parser->mattes); 602 darray_mirror_init(mem_allocator, &parser->mirrors); 603 darray_thin_dielectric_init(mem_allocator, &parser->thin_dielectrics); 604 605 /* Mediums */ 606 htable_yaml2sols_init(mem_allocator, &parser->yaml2mediums); 607 darray_medium_init(mem_allocator, &parser->mediums); 608 609 /* Deferred targeted anchors */ 610 darray_tgtalias_init(mem_allocator, &parser->tgtaliases); 611 612 /* Shapes */ 613 darray_shape_init(mem_allocator, &parser->shapes); 614 darray_cuboid_init(mem_allocator, &parser->cuboids); 615 darray_cylinder_init(mem_allocator, &parser->cylinders); 616 darray_impgeom_init(mem_allocator, &parser->objs); 617 darray_paraboloid_init(mem_allocator, &parser->parabols); 618 darray_paraboloid_init(mem_allocator, &parser->parabolic_cylinders); 619 darray_hyperboloid_init(mem_allocator, &parser->hyperbols); 620 darray_hemisphere_init(mem_allocator, &parser->hemispheres); 621 darray_plane_init(mem_allocator, &parser->planes); 622 darray_sphere_init(mem_allocator, &parser->spheres); 623 darray_impgeom_init(mem_allocator, &parser->stls); 624 625 /* Geometries */ 626 htable_yaml2sols_init(mem_allocator, &parser->yaml2geoms); 627 darray_object_init(mem_allocator, &parser->objects); 628 darray_geometry_init(mem_allocator, &parser->geometries); 629 630 /* Sun */ 631 solparser_sun_init(mem_allocator, &parser->sun); 632 633 /* Atmosphere */ 634 solparser_atmosphere_init(mem_allocator, &parser->atmosphere); 635 636 /* Entities */ 637 htable_str2sols_init(mem_allocator, &parser->str2entities); 638 darray_entity_init(mem_allocator, &parser->entities); 639 640 /* Miscellaneous */ 641 darray_anchor_init(mem_allocator, &parser->anchors); 642 darray_x_pivot_init(mem_allocator, &parser->x_pivots); 643 darray_zx_pivot_init(mem_allocator, &parser->zx_pivots); 644 darray_spectrum_init(mem_allocator, &parser->spectra); 645 646 exit: 647 *out_parser = parser; 648 return res; 649 error: 650 if(parser) { 651 solparser_ref_put(parser); 652 parser = NULL; 653 } 654 goto exit; 655 } 656 657 void 658 solparser_ref_get(struct solparser* parser) 659 { 660 ASSERT(parser); 661 ref_get(&parser->ref); 662 } 663 664 void 665 solparser_ref_put(struct solparser* parser) 666 { 667 ASSERT(parser); 668 ref_put(&parser->ref, parser_release); 669 } 670 671 res_T 672 solparser_setup 673 (struct solparser* parser, 674 const char* stream_name, 675 FILE* stream) 676 { 677 res_T res = RES_OK; 678 ASSERT(parser && stream); 679 680 if(parser->parser_is_init) { 681 yaml_parser_delete(&parser->parser); 682 parser->parser_is_init = 0; 683 } 684 res = str_set(&parser->stream_name, stream_name ? stream_name : "<stream>"); 685 if(res != RES_OK) { 686 fprintf(stderr, "Could not register the filename.\n"); 687 goto error; 688 } 689 if(!yaml_parser_initialize(&parser->parser)) { 690 fprintf(stderr, "Could not initialise the YAML parser.\n"); 691 res = RES_UNKNOWN_ERR; 692 goto error; 693 } 694 parser->parser_is_init = 1; 695 yaml_parser_set_input_file(&parser->parser, stream); 696 697 exit: 698 return res; 699 error: 700 str_clear(&parser->stream_name); 701 if(parser->parser_is_init) { 702 yaml_parser_delete(&parser->parser); 703 parser->parser_is_init = 0; 704 } 705 goto exit; 706 } 707 708 res_T 709 solparser_load(struct solparser* parser) 710 { 711 yaml_document_t doc; 712 yaml_node_t* root; 713 const char* filename; 714 intptr_t i, n; 715 int doc_is_init = 0; 716 res_T res = RES_OK; 717 ASSERT(parser); 718 719 filename = str_cget(&parser->stream_name); 720 721 parser_clear(parser); /* Clean up previously loaded data */ 722 723 if(!parser->parser_is_init) { 724 res = RES_BAD_OP; 725 goto error; 726 } 727 728 if(!yaml_parser_load(&parser->parser, &doc)) { 729 fprintf(stderr, "%s:%lu:%lu: %s.\n", 730 filename, 731 (unsigned long)parser->parser.problem_mark.line+1, 732 (unsigned long)parser->parser.problem_mark.column+1, 733 parser->parser.problem); 734 yaml_parser_delete(&parser->parser); 735 parser->parser_is_init = 0; 736 res = RES_BAD_OP; 737 goto error; 738 } 739 doc_is_init = 1; 740 741 root = yaml_document_get_root_node(&doc); 742 if(!root) { 743 yaml_parser_delete(&parser->parser); 744 parser->parser_is_init = 0; 745 res = RES_BAD_OP; 746 goto error; 747 } 748 749 if(root->type != YAML_SEQUENCE_NODE) { 750 log_err(parser, root, "expect a list of items.\n"); 751 res = RES_BAD_ARG; 752 goto error; 753 } 754 755 n = root->data.sequence.items.top - root->data.sequence.items.start; 756 FOR_EACH(i, 0, n) { 757 yaml_node_t* item; 758 759 item = yaml_document_get_node(&doc, root->data.sequence.items.start[i]); 760 res = parse_item(parser, &doc, item); 761 if(res != RES_OK) goto error; 762 } 763 764 if(!parser->sun_key) { 765 log_err(parser, root, "no sun definition in the document.\n"); 766 res = RES_BAD_ARG; 767 goto error; 768 } 769 770 exit: 771 if(doc_is_init) yaml_document_delete(&doc); 772 return res; 773 error: 774 parser_clear(parser); 775 goto exit; 776 } 777 778 const struct solparser_anchor* 779 solparser_find_anchor 780 (struct solparser* parser, const char* name) 781 { 782 struct str str; 783 struct str str_tk; 784 struct htable_str2sols* htable = NULL; 785 struct solparser_entity* entity = NULL; 786 struct solparser_anchor* anchor = NULL; 787 char* cstr; 788 char* tk; 789 char* tk_anchor; 790 res_T res = RES_OK; 791 ASSERT(parser && name); 792 793 str_init(parser->allocator, &str); 794 str_init(parser->allocator, &str_tk); 795 796 res = str_set(&str, name); 797 if(res != RES_OK) { 798 fprintf(stderr, "%s: could not copy the input string.\n", FUNC_NAME); 799 goto error; 800 } 801 res = str_reserve(&str_tk, str_len(&str)); 802 if(res != RES_OK) { 803 fprintf(stderr, "%s: could not allocate the temporary token string.\n", 804 FUNC_NAME); 805 goto error; 806 } 807 808 cstr = str_get(&str); 809 tk_anchor = strrchr(cstr, '.'); 810 if(!tk_anchor) goto exit; 811 *tk_anchor='\0'; 812 ++tk_anchor; 813 814 tk = strtok(cstr, "."); 815 htable = &parser->str2entities; 816 while(tk) { 817 size_t* pientity; 818 str_set(&str_tk, tk); 819 pientity = htable_str2sols_find(htable, &str_tk); 820 if(!pientity) { 821 tk = NULL; 822 entity = NULL; 823 } else { 824 tk = strtok(NULL, "."); 825 entity = darray_entity_data_get(&parser->entities) + *pientity; 826 htable = &entity->str2children; 827 } 828 } 829 830 if(entity) { 831 size_t* pianchor; 832 str_set(&str_tk, tk_anchor); 833 pianchor = htable_str2sols_find(&entity->str2anchors, &str_tk); 834 if(pianchor) { 835 anchor = darray_anchor_data_get(&parser->anchors) + *pianchor; 836 } 837 } 838 839 exit: 840 str_release(&str); 841 str_release(&str_tk); 842 return anchor; 843 error: 844 anchor = NULL; 845 goto exit; 846 } 847 848 const struct solparser_entity* 849 solparser_find_entity 850 (struct solparser* parser, const char* name) 851 { 852 struct htable_str2sols* htable = NULL; 853 struct solparser_entity* entity = NULL; 854 struct str str; 855 struct str str_tk; 856 char* cstr; 857 char* tk; 858 res_T res = RES_OK; 859 ASSERT(parser && name); 860 861 str_init(parser->allocator, &str); 862 str_init(parser->allocator, &str_tk); 863 864 res = str_set(&str, name); 865 if(res != RES_OK) { 866 fprintf(stderr, "%s: could not copy the input string.\n", FUNC_NAME); 867 goto error; 868 } 869 res = str_reserve(&str_tk, str_len(&str)); 870 if(res != RES_OK) { 871 fprintf(stderr, "%s: could not allocate the temporary token sting.\n", 872 FUNC_NAME); 873 goto error; 874 } 875 876 cstr = str_get(&str); 877 tk = strtok(cstr, "."); 878 htable = &parser->str2entities; 879 while(tk) { 880 size_t* pientity; 881 str_set(&str_tk, tk); 882 pientity = htable_str2sols_find(htable, &str_tk); 883 if(!pientity) { 884 tk = NULL; 885 entity = NULL; 886 } else { 887 tk = strtok(NULL, "."); 888 entity = darray_entity_data_get(&parser->entities) + *pientity; 889 htable = &entity->str2children; 890 } 891 } 892 893 exit: 894 str_release(&str); 895 str_release(&str_tk); 896 return entity; 897 error: 898 entity = NULL; 899 goto exit; 900 } 901 902 const struct solparser_anchor* 903 solparser_get_anchor 904 (const struct solparser* parser, 905 const struct solparser_anchor_id anchor) 906 { 907 ASSERT(parser && anchor.i < darray_anchor_size_get(&parser->anchors)); 908 return darray_anchor_cdata_get(&parser->anchors) + anchor.i; 909 } 910 911 const struct solparser_entity* 912 solparser_get_entity 913 (const struct solparser* parser, 914 const struct solparser_entity_id entity) 915 { 916 ASSERT(parser && entity.i < darray_entity_size_get(&parser->entities)); 917 return darray_entity_cdata_get(&parser->entities) + entity.i; 918 } 919 920 const struct solparser_image* 921 solparser_get_image 922 (const struct solparser* parser, 923 const struct solparser_image_id image) 924 { 925 ASSERT(parser && image.i < darray_image_size_get(&parser->images)); 926 return darray_image_cdata_get(&parser->images) + image.i; 927 } 928 929 const struct solparser_geometry* 930 solparser_get_geometry 931 (const struct solparser* parser, 932 const struct solparser_geometry_id geom) 933 { 934 ASSERT(parser && geom.i < darray_geometry_size_get(&parser->geometries)); 935 return darray_geometry_cdata_get(&parser->geometries) + geom.i; 936 } 937 938 const struct solparser_medium* 939 solparser_get_medium 940 (const struct solparser* parser, 941 const struct solparser_medium_id medium) 942 { 943 ASSERT(parser && medium.i < darray_medium_size_get(&parser->mediums)); 944 return darray_medium_cdata_get(&parser->mediums) + medium.i; 945 } 946 947 const struct solparser_material* 948 solparser_get_material 949 (const struct solparser* parser, 950 const struct solparser_material_id mtl) 951 { 952 ASSERT(parser && mtl.i < darray_material_size_get(&parser->mtls)); 953 return darray_material_cdata_get(&parser->mtls) + mtl.i; 954 } 955 956 const struct solparser_material_double_sided* 957 solparser_get_material_double_sided 958 (const struct solparser* parser, 959 const struct solparser_material_double_sided_id mtl2) 960 { 961 ASSERT(parser && mtl2.i < darray_material2_size_get(&parser->mtls2)); 962 return darray_material2_cdata_get(&parser->mtls2) + mtl2.i; 963 } 964 965 const struct solparser_material_dielectric* 966 solparser_get_material_dielectric 967 (const struct solparser* parser, 968 const struct solparser_material_dielectric_id dielectric) 969 { 970 ASSERT(parser); 971 ASSERT(dielectric.i < darray_dielectric_size_get(&parser->dielectrics)); 972 return darray_dielectric_cdata_get(&parser->dielectrics) + dielectric.i; 973 } 974 975 const struct solparser_material_matte* 976 solparser_get_material_matte 977 (const struct solparser* parser, 978 const struct solparser_material_matte_id matte) 979 { 980 ASSERT(parser && matte.i < darray_matte_size_get(&parser->mattes)); 981 return darray_matte_cdata_get(&parser->mattes) + matte.i; 982 } 983 984 const struct solparser_material_mirror* 985 solparser_get_material_mirror 986 (const struct solparser* parser, 987 const struct solparser_material_mirror_id mirror) 988 { 989 ASSERT(parser && mirror.i < darray_mirror_size_get(&parser->mirrors)); 990 return darray_mirror_cdata_get(&parser->mirrors) + mirror.i; 991 } 992 993 const struct solparser_material_thin_dielectric* 994 solparser_get_material_thin_dielectric 995 (const struct solparser* parser, 996 const struct solparser_material_thin_dielectric_id thin) 997 { 998 ASSERT(parser); 999 ASSERT(thin.i < darray_thin_dielectric_size_get(&parser->thin_dielectrics)); 1000 return darray_thin_dielectric_cdata_get(&parser->thin_dielectrics) + thin.i; 1001 } 1002 1003 const struct solparser_object* 1004 solparser_get_object 1005 (const struct solparser* parser, 1006 const struct solparser_object_id obj) 1007 { 1008 ASSERT(parser && obj.i < darray_object_size_get(&parser->objects)); 1009 return darray_object_cdata_get(&parser->objects) + obj.i; 1010 } 1011 1012 const struct solparser_x_pivot* 1013 solparser_get_x_pivot 1014 (const struct solparser* parser, 1015 const struct solparser_pivot_id x_pivot) 1016 { 1017 ASSERT(parser && x_pivot.i < darray_x_pivot_size_get(&parser->x_pivots)); 1018 return darray_x_pivot_cdata_get(&parser->x_pivots) + x_pivot.i; 1019 } 1020 1021 const struct solparser_zx_pivot* 1022 solparser_get_zx_pivot 1023 (const struct solparser* parser, 1024 const struct solparser_pivot_id zx_pivot) 1025 { 1026 ASSERT(parser && zx_pivot.i < darray_zx_pivot_size_get(&parser->zx_pivots)); 1027 return darray_zx_pivot_cdata_get(&parser->zx_pivots) + zx_pivot.i; 1028 } 1029 1030 const struct solparser_shape* 1031 solparser_get_shape 1032 (const struct solparser* parser, 1033 const struct solparser_shape_id shape) 1034 { 1035 ASSERT(parser && shape.i < darray_shape_size_get(&parser->shapes)); 1036 return darray_shape_cdata_get(&parser->shapes) + shape.i; 1037 } 1038 1039 const struct solparser_shape_cuboid* 1040 solparser_get_shape_cuboid 1041 (const struct solparser* parser, 1042 const struct solparser_shape_cuboid_id cuboid) 1043 { 1044 ASSERT(parser && cuboid.i < darray_cuboid_size_get(&parser->cuboids)); 1045 return darray_cuboid_cdata_get(&parser->cuboids) + cuboid.i; 1046 } 1047 1048 const struct solparser_shape_cylinder* 1049 solparser_get_shape_cylinder 1050 (const struct solparser* parser, 1051 const struct solparser_shape_cylinder_id cylinder) 1052 { 1053 ASSERT(parser && cylinder.i < darray_cylinder_size_get(&parser->cylinders)); 1054 return darray_cylinder_cdata_get(&parser->cylinders) + cylinder.i; 1055 } 1056 1057 const struct solparser_shape_imported_geometry* 1058 solparser_get_shape_obj 1059 (const struct solparser* parser, 1060 const struct solparser_shape_imported_geometry_id impgeom) 1061 { 1062 ASSERT(parser && impgeom.i < darray_impgeom_size_get(&parser->objs)); 1063 return darray_impgeom_cdata_get(&parser->objs) + impgeom.i; 1064 } 1065 1066 const struct solparser_shape_paraboloid* 1067 solparser_get_shape_parabol 1068 (const struct solparser* parser, 1069 const struct solparser_shape_paraboloid_id paraboloid) 1070 { 1071 ASSERT(parser && paraboloid.i < darray_paraboloid_size_get(&parser->parabols)); 1072 return darray_paraboloid_cdata_get(&parser->parabols) + paraboloid.i; 1073 } 1074 1075 const struct solparser_shape_paraboloid* 1076 solparser_get_shape_parabolic_cylinder 1077 (const struct solparser* parser, 1078 const struct solparser_shape_paraboloid_id paraboloid) 1079 { 1080 ASSERT(parser); 1081 ASSERT(paraboloid.i<darray_paraboloid_size_get(&parser->parabolic_cylinders)); 1082 return darray_paraboloid_cdata_get(&parser->parabolic_cylinders)+paraboloid.i; 1083 } 1084 1085 const struct solparser_shape_hyperboloid* 1086 solparser_get_shape_hyperbol 1087 (const struct solparser* parser, 1088 const struct solparser_shape_hyperboloid_id hyperboloid) 1089 { 1090 ASSERT(parser && hyperboloid.i < darray_hyperboloid_size_get(&parser->hyperbols)); 1091 return darray_hyperboloid_cdata_get(&parser->hyperbols) + hyperboloid.i; 1092 } 1093 1094 const struct solparser_shape_hemisphere* 1095 solparser_get_shape_hemisphere 1096 (const struct solparser* parser, 1097 const struct solparser_shape_hemisphere_id hemisphere) 1098 { 1099 ASSERT(parser && hemisphere.i < darray_hemisphere_size_get(&parser->hemispheres)); 1100 return darray_hemisphere_cdata_get(&parser->hemispheres) + hemisphere.i; 1101 } 1102 1103 const struct solparser_shape_plane* 1104 solparser_get_shape_plane 1105 (const struct solparser* parser, 1106 const struct solparser_shape_plane_id plane) 1107 { 1108 ASSERT(parser && plane.i < darray_plane_size_get(&parser->planes)); 1109 return darray_plane_cdata_get(&parser->planes) + plane.i; 1110 } 1111 1112 const struct solparser_shape_sphere* 1113 solparser_get_shape_sphere 1114 (const struct solparser* parser, 1115 const struct solparser_shape_sphere_id sphere) 1116 { 1117 ASSERT(parser && sphere.i < darray_sphere_size_get(&parser->spheres)); 1118 return darray_sphere_cdata_get(&parser->spheres) + sphere.i; 1119 } 1120 1121 const struct solparser_shape_imported_geometry* 1122 solparser_get_shape_stl 1123 (const struct solparser* parser, 1124 const struct solparser_shape_imported_geometry_id impgeom) 1125 { 1126 ASSERT(parser && impgeom.i < darray_impgeom_size_get(&parser->stls)); 1127 return darray_impgeom_cdata_get(&parser->stls) + impgeom.i; 1128 } 1129 1130 const struct solparser_spectrum* 1131 solparser_get_spectrum 1132 (const struct solparser* parser, 1133 const struct solparser_spectrum_id spectrum) 1134 { 1135 ASSERT(parser && spectrum.i < darray_spectrum_size_get(&parser->spectra)); 1136 return darray_spectrum_cdata_get(&parser->spectra) + spectrum.i; 1137 } 1138 1139 int 1140 solparser_has_spectrum(const struct solparser* parser) 1141 { 1142 ASSERT(parser); 1143 return darray_spectrum_size_get(&parser->spectra) != 0; 1144 } 1145 1146 const struct solparser_sun* 1147 solparser_get_sun(const struct solparser* parser) 1148 { 1149 ASSERT(parser && parser->sun_key); 1150 return &parser->sun; 1151 } 1152 1153 const struct solparser_atmosphere* 1154 solparser_get_atmosphere(const struct solparser* parser) 1155 { 1156 ASSERT(parser); 1157 if(parser->atmosphere_key) return &parser->atmosphere; 1158 else return NULL; 1159 } 1160 1161 void 1162 solparser_entity_iterator_begin 1163 (struct solparser* parser, 1164 struct solparser_entity_iterator* it) 1165 { 1166 ASSERT(parser && it); 1167 htable_str2sols_begin(&parser->str2entities, &it->it__); 1168 } 1169 1170 void 1171 solparser_entity_iterator_end 1172 (struct solparser* parser, 1173 struct solparser_entity_iterator* it) 1174 { 1175 ASSERT(parser && it); 1176 htable_str2sols_end(&parser->str2entities, &it->it__); 1177 } 1178 1179 void 1180 solparser_material_iterator_begin 1181 (struct solparser* parser, struct solparser_material_iterator* it) 1182 { 1183 ASSERT(parser && it); 1184 it->mtls__ = darray_material_cdata_get(&parser->mtls); 1185 it->imtl__ = 0; 1186 } 1187 1188 void 1189 solparser_material_iterator_end 1190 (struct solparser* parser, struct solparser_material_iterator* it) 1191 { 1192 ASSERT(parser && it); 1193 it->mtls__ = darray_material_cdata_get(&parser->mtls); 1194 it->imtl__ = darray_material_size_get(&parser->mtls); 1195 } 1196 1197 void 1198 solparser_geometry_iterator_begin 1199 (struct solparser* parser, struct solparser_geometry_iterator* it) 1200 { 1201 ASSERT(parser && it); 1202 it->geoms__ = darray_geometry_cdata_get(&parser->geometries); 1203 it->igeom__ = 0; 1204 } 1205 1206 void 1207 solparser_geometry_iterator_end 1208 (struct solparser* parser, struct solparser_geometry_iterator* it) 1209 { 1210 ASSERT(parser && it); 1211 it->geoms__ = darray_geometry_cdata_get(&parser->geometries); 1212 it->igeom__ = darray_geometry_size_get(&parser->geometries); 1213 } 1214