commit 054fb381cc6c2698ddb7964213f28f0fc6d78cb0
parent 9286d2298cbf03a0a798510ad0fc85c1514e9290
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 2 Dec 2016 09:07:33 +0100
Rename the parser API
Prefix the parser API functions by "solparser_" and its constants par
"SOLPARSER_".
Diffstat:
27 files changed, 5256 insertions(+), 5258 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -70,7 +70,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
endif()
add_executable(solstice ${SOLSTICE_SOURCE_DIR}/solstice.c)
-target_link_libraries(solstice LibYAML RSys ${MATH_LIB} solstice-parser SolAnim SolSolver)
+target_link_libraries(solstice LibYAML RSys ${MATH_LIB} solparser SolAnim SolSolver)
set_target_properties(solstice PROPERTIES
VERSION ${VERSION}
SOVERSION ${VERSION_MAJOR})
diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt
@@ -16,7 +16,7 @@
cmake_minimum_required(VERSION 2.8)
project(solstice-parser C CXX)
-set(PARSER_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/parser)
+set(SOLPARSER_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/parser)
################################################################################
# Define include directories
@@ -24,31 +24,31 @@ set(PARSER_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/parser)
include_directories(
${LibYAML_INCLUDE_DIR}
${RSys_INCLUDE_DIR}
- ${PARSER_SOURCE_DIR}/../)
+ ${SOLPARSER_SOURCE_DIR}/../)
################################################################################
# Configure and define targets
################################################################################
-set(PARSER_FILES_SRC
- solstice_parser.c)
-set(PARSER_FILES_INC
- solstice_entity.h
- solstice_material.h
- solstice_parser.h
- solstice_pivot.h
- solstice_shape.h
- solstice_sun.h)
+set(SOLPARSER_FILES_SRC
+ solparser.c)
+set(SOLPARSER_FILES_INC
+ solparser.h
+ solparser_entity.h
+ solparser_material.h
+ solparser_pivot.h
+ solparser_shape.h
+ solparser_sun.h)
# Prepend each file in the `SOLSTICE_FILES_<SRC|INC>' list by `SOLSTICE_SOURCE_DIR'
-rcmake_prepend_path(PARSER_FILES_SRC ${PARSER_SOURCE_DIR})
-rcmake_prepend_path(PARSER_FILES_INC ${PARSER_SOURCE_DIR})
-rcmake_prepend_path(PARSER_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
+rcmake_prepend_path(SOLPARSER_FILES_SRC ${SOLPARSER_SOURCE_DIR})
+rcmake_prepend_path(SOLPARSER_FILES_INC ${SOLPARSER_SOURCE_DIR})
+rcmake_prepend_path(SOLPARSER_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
if(CMAKE_COMPILER_IS_GNUCC)
set(MATH_LIB m)
endif()
-add_library(solstice-parser STATIC ${PARSER_FILES_SRC} ${PARSER_FILES_INC})
+add_library(solparser STATIC ${SOLPARSER_FILES_SRC} ${SOLPARSER_FILES_INC})
################################################################################
# Tests
@@ -56,9 +56,9 @@ add_library(solstice-parser STATIC ${PARSER_FILES_SRC} ${PARSER_FILES_INC})
if(NOT NO_TEST)
function(build_test _name)
add_executable(${_name}
- ${PARSER_SOURCE_DIR}/${_name}.c
- ${PARSER_SOURCE_DIR}/../test_solstice_utils.h)
- target_link_libraries(${_name} LibYAML ${MATH_LIB} RSys solstice-parser)
+ ${SOLPARSER_SOURCE_DIR}/${_name}.c
+ ${SOLPARSER_SOURCE_DIR}/../test_solstice_utils.h)
+ target_link_libraries(${_name} LibYAML ${MATH_LIB} RSys solparser)
endfunction()
function(new_test _name)
@@ -66,15 +66,15 @@ if(NOT NO_TEST)
add_test(${_name} ${_name})
endfunction()
- build_test(test_solstice_parser)
- add_test(test_solstice_parser_ok_0 test_solstice_parser
- ${PARSER_SOURCE_DIR}/yaml/test_ok_0.yaml)
- add_test(test_solstice_parser_ok_1 test_solstice_parser
- ${PARSER_SOURCE_DIR}/yaml/test_ok_1.yaml)
- add_test(test_solstice_parser_ok_2 test_solstice_parser
- ${PARSER_SOURCE_DIR}/yaml/test_ok_2.yaml)
- add_test(test_solstice_parser_ok_2 test_solstice_parser
- ${PARSER_SOURCE_DIR}/yaml/test_ok_3.yaml)
+ build_test(test_solparser)
+ add_test(test_solparser_ok_0 test_solparser
+ ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_0.yaml)
+ add_test(test_solparser_ok_1 test_solparser
+ ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_1.yaml)
+ add_test(test_solparser_ok_2 test_solparser
+ ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_2.yaml)
+ add_test(test_solparser_ok_2 test_solparser
+ ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_3.yaml)
# TODO rewrite them wrt the update of the input specification
# add_test(test_solstice_parser_ko_0 test_solstice_parser -e
# ${SOLSTICE_SOURCE_DIR}/yaml/test_ko_0.yaml)
@@ -83,11 +83,11 @@ if(NOT NO_TEST)
# add_test(test_solstice_parser_ko_2 test_solstice_parser -e
# ${SOLSTICE_SOURCE_DIR}/yaml/test_ko_2.yaml)
- new_test(test_solstice_parser2)
- new_test(test_solstice_parser3)
- new_test(test_solstice_parser4)
+ new_test(test_solparser2)
+ new_test(test_solparser3)
+ new_test(test_solparser4)
- rcmake_copy_runtime_libraries(test_solstice_parser)
+ rcmake_copy_runtime_libraries(test_solparser)
endif()
diff --git a/src/parser/solparser.c b/src/parser/solparser.c
@@ -0,0 +1,3402 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#define _POSIX_C_SOURCE 200112L /* nextafter support */
+
+#include "solparser.h"
+#include "solparser_entity.h"
+#include "solparser_material.h"
+#include "solparser_pivot.h"
+#include "solparser_shape.h"
+#include "solparser_sun.h"
+
+#include <rsys/cstr.h>
+#include <rsys/double3.h>
+#include <rsys/dynamic_array.h>
+#include <rsys/hash_table.h>
+#include <rsys/ref_count.h>
+#include <rsys/str.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <yaml.h>
+
+/* Declare the array of matte materials */
+#define DARRAY_NAME matte
+#define DARRAY_DATA struct solparser_material_matte
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of mirror materials */
+#define DARRAY_NAME mirror
+#define DARRAY_DATA struct solparser_material_mirror
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of materials */
+#define DARRAY_NAME material
+#define DARRAY_DATA struct solparser_material
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of the double sided materials */
+#define DARRAY_NAME material2
+#define DARRAY_DATA struct solparser_material_double_sided
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of the shapes */
+#define DARRAY_NAME shape
+#define DARRAY_DATA struct solparser_shape
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of cuboid */
+#define DARRAY_NAME cuboid
+#define DARRAY_DATA struct solparser_shape_cuboid
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of cylinder */
+#define DARRAY_NAME cylinder
+#define DARRAY_DATA struct solparser_shape_cylinder
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of imported geometries */
+#define DARRAY_NAME impgeom
+#define DARRAY_DATA struct solparser_shape_imported_geometry
+#define DARRAY_FUNCTOR_INIT solparser_shape_imported_geometry_init
+#define DARRAY_FUNCTOR_RELEASE solparser_shape_imported_geometry_release
+#define DARRAY_FUNCTOR_COPY solparser_shape_imported_geometry_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE \
+ solparser_shape_imported_geometry_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of paraboloids */
+#define DARRAY_NAME paraboloid
+#define DARRAY_DATA struct solparser_shape_paraboloid
+#define DARRAY_FUNCTOR_INIT solparser_shape_paraboloid_init
+#define DARRAY_FUNCTOR_RELEASE solparser_shape_paraboloid_release
+#define DARRAY_FUNCTOR_COPY solparser_shape_paraboloid_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE \
+ solparser_shape_paraboloid_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of planes */
+#define DARRAY_NAME plane
+#define DARRAY_DATA struct solparser_shape_plane
+#define DARRAY_FUNCTOR_INIT solparser_shape_plane_init
+#define DARRAY_FUNCTOR_RELEASE solparser_shape_plane_release
+#define DARRAY_FUNCTOR_COPY solparser_shape_plane_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_shape_plane_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of spheres */
+#define DARRAY_NAME sphere
+#define DARRAY_DATA struct solparser_shape_sphere
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of objects */
+#define DARRAY_NAME object
+#define DARRAY_DATA struct solparser_object
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of geometries */
+#define DARRAY_NAME geometry
+#define DARRAY_DATA struct solparser_geometry
+#define DARRAY_FUNCTOR_INIT solparser_geometry_init
+#define DARRAY_FUNCTOR_RELEASE solparser_geometry_release
+#define DARRAY_FUNCTOR_COPY solparser_geometry_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_geometry_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of entities */
+#define DARRAY_NAME entity
+#define DARRAY_DATA struct solparser_entity
+#define DARRAY_FUNCTOR_INIT solparser_entity_init
+#define DARRAY_FUNCTOR_RELEASE solparser_entity_release
+#define DARRAY_FUNCTOR_COPY solparser_entity_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_entity_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of anchors */
+#define DARRAY_NAME anchor
+#define DARRAY_DATA struct solparser_anchor
+#define DARRAY_FUNCTOR_INIT solparser_anchor_init
+#define DARRAY_FUNCTOR_RELEASE solparser_anchor_release
+#define DARRAY_FUNCTOR_COPY solparser_anchor_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_anchor_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/* Declare the array of pivots */
+#define DARRAY_NAME pivot
+#define DARRAY_DATA struct solparser_pivot
+#include <rsys/dynamic_array.h>
+
+/* Declare the hash table that maps the address of a YAML node to the id of its
+ * in memory representation. */
+#define HTABLE_NAME yaml2sols
+#define HTABLE_KEY yaml_node_t*
+#define HTABLE_DATA size_t
+#include <rsys/hash_table.h>
+
+struct solparser {
+ yaml_parser_t parser;
+ struct str stream_name;
+ int parser_is_init;
+
+ /* Materia data */
+ struct htable_yaml2sols yaml2mtls; /* Cache of materials */
+ struct darray_material mtls;
+ struct darray_material2 mtls2; /* Double sided materials */
+ struct darray_matte mattes;
+ struct darray_mirror mirrors;
+
+ /* Shape data */
+ struct darray_shape shapes; /* Generic loaded shapes */
+ struct darray_cuboid cuboids;
+ struct darray_cylinder cylinders;
+ struct darray_impgeom objs;
+ struct darray_paraboloid parabols;
+ struct darray_paraboloid parabolic_cylinders;
+ struct darray_plane planes;
+ struct darray_sphere spheres;
+ struct darray_impgeom stls;
+
+ /* Geometries & objects */
+ struct htable_yaml2sols yaml2geoms; /* Cache of geometries */
+ struct darray_object objects;
+ struct darray_geometry geometries;
+
+ /* Sun. Note that only one sun is supported */
+ const yaml_node_t* sun_key; /* yaml_node_t ptr used to spawn the sun */
+ struct solparser_sun sun; /* The loaded sun */
+
+ /* Entity */
+ struct htable_yaml2sols yaml2entities; /* Cache of entities */
+ struct htable_str2sols str2entities;
+ struct darray_entity entities;
+
+ /* Miscellaneous */
+ struct darray_anchor anchors;
+ struct darray_pivot pivots;
+
+ ref_T ref;
+ struct mem_allocator* allocator;
+};
+
+static res_T
+parse_entity
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* entity,
+ struct htable_str2sols* htable,
+ struct solparser_entity_id* solent);
+
+static res_T
+parse_geometry
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* geometry,
+ struct solparser_geometry_id* solgeom);
+
+static res_T
+parse_pivot
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* pivot,
+ struct solparser_pivot_id* out_isolpivot);
+
+static res_T
+parse_sun
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* sun,
+ struct solparser_sun** solsun);
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static INLINE void
+log_err
+ (const struct solparser* parser,
+ const yaml_node_t* node,
+ const char* fmt,
+ ...)
+{
+ va_list vargs_list;
+ ASSERT(parser && node && fmt);
+
+ fprintf(stderr, "%s:%lu:%lu: ",
+ str_cget(&parser->stream_name),
+ (unsigned long)node->start_mark.line+1,
+ (unsigned long)node->start_mark.column+1);
+ va_start(vargs_list, fmt);
+ vfprintf(stderr, fmt, vargs_list);
+ va_end(vargs_list);
+}
+
+/* Clean up loaded data */
+static INLINE void
+parser_clear(struct solparser* parser)
+{
+ ASSERT(parser);
+
+ /* Materials */
+ htable_yaml2sols_clear(&parser->yaml2mtls);
+ darray_material_clear(&parser->mtls);
+ darray_material2_clear(&parser->mtls2);
+ darray_matte_clear(&parser->mattes);
+ darray_mirror_clear(&parser->mirrors);
+
+ /* Shapes */
+ darray_shape_clear(&parser->shapes);
+ darray_cuboid_clear(&parser->cuboids);
+ darray_cylinder_clear(&parser->cylinders);
+ darray_impgeom_clear(&parser->objs);
+ darray_paraboloid_clear(&parser->parabols);
+ darray_paraboloid_clear(&parser->parabolic_cylinders);
+ darray_plane_clear(&parser->planes);
+ darray_sphere_clear(&parser->spheres);
+ darray_impgeom_clear(&parser->stls);
+
+ /* Geometries */
+ htable_yaml2sols_clear(&parser->yaml2geoms);
+ darray_object_clear(&parser->objects);
+ darray_geometry_clear(&parser->geometries);
+
+ /* Sun */
+ solparser_sun_clear(&parser->sun);
+ parser->sun_key = 0;
+
+ /* Entities */
+ htable_yaml2sols_clear(&parser->yaml2entities);
+ htable_str2sols_clear(&parser->str2entities);
+ darray_entity_clear(&parser->entities);
+
+ /* Miscellaneous */
+ darray_anchor_clear(&parser->anchors);
+ darray_pivot_clear(&parser->pivots);
+}
+
+static void
+parser_release(ref_T* ref)
+{
+ struct solparser* parser;
+ ASSERT(ref);
+
+ parser = CONTAINER_OF(ref, struct solparser, ref);
+ if(parser->parser_is_init) yaml_parser_delete(&parser->parser);
+ str_release(&parser->stream_name);
+
+ /* Materials */
+ htable_yaml2sols_release(&parser->yaml2mtls);
+ darray_material_release(&parser->mtls);
+ darray_material2_release(&parser->mtls2);
+ darray_matte_release(&parser->mattes);
+ darray_mirror_release(&parser->mirrors);
+
+ /* Shapes */
+ darray_shape_release(&parser->shapes);
+ darray_cuboid_release(&parser->cuboids);
+ darray_cylinder_release(&parser->cylinders);
+ darray_impgeom_release(&parser->objs);
+ darray_paraboloid_release(&parser->parabols);
+ darray_paraboloid_release(&parser->parabolic_cylinders);
+ darray_plane_release(&parser->planes);
+ darray_sphere_release(&parser->spheres);
+ darray_impgeom_release(&parser->stls);
+
+ /* Geometries */
+ htable_yaml2sols_release(&parser->yaml2geoms);
+ darray_object_release(&parser->objects);
+ darray_geometry_release(&parser->geometries);
+
+ /* Sun */
+ solparser_sun_release(&parser->sun);
+
+ /* Entities */
+ htable_yaml2sols_release(&parser->yaml2entities);
+ htable_str2sols_release(&parser->str2entities);
+ darray_entity_release(&parser->entities);
+
+ /* Miscellaneous */
+ darray_anchor_release(&parser->anchors);
+ darray_pivot_release(&parser->pivots);
+
+ MEM_RM(parser->allocator, parser);
+}
+
+/*******************************************************************************
+ * Miscellaneous parsing functions
+ ******************************************************************************/
+static res_T
+parse_real
+ (struct solparser* parser,
+ const yaml_node_t* real,
+ const double lower_bound,
+ const double upper_bound,
+ double* dst)
+{
+ res_T res = RES_OK;
+ ASSERT(real && dst && lower_bound < upper_bound);
+
+ if(real->type != YAML_SCALAR_NODE
+ || !strlen((char*)real->data.scalar.value)) {
+ log_err(parser, real, "expect a floating point number.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = cstr_to_double((char*)real->data.scalar.value, dst);
+ if(res != RES_OK) {
+ log_err(parser, real, "invalid floating point number `%s'.\n",
+ real->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(*dst < lower_bound || *dst > upper_bound) {
+ log_err(parser, real, "%g is not in [%g, %g].\n",
+ *dst, lower_bound, upper_bound);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_real3
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* real3,
+ const double lower_bound,
+ const double upper_bound,
+ double dst[3])
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && real3 && dst);
+
+ if(real3->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, real3, "expect a sequence of 3 reals.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = real3->data.sequence.items.top - real3->data.sequence.items.start;
+ if(n != 3) {
+ log_err(parser, real3, "expect 3 reals while `%li' %s submitted.\n",
+ n, n > 1 ? "are" : "is");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* real;
+ real = yaml_document_get_node(doc, real3->data.sequence.items.start[i]);
+ res = parse_real(parser, real, lower_bound, upper_bound, dst + i);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_integer
+ (struct solparser* parser,
+ yaml_node_t* integer,
+ const long lower_bound,
+ const long upper_bound,
+ long* dst)
+{
+ res_T res = RES_OK;
+ ASSERT(integer && dst && lower_bound < upper_bound);
+
+ if(integer->type != YAML_SCALAR_NODE
+ || !strlen((char*)integer->data.scalar.value)) {
+ log_err(parser, integer, "expect an integer.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = cstr_to_long((char*)integer->data.scalar.value, dst);
+ if(res != RES_OK) {
+ log_err(parser, integer, "invalid integer `%s'.\n",
+ integer->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(*dst < lower_bound || *dst > upper_bound) {
+ log_err(parser, integer, "%li is not in [%li, %li].\n",
+ *dst, lower_bound, upper_bound);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_string
+ (struct solparser* parser,
+ yaml_node_t* string,
+ struct str* str)
+{
+ res_T res = RES_OK;
+ ASSERT(string && str);
+
+ if(string->type != YAML_SCALAR_NODE
+ || !strlen((char*)string->data.scalar.value)) {
+ log_err(parser, string, "expect a character string.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ res = str_set(str, (char*)string->data.scalar.value);
+ if(res != RES_OK) {
+ log_err(parser, string, "could not register the string `%s'.\n",
+ string->data.scalar.value);
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_transform
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* transform,
+ double translation[3],
+ double rotation[3])
+{
+ enum { ROTATION, TRANSLATION };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && translation && rotation && transform);
+
+ d3_splat(translation, 0);
+ d3_splat(rotation, 0);
+
+ if(transform->type != YAML_MAPPING_NODE) {
+ log_err(parser, transform, "expect a mapping of transform parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = transform->data.mapping.pairs.top - transform->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, transform->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, transform->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect transform parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, "the transform `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "translation")) {
+ SETUP_MASK(TRANSLATION, "translation");
+ res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, translation);
+ } else if(!strcmp((char*)key->data.scalar.value, "rotation")) {
+ SETUP_MASK(ROTATION, "rotation");
+ res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, rotation);
+ } else {
+ log_err(parser, key, "unknown transform parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_spectrum_data
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const double lower_bound,
+ const double upper_bound,
+ const yaml_node_t* sdata,
+ struct solparser_spectrum_data* spectrum_data)
+{
+ enum { DATA, WAVELENGTH };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && sdata && lower_bound < upper_bound && spectrum_data);
+
+ if(sdata->type != YAML_MAPPING_NODE) {
+ log_err(parser, sdata, "expect the definition of a spectrum data.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = sdata->data.mapping.pairs.top - sdata->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, sdata->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, sdata->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a spectrum data parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the `"Name"' of the spectrum data is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "data")) {
+ SETUP_MASK(DATA, "data");
+ res = parse_real(parser, val, lower_bound, upper_bound, &spectrum_data->data);
+ } else if(!strcmp((char*)key->data.scalar.value, "wavelength")) {
+ SETUP_MASK(WAVELENGTH, "wavelength");
+ res = parse_real(parser, val, 0, DBL_MAX, &spectrum_data->wavelength);
+ } else {
+ log_err(parser, key, "unknown spectrum data parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, sdata,"the "Name" of the spectrum data is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(DATA, "data");
+ CHECK_PARAM(WAVELENGTH, "wavelength");
+ #undef CHECK_PARAM
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_spectrum
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const double lower_bound,
+ const double upper_bound,
+ const yaml_node_t* spectrum,
+ struct darray_spectrum_data* data)
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && spectrum && lower_bound < upper_bound && data);
+
+ if(spectrum->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, spectrum, "expect a list of spectrum data.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = spectrum->data.sequence.items.top - spectrum->data.sequence.items.start;
+ res = darray_spectrum_data_resize(data, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, spectrum, "could not allocate the list of spectrum data.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* sdata;
+ struct solparser_spectrum_data* spectrum_data;
+
+ sdata = yaml_document_get_node(doc, spectrum->data.sequence.items.start[i]);
+ spectrum_data = darray_spectrum_data_data_get(data) + i;
+ res = parse_spectrum_data
+ (parser, doc, lower_bound, upper_bound, sdata, spectrum_data);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ darray_spectrum_data_clear(data);
+ goto exit;
+}
+
+/*******************************************************************************
+ * Material
+ ******************************************************************************/
+static res_T
+parse_material_matte
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* matte,
+ struct solparser_material_matte_id* out_imtl)
+{
+ enum { REFLECTIVITY };
+ struct solparser_material_matte* mtl = NULL;
+ size_t imtl = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && matte && out_imtl);
+
+ if(matte->type != YAML_MAPPING_NODE) {
+ log_err(parser, matte, "expect a mapping of matte material parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the matte material */
+ imtl = darray_matte_size_get(&parser->mattes);
+ res = darray_matte_resize(&parser->mattes, imtl + 1);
+ if(res != RES_OK) {
+ log_err(parser, matte, "could not allocate the matte material.\n");
+ goto error;
+ }
+ mtl = darray_matte_data_get(&parser->mattes) + imtl;
+
+ n = matte->data.mapping.pairs.top - matte->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, matte->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, matte->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a matte material parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!strcmp((char*)key->data.scalar.value, "reflectivity")) {
+ if(mask & BIT(REFLECTIVITY)) {
+ log_err(parser, key, "the matte reflectivity is already defined.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ mask |= BIT(REFLECTIVITY);
+ res = parse_real(parser, val, 0, 1, &mtl->reflectivity);
+ } else {
+ log_err(parser, key, "unknown matte parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ }
+
+ if(!(mask & BIT(REFLECTIVITY))) {
+ log_err(parser, matte, "the matte reflectivity is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ out_imtl->i = imtl;
+ return res;
+error:
+ if(mtl) {
+ darray_matte_pop_back(&parser->mattes);
+ imtl = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_material_mirror
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* mirror,
+ struct solparser_material_mirror_id* out_imtl)
+{
+ enum { REFLECTIVITY, ROUGHNESS };
+ struct solparser_material_mirror* mtl = NULL;
+ size_t imtl = SIZE_MAX;
+ int mask = 0; /* Register the parsed attributes */
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && mirror && out_imtl);
+
+ if(mirror->type != YAML_MAPPING_NODE) {
+ log_err(parser, mirror,
+ "expect a mapping of mirror material attributes .\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the mirror material */
+ imtl = darray_mirror_size_get(&parser->mirrors);
+ res = darray_mirror_resize(&parser->mirrors, imtl + 1);
+ if(res != RES_OK) {
+ log_err(parser, mirror, "could not allocate the mirror material.\n");
+ goto error;
+ }
+ mtl = darray_mirror_data_get(&parser->mirrors) + imtl;
+
+ n = mirror->data.mapping.pairs.top - mirror->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, mirror->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, mirror->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a mirror material parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the "Name" of the mirror material is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "reflectivity")) {
+ SETUP_MASK(REFLECTIVITY, "reflectivity");
+ res = parse_real(parser, val, 0, 1, &mtl->reflectivity);
+ } else if(!strcmp((char*)key->data.scalar.value, "roughness")) {
+ SETUP_MASK(ROUGHNESS, "roughness");
+ res = parse_real(parser, val, 0, 1, &mtl->roughness);
+ } else {
+ log_err(parser, key, "unknown mirror attribute `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, mirror, "the mirror "Name" is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(REFLECTIVITY, "reflectivity");
+ CHECK_PARAM(ROUGHNESS, "roughness");
+ #undef CHECK_PARAM
+
+exit:
+ out_imtl->i = imtl;
+ return res;
+error:
+ if(mtl) {
+ darray_mirror_pop_back(&parser->mirrors);
+ imtl = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_material_descriptor
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* desc,
+ struct solparser_material_id* out_imtl)
+{
+ enum { DESCRIPTOR };
+ struct solparser_material* mtl = NULL;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ size_t* pimtl;
+ size_t imtl = SIZE_MAX;
+ res_T res = RES_OK;
+ ASSERT(doc && desc && out_imtl);
+
+ /* Check whether or not the YAML descriptor alias an already created Solstice
+ * material */
+ pimtl = htable_yaml2sols_find(&parser->yaml2mtls, &desc);
+ if(pimtl) {
+ imtl = *pimtl;
+ goto exit;
+ }
+
+ /* Allocate the solstice material */
+ imtl = darray_material_size_get(&parser->mtls);
+ res = darray_material_resize(&parser->mtls, imtl + 1);
+ if(res != RES_OK) {
+ log_err(parser, desc, "could not allocate the material descriptor.\n");
+ goto error;
+ }
+ mtl = darray_material_data_get(&parser->mtls) + imtl;
+
+ if(desc->type != YAML_MAPPING_NODE) {
+ log_err(parser, desc, "expect a material descriptor.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = desc->data.mapping.pairs.top - desc->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a material name.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, "the material "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "matte")) {
+ SETUP_MASK(DESCRIPTOR, "descriptor");
+ mtl->type = SOLPARSER_MATERIAL_MATTE;
+ res = parse_material_matte(parser, doc, val, &mtl->data.matte);
+ } else if(!strcmp((char*)key->data.scalar.value, "mirror")) {
+ SETUP_MASK(DESCRIPTOR, "descriptor");
+ mtl->type = SOLPARSER_MATERIAL_MIRROR;
+ res = parse_material_mirror(parser, doc, val, &mtl->data.mirror);
+ } else {
+ log_err(parser, key, "unknown material descriptor `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ if(!(mask & BIT(DESCRIPTOR))) {
+ log_err(parser, desc, "the material descriptor is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Cache the material */
+ res = htable_yaml2sols_set(&parser->yaml2mtls, &desc, &imtl);
+ if(res != RES_OK) {
+ log_err(parser, desc, "could not register the material.\n");
+ goto error;
+ }
+
+exit:
+ out_imtl->i = imtl;
+ return res;
+error:
+ if(mtl) {
+ darray_material_pop_back(&parser->mtls);
+ imtl = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_material
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* mtl,
+ struct solparser_material_double_sided_id* out_imtl2)
+{
+ enum { FRONT, BACK };
+ struct solparser_material_double_sided* mtl2 = NULL;
+ size_t imtl2 = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && mtl && out_imtl2);
+
+ if(mtl->type != YAML_MAPPING_NODE) {
+ log_err(parser, mtl, "expect a material definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the double sided material */
+ imtl2 = darray_material2_size_get(&parser->mtls2);
+ res = darray_material2_resize(&parser->mtls2, imtl2 + 1);
+ if(res != RES_OK) {
+ log_err(parser, mtl, "could not allocate the material.\n");
+ goto error;
+ }
+ mtl2 = darray_material2_data_get(&parser->mtls2) + imtl2;
+
+ n = mtl->data.mapping.pairs.top - mtl->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, mtl->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, mtl->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key,
+ "expect a material descriptor or a double sided material.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the "Name" material descriptor is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "front")) {
+ SETUP_MASK(FRONT, "front");
+ res = parse_material_descriptor(parser, doc, val, &mtl2->front);
+ } else if(!strcmp((char*)key->data.scalar.value, "back")) {
+ SETUP_MASK(BACK, "back");
+ res = parse_material_descriptor(parser, doc, val, &mtl2->back);
+ } else {
+ SETUP_MASK(FRONT, "front");
+ SETUP_MASK(BACK, "back");
+ res = parse_material_descriptor(parser, doc, mtl, &mtl2->front);
+ mtl2->back = mtl2->front;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, mtl, "the "Name" material descriptor is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(FRONT, "front");
+ CHECK_PARAM(BACK, "back");
+ #undef CHECK_PARAM
+
+exit:
+ out_imtl2->i = imtl2;
+ return res;
+error:
+ if(mtl2) {
+ darray_material2_pop_back(&parser->mtls2);
+ imtl2 = SIZE_MAX;
+ }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Clipping polygon
+ ******************************************************************************/
+static res_T
+parse_clip_op
+ (struct solparser* parser,
+ const yaml_node_t* op,
+ enum solparser_clip_op* clip_op)
+{
+ res_T res = RES_OK;
+ ASSERT(op && clip_op);
+
+ if(op->type != YAML_SCALAR_NODE) {
+ log_err(parser, op, "expect a clipping operation.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!strcmp((char*)op->data.scalar.value, "AND")) {
+ *clip_op = SOLPARSER_CLIP_OP_AND;
+ } else if(!strcmp((char*)op->data.scalar.value, "SUB")) {
+ *clip_op = SOLPARSER_CLIP_OP_SUB;
+ } else {
+ log_err(parser, op, "unknown clipping operation `%s'.\n",
+ op->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_vertices
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* vertices,
+ struct darray_double* coords)
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && vertices && coords);
+
+ if(vertices->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, vertices, "expect a list of vertices.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = vertices->data.sequence.items.top - vertices->data.sequence.items.start;
+ if(n < 3) {
+ log_err(parser, vertices, "expect at least 3 vertices.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = darray_double_resize(coords, (size_t)n*3/*#coords per vertex*/);
+ if(res != RES_OK) {
+ log_err(parser, vertices, "could not allocate the array of vertices.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* vertex;
+ double* real3 = darray_double_data_get(coords) + i*3/*#coords per vertex*/;
+
+ vertex = yaml_document_get_node(doc, vertices->data.sequence.items.start[i]);
+ res = parse_real3(parser, doc, vertex, -DBL_MAX, DBL_MAX, real3);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ darray_double_clear(coords);
+ goto exit;
+}
+
+static res_T
+parse_polyclip
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* polyclip,
+ struct solparser_polyclip* clip)
+{
+ enum { OPERATION, VERTICES };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && polyclip && clip);
+
+ if(polyclip->type != YAML_MAPPING_NODE) {
+ log_err(parser, polyclip,
+ "expect a mapping of clipping polygon parameters.\n");
+ res = RES_OK;
+ goto error;
+ }
+
+ n = polyclip->data.mapping.pairs.top - polyclip->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, polyclip->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, polyclip->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a clipping polygon parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the clipping polygon parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "operation")) {
+ SETUP_MASK(OPERATION, "operation");
+ res = parse_clip_op(parser, val, &clip->op);
+ } else if(!strcmp((char*)key->data.scalar.value, "vertices")) {
+ SETUP_MASK(VERTICES, "vertices");
+ res = parse_vertices(parser, doc, val, &clip->vertices);
+ } else {
+ log_err(parser, key, "unknown clipping polygon parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, polyclip, \
+ "the clipping polygon parameter `"Name"' is missing"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(OPERATION, "operation");
+ CHECK_PARAM(VERTICES, "vertices");
+ #undef CHECK_PARAM
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_clip
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* clip,
+ struct darray_polyclip* polyclips)
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && clip && polyclips);
+
+ if(clip->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, clip, "expect a list of clipping polygons.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = clip->data.sequence.items.top - clip->data.sequence.items.start;
+
+ /* Allocate the clipping polygons */
+ res = darray_polyclip_resize(polyclips, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, clip, "could not allocate the list of clipping polygons.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* node;
+ struct solparser_polyclip* polyclip = darray_polyclip_data_get(polyclips) + i;
+
+ node = yaml_document_get_node(doc, clip->data.sequence.items.start[i]);
+ res = parse_polyclip(parser, doc, node, polyclip);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * Shapes
+ ******************************************************************************/
+static res_T
+parse_cuboid
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* cuboid,
+ struct solparser_shape_cuboid_id* out_ishape)
+{
+ enum { SIZE };
+ struct solparser_shape_cuboid* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && cuboid && out_ishape);
+
+ if(cuboid->type != YAML_MAPPING_NODE) {
+ log_err(parser, cuboid, "expect a mapping of cuboid parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a cuboid */
+ ishape = darray_cuboid_size_get(&parser->cuboids);
+ res = darray_cuboid_resize(&parser->cuboids, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, cuboid, "could not allocate the cuboid shape.\n");
+ goto exit;
+ }
+ shape = darray_cuboid_data_get(&parser->cuboids) + ishape;
+
+ n = cuboid->data.mapping.pairs.top - cuboid->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, cuboid->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, cuboid->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect cuboid parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(!strcmp((char*)key->data.scalar.value, "size")) {
+ if(mask & BIT(SIZE)) {
+ log_err(parser, key, "the cuboid size is already defined.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ mask |= BIT(SIZE);
+ res = parse_real3(parser, doc, val, 0, DBL_MAX, shape->size);
+ } else {
+ log_err(parser, key, "unknown cuboid parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ }
+
+ if(!(mask & BIT(SIZE))) {
+ log_err(parser, cuboid, "the size of the cuboid is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ out_ishape->i = ishape;
+ return res;
+error:
+ if(shape) {
+ darray_cuboid_pop_back(&parser->cuboids);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_cylinder
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* cylinder,
+ struct solparser_shape_cylinder_id* out_ishape)
+{
+ enum { HEIGHT, RADIUS, SLICES };
+ struct solparser_shape_cylinder* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && cylinder && out_ishape);
+
+ if(cylinder->type != YAML_MAPPING_NODE) {
+ log_err(parser, cylinder, "expect a mapping of cylinder parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a cylinder */
+ ishape = darray_cylinder_size_get(&parser->cylinders);
+ res = darray_cylinder_resize(&parser->cylinders, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, cylinder, "could not alocate the cylinder shape.\n");
+ goto exit;
+ }
+ shape = darray_cylinder_data_get(&parser->cylinders) + ishape;
+
+ n = cylinder->data.mapping.pairs.top - cylinder->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, cylinder->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, cylinder->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect cylinder parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the cylinder parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "height")) {
+ SETUP_MASK(HEIGHT, "height");
+ res = parse_real(parser, val, 0, DBL_MAX, &shape->height);
+ } else if(!strcmp((char*)key->data.scalar.value, "radius")) {
+ SETUP_MASK(RADIUS, "radius");
+ res = parse_real(parser, val, 0, DBL_MAX, &shape->radius);
+ } else if(!strcmp((char*)key->data.scalar.value, "slices")) {
+ SETUP_MASK(SLICES, "slices");
+ res = parse_integer(parser, val, 4, 4096, &shape->nslices);
+ } else {
+ log_err(parser, key, "unknown cylinder parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, cylinder, \
+ "the cylinder parameter `"Name"' is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(HEIGHT, "height");
+ CHECK_PARAM(RADIUS, "radius");
+ #undef CHECK_PARAM
+
+exit:
+ out_ishape->i = ishape;
+ return res;
+error:
+ if(shape) {
+ darray_cylinder_pop_back(&parser->cylinders);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_imported_geometry
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* geom,
+ const enum solparser_shape_type type,
+ struct solparser_shape_imported_geometry_id* out_ishape)
+{
+ enum { PATH };
+ struct solparser_shape_imported_geometry* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ const char* name;
+ struct darray_impgeom* impgeoms;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && geom && out_ishape);
+
+ switch(type) {
+ case SOLPARSER_SHAPE_OBJ: name = "obj"; impgeoms = &parser->objs; break;
+ case SOLPARSER_SHAPE_STL: name = "stl"; impgeoms = &parser->stls; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+
+ if(geom->type != YAML_MAPPING_NODE) {
+ log_err(parser, geom, "expect a mapping of %s parameters.\n", name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate an imported geometry */
+ ishape = darray_impgeom_size_get(impgeoms);
+ res = darray_impgeom_resize(impgeoms, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, geom, "could not allocate the %s shape.\n", name);
+ goto error;
+ }
+ shape = darray_impgeom_data_get(impgeoms) + ishape;
+
+ n = geom->data.mapping.pairs.top - geom->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, geom->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, geom->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect %s parameters.\n", name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(!strcmp((char*)key->data.scalar.value, "path")) {
+ if(mask & BIT(PATH)) {
+ log_err(parser, key, "the %s path is already defined.\n", name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ mask |= BIT(PATH);
+ res = parse_string(parser, val, &shape->filename);
+ } else {
+ log_err(parser, key, "unknown %s parameter `%s'.\n",
+ name, key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ }
+
+ if(!(mask & BIT(PATH))) {
+ log_err(parser, geom, "the path of the %s geometry is missing.\n", name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ out_ishape->i = ishape;
+ return res;
+error:
+ if(shape) {
+ darray_impgeom_pop_back(impgeoms);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_paraboloid
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* paraboloid,
+ const enum solparser_shape_type type,
+ struct solparser_shape_paraboloid_id* out_ishape)
+{
+ enum { CLIP, FOCAL };
+ struct solparser_shape_paraboloid* shape = NULL;
+ struct darray_paraboloid* paraboloids;
+ const char* name;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && paraboloid && out_ishape);
+
+ switch(type) {
+ case SOLPARSER_SHAPE_PARABOL:
+ name = "parabol";
+ paraboloids = &parser->parabols;
+ break;
+ case SOLPARSER_SHAPE_PARABOLIC_CYLINDER:
+ name = "parabolic cylinder";
+ paraboloids = &parser->parabolic_cylinders;
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+
+ if(paraboloid->type != YAML_MAPPING_NODE) {
+ log_err(parser, paraboloid, "expect a mapping of %s parameters.\n", name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a paraboloid shape */
+ ishape = darray_paraboloid_size_get(paraboloids);
+ res = darray_paraboloid_resize(paraboloids, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, paraboloid, "could not allocate the %s shape.\n", name);
+ goto error;
+ }
+ shape = darray_paraboloid_data_get(paraboloids) + ishape;
+
+ n = paraboloid->data.mapping.pairs.top - paraboloid->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, paraboloid->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, paraboloid->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect %s parameters.\n", name);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the %s parameter `"Name"' is already defined.\n", name); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "clip")) {
+ SETUP_MASK(CLIP, "clip");
+ res = parse_clip(parser, doc, val, &shape->polyclips);
+ } else if(!strcmp((char*)key->data.scalar.value, "focal")) {
+ SETUP_MASK(FOCAL, "focal");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &shape->focal);
+ } else {
+ log_err(parser, key, "unknown %s parameter `%s'.\n",
+ name, key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, paraboloid, \
+ "the %s parameter `"Name"' is missing.\n", name); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(CLIP, "clip");
+ CHECK_PARAM(FOCAL, "focal");
+ #undef CHECK_PARAM
+
+exit:
+ out_ishape->i = ishape;
+ return res;
+error:
+ if(shape) {
+ darray_paraboloid_pop_back(paraboloids);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_plane
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* plane,
+ struct solparser_shape_plane_id* out_ishape)
+{
+ enum { CLIP };
+ struct solparser_shape_plane* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && plane && out_ishape);
+
+ if(plane->type != YAML_MAPPING_NODE) {
+ log_err(parser, plane, "expect a mapping of plane parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a plane shape */
+ ishape = darray_plane_size_get(&parser->planes);
+ res = darray_plane_resize(&parser->planes, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, plane, "could not allocate the plane shape.\n");
+ goto error;
+ }
+ shape = darray_plane_data_get(&parser->planes) + ishape;
+
+ n = plane->data.mapping.pairs.top - plane->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, plane->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, plane->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect plane parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(!strcmp((char*)key->data.scalar.value, "clip")) {
+ if(mask & BIT(CLIP)) {
+ log_err(parser, key, "the plane clipping is already defined.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ mask |= BIT(CLIP);
+ res = parse_clip(parser, doc, val, &shape->polyclips);
+ } else {
+ log_err(parser, key, "unknown plane parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ }
+ if(!(mask & BIT(CLIP))) {
+ log_err(parser, plane, "the plane parameter `clip' is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ out_ishape->i = ishape;
+ return res;
+error:
+ if(shape) {
+ darray_plane_pop_back(&parser->planes);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_sphere
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* sphere,
+ struct solparser_shape_sphere_id* out_ishape)
+{
+ enum { RADIUS, SLICES };
+ struct solparser_shape_sphere* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && sphere && out_ishape);
+
+ if(sphere->type != YAML_MAPPING_NODE) {
+ log_err(parser, sphere, "expect a mapping of sphere parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a shpere shape */
+ ishape = darray_sphere_size_get(&parser->spheres);
+ res = darray_sphere_resize(&parser->spheres, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, sphere, "could not allocate the sphere shape.\n");
+ goto error;
+ }
+ shape = darray_sphere_data_get(&parser->spheres) + ishape;
+
+ n = sphere->data.mapping.pairs.top - sphere->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, sphere->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, sphere->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect sphere parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the sphere parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "radius")) {
+ SETUP_MASK(RADIUS, "radius");
+ res = parse_real(parser, val, 0, DBL_MAX, &shape->radius);
+ } else if(!strcmp((char*)key->data.scalar.value, "slices")) {
+ SETUP_MASK(SLICES, "slices");
+ res = parse_integer(parser, val, 4, 4096, &shape->nslices);
+ } else {
+ log_err(parser, key, "unknown sphere parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ if(!(mask & BIT(RADIUS))) {
+ log_err(parser, sphere, "the sphere radius is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ out_ishape->i = ishape;
+ return res;
+error:
+ if(shape) {
+ darray_sphere_pop_back(&parser->spheres);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Geometry
+ ******************************************************************************/
+static res_T
+parse_object
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* object,
+ struct solparser_object_id* out_iobj)
+{
+ enum { MATERIAL, SHAPE, TRANSFORM };
+ struct solparser_object* obj = NULL;
+ struct solparser_shape* shape = NULL;
+ size_t iobj = SIZE_MAX;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && object && out_iobj);
+
+ if(object->type != YAML_MAPPING_NODE) {
+ log_err(parser, object, "expect an object definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate an object */
+ iobj = darray_object_size_get(&parser->objects);
+ res = darray_object_resize(&parser->objects, iobj + 1);
+ if(res != RES_OK) {
+ log_err(parser, object, "could not allocate the object.\n");
+ goto error;
+ }
+ obj = darray_object_data_get(&parser->objects) + iobj;
+
+ /* Allocate a shape */
+ ishape = darray_shape_size_get(&parser->shapes);
+ res = darray_shape_resize(&parser->shapes, ishape + 1);
+ if(res != RES_OK) {
+ log_err(parser, object, "could not allocate the object shape.\n");
+ goto error;
+ }
+ shape = darray_shape_data_get(&parser->shapes) + ishape;
+ obj->shape.i = ishape;
+
+ /* Setup default object transformation */
+ d3_splat(obj->translation, 0);
+ d3_splat(obj->rotation, 0);
+
+ n = object->data.mapping.pairs.top - object->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, object->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, object->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect an object parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the object "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "material")) {
+ SETUP_MASK(MATERIAL, "material");
+ res = parse_material(parser, doc, val, &obj->mtl2);
+ } else if(!strcmp((char*)key->data.scalar.value, "cuboid")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_CUBOID;
+ res = parse_cuboid(parser, doc, val, &shape->data.cuboid);
+ } else if(!strcmp((char*)key->data.scalar.value, "cylinder")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_CYLINDER;
+ res = parse_cylinder(parser, doc, val, &shape->data.cylinder);
+ } else if(!strcmp((char*)key->data.scalar.value, "obj")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_OBJ;
+ res = parse_imported_geometry
+ (parser, doc, val, shape->type, &shape->data.obj);
+ } else if(!strcmp((char*)key->data.scalar.value, "parabol")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_PARABOL;
+ res = parse_paraboloid
+ (parser, doc, val, shape->type, &shape->data.parabol);
+ } else if(!strcmp((char*)key->data.scalar.value, "parabolic-cylinder")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_PARABOLIC_CYLINDER;
+ res = parse_paraboloid
+ (parser, doc, val, shape->type, &shape->data.parabolic_cylinder);
+ } else if(!strcmp((char*)key->data.scalar.value, "plane")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_PLANE;
+ res = parse_plane(parser, doc, val, &shape->data.plane);
+ } else if(!strcmp((char*)key->data.scalar.value, "sphere")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_SPHERE;
+ res = parse_sphere(parser, doc, val, &shape->data.sphere);
+ } else if(!strcmp((char*)key->data.scalar.value, "stl")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_STL;
+ res = parse_imported_geometry
+ (parser, doc, val, shape->type, &shape->data.stl);
+ } else if(!strcmp((char*)key->data.scalar.value, "transform")) {
+ SETUP_MASK(TRANSFORM, "transform");
+ res = parse_transform(parser, doc, val, obj->translation, obj->rotation);
+ } else {
+ log_err(parser, key, "unknown object parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, object, "the object "Name" is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(MATERIAL, "material");
+ CHECK_PARAM(SHAPE, "shape");
+ #undef CHECK_PARAM
+
+exit:
+ out_iobj->i = iobj;
+ return res;
+error:
+ if(obj) {
+ if(shape) darray_shape_pop_back(&parser->shapes);
+ darray_object_pop_back(&parser->objects);
+ obj = NULL;
+ }
+ goto exit;
+}
+
+static res_T
+parse_geometry
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* geometry,
+ struct solparser_geometry_id* out_isolgeom)
+{
+ struct solparser_geometry* solgeom = NULL;
+ size_t* pisolgeom;
+ size_t isolgeom = SIZE_MAX;
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && geometry && out_isolgeom);
+
+ if(geometry->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, geometry, "expect a list of objects.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Check whether or not the YAML descriptor alias an already created Solstice
+ * geometry */
+ pisolgeom = htable_yaml2sols_find(&parser->yaml2geoms, &geometry);
+ if(pisolgeom) {
+ isolgeom = *pisolgeom;
+ goto exit;
+ }
+
+ /* Allocate the geometry */
+ isolgeom = darray_geometry_size_get(&parser->geometries);
+ res = darray_geometry_resize(&parser->geometries, isolgeom + 1);
+ if(res != RES_OK) {
+ log_err(parser, geometry, "could not allocate the geometry.\n");
+ goto error;
+ }
+ solgeom = darray_geometry_data_get(&parser->geometries) + isolgeom;
+
+ n = geometry->data.sequence.items.top - geometry->data.sequence.items.start;
+ res = darray_object_id_resize(&solgeom->objects, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, geometry, "could not allocate the objects list.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ struct solparser_object_id* obj_id;
+ yaml_node_t* obj;
+
+ obj_id = darray_object_id_data_get(&solgeom->objects) + i;
+ obj = yaml_document_get_node(doc, geometry->data.sequence.items.start[i]);
+ res = parse_object(parser, doc, obj, obj_id);
+ if(res != RES_OK) goto error;
+ }
+
+ /* Cache the geometry */
+ res = htable_yaml2sols_set(&parser->yaml2geoms, &geometry, &isolgeom);
+ if(res != RES_OK) {
+ log_err(parser, geometry, "could not register the geometry.\n");
+ goto error;
+ }
+
+exit:
+ out_isolgeom->i = isolgeom;
+ return res;
+error:
+ if(solgeom) {
+ darray_geometry_pop_back(&parser->geometries);
+ isolgeom = SIZE_MAX;
+ }
+ goto exit;
+}
+
+
+/*******************************************************************************
+ * Entity
+ ******************************************************************************/
+static res_T
+entity_register_name
+ (struct solparser* parser,
+ const yaml_node_t* entity,
+ struct htable_str2sols* htable,
+ const size_t isolent)
+{
+ struct solparser_entity* solent;
+ size_t* pisolent;
+ res_T res = RES_OK;
+ ASSERT(parser && htable);
+ ASSERT(isolent < darray_entity_size_get(&parser->entities));
+
+ solent = darray_entity_data_get(&parser->entities) + isolent;
+
+ pisolent = htable_str2sols_find(htable, &solent->name);
+ if(pisolent) {
+ log_err(parser, entity,
+ "an entity with the name `%s' is already defined in the current context.\n",
+ str_cget(&solent->name));
+ return RES_BAD_ARG;
+ }
+
+ res = htable_str2sols_set(htable, &solent->name, &isolent);
+ if(res != RES_OK) {
+ log_err(parser, entity, "could not register the entity.\n");
+ return res;
+ }
+ return RES_OK;
+}
+
+static res_T
+anchor_register_name
+ (struct solparser* parser,
+ const yaml_node_t* anchor,
+ struct htable_str2sols* htable,
+ const size_t isolanchor)
+{
+ struct solparser_anchor* solanchor;
+ size_t* pisolanchor;
+ res_T res = RES_OK;
+ ASSERT(parser && htable);
+ ASSERT(isolanchor < darray_anchor_size_get(&parser->anchors));
+
+ solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor;
+
+ pisolanchor = htable_str2sols_find(htable, &solanchor->name);
+ if(pisolanchor) {
+ log_err(parser, anchor,
+ "an anchor with the name `%s' is already defined in the cunrrent context.\n",
+ str_cget(&solanchor->name));
+ return RES_BAD_ARG;
+ }
+
+ res = htable_str2sols_set(htable, &solanchor->name, &isolanchor);
+ if(res != RES_OK) {
+ log_err(parser, anchor, "could not register the anchor.\n");
+ return res;
+ }
+ return RES_OK;
+}
+
+static res_T
+parse_identifier_string
+ (struct solparser* parser,
+ yaml_node_t* name,
+ struct str* str)
+{
+ res_T res = RES_OK;
+ ASSERT(parser && name && str);
+
+ res = parse_string(parser, name, str);
+ if(res != RES_OK) goto error;
+
+ if(strchr(str_cget(str), '.')) {
+ log_err(parser, name, "invalid character `.' in the name `%s'.\n",
+ str_cget(str));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_anchor
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* anchor,
+ struct htable_str2sols* htable,
+ struct solparser_anchor_id* out_isolanchor)
+{
+ enum { NAME, POSITION };
+ struct solparser_anchor* solanchor = NULL;
+ size_t isolanchor = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(parser && anchor && out_isolanchor);
+
+ if(anchor->type != YAML_MAPPING_NODE) {
+ log_err(parser, anchor, "expect an anchor definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the anchor */
+ isolanchor = darray_anchor_size_get(&parser->anchors);
+ res = darray_anchor_resize(&parser->anchors, isolanchor + 1);
+ if(res != RES_OK) {
+ log_err(parser, anchor, "could not allocate the anchor.\n");
+ goto error;
+ }
+ solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor;
+
+ n = anchor->data.mapping.pairs.top - anchor->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect an anchor attribute.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, "the anchor "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "name")) {
+ SETUP_MASK(NAME, "name");
+ res = parse_identifier_string(parser, val, &solanchor->name);
+ } else if(!strcmp((char*)key->data.scalar.value, "position")) {
+ SETUP_MASK(POSITION, "position");
+ res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solanchor->position);
+ } else {
+ log_err(parser, key, "unknown anchor parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, anchor, "the anchor "Name" is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(NAME, "name");
+ CHECK_PARAM(POSITION, "position");
+ #undef CHECK_PARAM
+
+ res = anchor_register_name(parser, anchor, htable, isolanchor);
+ if(res != RES_OK) goto error;
+
+exit:
+ out_isolanchor->i = isolanchor;
+ return res;
+error:
+ if(solanchor) {
+ darray_anchor_pop_back(&parser->anchors);
+ isolanchor = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
+parse_anchors
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* anchors,
+ struct htable_str2sols* htable,
+ struct darray_anchor_id* solanchors)
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(parser && anchors);
+
+ if(anchors->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, anchors, "expect a list of anchors.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = anchors->data.sequence.items.top - anchors->data.sequence.items.start;
+ res = darray_anchor_id_resize(solanchors, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, anchors, "could not allocate the anchors list.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ struct solparser_anchor_id* anchor_id;
+ yaml_node_t* anchor;
+
+ anchor_id = darray_anchor_id_data_get(solanchors)+i;
+ anchor = yaml_document_get_node(doc, anchors->data.sequence.items.start[i]);
+ res = parse_anchor(parser, doc, anchor, htable, anchor_id);
+ if(res != RES_OK) goto error;
+ }
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_children
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* children,
+ struct htable_str2sols* htable,
+ struct darray_child_id* entities)
+{
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(parser && children && htable && entities);
+
+ if(children->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, children, "expect a list of entities.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = children->data.sequence.items.top - children->data.sequence.items.start;
+ res = darray_child_id_resize(entities, (size_t)n);
+ if(res != RES_OK) {
+ log_err(parser, children, "could not allocate the children list.\n");
+ goto error;
+ }
+
+ FOR_EACH(i, 0, n) {
+ struct solparser_entity_id* entity_id = darray_child_id_data_get(entities) + i;
+ yaml_node_t* child;
+
+ child = yaml_document_get_node(doc, children->data.sequence.items.start[i]);
+ res = parse_entity(parser, doc, child, htable, entity_id);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ darray_child_id_clear(entities);
+ goto exit;
+}
+
+res_T
+parse_entity
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ yaml_node_t* entity,
+ struct htable_str2sols* htable,
+ struct solparser_entity_id* out_isolent)
+{
+ enum { ANCHORS, CHILDREN, DATA, NAME, TRANSFORM };
+ struct solparser_entity solent;
+ struct solparser_entity* psolent;
+ const size_t *pisolent;
+ size_t isolent = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && entity && htable && out_isolent);
+
+ solparser_entity_init(parser->allocator, &solent);
+
+ pisolent = htable_yaml2sols_find(&parser->yaml2entities, &entity);
+ if(pisolent) {
+ isolent = *pisolent;
+ res = entity_register_name(parser, entity, htable, *pisolent);
+ if(res != RES_OK) goto error;
+ goto exit;
+ }
+
+ if(entity->type != YAML_MAPPING_NODE) {
+ log_err(parser, entity, "expect an entity definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the entity but *DO NOT* retrieve a pointer onto it since the
+ * allocation of its children may update its memory location. Use the "on
+ * stack" entity `solent' instead. */
+ isolent = darray_entity_size_get(&parser->entities);
+ res = darray_entity_resize(&parser->entities, isolent + 1);
+ if(res != RES_OK) {
+ log_err(parser, entity, "could not allocate the entity.\n");
+ goto error;
+ }
+
+ n = entity->data.mapping.pairs.top - entity->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, entity->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, entity->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect an entity attribute.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the entity "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "anchors")) {
+ SETUP_MASK(ANCHORS, "anchors");
+ res = parse_anchors
+ (parser, doc, val, &solent.str2anchors, &solent.anchors);
+ } else if(!strcmp((char*)key->data.scalar.value, "children")) {
+ SETUP_MASK(CHILDREN, "children");
+ res = parse_children
+ (parser, doc, val, &solent.str2children, &solent.children);
+ } else if(!strcmp((char*)key->data.scalar.value, "geometry")) {
+ SETUP_MASK(DATA, "data");
+ solent.type = SOLPARSER_ENTITY_GEOMETRY;
+ res = parse_geometry(parser, doc, val, &solent.data.geometry);
+ } else if(!strcmp((char*)key->data.scalar.value, "name")) {
+ SETUP_MASK(NAME, "name");
+ res = parse_identifier_string(parser, val, &solent.name);
+ } else if(!strcmp((char*)key->data.scalar.value, "pivot")) {
+ SETUP_MASK(DATA, "data");
+ solent.type = SOLPARSER_ENTITY_PIVOT;
+ res = parse_pivot(parser, doc, val, &solent.data.pivot);
+ } else if(!strcmp((char*)key->data.scalar.value, "transform")) {
+ SETUP_MASK(TRANSFORM, "transform");
+ res = parse_transform
+ (parser, doc, val, solent.translation, solent.rotation);
+ } else {
+ log_err(parser, key, "unknown entity parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ if(!(mask & BIT(DATA))) {
+ solent.type = SOLPARSER_ENTITY_EMPTY;
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, entity, "the entity "Name" is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(NAME, "name");
+ #undef CHECK_PARAM
+
+ psolent = darray_entity_data_get(&parser->entities) + isolent;
+ res = solparser_entity_copy_and_clear(psolent, &solent);
+ if(res != RES_OK) {
+ log_err(parser, entity,
+ "could not copy the loaded entity into the parser data structures.\n");
+ goto error;
+ }
+ res = entity_register_name(parser, entity, htable, isolent);
+ if(res != RES_OK) goto error;
+
+ res = htable_yaml2sols_set(&parser->yaml2entities, &entity, &isolent);
+ if(res != RES_OK) {
+ log_err(parser, entity, "could not register the entity.\n");
+ goto error;
+ }
+
+exit:
+ solparser_entity_release(&solent);
+ out_isolent->i = isolent;
+ return res;
+error:
+ if(isolent != SIZE_MAX) {
+ htable_str2sols_erase(htable, &solent.name);
+ darray_entity_pop_back(&parser->entities);
+ isolent = SIZE_MAX;
+ }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Pivot
+ ******************************************************************************/
+static res_T
+parse_anchor_alias
+ (struct solparser* parser,
+ const yaml_node_t* alias,
+ struct solparser_anchor_id* out_ianchor)
+{
+ const struct solparser_anchor* anchor = NULL;
+ intptr_t ianchor = INTPTR_MAX;
+ res_T res = RES_OK;
+ ASSERT(parser && alias && out_ianchor);
+
+ if(alias->type != YAML_SCALAR_NODE) {
+ log_err(parser, alias, "expect an anchor idententifier.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ anchor = solparser_find_anchor(parser, (char*)alias->data.scalar.value);
+ if(!anchor) {
+ log_err(parser, alias, "undefined anchor `%s'.\n",
+ alias->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ianchor = anchor - darray_anchor_cdata_get(&parser->anchors);
+ ASSERT(ianchor >= 0);
+ ASSERT((size_t)ianchor < darray_anchor_size_get(&parser->anchors));
+
+exit:
+ out_ianchor->i = (size_t)ianchor;
+ return res;
+error:
+ ianchor = INTPTR_MAX;
+ goto exit;
+}
+
+static res_T
+parse_target
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* target,
+ struct solparser_pivot* pivot)
+{
+ enum { POLICY };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && target && pivot);
+
+ if(target->type != YAML_MAPPING_NODE) {
+ log_err(parser, target, "expect a target definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = target->data.mapping.pairs.top - target->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, target->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, target->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a target parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, "the target "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "anchor")) {
+ SETUP_MASK(POLICY, "policy");
+ pivot->target_type = SOLPARSER_TARGET_ANCHOR;
+ res = parse_anchor_alias(parser, val, &pivot->target.anchor);
+ } else if(!strcmp((char*)key->data.scalar.value, "direction")) {
+ SETUP_MASK(POLICY, "policy");
+ pivot->target_type = SOLPARSER_TARGET_DIRECTION;
+ res = parse_real3
+ (parser, doc, val, -DBL_MAX, DBL_MAX, pivot->target.direction);
+ } else if(!strcmp((char*)key->data.scalar.value, "position")) {
+ SETUP_MASK(POLICY, "policy");
+ pivot->target_type = SOLPARSER_TARGET_POSITION;
+ res = parse_real3
+ (parser, doc, val, -DBL_MAX, DBL_MAX, pivot->target.position);
+ } else if(!strcmp((char*)key->data.scalar.value, "sun")) {
+ /* There is only one sun per YAML file. It is thus sufficient to define
+ * the target_type to SOLPARSER_TARGET_SUN to indentify which data is
+ * targeted, i.e. it is not necessary to store the identifier of the sun
+ * to target */
+ struct solparser_sun* sun;
+ SETUP_MASK(POLICY, "policy");
+ pivot->target_type = SOLPARSER_TARGET_SUN;
+ res = parse_sun(parser, doc, val, &sun);
+ } else {
+ log_err(parser, key, "unknown target parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ if(!(mask & BIT(POLICY))) {
+ log_err(parser, target, "the target policy is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_pivot
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* pivot,
+ struct solparser_pivot_id* out_isolpivot)
+{
+ enum { NORMAL, POINT, TARGET, TRANSFORM };
+ struct solparser_pivot* solpivot = NULL;
+ size_t isolpivot = SIZE_MAX;
+ int mask = 0; /* Register the parsed attributes */
+ intptr_t i, n;
+ res_T res = RES_OK;
+ ASSERT(doc && pivot && out_isolpivot);
+
+ if(pivot->type != YAML_MAPPING_NODE) {
+ log_err(parser, pivot, "expect a pivot definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate the solstice pivot */
+ isolpivot = darray_pivot_size_get(&parser->pivots);
+ res = darray_pivot_resize(&parser->pivots, isolpivot + 1);
+ if(res != RES_OK) {
+ log_err(parser, pivot, "could not allocate the pivot.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ solpivot = darray_pivot_data_get(&parser->pivots) + isolpivot;
+
+ n = pivot->data.mapping.pairs.top - pivot->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, pivot->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, pivot->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect pivot parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the pivot parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "point")) {
+ SETUP_MASK(POINT, "point");
+ res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solpivot->point);
+ } else if(!strcmp((char*)key->data.scalar.value, "normal")) {
+ SETUP_MASK(NORMAL, "normal");
+ res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solpivot->normal);
+ } else if(!strcmp((char*)key->data.scalar.value, "target")) {
+ SETUP_MASK(TARGET, "target");
+ res = parse_target(parser, doc, val, solpivot);
+ } else if(!strcmp((char*)key->data.scalar.value, "transform")) {
+ SETUP_MASK(TRANSFORM, "transform");
+ res = parse_transform
+ (parser, doc, val, solpivot->translation, solpivot->rotation);
+ } else {
+ log_err(parser, key, "unknown pivot parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, pivot, "the pivot parameter `"Name"' is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(POINT, "point");
+ CHECK_PARAM(NORMAL, "normal");
+ CHECK_PARAM(TARGET, "target");
+ #undef CHECK_PARAM
+
+exit:
+ out_isolpivot->i = isolpivot;
+ return res;
+error:
+ if(solpivot) {
+ darray_pivot_pop_back(&parser->pivots);
+ isolpivot = SIZE_MAX;
+ }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Sun
+ ******************************************************************************/
+static res_T
+parse_buie
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* buie,
+ struct solparser_sun_buie* sun)
+{
+ enum { CSR };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && buie && sun);
+
+ if(buie->type != YAML_MAPPING_NODE) {
+ log_err(parser, buie,
+ "expect a buie definition of the sun radial angular distribution.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = buie->data.mapping.pairs.top - buie->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, buie->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, buie->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a buie parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!strcmp((char*)key->data.scalar.value, "csr")) {
+ if(mask & BIT(CSR)) {
+ log_err(parser, key, "the buie `csr' is already defined.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ mask |= BIT(CSR);
+ res = parse_real(parser, val, nextafter(0, 1), nextafter(1, 0), &sun->csr);
+ } else {
+ log_err(parser, key, "unknown buie parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ }
+
+ if(!(mask & BIT(CSR))) {
+ log_err(parser, buie, "the buie csr parameter is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_pillbox
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* pillbox,
+ struct solparser_sun_pillbox* sun)
+{
+ enum { APERTURE };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && pillbox && sun);
+
+ if(pillbox->type != YAML_MAPPING_NODE) {
+ log_err(parser, pillbox,
+ "expect a pillbox definition of the sun radial angular distribution.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = pillbox->data.mapping.pairs.top - pillbox->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, pillbox->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, pillbox->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a pillbox parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(!strcmp((char*)key->data.scalar.value, "aperture")) {
+ if(mask & BIT(APERTURE)) {
+ log_err(parser, key, "the pillbox `aperture' is already defined.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ mask |= BIT(APERTURE);
+ res = parse_real(parser, val, nextafter(0, 1), PI/2.0, &sun->aperture);
+ } else {
+ log_err(parser, pillbox, "unknown pillbox parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ }
+
+ if(!(mask & BIT(APERTURE))) {
+ log_err(parser, pillbox, "the pillbox aperture parameter is missing.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+parse_sun
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* sun,
+ struct solparser_sun** out_solsun)
+{
+ enum { DNI, RADIAL_ANGULAR_DISTRIB, SPECTRUM };
+ struct solparser_sun* solsun = NULL;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && sun && out_solsun);
+
+ if(sun == parser->sun_key) {
+ solsun = &parser->sun;
+ goto exit;
+ } else if(parser->sun_key != 0) {
+ log_err(parser, sun,
+ "a sun is already defined. Previous definition is here %lu:%lu.\n",
+ (unsigned long)parser->sun_key->start_mark.line+1,
+ (unsigned long)parser->sun_key->start_mark.column+1);
+ res = RES_BAD_ARG;
+ goto error;
+ } else {
+ solsun = &parser->sun;
+ parser->sun_key = sun;
+ solsun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL;
+ }
+
+ if(sun->type != YAML_MAPPING_NODE) {
+ log_err(parser, sun, "expect a sun definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = sun->data.mapping.pairs.top - sun->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, sun->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, sun->data.mapping.pairs.start[i].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect sun parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, "the sun "Name" is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "dni")) {
+ SETUP_MASK(DNI, "dni");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &solsun->dni);
+ } else if(!strcmp((char*)key->data.scalar.value, "buie")) {
+ SETUP_MASK(RADIAL_ANGULAR_DISTRIB, "radial angular distribution");
+ solsun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_BUIE;
+ res = parse_buie(parser, doc, val, &solsun->radang_distrib.buie);
+ } else if(!strcmp((char*)key->data.scalar.value, "pillbox")) {
+ SETUP_MASK(RADIAL_ANGULAR_DISTRIB, "radial angular distribution");
+ solsun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX;
+ res = parse_pillbox(parser, doc, val, &solsun->radang_distrib.pillbox);
+ } else if(!strcmp((char*)key->data.scalar.value, "spectrum")) {
+ SETUP_MASK(SPECTRUM, "spectrum");
+ res = parse_spectrum(parser, doc, 0, DBL_MAX, val, &solsun->spectrum);
+ } else {
+ log_err(parser, key, "unknown sun parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+ #undef SETUP_MASK
+ }
+
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, sun, "the sun "Name" is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(DNI, "dni");
+ CHECK_PARAM(SPECTRUM, "spectrum");
+ #undef CHECK_PARAM
+
+exit:
+ *out_solsun = solsun;
+ return res;
+error:
+ if(solsun) {
+ solparser_sun_clear(solsun);
+ solsun = NULL;
+ parser->sun_key = 0;
+ }
+ goto exit;
+}
+
+/*******************************************************************************
+ * Item
+ ******************************************************************************/
+static res_T
+parse_item
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* item)
+{
+ yaml_node_t* key;
+ yaml_node_t* val;
+ struct solparser_material_double_sided_id mtl2; /* TODO */
+ struct solparser_entity_id entity; /* TODO */
+ struct solparser_geometry_id geometry; /* TODO */
+ struct solparser_sun* sun; /* TODO */
+ intptr_t n;
+ res_T res = RES_OK;
+ ASSERT(doc && item);
+
+ if(item->type != YAML_MAPPING_NODE) {
+ log_err(parser, item, "expect an item definition.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = item->data.mapping.pairs.top - item->data.mapping.pairs.start;
+ if(n != 1) {
+ log_err(parser, item,
+ "expect only one \"key:value\" pair while %li are provided.\n", n);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ key = yaml_document_get_node(doc, item->data.mapping.pairs.start[0].key);
+ val = yaml_document_get_node(doc, item->data.mapping.pairs.start[0].value);
+ if(key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expecting an item name.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!strcmp((char*)key->data.scalar.value, "material")) {
+ res = parse_material(parser, doc, val, &mtl2);
+ } else if(!strcmp((char*)key->data.scalar.value, "entity")) {
+ res = parse_entity(parser, doc, val, &parser->str2entities, &entity);
+ } else if(!strcmp((char*)key->data.scalar.value, "template")) {
+ /* The parsing of the template data is deferred to its explicit used in the
+ * definition of an entity. If the parsing of the template becomes a
+ * bottleneck, parse the data only once here and cache them for reuse. */
+ } else if(!strcmp((char*)key->data.scalar.value, "geometry")) {
+ res = parse_geometry(parser, doc, val, &geometry);
+ } else if(!strcmp((char*)key->data.scalar.value, "sun")) {
+ res = parse_sun(parser, doc, val, &sun);
+ } else {
+ log_err(parser, key, "unknown item `%s'.\n", key->data.scalar.value);
+ res = RES_BAD_ARG;
+ }
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+solparser_create
+ (struct mem_allocator* allocator, struct solparser** out_parser)
+{
+ struct solparser* parser = NULL;
+ struct mem_allocator* mem_allocator;
+ res_T res = RES_OK;
+ ASSERT(out_parser);
+
+ mem_allocator = allocator ? allocator : &mem_default_allocator;
+ parser = MEM_CALLOC(mem_allocator, 1, sizeof(struct solparser));
+ if(!parser) {
+ fprintf(stderr, "Could not allocat the Solstice parser.\n");
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ parser->allocator = mem_allocator;
+ ref_init(&parser->ref);
+ str_init(mem_allocator, &parser->stream_name);
+
+ /* Materials */
+ htable_yaml2sols_init(mem_allocator, &parser->yaml2mtls);
+ darray_material_init(mem_allocator, &parser->mtls);
+ darray_material2_init(mem_allocator, &parser->mtls2);
+ darray_matte_init(mem_allocator, &parser->mattes);
+ darray_mirror_init(mem_allocator, &parser->mirrors);
+
+ /* Shapes */
+ darray_shape_init(mem_allocator, &parser->shapes);
+ darray_cuboid_init(mem_allocator, &parser->cuboids);
+ darray_cylinder_init(mem_allocator, &parser->cylinders);
+ darray_impgeom_init(mem_allocator, &parser->objs);
+ darray_paraboloid_init(mem_allocator, &parser->parabols);
+ darray_paraboloid_init(mem_allocator, &parser->parabolic_cylinders);
+ darray_plane_init(mem_allocator, &parser->planes);
+ darray_sphere_init(mem_allocator, &parser->spheres);
+ darray_impgeom_init(mem_allocator, &parser->stls);
+
+ /* Geometries */
+ htable_yaml2sols_init(mem_allocator, &parser->yaml2geoms);
+ darray_object_init(mem_allocator, &parser->objects);
+ darray_geometry_init(mem_allocator, &parser->geometries);
+
+ /* Sun */
+ solparser_sun_init(mem_allocator, &parser->sun);
+
+ /* Entities */
+ htable_yaml2sols_init(mem_allocator, &parser->yaml2entities);
+ htable_str2sols_init(mem_allocator, &parser->str2entities);
+ darray_entity_init(mem_allocator, &parser->entities);
+
+ /* Anchors */
+ darray_anchor_init(mem_allocator, &parser->anchors);
+ darray_pivot_init(mem_allocator, &parser->pivots);
+
+exit:
+ *out_parser = parser;
+ return res;
+error:
+ if(parser) {
+ solparser_ref_put(parser);
+ parser = NULL;
+ }
+ goto exit;
+}
+
+void
+solparser_ref_get(struct solparser* parser)
+{
+ ASSERT(parser);
+ ref_get(&parser->ref);
+}
+
+void
+solparser_ref_put(struct solparser* parser)
+{
+ ASSERT(parser);
+ ref_put(&parser->ref, parser_release);
+}
+
+res_T
+solparser_setup
+ (struct solparser* parser,
+ const char* stream_name,
+ FILE* stream)
+{
+ res_T res = RES_OK;
+ ASSERT(parser && stream );
+
+ if(parser->parser_is_init) {
+ yaml_parser_delete(&parser->parser);
+ parser->parser_is_init = 0;
+ }
+ res = str_set(&parser->stream_name, stream_name ? stream_name : "<stream>");
+ if(res != RES_OK) {
+ fprintf(stderr, "Could not register the filename.\n");
+ goto error;
+ }
+ if(!yaml_parser_initialize(&parser->parser)) {
+ fprintf(stderr, "Could not initialise the YAML parser.\n");
+ res = RES_UNKNOWN_ERR;
+ goto error;
+ }
+ parser->parser_is_init = 1;
+ yaml_parser_set_input_file(&parser->parser, stream);
+
+exit:
+ return res;
+error:
+ str_clear(&parser->stream_name);
+ if(parser->parser_is_init) {
+ yaml_parser_delete(&parser->parser);
+ parser->parser_is_init = 0;
+ }
+ goto exit;
+}
+
+res_T
+solparser_load(struct solparser* parser)
+{
+ yaml_document_t doc;
+ yaml_node_t* root;
+ const char* filename;
+ intptr_t i, n;
+ int doc_is_init = 0;
+ res_T res = RES_OK;
+ ASSERT(parser);
+
+ filename = str_cget(&parser->stream_name);
+
+ parser_clear(parser); /* Clean up previously loaded data */
+
+ if(!parser->parser_is_init) {
+ res = RES_BAD_OP;
+ goto error;
+ }
+
+ if(!yaml_parser_load(&parser->parser, &doc)) {
+ fprintf(stderr, "%s:%lu:%lu: %s.\n",
+ filename,
+ (unsigned long)parser->parser.problem_mark.line+1,
+ (unsigned long)parser->parser.problem_mark.column+1,
+ parser->parser.problem);
+ yaml_parser_delete(&parser->parser);
+ parser->parser_is_init = 0;
+ res = RES_BAD_OP;
+ goto error;
+ }
+ doc_is_init = 1;
+
+ root = yaml_document_get_root_node(&doc);
+ if(!root) {
+ yaml_parser_delete(&parser->parser);
+ parser->parser_is_init = 0;
+ res = RES_BAD_OP;
+ goto error;
+ }
+
+ if(root->type != YAML_SEQUENCE_NODE) {
+ log_err(parser, root, "expect a list of items.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = root->data.sequence.items.top - root->data.sequence.items.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* item;
+
+ item = yaml_document_get_node(&doc, root->data.sequence.items.start[i]);
+ res = parse_item(parser, &doc, item);
+ if(res != RES_OK) goto error;
+ }
+
+ if(!parser->sun_key) {
+ log_err(parser, root, "%s: no sun definition in the document.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ if(doc_is_init) yaml_document_delete(&doc);
+ return res;
+error:
+ parser_clear(parser);
+ goto exit;
+}
+
+const struct solparser_anchor*
+solparser_find_anchor
+ (struct solparser* parser, const char* name)
+{
+ struct str str;
+ struct str str_tk;
+ struct htable_str2sols* htable = NULL;
+ struct solparser_entity* entity = NULL;
+ struct solparser_anchor* anchor = NULL;
+ char* cstr;
+ char* tk;
+ char* tk_anchor;
+ res_T res = RES_OK;
+ ASSERT(parser && name);
+
+ str_init(parser->allocator, &str);
+ str_init(parser->allocator, &str_tk);
+
+ res = str_set(&str, name);
+ if(res != RES_OK) {
+ fprintf(stderr, "%s: could not copy the input string.\n", FUNC_NAME);
+ goto error;
+ }
+ res = str_reserve(&str_tk, str_len(&str));
+ if(res != RES_OK) {
+ fprintf(stderr, "%s: could not allocate the temporary token string.\n",
+ FUNC_NAME);
+ goto error;
+ }
+
+ cstr = str_get(&str);
+ tk_anchor = strrchr(cstr, '.');
+ if(!tk_anchor) goto exit;
+ *tk_anchor='\0';
+ ++tk_anchor;
+
+ tk = strtok(cstr, ".");
+ htable = &parser->str2entities;
+ while(tk) {
+ size_t* pientity;
+ str_set(&str_tk, tk);
+ pientity = htable_str2sols_find(htable, &str_tk);
+ if(!pientity) {
+ tk = NULL;
+ entity = NULL;
+ } else {
+ tk = strtok(NULL, ".");
+ entity = darray_entity_data_get(&parser->entities) + *pientity;
+ htable = &entity->str2children;
+ }
+ }
+
+ if(entity) {
+ size_t* pianchor;
+ str_set(&str_tk, tk_anchor);
+ pianchor = htable_str2sols_find(&entity->str2anchors, &str_tk);
+ if(pianchor) {
+ anchor = darray_anchor_data_get(&parser->anchors) + *pianchor;
+ }
+ }
+
+exit:
+ str_release(&str);
+ str_release(&str_tk);
+ return anchor;
+error:
+ anchor = NULL;
+ goto exit;
+}
+
+const struct solparser_entity*
+solparser_find_entity
+ (struct solparser* parser, const char* name)
+{
+ struct htable_str2sols* htable = NULL;
+ struct solparser_entity* entity = NULL;
+ struct str str;
+ struct str str_tk;
+ char* cstr;
+ char* tk;
+ res_T res = RES_OK;
+ ASSERT(parser && name);
+
+ str_init(parser->allocator, &str);
+ str_init(parser->allocator, &str_tk);
+
+ res = str_set(&str, name);
+ if(res != RES_OK) {
+ fprintf(stderr, "%s: could not copy the input string.\n", FUNC_NAME);
+ goto error;
+ }
+ res = str_reserve(&str_tk, str_len(&str));
+ if(res != RES_OK) {
+ fprintf(stderr, "%s: could not allocate the temporary token sting.\n",
+ FUNC_NAME);
+ goto error;
+ }
+
+ cstr = str_get(&str);
+ tk = strtok(cstr, ".");
+ htable = &parser->str2entities;
+ while(tk) {
+ size_t* pientity;
+ str_set(&str_tk, tk);
+ pientity = htable_str2sols_find(htable, &str_tk);
+ if(!pientity) {
+ tk = NULL;
+ entity = NULL;
+ } else {
+ tk = strtok(NULL, ".");
+ entity = darray_entity_data_get(&parser->entities) + *pientity;
+ htable = &entity->str2children;
+ }
+ }
+
+exit:
+ str_release(&str);
+ str_release(&str_tk);
+ return entity;
+error:
+ entity = NULL;
+ goto exit;
+}
+
+const struct solparser_anchor*
+solparser_get_anchor
+ (const struct solparser* parser,
+ const struct solparser_anchor_id anchor)
+{
+ ASSERT(parser && anchor.i < darray_anchor_size_get(&parser->anchors));
+ return darray_anchor_cdata_get(&parser->anchors) + anchor.i;
+}
+
+const struct solparser_entity*
+solparser_get_entity
+ (const struct solparser* parser,
+ const struct solparser_entity_id entity)
+{
+ ASSERT(parser && entity.i < darray_entity_size_get(&parser->entities));
+ return darray_entity_cdata_get(&parser->entities) + entity.i;
+}
+
+const struct solparser_geometry*
+solparser_get_geometry
+ (const struct solparser* parser,
+ const struct solparser_geometry_id geom)
+{
+ ASSERT(parser && geom.i < darray_geometry_size_get(&parser->geometries));
+ return darray_geometry_cdata_get(&parser->geometries) + geom.i;
+}
+
+const struct solparser_material*
+solparser_get_material
+ (const struct solparser* parser,
+ const struct solparser_material_id mtl)
+{
+ ASSERT(parser && mtl.i < darray_material_size_get(&parser->mtls));
+ return darray_material_cdata_get(&parser->mtls) + mtl.i;
+}
+
+const struct solparser_material_double_sided*
+solparser_get_material_double_sided
+ (const struct solparser* parser,
+ const struct solparser_material_double_sided_id mtl2)
+{
+ ASSERT(parser && mtl2.i < darray_material2_size_get(&parser->mtls2));
+ return darray_material2_cdata_get(&parser->mtls2) + mtl2.i;
+}
+
+const struct solparser_material_matte*
+solparser_get_material_matte
+ (const struct solparser* parser,
+ const struct solparser_material_matte_id matte)
+{
+ ASSERT(parser && matte.i < darray_matte_size_get(&parser->mattes));
+ return darray_matte_cdata_get(&parser->mattes) + matte.i;
+}
+
+const struct solparser_material_mirror*
+solparser_get_material_mirror
+ (const struct solparser* parser,
+ const struct solparser_material_mirror_id mirror)
+{
+ ASSERT(parser && mirror.i < darray_mirror_size_get(&parser->mirrors));
+ return darray_mirror_cdata_get(&parser->mirrors) + mirror.i;
+}
+
+const struct solparser_object*
+solparser_get_object
+ (const struct solparser* parser,
+ const struct solparser_object_id obj)
+{
+ ASSERT(parser && obj.i < darray_object_size_get(&parser->objects));
+ return darray_object_cdata_get(&parser->objects) + obj.i;
+}
+
+const struct solparser_pivot*
+solparser_get_pivot
+ (const struct solparser* parser,
+ const struct solparser_pivot_id pivot)
+{
+ ASSERT(parser && pivot.i < darray_pivot_size_get(&parser->pivots));
+ return darray_pivot_cdata_get(&parser->pivots) + pivot.i;
+}
+
+const struct solparser_shape*
+solparser_get_shape
+ (const struct solparser* parser,
+ const struct solparser_shape_id shape)
+{
+ ASSERT(parser && shape.i < darray_shape_size_get(&parser->shapes));
+ return darray_shape_cdata_get(&parser->shapes) + shape.i;
+}
+
+const struct solparser_shape_cuboid*
+solparser_get_shape_cuboid
+ (const struct solparser* parser,
+ const struct solparser_shape_cuboid_id cuboid)
+{
+ ASSERT(parser && cuboid.i < darray_cuboid_size_get(&parser->cuboids));
+ return darray_cuboid_cdata_get(&parser->cuboids) + cuboid.i;
+}
+
+const struct solparser_shape_cylinder*
+solparser_get_shape_cylinder
+ (const struct solparser* parser,
+ const struct solparser_shape_cylinder_id cylinder)
+{
+ ASSERT(parser && cylinder.i < darray_cylinder_size_get(&parser->cylinders));
+ return darray_cylinder_cdata_get(&parser->cylinders) + cylinder.i;
+}
+
+const struct solparser_shape_imported_geometry*
+solparser_get_shape_obj
+ (const struct solparser* parser,
+ const struct solparser_shape_imported_geometry_id impgeom)
+{
+ ASSERT(parser && impgeom.i < darray_impgeom_size_get(&parser->objs));
+ return darray_impgeom_cdata_get(&parser->objs) + impgeom.i;
+}
+
+const struct solparser_shape_paraboloid*
+solparser_get_shape_parabol
+ (const struct solparser* parser,
+ const struct solparser_shape_paraboloid_id paraboloid)
+{
+ ASSERT(parser && paraboloid.i < darray_paraboloid_size_get(&parser->parabols));
+ return darray_paraboloid_cdata_get(&parser->parabols) + paraboloid.i;
+}
+
+const struct solparser_shape_paraboloid*
+solparser_get_shape_parabolic_cylinder
+ (const struct solparser* parser,
+ const struct solparser_shape_paraboloid_id paraboloid)
+{
+ ASSERT(parser);
+ ASSERT(paraboloid.i<darray_paraboloid_size_get(&parser->parabolic_cylinders));
+ return darray_paraboloid_cdata_get(&parser->parabolic_cylinders)+paraboloid.i;
+}
+
+const struct solparser_shape_plane*
+solparser_get_shape_plane
+ (const struct solparser* parser,
+ const struct solparser_shape_plane_id plane)
+{
+ ASSERT(parser && plane.i < darray_plane_size_get(&parser->planes));
+ return darray_plane_cdata_get(&parser->planes) + plane.i;
+}
+
+const struct solparser_shape_sphere*
+solparser_get_shape_sphere
+ (const struct solparser* parser,
+ const struct solparser_shape_sphere_id sphere)
+{
+ ASSERT(parser && sphere.i < darray_sphere_size_get(&parser->spheres));
+ return darray_sphere_cdata_get(&parser->spheres) + sphere.i;
+}
+
+const struct solparser_shape_imported_geometry*
+solparser_get_shape_stl
+ (const struct solparser* parser,
+ const struct solparser_shape_imported_geometry_id impgeom)
+{
+ ASSERT(parser && impgeom.i < darray_impgeom_size_get(&parser->stls));
+ return darray_impgeom_cdata_get(&parser->stls) + impgeom.i;
+}
+
+const struct solparser_sun*
+solparser_get_sun(const struct solparser* parser)
+{
+ ASSERT(parser && parser->sun_key);
+ return &parser->sun;
+}
+
+void
+solparser_entity_iterator_begin
+ (struct solparser* parser,
+ struct solparser_entity_iterator* it)
+{
+ ASSERT(parser && it);
+ htable_str2sols_begin(&parser->str2entities, &it->it__);
+}
+
+void
+solparser_entity_iterator_end
+ (struct solparser* parser,
+ struct solparser_entity_iterator* it)
+{
+ ASSERT(parser && it);
+ htable_str2sols_end(&parser->str2entities, &it->it__);
+}
+
+void
+solparser_material_iterator_begin
+ (struct solparser* parser, struct solparser_material_iterator* it)
+{
+ ASSERT(parser && it);
+ it->mtls__ = darray_material_cdata_get(&parser->mtls);
+ it->imtl__ = 0;
+}
+
+void
+solparser_material_iterator_end
+ (struct solparser* parser, struct solparser_material_iterator* it)
+{
+ ASSERT(parser && it);
+ it->mtls__ = darray_material_cdata_get(&parser->mtls);
+ it->imtl__ = darray_material_size_get(&parser->mtls);
+}
+
+void
+solparser_geometry_iterator_begin
+ (struct solparser* parser, struct solparser_geometry_iterator* it)
+{
+ ASSERT(parser && it);
+ it->geoms__ = darray_geometry_cdata_get(&parser->geometries);
+ it->igeom__ = 0;
+}
+
+void
+solparser_geometry_iterator_end
+ (struct solparser* parser, struct solparser_geometry_iterator* it)
+{
+ ASSERT(parser && it);
+ it->geoms__ = darray_geometry_cdata_get(&parser->geometries);
+ it->igeom__ = darray_geometry_size_get(&parser->geometries);
+}
+
diff --git a/src/parser/solparser.h b/src/parser/solparser.h
@@ -0,0 +1,287 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_H
+#define SOLPARSER_H
+
+#include "solparser_entity.h"
+#include <rsys/rsys.h>
+
+struct mem_allocator;
+struct solparser;
+
+struct solparser_entity_iterator {
+ struct htable_str2sols_iterator it__; /* Internal data */
+};
+
+struct solparser_material_iterator {
+ /* Internal data */
+ const struct solparser_material* mtls__;
+ size_t imtl__;
+};
+
+struct solparser_geometry_iterator {
+ /* Internal data */
+ const struct solparser_geometry* geoms__;
+ size_t igeom__;
+};
+
+/*******************************************************************************
+ * Solstice parser API.
+ ******************************************************************************/
+extern LOCAL_SYM res_T
+solparser_create
+ (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
+ struct solparser** parser);
+
+extern LOCAL_SYM void
+solparser_ref_get
+ (struct solparser* parser);
+
+extern LOCAL_SYM void
+solparser_ref_put
+ (struct solparser* parser);
+
+extern LOCAL_SYM res_T
+solparser_setup
+ (struct solparser* parser,
+ const char* stream_name, /* May be NULL */
+ FILE* stream);
+
+/* Return RES_BAD_OP if there is no more YAML document to parse */
+extern LOCAL_SYM res_T
+solparser_load
+ (struct solparser* parser);
+
+/* Return NULL if no entity is found */
+extern LOCAL_SYM const struct solparser_anchor*
+solparser_find_anchor
+ (struct solparser* parser,
+ const char* anchor_name);
+
+/* Return NULL if no entity is found */
+extern LOCAL_SYM const struct solparser_entity*
+solparser_find_entity
+ (struct solparser* parser,
+ const char* entity_name);
+
+extern LOCAL_SYM const struct solparser_anchor*
+solparser_get_anchor
+ (const struct solparser* parser,
+ const struct solparser_anchor_id anchor);
+
+extern LOCAL_SYM const struct solparser_entity*
+solparser_get_entity
+ (const struct solparser* parser,
+ const struct solparser_entity_id entity);
+
+extern LOCAL_SYM const struct solparser_geometry*
+solparser_get_geometry
+ (const struct solparser* parser,
+ const struct solparser_geometry_id geom);
+
+extern LOCAL_SYM const struct solparser_material*
+solparser_get_material
+ (const struct solparser* parser,
+ const struct solparser_material_id mtl);
+
+extern LOCAL_SYM const struct solparser_material_double_sided*
+solparser_get_material_double_sided
+ (const struct solparser* parser,
+ const struct solparser_material_double_sided_id mtl2);
+
+extern LOCAL_SYM const struct solparser_material_matte*
+solparser_get_material_matte
+ (const struct solparser* parser,
+ const struct solparser_material_matte_id matte);
+
+extern LOCAL_SYM const struct solparser_material_mirror*
+solparser_get_material_mirror
+ (const struct solparser* parser,
+ const struct solparser_material_mirror_id mirror);
+
+extern LOCAL_SYM const struct solparser_object*
+solparser_get_object
+ (const struct solparser* parser,
+ const struct solparser_object_id obj);
+
+extern LOCAL_SYM const struct solparser_pivot*
+solparser_get_pivot
+ (const struct solparser* parser,
+ const struct solparser_pivot_id pivot);
+
+extern LOCAL_SYM const struct solparser_shape*
+solparser_get_shape
+ (const struct solparser* parser,
+ const struct solparser_shape_id shape);
+
+extern LOCAL_SYM const struct solparser_shape_cuboid*
+solparser_get_shape_cuboid
+ (const struct solparser* parser,
+ const struct solparser_shape_cuboid_id cuboid);
+
+extern LOCAL_SYM const struct solparser_shape_cylinder*
+solparser_get_shape_cylinder
+ (const struct solparser* parser,
+ const struct solparser_shape_cylinder_id cylinder);
+
+extern LOCAL_SYM const struct solparser_shape_imported_geometry*
+solparser_get_shape_obj
+ (const struct solparser* parser,
+ const struct solparser_shape_imported_geometry_id impgeom);
+
+extern LOCAL_SYM const struct solparser_shape_paraboloid*
+solparser_get_shape_parabol
+ (const struct solparser* parser,
+ const struct solparser_shape_paraboloid_id paraboloid);
+
+extern LOCAL_SYM const struct solparser_shape_paraboloid*
+solparser_get_shape_parabolic_cylinder
+ (const struct solparser* parser,
+ const struct solparser_shape_paraboloid_id paraboloid);
+
+extern LOCAL_SYM const struct solparser_shape_plane*
+solparser_get_shape_plane
+ (const struct solparser* parser,
+ const struct solparser_shape_plane_id plane);
+
+extern LOCAL_SYM const struct solparser_shape_sphere*
+solparser_get_shape_sphere
+ (const struct solparser* parser,
+ const struct solparser_shape_sphere_id sphere);
+
+extern LOCAL_SYM const struct solparser_shape_imported_geometry*
+solparser_get_shape_stl
+ (const struct solparser* parser,
+ const struct solparser_shape_imported_geometry_id impgeom);
+
+extern LOCAL_SYM const struct solparser_sun*
+solparser_get_sun
+ (const struct solparser* parser);
+
+/*******************************************************************************
+ * Entity interator
+ ******************************************************************************/
+extern LOCAL_SYM void
+solparser_entity_iterator_begin
+ (struct solparser* parser,
+ struct solparser_entity_iterator* it);
+
+extern LOCAL_SYM void
+solparser_entity_iterator_end
+ (struct solparser* parser,
+ struct solparser_entity_iterator* it);
+
+static FINLINE void
+solparser_entity_iterator_next(struct solparser_entity_iterator* it)
+{
+ ASSERT(it);
+ htable_str2sols_iterator_next(&it->it__);
+}
+
+static FINLINE int
+solparser_entity_iterator_eq
+ (const struct solparser_entity_iterator* a,
+ const struct solparser_entity_iterator* b)
+{
+ ASSERT(a && b);
+ return htable_str2sols_iterator_eq(&a->it__, &b->it__);
+}
+
+static FINLINE struct solparser_entity_id
+solparser_entity_iterator_get(struct solparser_entity_iterator* it)
+{
+ struct solparser_entity_id id;
+ ASSERT(it);
+ id.i = *htable_str2sols_iterator_data_get(&it->it__);
+ return id;
+}
+
+/*******************************************************************************
+ * Material iterator
+ ******************************************************************************/
+extern LOCAL_SYM void
+solparser_material_iterator_begin
+ (struct solparser* parser,
+ struct solparser_material_iterator* it);
+
+extern LOCAL_SYM void
+solparser_material_iterator_end
+ (struct solparser* parser,
+ struct solparser_material_iterator* it);
+
+static FINLINE void
+solparser_material_iterator_next(struct solparser_material_iterator* it)
+{
+ ASSERT(it);
+ ++it->imtl__;
+}
+
+static FINLINE int
+solparser_material_iterator_eq
+ (const struct solparser_material_iterator* a,
+ const struct solparser_material_iterator* b)
+{
+ ASSERT(a && b);
+ return a->mtls__ == b->mtls__ && a->imtl__ == b->imtl__;
+}
+
+static FINLINE struct solparser_material_id
+solparser_material_iterator_get(struct solparser_material_iterator* it)
+{
+ struct solparser_material_id id;
+ ASSERT(it);
+ id.i = it->imtl__;
+ return id;
+}
+
+/*******************************************************************************
+ * Geometry iterator
+ ******************************************************************************/
+extern LOCAL_SYM void
+solparser_geometry_iterator_begin
+ (struct solparser* parser, struct solparser_geometry_iterator* it);
+
+extern LOCAL_SYM void
+solparser_geometry_iterator_end
+ (struct solparser* parser, struct solparser_geometry_iterator* it);
+
+static FINLINE void
+solparser_geometry_iterator_next(struct solparser_geometry_iterator* it)
+{
+ ASSERT(it);
+ ++it->igeom__;
+}
+
+static FINLINE int
+solparser_geometry_iterator_eq
+ (const struct solparser_geometry_iterator* a,
+ const struct solparser_geometry_iterator* b)
+{
+ ASSERT(a && b);
+ return a->geoms__ == b->geoms__ && a->igeom__ == b->igeom__;
+}
+
+static FINLINE struct solparser_geometry_id
+solparser_geometry_iterator_get(struct solparser_geometry_iterator* it)
+{
+ struct solparser_geometry_id id;
+ ASSERT(it);
+ id.i = it->igeom__;
+ return id;
+}
+
+#endif /* SOLPARSER_H */
+
diff --git a/src/parser/solparser_entity.h b/src/parser/solparser_entity.h
@@ -0,0 +1,202 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_ENTITY_H
+#define SOLPARSER_ENTITY_H
+
+#include "solparser_geometry.h"
+#include "solparser_pivot.h"
+#include "solparser_shape.h"
+
+#include <rsys/double3.h>
+#include <rsys/dynamic_array.h>
+#include <rsys/hash_table.h>
+#include <rsys/list.h>
+#include <rsys/str.h>
+
+enum solparser_entity_type {
+ SOLPARSER_ENTITY_EMPTY,
+ SOLPARSER_ENTITY_GEOMETRY,
+ SOLPARSER_ENTITY_PIVOT
+};
+
+struct solparser_entity_id { size_t i; };
+
+#define DARRAY_NAME child_id
+#define DARRAY_DATA struct solparser_entity_id
+#include <rsys/dynamic_array.h>
+
+#define DARRAY_NAME anchor_id
+#define DARRAY_DATA struct solparser_anchor_id
+#include <rsys/dynamic_array.h>
+
+/* Declare the hash table that map an entity name to the index of its in memory
+ * solstice representation. */
+#define HTABLE_NAME str2sols
+#define HTABLE_KEY struct str
+#define HTABLE_KEY_FUNCTOR_INIT str_init
+#define HTABLE_KEY_FUNCTOR_RELEASE str_release
+#define HTABLE_KEY_FUNCTOR_COPY str_copy
+#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
+#define HTABLE_KEY_FUNCTOR_EQ str_eq
+#define HTABLE_KEY_FUNCTOR_HASH str_hash
+#define HTABLE_DATA size_t
+#include <rsys/hash_table.h>
+
+struct solparser_entity {
+ double rotation[3];
+ double translation[3];
+
+ struct str name;
+
+ enum solparser_entity_type type;
+ union {
+ struct solparser_geometry_id geometry;
+ struct solparser_pivot_id pivot;
+ } data;
+
+ /* Internal data. Should not be acceded directly. */
+ struct htable_str2sols str2anchors;
+ struct htable_str2sols str2children;
+ struct darray_anchor_id anchors; /* List of anchors */
+ struct darray_child_id children; /* List of children nodes */
+};
+
+static INLINE void
+solparser_entity_init
+ (struct mem_allocator* allocator, struct solparser_entity* entity)
+{
+ ASSERT(entity);
+ d3_splat(entity->rotation, 0);
+ d3_splat(entity->translation, 0);
+ entity->type = SOLPARSER_ENTITY_GEOMETRY;
+ entity->data.geometry.i = SIZE_MAX;
+ str_init(allocator, &entity->name);
+ htable_str2sols_init(allocator, &entity->str2anchors);
+ htable_str2sols_init(allocator, &entity->str2children);
+ darray_anchor_id_init(allocator, &entity->anchors);
+ darray_child_id_init(allocator, &entity->children);
+}
+
+static INLINE void
+solparser_entity_release(struct solparser_entity* entity)
+{
+ ASSERT(entity);
+ str_release(&entity->name);
+ htable_str2sols_release(&entity->str2anchors);
+ htable_str2sols_release(&entity->str2children);
+ darray_anchor_id_release(&entity->anchors);
+ darray_child_id_release(&entity->children);
+}
+
+static INLINE res_T
+solparser_entity_copy
+ (struct solparser_entity* dst, const struct solparser_entity* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ d3_set(dst->translation, src->translation);
+ d3_set(dst->rotation, src->rotation);
+ dst->type = src->type;
+ dst->data = src->data;
+ res = str_copy(&dst->name, &src->name);
+ if(res != RES_OK) return res;
+ res = htable_str2sols_copy(&dst->str2anchors, &src->str2anchors);
+ if(res != RES_OK) return res;
+ res = htable_str2sols_copy(&dst->str2children, &src->str2children);
+ if(res != RES_OK) return res;
+ res = darray_anchor_id_copy(&dst->anchors, &src->anchors);
+ if(res != RES_OK) return res;
+ res = darray_child_id_copy(&dst->children, &src->children);
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+static INLINE res_T
+solparser_entity_copy_and_release
+ (struct solparser_entity* dst, struct solparser_entity* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ d3_set(dst->translation, src->translation);
+ d3_set(dst->rotation, src->rotation);
+ dst->type = src->type;
+ dst->data = src->data;
+ res = str_copy_and_release(&dst->name, &src->name);
+ if(res != RES_OK) return res;
+ res = htable_str2sols_copy_and_release(&dst->str2anchors, &src->str2anchors);
+ if(res != RES_OK) return res;
+ res = htable_str2sols_copy_and_release(&dst->str2children, &src->str2children);
+ if(res != RES_OK) return res;
+ res = darray_anchor_id_copy_and_release(&dst->anchors, &src->anchors);
+ if(res != RES_OK) return res;
+ res = darray_child_id_copy_and_release(&dst->children, &src->children);
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+static INLINE res_T
+solparser_entity_copy_and_clear
+ (struct solparser_entity* dst, struct solparser_entity* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ d3_set(dst->translation, src->translation);
+ d3_set(dst->rotation, src->rotation);
+ dst->type = src->type;
+ dst->data = src->data;
+ res = str_copy_and_clear(&dst->name, &src->name);
+ if(res != RES_OK) return res;
+ res = htable_str2sols_copy_and_clear(&dst->str2anchors, &src->str2anchors);
+ if(res != RES_OK) return res;
+ res = htable_str2sols_copy_and_clear(&dst->str2children, &src->str2children);
+ if(res != RES_OK) return res;
+ res = darray_anchor_id_copy_and_clear(&dst->anchors, &src->anchors);
+ if(res != RES_OK) return res;
+ res = darray_child_id_copy_and_clear(&dst->children, &src->children);
+ if(res != RES_OK) return res;
+ return RES_OK;
+}
+
+static INLINE size_t
+solparser_entity_get_anchors_count(const struct solparser_entity* entity)
+{
+ ASSERT(entity);
+ return darray_anchor_id_size_get(&entity->anchors);
+}
+
+static INLINE struct solparser_anchor_id
+solparser_entity_get_anchor(const struct solparser_entity* entity, const size_t i)
+{
+ ASSERT(entity && i < solparser_entity_get_anchors_count(entity));
+ return darray_anchor_id_cdata_get(&entity->anchors)[i];
+}
+
+static INLINE size_t
+solparser_entity_get_children_count(const struct solparser_entity* entity)
+{
+ ASSERT(entity);
+ return darray_child_id_size_get(&entity->children);
+}
+
+static INLINE struct solparser_entity_id
+solparser_entity_get_child(const struct solparser_entity* entity, const size_t i)
+{
+ ASSERT(entity && i < solparser_entity_get_children_count(entity));
+ return darray_child_id_cdata_get(&entity->children)[i];
+}
+
+#endif /* SOLPARSER_ENTITY_H */
+
diff --git a/src/parser/solparser_geometry.h b/src/parser/solparser_geometry.h
@@ -0,0 +1,90 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_GEOMETRY_H
+#define SOLPARSER_GEOMETRY_H
+
+#include "solparser_material.h"
+#include "solparser_shape.h"
+
+#include <rsys/dynamic_array.h>
+
+struct solparser_object {
+ struct solparser_material_double_sided_id mtl2;
+ struct solparser_shape_id shape;
+ double rotation[3];
+ double translation[3];
+};
+
+struct solparser_object_id { size_t i; };
+
+#define DARRAY_NAME object_id
+#define DARRAY_DATA struct solparser_object_id
+#include <rsys/dynamic_array.h>
+
+struct solparser_geometry {
+ /* Internal data. Should not be acceded directly. */
+ struct darray_object_id objects;
+};
+
+struct solparser_geometry_id { size_t i; };
+
+static INLINE void
+solparser_geometry_init
+ (struct mem_allocator* allocator, struct solparser_geometry* geom)
+{
+ ASSERT(geom);
+ darray_object_id_init(allocator, &geom->objects);
+}
+
+static INLINE void
+solparser_geometry_release(struct solparser_geometry* geom)
+{
+ ASSERT(geom);
+ darray_object_id_release(&geom->objects);
+}
+
+static INLINE res_T
+solparser_geometry_copy
+ (struct solparser_geometry* dst, const struct solparser_geometry* src)
+{
+ ASSERT(dst && src);
+ return darray_object_id_copy(&dst->objects, &src->objects);
+}
+
+static INLINE res_T
+solparser_geometry_copy_and_release
+ (struct solparser_geometry* dst, struct solparser_geometry* src)
+{
+ ASSERT(dst && src);
+ return darray_object_id_copy_and_release(&dst->objects, &src->objects);
+}
+
+static FINLINE size_t
+solparser_geometry_get_objects_count(const struct solparser_geometry* geom)
+{
+ ASSERT(geom);
+ return darray_object_id_size_get(&geom->objects);
+}
+
+static FINLINE struct solparser_object_id
+solparser_geometry_get_object
+ (const struct solparser_geometry* geom, const size_t i)
+{
+ ASSERT(geom && i < solparser_geometry_get_objects_count(geom));
+ return darray_object_id_cdata_get(&geom->objects)[i];
+}
+
+#endif /* SOLPARSER_GEOMETRY_H */
diff --git a/src/parser/solparser_material.h b/src/parser/solparser_material.h
@@ -0,0 +1,56 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_MATERIAL_H
+#define SOLPARSER_MATERIAL_H
+
+#include <stddef.h>
+
+enum solparser_material_type {
+ SOLPARSER_MATERIAL_MATTE,
+ SOLPARSER_MATERIAL_MIRROR
+};
+
+struct solparser_material_matte {
+ double reflectivity; /* In [0, 1] */
+};
+
+struct solparser_material_matte_id { size_t i; };
+
+struct solparser_material_mirror {
+ double roughness; /* In [0, 1] */
+ double reflectivity; /* In [0, 1] */
+};
+
+struct solparser_material_mirror_id { size_t i; };
+
+struct solparser_material {
+ enum solparser_material_type type;
+ union {
+ struct solparser_material_matte_id matte;
+ struct solparser_material_mirror_id mirror;
+ } data;
+};
+
+struct solparser_material_id { size_t i; };
+
+struct solparser_material_double_sided {
+ struct solparser_material_id front;
+ struct solparser_material_id back;
+};
+
+struct solparser_material_double_sided_id { size_t i; };
+
+#endif /* SOLPARSER_MATERIAL_H */
diff --git a/src/parser/solparser_pivot.h b/src/parser/solparser_pivot.h
@@ -0,0 +1,84 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_PIVOT_H
+#define SOLPARSER_PIVOT_H
+
+#include <rsys/double3.h>
+
+enum solparser_target_type {
+ SOLPARSER_TARGET_ANCHOR,
+ SOLPARSER_TARGET_DIRECTION,
+ SOLPARSER_TARGET_POSITION,
+ SOLPARSER_TARGET_SUN
+};
+
+struct solparser_anchor_id { size_t i; };
+
+struct solparser_anchor {
+ struct str name;
+ double position[3];
+};
+
+static INLINE void
+solparser_anchor_init
+ (struct mem_allocator* allocator, struct solparser_anchor* anchor)
+{
+ ASSERT(anchor);
+ str_init(allocator, &anchor->name);
+}
+
+static INLINE void
+solparser_anchor_release(struct solparser_anchor* anchor)
+{
+ ASSERT(anchor);
+ str_release(&anchor->name);
+}
+
+static INLINE res_T
+solparser_anchor_copy
+ (struct solparser_anchor* dst, const struct solparser_anchor* src)
+{
+ ASSERT(dst && src);
+ d3_set(dst->position, src->position);
+ return str_copy(&dst->name, &src->name);
+}
+
+static INLINE res_T
+solparser_anchor_copy_and_release
+ (struct solparser_anchor* dst, struct solparser_anchor* src)
+{
+ ASSERT(dst && src);
+ d3_set(dst->position, src->position);
+ return str_copy_and_release(&dst->name, &src->name);
+}
+
+struct solparser_pivot {
+ double point[3];
+ double normal[3];
+ double rotation[3];
+ double translation[3];
+ enum solparser_target_type target_type;
+ union {
+ double position[3]; /* World space position */
+ double direction[3]; /* World space direction */
+ struct solparser_anchor_id anchor;
+ } target;
+};
+
+struct solparser_pivot_id { size_t i; };
+
+#endif /* SOLPARSER_PIVOT_H */
+
diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h
@@ -0,0 +1,260 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_SHAPE_H
+#define SOLPARSER_SHAPE_H
+
+#include "solparser_material.h"
+
+#include <rsys/dynamic_array_double.h>
+#include <rsys/str.h>
+
+enum solparser_clip_op {
+ SOLPARSER_CLIP_OP_AND,
+ SOLPARSER_CLIP_OP_SUB
+};
+
+enum solparser_shape_type {
+ SOLPARSER_SHAPE_CUBOID,
+ SOLPARSER_SHAPE_CYLINDER,
+ SOLPARSER_SHAPE_OBJ, /* Imported Alias Wavefront obj */
+ SOLPARSER_SHAPE_PARABOL,
+ SOLPARSER_SHAPE_PARABOLIC_CYLINDER,
+ SOLPARSER_SHAPE_PLANE,
+ SOLPARSER_SHAPE_SPHERE,
+ SOLPARSER_SHAPE_STL /* Imported STereo Lithography */
+};
+
+/*******************************************************************************
+ * Clipping polygon
+ ******************************************************************************/
+struct solparser_polyclip {
+ enum solparser_clip_op op;
+ struct darray_double vertices;
+};
+
+static INLINE void
+solparser_polyclip_init
+ (struct mem_allocator* allocator,
+ struct solparser_polyclip* polyclip)
+{
+ ASSERT(polyclip);
+ darray_double_init(allocator, &polyclip->vertices);
+}
+
+static INLINE void
+solparser_polyclip_release(struct solparser_polyclip* polyclip)
+{
+ ASSERT(polyclip);
+ darray_double_release(&polyclip->vertices);
+}
+
+static INLINE res_T
+solparser_polyclip_copy
+ (struct solparser_polyclip* dst, const struct solparser_polyclip* src)
+{
+ ASSERT(dst && src);
+ dst->op = src->op;
+ return darray_double_copy(&dst->vertices, &src->vertices);
+}
+
+static INLINE res_T
+solparser_polyclip_copy_and_release
+ (struct solparser_polyclip* dst, struct solparser_polyclip* src)
+{
+ ASSERT(dst && src);
+ dst->op = src->op;
+ return darray_double_copy_and_release(&dst->vertices, &src->vertices);
+}
+
+/* Declare the array of clipping polygons */
+#define DARRAY_NAME polyclip
+#define DARRAY_DATA struct solparser_polyclip
+#define DARRAY_FUNCTOR_INIT solparser_polyclip_init
+#define DARRAY_FUNCTOR_RELEASE solparser_polyclip_release
+#define DARRAY_FUNCTOR_COPY solparser_polyclip_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE solparser_polyclip_copy_and_release
+#include <rsys/dynamic_array.h>
+
+/*******************************************************************************
+ * Imported geometry shape
+ ******************************************************************************/
+struct solparser_shape_imported_geometry {
+ struct str filename;
+};
+
+static INLINE void
+solparser_shape_imported_geometry_init
+ (struct mem_allocator* allocator,
+ struct solparser_shape_imported_geometry* impgeom)
+{
+ ASSERT(impgeom);
+ str_init(allocator, &impgeom->filename);
+}
+
+static INLINE void
+solparser_shape_imported_geometry_release
+ (struct solparser_shape_imported_geometry* impgeom)
+{
+ ASSERT(impgeom);
+ str_release(&impgeom->filename);
+}
+
+static INLINE res_T
+solparser_shape_imported_geometry_copy
+ (struct solparser_shape_imported_geometry* dst,
+ const struct solparser_shape_imported_geometry* src)
+{
+ ASSERT(dst && src);
+ return str_copy(&dst->filename, &src->filename);
+}
+
+static INLINE res_T
+solparser_shape_imported_geometry_copy_and_release
+ (struct solparser_shape_imported_geometry* dst,
+ struct solparser_shape_imported_geometry* src)
+{
+ ASSERT(dst && src);
+ return str_copy_and_release(&dst->filename, &src->filename);
+}
+
+/*******************************************************************************
+ * Paraboloid shape
+ ******************************************************************************/
+struct solparser_shape_paraboloid {
+ double focal;
+ struct darray_polyclip polyclips;
+};
+
+static INLINE void
+solparser_shape_paraboloid_init
+ (struct mem_allocator* allocator,
+ struct solparser_shape_paraboloid* paraboloid)
+{
+ ASSERT(paraboloid);
+ darray_polyclip_init(allocator, ¶boloid->polyclips);
+}
+
+static INLINE void
+solparser_shape_paraboloid_release(struct solparser_shape_paraboloid* paraboloid)
+{
+ ASSERT(paraboloid);
+ darray_polyclip_release(¶boloid->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_paraboloid_copy
+ (struct solparser_shape_paraboloid* dst,
+ const struct solparser_shape_paraboloid* src)
+{
+ ASSERT(dst && src);
+ dst->focal = src->focal;
+ return darray_polyclip_copy(&dst->polyclips, &src->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_paraboloid_copy_and_release
+ (struct solparser_shape_paraboloid* dst,
+ struct solparser_shape_paraboloid* src)
+{
+ ASSERT(dst && src);
+ dst->focal = src->focal;
+ return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips);
+}
+
+/*******************************************************************************
+ * Plane shape
+ ******************************************************************************/
+struct solparser_shape_plane {
+ struct darray_polyclip polyclips;
+};
+
+static INLINE void
+solparser_shape_plane_init
+ (struct mem_allocator* allocator,
+ struct solparser_shape_plane* plane)
+{
+ ASSERT(plane);
+ darray_polyclip_init(allocator, &plane->polyclips);
+}
+
+static INLINE void
+solparser_shape_plane_release(struct solparser_shape_plane* plane)
+{
+ ASSERT(plane);
+ darray_polyclip_release(&plane->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_plane_copy
+ (struct solparser_shape_plane* dst,
+ const struct solparser_shape_plane* src)
+{
+ ASSERT(dst && src);
+ return darray_polyclip_copy(&dst->polyclips, &src->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_plane_copy_and_release
+ (struct solparser_shape_plane* dst,
+ struct solparser_shape_plane* src)
+{
+ ASSERT(dst && src);
+ return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips);
+}
+
+/*******************************************************************************
+ * POD shape data
+ ******************************************************************************/
+struct solparser_shape_cuboid {
+ double size[3]; /* Size along the X, Y and Z dimension */
+};
+
+struct solparser_shape_cylinder {
+ double height;
+ double radius;
+ long nslices;
+};
+
+struct solparser_shape_sphere {
+ double radius;
+ long nslices;
+};
+
+struct solparser_shape_cuboid_id { size_t i; };
+struct solparser_shape_cylinder_id { size_t i; };
+struct solparser_shape_imported_geometry_id { size_t i; };
+struct solparser_shape_paraboloid_id { size_t i; };
+struct solparser_shape_plane_id { size_t i; };
+struct solparser_shape_sphere_id { size_t i; };
+
+struct solparser_shape {
+ enum solparser_shape_type type;
+ union {
+ struct solparser_shape_cuboid_id cuboid;
+ struct solparser_shape_cylinder_id cylinder;
+ struct solparser_shape_imported_geometry_id obj;
+ struct solparser_shape_paraboloid_id parabol;
+ struct solparser_shape_paraboloid_id parabolic_cylinder;
+ struct solparser_shape_plane_id plane;
+ struct solparser_shape_sphere_id sphere;
+ struct solparser_shape_imported_geometry_id stl;
+ } data;
+};
+
+struct solparser_shape_id { size_t i; };
+
+#endif /* SOLPARSER_SHAPE_H */
+
diff --git a/src/parser/solparser_sun.h b/src/parser/solparser_sun.h
@@ -0,0 +1,88 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SOLPARSER_SUN_H
+#define SOLPARSER_SUN_H
+
+#include <rsys/dynamic_array.h>
+
+enum solparser_sun_radang_distrib_type { /* Radial Angular distribution */
+ SOLPARSER_SUN_RADANG_DISTRIB_BUIE,
+ SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL,
+ SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX
+};
+
+struct solparser_spectrum_data {
+ double wavelength;
+ double data;
+};
+
+#define DARRAY_NAME spectrum_data
+#define DARRAY_DATA struct solparser_spectrum_data
+#include <rsys/dynamic_array.h>
+
+struct solparser_sun_buie { double csr; };
+struct solparser_sun_pillbox { double aperture; };
+
+struct solparser_sun {
+ double dni; /* In ]0, INF) */
+ struct darray_spectrum_data spectrum;
+ enum solparser_sun_radang_distrib_type radang_distrib_type;
+ union {
+ struct solparser_sun_buie buie;
+ struct solparser_sun_pillbox pillbox;
+ } radang_distrib;
+};
+
+static INLINE void
+solparser_sun_init(struct mem_allocator* allocator, struct solparser_sun* sun)
+{
+ ASSERT(sun);
+ sun->dni = 1.0;
+ sun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL;
+ darray_spectrum_data_init(allocator, &sun->spectrum);
+}
+
+static INLINE void
+solparser_sun_release(struct solparser_sun* sun)
+{
+ ASSERT(sun);
+ darray_spectrum_data_release(&sun->spectrum);
+}
+
+static INLINE res_T
+solparser_sun_copy(struct solparser_sun* dst, const struct solparser_sun* src)
+{
+ ASSERT(dst && src);
+ return darray_spectrum_data_copy(&dst->spectrum, &src->spectrum);
+}
+
+static INLINE res_T
+solparser_sun_copy_and_release
+ (struct solparser_sun* dst, struct solparser_sun* src)
+{
+ ASSERT(dst && src);
+ return darray_spectrum_data_copy_and_release(&dst->spectrum, &src->spectrum);
+}
+
+static INLINE void
+solparser_sun_clear(struct solparser_sun* sun)
+{
+ ASSERT(sun);
+ darray_spectrum_data_clear(&sun->spectrum);
+}
+
+#endif /* SOLPARSER_SUN_H */
+
diff --git a/src/parser/solstice_entity.h b/src/parser/solstice_entity.h
@@ -1,202 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_ENTITY_H
-#define SOLSTICE_ENTITY_H
-
-#include "solstice_geometry.h"
-#include "solstice_pivot.h"
-#include "solstice_shape.h"
-
-#include <rsys/double3.h>
-#include <rsys/dynamic_array.h>
-#include <rsys/hash_table.h>
-#include <rsys/list.h>
-#include <rsys/str.h>
-
-enum solstice_entity_type {
- SOLSTICE_ENTITY_EMPTY,
- SOLSTICE_ENTITY_GEOMETRY,
- SOLSTICE_ENTITY_PIVOT
-};
-
-struct solstice_entity_id { size_t i; };
-
-#define DARRAY_NAME child_id
-#define DARRAY_DATA struct solstice_entity_id
-#include <rsys/dynamic_array.h>
-
-#define DARRAY_NAME anchor_id
-#define DARRAY_DATA struct solstice_anchor_id
-#include <rsys/dynamic_array.h>
-
-/* Declare the hash table that map an entity name to the index of its in memory
- * solstice representation. */
-#define HTABLE_NAME str2sols
-#define HTABLE_KEY struct str
-#define HTABLE_KEY_FUNCTOR_INIT str_init
-#define HTABLE_KEY_FUNCTOR_RELEASE str_release
-#define HTABLE_KEY_FUNCTOR_COPY str_copy
-#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
-#define HTABLE_KEY_FUNCTOR_EQ str_eq
-#define HTABLE_KEY_FUNCTOR_HASH str_hash
-#define HTABLE_DATA size_t
-#include <rsys/hash_table.h>
-
-struct solstice_entity {
- double rotation[3];
- double translation[3];
-
- struct str name;
-
- enum solstice_entity_type type;
- union {
- struct solstice_geometry_id geometry;
- struct solstice_pivot_id pivot;
- } data;
-
- /* Internal data. Should not be acceded directly. */
- struct htable_str2sols str2anchors;
- struct htable_str2sols str2children;
- struct darray_anchor_id anchors; /* List of anchors */
- struct darray_child_id children; /* List of children nodes */
-};
-
-static INLINE void
-solstice_entity_init
- (struct mem_allocator* allocator, struct solstice_entity* entity)
-{
- ASSERT(entity);
- d3_splat(entity->rotation, 0);
- d3_splat(entity->translation, 0);
- entity->type = SOLSTICE_ENTITY_GEOMETRY;
- entity->data.geometry.i = SIZE_MAX;
- str_init(allocator, &entity->name);
- htable_str2sols_init(allocator, &entity->str2anchors);
- htable_str2sols_init(allocator, &entity->str2children);
- darray_anchor_id_init(allocator, &entity->anchors);
- darray_child_id_init(allocator, &entity->children);
-}
-
-static INLINE void
-solstice_entity_release(struct solstice_entity* entity)
-{
- ASSERT(entity);
- str_release(&entity->name);
- htable_str2sols_release(&entity->str2anchors);
- htable_str2sols_release(&entity->str2children);
- darray_anchor_id_release(&entity->anchors);
- darray_child_id_release(&entity->children);
-}
-
-static INLINE res_T
-solstice_entity_copy
- (struct solstice_entity* dst, const struct solstice_entity* src)
-{
- res_T res = RES_OK;
- ASSERT(dst && src);
- d3_set(dst->translation, src->translation);
- d3_set(dst->rotation, src->rotation);
- dst->type = src->type;
- dst->data = src->data;
- res = str_copy(&dst->name, &src->name);
- if(res != RES_OK) return res;
- res = htable_str2sols_copy(&dst->str2anchors, &src->str2anchors);
- if(res != RES_OK) return res;
- res = htable_str2sols_copy(&dst->str2children, &src->str2children);
- if(res != RES_OK) return res;
- res = darray_anchor_id_copy(&dst->anchors, &src->anchors);
- if(res != RES_OK) return res;
- res = darray_child_id_copy(&dst->children, &src->children);
- if(res != RES_OK) return res;
- return RES_OK;
-}
-
-static INLINE res_T
-solstice_entity_copy_and_release
- (struct solstice_entity* dst, struct solstice_entity* src)
-{
- res_T res = RES_OK;
- ASSERT(dst && src);
- d3_set(dst->translation, src->translation);
- d3_set(dst->rotation, src->rotation);
- dst->type = src->type;
- dst->data = src->data;
- res = str_copy_and_release(&dst->name, &src->name);
- if(res != RES_OK) return res;
- res = htable_str2sols_copy_and_release(&dst->str2anchors, &src->str2anchors);
- if(res != RES_OK) return res;
- res = htable_str2sols_copy_and_release(&dst->str2children, &src->str2children);
- if(res != RES_OK) return res;
- res = darray_anchor_id_copy_and_release(&dst->anchors, &src->anchors);
- if(res != RES_OK) return res;
- res = darray_child_id_copy_and_release(&dst->children, &src->children);
- if(res != RES_OK) return res;
- return RES_OK;
-}
-
-static INLINE res_T
-solstice_entity_copy_and_clear
- (struct solstice_entity* dst, struct solstice_entity* src)
-{
- res_T res = RES_OK;
- ASSERT(dst && src);
- d3_set(dst->translation, src->translation);
- d3_set(dst->rotation, src->rotation);
- dst->type = src->type;
- dst->data = src->data;
- res = str_copy_and_clear(&dst->name, &src->name);
- if(res != RES_OK) return res;
- res = htable_str2sols_copy_and_clear(&dst->str2anchors, &src->str2anchors);
- if(res != RES_OK) return res;
- res = htable_str2sols_copy_and_clear(&dst->str2children, &src->str2children);
- if(res != RES_OK) return res;
- res = darray_anchor_id_copy_and_clear(&dst->anchors, &src->anchors);
- if(res != RES_OK) return res;
- res = darray_child_id_copy_and_clear(&dst->children, &src->children);
- if(res != RES_OK) return res;
- return RES_OK;
-}
-
-static INLINE size_t
-solstice_entity_get_anchors_count(const struct solstice_entity* entity)
-{
- ASSERT(entity);
- return darray_anchor_id_size_get(&entity->anchors);
-}
-
-static INLINE struct solstice_anchor_id
-solstice_entity_get_anchor(const struct solstice_entity* entity, const size_t i)
-{
- ASSERT(entity && i < solstice_entity_get_anchors_count(entity));
- return darray_anchor_id_cdata_get(&entity->anchors)[i];
-}
-
-static INLINE size_t
-solstice_entity_get_children_count(const struct solstice_entity* entity)
-{
- ASSERT(entity);
- return darray_child_id_size_get(&entity->children);
-}
-
-static INLINE struct solstice_entity_id
-solstice_entity_get_child(const struct solstice_entity* entity, const size_t i)
-{
- ASSERT(entity && i < solstice_entity_get_children_count(entity));
- return darray_child_id_cdata_get(&entity->children)[i];
-}
-
-#endif /* SOLSTICE_ENTITY_H */
-
diff --git a/src/parser/solstice_geometry.h b/src/parser/solstice_geometry.h
@@ -1,90 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_GEOMETRY_H
-#define SOLSTICE_GEOMETRY_H
-
-#include "solstice_material.h"
-#include "solstice_shape.h"
-
-#include <rsys/dynamic_array.h>
-
-struct solstice_object {
- struct solstice_material_double_sided_id mtl2;
- struct solstice_shape_id shape;
- double rotation[3];
- double translation[3];
-};
-
-struct solstice_object_id { size_t i; };
-
-#define DARRAY_NAME object_id
-#define DARRAY_DATA struct solstice_object_id
-#include <rsys/dynamic_array.h>
-
-struct solstice_geometry {
- /* Internal data. Should not be acceded directly. */
- struct darray_object_id objects;
-};
-
-struct solstice_geometry_id { size_t i; };
-
-static INLINE void
-solstice_geometry_init
- (struct mem_allocator* allocator, struct solstice_geometry* geom)
-{
- ASSERT(geom);
- darray_object_id_init(allocator, &geom->objects);
-}
-
-static INLINE void
-solstice_geometry_release(struct solstice_geometry* geom)
-{
- ASSERT(geom);
- darray_object_id_release(&geom->objects);
-}
-
-static INLINE res_T
-solstice_geometry_copy
- (struct solstice_geometry* dst, const struct solstice_geometry* src)
-{
- ASSERT(dst && src);
- return darray_object_id_copy(&dst->objects, &src->objects);
-}
-
-static INLINE res_T
-solstice_geometry_copy_and_release
- (struct solstice_geometry* dst, struct solstice_geometry* src)
-{
- ASSERT(dst && src);
- return darray_object_id_copy_and_release(&dst->objects, &src->objects);
-}
-
-static FINLINE size_t
-solstice_geometry_get_objects_count(const struct solstice_geometry* geom)
-{
- ASSERT(geom);
- return darray_object_id_size_get(&geom->objects);
-}
-
-static FINLINE struct solstice_object_id
-solstice_geometry_get_object
- (const struct solstice_geometry* geom, const size_t i)
-{
- ASSERT(geom && i < solstice_geometry_get_objects_count(geom));
- return darray_object_id_cdata_get(&geom->objects)[i];
-}
-
-#endif /* SOLSTICE_GEOMETRY_H */
diff --git a/src/parser/solstice_material.h b/src/parser/solstice_material.h
@@ -1,56 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_MATERIAL_H
-#define SOLSTICE_MATERIAL_H
-
-#include <stddef.h>
-
-enum solstice_material_type {
- SOLSTICE_MATERIAL_MATTE,
- SOLSTICE_MATERIAL_MIRROR
-};
-
-struct solstice_material_matte {
- double reflectivity; /* In [0, 1] */
-};
-
-struct solstice_material_matte_id { size_t i; };
-
-struct solstice_material_mirror {
- double roughness; /* In [0, 1] */
- double reflectivity; /* In [0, 1] */
-};
-
-struct solstice_material_mirror_id { size_t i; };
-
-struct solstice_material {
- enum solstice_material_type type;
- union {
- struct solstice_material_matte_id matte;
- struct solstice_material_mirror_id mirror;
- } data;
-};
-
-struct solstice_material_id { size_t i; };
-
-struct solstice_material_double_sided {
- struct solstice_material_id front;
- struct solstice_material_id back;
-};
-
-struct solstice_material_double_sided_id { size_t i; };
-
-#endif /* SOLSTICE_MATERIAL_H */
diff --git a/src/parser/solstice_parser.c b/src/parser/solstice_parser.c
@@ -1,3402 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#define _POSIX_C_SOURCE 200112L /* nextafter support */
-
-#include "solstice_entity.h"
-#include "solstice_material.h"
-#include "solstice_parser.h"
-#include "solstice_pivot.h"
-#include "solstice_shape.h"
-#include "solstice_sun.h"
-
-#include <rsys/cstr.h>
-#include <rsys/double3.h>
-#include <rsys/dynamic_array.h>
-#include <rsys/hash_table.h>
-#include <rsys/ref_count.h>
-#include <rsys/str.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <yaml.h>
-
-/* Declare the array of matte materials */
-#define DARRAY_NAME matte
-#define DARRAY_DATA struct solstice_material_matte
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of mirror materials */
-#define DARRAY_NAME mirror
-#define DARRAY_DATA struct solstice_material_mirror
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of materials */
-#define DARRAY_NAME material
-#define DARRAY_DATA struct solstice_material
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of the double sided materials */
-#define DARRAY_NAME material2
-#define DARRAY_DATA struct solstice_material_double_sided
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of the shapes */
-#define DARRAY_NAME shape
-#define DARRAY_DATA struct solstice_shape
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of cuboid */
-#define DARRAY_NAME cuboid
-#define DARRAY_DATA struct solstice_shape_cuboid
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of cylinder */
-#define DARRAY_NAME cylinder
-#define DARRAY_DATA struct solstice_shape_cylinder
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of imported geometries */
-#define DARRAY_NAME impgeom
-#define DARRAY_DATA struct solstice_shape_imported_geometry
-#define DARRAY_FUNCTOR_INIT solstice_shape_imported_geometry_init
-#define DARRAY_FUNCTOR_RELEASE solstice_shape_imported_geometry_release
-#define DARRAY_FUNCTOR_COPY solstice_shape_imported_geometry_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE \
- solstice_shape_imported_geometry_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of paraboloids */
-#define DARRAY_NAME paraboloid
-#define DARRAY_DATA struct solstice_shape_paraboloid
-#define DARRAY_FUNCTOR_INIT solstice_shape_paraboloid_init
-#define DARRAY_FUNCTOR_RELEASE solstice_shape_paraboloid_release
-#define DARRAY_FUNCTOR_COPY solstice_shape_paraboloid_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE \
- solstice_shape_paraboloid_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of planes */
-#define DARRAY_NAME plane
-#define DARRAY_DATA struct solstice_shape_plane
-#define DARRAY_FUNCTOR_INIT solstice_shape_plane_init
-#define DARRAY_FUNCTOR_RELEASE solstice_shape_plane_release
-#define DARRAY_FUNCTOR_COPY solstice_shape_plane_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_shape_plane_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of spheres */
-#define DARRAY_NAME sphere
-#define DARRAY_DATA struct solstice_shape_sphere
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of objects */
-#define DARRAY_NAME object
-#define DARRAY_DATA struct solstice_object
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of geometries */
-#define DARRAY_NAME geometry
-#define DARRAY_DATA struct solstice_geometry
-#define DARRAY_FUNCTOR_INIT solstice_geometry_init
-#define DARRAY_FUNCTOR_RELEASE solstice_geometry_release
-#define DARRAY_FUNCTOR_COPY solstice_geometry_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_geometry_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of entities */
-#define DARRAY_NAME entity
-#define DARRAY_DATA struct solstice_entity
-#define DARRAY_FUNCTOR_INIT solstice_entity_init
-#define DARRAY_FUNCTOR_RELEASE solstice_entity_release
-#define DARRAY_FUNCTOR_COPY solstice_entity_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_entity_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of anchors */
-#define DARRAY_NAME anchor
-#define DARRAY_DATA struct solstice_anchor
-#define DARRAY_FUNCTOR_INIT solstice_anchor_init
-#define DARRAY_FUNCTOR_RELEASE solstice_anchor_release
-#define DARRAY_FUNCTOR_COPY solstice_anchor_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_anchor_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/* Declare the array of pivots */
-#define DARRAY_NAME pivot
-#define DARRAY_DATA struct solstice_pivot
-#include <rsys/dynamic_array.h>
-
-/* Declare the hash table that maps the address of a YAML node to the id of its
- * in memory representation. */
-#define HTABLE_NAME yaml2sols
-#define HTABLE_KEY yaml_node_t*
-#define HTABLE_DATA size_t
-#include <rsys/hash_table.h>
-
-struct solstice_parser {
- yaml_parser_t parser;
- struct str stream_name;
- int parser_is_init;
-
- /* Materia data */
- struct htable_yaml2sols yaml2mtls; /* Cache of materials */
- struct darray_material mtls;
- struct darray_material2 mtls2; /* Double sided materials */
- struct darray_matte mattes;
- struct darray_mirror mirrors;
-
- /* Shape data */
- struct darray_shape shapes; /* Generic loaded shapes */
- struct darray_cuboid cuboids;
- struct darray_cylinder cylinders;
- struct darray_impgeom objs;
- struct darray_paraboloid parabols;
- struct darray_paraboloid parabolic_cylinders;
- struct darray_plane planes;
- struct darray_sphere spheres;
- struct darray_impgeom stls;
-
- /* Geometries & objects */
- struct htable_yaml2sols yaml2geoms; /* Cache of geometries */
- struct darray_object objects;
- struct darray_geometry geometries;
-
- /* Sun. Note that only one sun is supported */
- const yaml_node_t* sun_key; /* yaml_node_t ptr used to spawn the sun */
- struct solstice_sun sun; /* The loaded sun */
-
- /* Entity */
- struct htable_yaml2sols yaml2entities; /* Cache of entities */
- struct htable_str2sols str2entities;
- struct darray_entity entities;
-
- /* Miscellaneous */
- struct darray_anchor anchors;
- struct darray_pivot pivots;
-
- ref_T ref;
- struct mem_allocator* allocator;
-};
-
-static res_T
-parse_entity
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* entity,
- struct htable_str2sols* htable,
- struct solstice_entity_id* solent);
-
-static res_T
-parse_geometry
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* geometry,
- struct solstice_geometry_id* solgeom);
-
-static res_T
-parse_pivot
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* pivot,
- struct solstice_pivot_id* out_isolpivot);
-
-static res_T
-parse_sun
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* sun,
- struct solstice_sun** solsun);
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static INLINE void
-log_err
- (const struct solstice_parser* parser,
- const yaml_node_t* node,
- const char* fmt,
- ...)
-{
- va_list vargs_list;
- ASSERT(parser && node && fmt);
-
- fprintf(stderr, "%s:%lu:%lu: ",
- str_cget(&parser->stream_name),
- (unsigned long)node->start_mark.line+1,
- (unsigned long)node->start_mark.column+1);
- va_start(vargs_list, fmt);
- vfprintf(stderr, fmt, vargs_list);
- va_end(vargs_list);
-}
-
-/* Clean up loaded data */
-static INLINE void
-parser_clear(struct solstice_parser* parser)
-{
- ASSERT(parser);
-
- /* Materials */
- htable_yaml2sols_clear(&parser->yaml2mtls);
- darray_material_clear(&parser->mtls);
- darray_material2_clear(&parser->mtls2);
- darray_matte_clear(&parser->mattes);
- darray_mirror_clear(&parser->mirrors);
-
- /* Shapes */
- darray_shape_clear(&parser->shapes);
- darray_cuboid_clear(&parser->cuboids);
- darray_cylinder_clear(&parser->cylinders);
- darray_impgeom_clear(&parser->objs);
- darray_paraboloid_clear(&parser->parabols);
- darray_paraboloid_clear(&parser->parabolic_cylinders);
- darray_plane_clear(&parser->planes);
- darray_sphere_clear(&parser->spheres);
- darray_impgeom_clear(&parser->stls);
-
- /* Geometries */
- htable_yaml2sols_clear(&parser->yaml2geoms);
- darray_object_clear(&parser->objects);
- darray_geometry_clear(&parser->geometries);
-
- /* Sun */
- solstice_sun_clear(&parser->sun);
- parser->sun_key = 0;
-
- /* Entities */
- htable_yaml2sols_clear(&parser->yaml2entities);
- htable_str2sols_clear(&parser->str2entities);
- darray_entity_clear(&parser->entities);
-
- /* Miscellaneous */
- darray_anchor_clear(&parser->anchors);
- darray_pivot_clear(&parser->pivots);
-}
-
-static void
-parser_release(ref_T* ref)
-{
- struct solstice_parser* parser;
- ASSERT(ref);
-
- parser = CONTAINER_OF(ref, struct solstice_parser, ref);
- if(parser->parser_is_init) yaml_parser_delete(&parser->parser);
- str_release(&parser->stream_name);
-
- /* Materials */
- htable_yaml2sols_release(&parser->yaml2mtls);
- darray_material_release(&parser->mtls);
- darray_material2_release(&parser->mtls2);
- darray_matte_release(&parser->mattes);
- darray_mirror_release(&parser->mirrors);
-
- /* Shapes */
- darray_shape_release(&parser->shapes);
- darray_cuboid_release(&parser->cuboids);
- darray_cylinder_release(&parser->cylinders);
- darray_impgeom_release(&parser->objs);
- darray_paraboloid_release(&parser->parabols);
- darray_paraboloid_release(&parser->parabolic_cylinders);
- darray_plane_release(&parser->planes);
- darray_sphere_release(&parser->spheres);
- darray_impgeom_release(&parser->stls);
-
- /* Geometries */
- htable_yaml2sols_release(&parser->yaml2geoms);
- darray_object_release(&parser->objects);
- darray_geometry_release(&parser->geometries);
-
- /* Sun */
- solstice_sun_release(&parser->sun);
-
- /* Entities */
- htable_yaml2sols_release(&parser->yaml2entities);
- htable_str2sols_release(&parser->str2entities);
- darray_entity_release(&parser->entities);
-
- /* Miscellaneous */
- darray_anchor_release(&parser->anchors);
- darray_pivot_release(&parser->pivots);
-
- MEM_RM(parser->allocator, parser);
-}
-
-/*******************************************************************************
- * Miscellaneous parsing functions
- ******************************************************************************/
-static res_T
-parse_real
- (struct solstice_parser* parser,
- const yaml_node_t* real,
- const double lower_bound,
- const double upper_bound,
- double* dst)
-{
- res_T res = RES_OK;
- ASSERT(real && dst && lower_bound < upper_bound);
-
- if(real->type != YAML_SCALAR_NODE
- || !strlen((char*)real->data.scalar.value)) {
- log_err(parser, real, "expect a floating point number.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- res = cstr_to_double((char*)real->data.scalar.value, dst);
- if(res != RES_OK) {
- log_err(parser, real, "invalid floating point number `%s'.\n",
- real->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(*dst < lower_bound || *dst > upper_bound) {
- log_err(parser, real, "%g is not in [%g, %g].\n",
- *dst, lower_bound, upper_bound);
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_real3
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* real3,
- const double lower_bound,
- const double upper_bound,
- double dst[3])
-{
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && real3 && dst);
-
- if(real3->type != YAML_SEQUENCE_NODE) {
- log_err(parser, real3, "expect a sequence of 3 reals.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = real3->data.sequence.items.top - real3->data.sequence.items.start;
- if(n != 3) {
- log_err(parser, real3, "expect 3 reals while `%li' %s submitted.\n",
- n, n > 1 ? "are" : "is");
- res = RES_BAD_ARG;
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- yaml_node_t* real;
- real = yaml_document_get_node(doc, real3->data.sequence.items.start[i]);
- res = parse_real(parser, real, lower_bound, upper_bound, dst + i);
- if(res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_integer
- (struct solstice_parser* parser,
- yaml_node_t* integer,
- const long lower_bound,
- const long upper_bound,
- long* dst)
-{
- res_T res = RES_OK;
- ASSERT(integer && dst && lower_bound < upper_bound);
-
- if(integer->type != YAML_SCALAR_NODE
- || !strlen((char*)integer->data.scalar.value)) {
- log_err(parser, integer, "expect an integer.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- res = cstr_to_long((char*)integer->data.scalar.value, dst);
- if(res != RES_OK) {
- log_err(parser, integer, "invalid integer `%s'.\n",
- integer->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(*dst < lower_bound || *dst > upper_bound) {
- log_err(parser, integer, "%li is not in [%li, %li].\n",
- *dst, lower_bound, upper_bound);
- res = RES_BAD_ARG;
- goto error;
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_string
- (struct solstice_parser* parser,
- yaml_node_t* string,
- struct str* str)
-{
- res_T res = RES_OK;
- ASSERT(string && str);
-
- if(string->type != YAML_SCALAR_NODE
- || !strlen((char*)string->data.scalar.value)) {
- log_err(parser, string, "expect a character string.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- res = str_set(str, (char*)string->data.scalar.value);
- if(res != RES_OK) {
- log_err(parser, string, "could not register the string `%s'.\n",
- string->data.scalar.value);
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_transform
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* transform,
- double translation[3],
- double rotation[3])
-{
- enum { ROTATION, TRANSLATION };
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && translation && rotation && transform);
-
- d3_splat(translation, 0);
- d3_splat(rotation, 0);
-
- if(transform->type != YAML_MAPPING_NODE) {
- log_err(parser, transform, "expect a mapping of transform parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = transform->data.mapping.pairs.top - transform->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, transform->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, transform->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect transform parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, "the transform `"Name"' is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "translation")) {
- SETUP_MASK(TRANSLATION, "translation");
- res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, translation);
- } else if(!strcmp((char*)key->data.scalar.value, "rotation")) {
- SETUP_MASK(ROTATION, "rotation");
- res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, rotation);
- } else {
- log_err(parser, key, "unknown transform parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_spectrum_data
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const double lower_bound,
- const double upper_bound,
- const yaml_node_t* sdata,
- struct solstice_spectrum_data* spectrum_data)
-{
- enum { DATA, WAVELENGTH };
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && sdata && lower_bound < upper_bound && spectrum_data);
-
- if(sdata->type != YAML_MAPPING_NODE) {
- log_err(parser, sdata, "expect the definition of a spectrum data.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = sdata->data.mapping.pairs.top - sdata->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, sdata->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, sdata->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a spectrum data parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the `"Name"' of the spectrum data is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "data")) {
- SETUP_MASK(DATA, "data");
- res = parse_real(parser, val, lower_bound, upper_bound, &spectrum_data->data);
- } else if(!strcmp((char*)key->data.scalar.value, "wavelength")) {
- SETUP_MASK(WAVELENGTH, "wavelength");
- res = parse_real(parser, val, 0, DBL_MAX, &spectrum_data->wavelength);
- } else {
- log_err(parser, key, "unknown spectrum data parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, sdata,"the "Name" of the spectrum data is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(DATA, "data");
- CHECK_PARAM(WAVELENGTH, "wavelength");
- #undef CHECK_PARAM
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_spectrum
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const double lower_bound,
- const double upper_bound,
- const yaml_node_t* spectrum,
- struct darray_spectrum_data* data)
-{
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && spectrum && lower_bound < upper_bound && data);
-
- if(spectrum->type != YAML_SEQUENCE_NODE) {
- log_err(parser, spectrum, "expect a list of spectrum data.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = spectrum->data.sequence.items.top - spectrum->data.sequence.items.start;
- res = darray_spectrum_data_resize(data, (size_t)n);
- if(res != RES_OK) {
- log_err(parser, spectrum, "could not allocate the list of spectrum data.\n");
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- yaml_node_t* sdata;
- struct solstice_spectrum_data* spectrum_data;
-
- sdata = yaml_document_get_node(doc, spectrum->data.sequence.items.start[i]);
- spectrum_data = darray_spectrum_data_data_get(data) + i;
- res = parse_spectrum_data
- (parser, doc, lower_bound, upper_bound, sdata, spectrum_data);
- if(res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- darray_spectrum_data_clear(data);
- goto exit;
-}
-
-/*******************************************************************************
- * Material
- ******************************************************************************/
-static res_T
-parse_material_matte
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* matte,
- struct solstice_material_matte_id* out_imtl)
-{
- enum { REFLECTIVITY };
- struct solstice_material_matte* mtl = NULL;
- size_t imtl = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && matte && out_imtl);
-
- if(matte->type != YAML_MAPPING_NODE) {
- log_err(parser, matte, "expect a mapping of matte material parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate the matte material */
- imtl = darray_matte_size_get(&parser->mattes);
- res = darray_matte_resize(&parser->mattes, imtl + 1);
- if(res != RES_OK) {
- log_err(parser, matte, "could not allocate the matte material.\n");
- goto error;
- }
- mtl = darray_matte_data_get(&parser->mattes) + imtl;
-
- n = matte->data.mapping.pairs.top - matte->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, matte->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, matte->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a matte material parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!strcmp((char*)key->data.scalar.value, "reflectivity")) {
- if(mask & BIT(REFLECTIVITY)) {
- log_err(parser, key, "the matte reflectivity is already defined.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- mask |= BIT(REFLECTIVITY);
- res = parse_real(parser, val, 0, 1, &mtl->reflectivity);
- } else {
- log_err(parser, key, "unknown matte parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- }
-
- if(!(mask & BIT(REFLECTIVITY))) {
- log_err(parser, matte, "the matte reflectivity is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- out_imtl->i = imtl;
- return res;
-error:
- if(mtl) {
- darray_matte_pop_back(&parser->mattes);
- imtl = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_material_mirror
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* mirror,
- struct solstice_material_mirror_id* out_imtl)
-{
- enum { REFLECTIVITY, ROUGHNESS };
- struct solstice_material_mirror* mtl = NULL;
- size_t imtl = SIZE_MAX;
- int mask = 0; /* Register the parsed attributes */
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && mirror && out_imtl);
-
- if(mirror->type != YAML_MAPPING_NODE) {
- log_err(parser, mirror,
- "expect a mapping of mirror material attributes .\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate the mirror material */
- imtl = darray_mirror_size_get(&parser->mirrors);
- res = darray_mirror_resize(&parser->mirrors, imtl + 1);
- if(res != RES_OK) {
- log_err(parser, mirror, "could not allocate the mirror material.\n");
- goto error;
- }
- mtl = darray_mirror_data_get(&parser->mirrors) + imtl;
-
- n = mirror->data.mapping.pairs.top - mirror->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, mirror->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, mirror->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a mirror material parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the "Name" of the mirror material is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "reflectivity")) {
- SETUP_MASK(REFLECTIVITY, "reflectivity");
- res = parse_real(parser, val, 0, 1, &mtl->reflectivity);
- } else if(!strcmp((char*)key->data.scalar.value, "roughness")) {
- SETUP_MASK(ROUGHNESS, "roughness");
- res = parse_real(parser, val, 0, 1, &mtl->roughness);
- } else {
- log_err(parser, key, "unknown mirror attribute `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, mirror, "the mirror "Name" is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(REFLECTIVITY, "reflectivity");
- CHECK_PARAM(ROUGHNESS, "roughness");
- #undef CHECK_PARAM
-
-exit:
- out_imtl->i = imtl;
- return res;
-error:
- if(mtl) {
- darray_mirror_pop_back(&parser->mirrors);
- imtl = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_material_descriptor
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* desc,
- struct solstice_material_id* out_imtl)
-{
- enum { DESCRIPTOR };
- struct solstice_material* mtl = NULL;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- size_t* pimtl;
- size_t imtl = SIZE_MAX;
- res_T res = RES_OK;
- ASSERT(doc && desc && out_imtl);
-
- /* Check whether or not the YAML descriptor alias an already created Solstice
- * material */
- pimtl = htable_yaml2sols_find(&parser->yaml2mtls, &desc);
- if(pimtl) {
- imtl = *pimtl;
- goto exit;
- }
-
- /* Allocate the solstice material */
- imtl = darray_material_size_get(&parser->mtls);
- res = darray_material_resize(&parser->mtls, imtl + 1);
- if(res != RES_OK) {
- log_err(parser, desc, "could not allocate the material descriptor.\n");
- goto error;
- }
- mtl = darray_material_data_get(&parser->mtls) + imtl;
-
- if(desc->type != YAML_MAPPING_NODE) {
- log_err(parser, desc, "expect a material descriptor.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = desc->data.mapping.pairs.top - desc->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a material name.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, "the material "Name" is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "matte")) {
- SETUP_MASK(DESCRIPTOR, "descriptor");
- mtl->type = SOLSTICE_MATERIAL_MATTE;
- res = parse_material_matte(parser, doc, val, &mtl->data.matte);
- } else if(!strcmp((char*)key->data.scalar.value, "mirror")) {
- SETUP_MASK(DESCRIPTOR, "descriptor");
- mtl->type = SOLSTICE_MATERIAL_MIRROR;
- res = parse_material_mirror(parser, doc, val, &mtl->data.mirror);
- } else {
- log_err(parser, key, "unknown material descriptor `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- if(!(mask & BIT(DESCRIPTOR))) {
- log_err(parser, desc, "the material descriptor is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Cache the material */
- res = htable_yaml2sols_set(&parser->yaml2mtls, &desc, &imtl);
- if(res != RES_OK) {
- log_err(parser, desc, "could not register the material.\n");
- goto error;
- }
-
-exit:
- out_imtl->i = imtl;
- return res;
-error:
- if(mtl) {
- darray_material_pop_back(&parser->mtls);
- imtl = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_material
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* mtl,
- struct solstice_material_double_sided_id* out_imtl2)
-{
- enum { FRONT, BACK };
- struct solstice_material_double_sided* mtl2 = NULL;
- size_t imtl2 = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && mtl && out_imtl2);
-
- if(mtl->type != YAML_MAPPING_NODE) {
- log_err(parser, mtl, "expect a material definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate the double sided material */
- imtl2 = darray_material2_size_get(&parser->mtls2);
- res = darray_material2_resize(&parser->mtls2, imtl2 + 1);
- if(res != RES_OK) {
- log_err(parser, mtl, "could not allocate the material.\n");
- goto error;
- }
- mtl2 = darray_material2_data_get(&parser->mtls2) + imtl2;
-
- n = mtl->data.mapping.pairs.top - mtl->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, mtl->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, mtl->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key,
- "expect a material descriptor or a double sided material.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the "Name" material descriptor is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "front")) {
- SETUP_MASK(FRONT, "front");
- res = parse_material_descriptor(parser, doc, val, &mtl2->front);
- } else if(!strcmp((char*)key->data.scalar.value, "back")) {
- SETUP_MASK(BACK, "back");
- res = parse_material_descriptor(parser, doc, val, &mtl2->back);
- } else {
- SETUP_MASK(FRONT, "front");
- SETUP_MASK(BACK, "back");
- res = parse_material_descriptor(parser, doc, mtl, &mtl2->front);
- mtl2->back = mtl2->front;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, mtl, "the "Name" material descriptor is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(FRONT, "front");
- CHECK_PARAM(BACK, "back");
- #undef CHECK_PARAM
-
-exit:
- out_imtl2->i = imtl2;
- return res;
-error:
- if(mtl2) {
- darray_material2_pop_back(&parser->mtls2);
- imtl2 = SIZE_MAX;
- }
- goto exit;
-}
-
-/*******************************************************************************
- * Clipping polygon
- ******************************************************************************/
-static res_T
-parse_clip_op
- (struct solstice_parser* parser,
- const yaml_node_t* op,
- enum solstice_clip_op* clip_op)
-{
- res_T res = RES_OK;
- ASSERT(op && clip_op);
-
- if(op->type != YAML_SCALAR_NODE) {
- log_err(parser, op, "expect a clipping operation.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!strcmp((char*)op->data.scalar.value, "AND")) {
- *clip_op = SOLSTICE_CLIP_OP_AND;
- } else if(!strcmp((char*)op->data.scalar.value, "SUB")) {
- *clip_op = SOLSTICE_CLIP_OP_SUB;
- } else {
- log_err(parser, op, "unknown clipping operation `%s'.\n",
- op->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_vertices
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* vertices,
- struct darray_double* coords)
-{
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && vertices && coords);
-
- if(vertices->type != YAML_SEQUENCE_NODE) {
- log_err(parser, vertices, "expect a list of vertices.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = vertices->data.sequence.items.top - vertices->data.sequence.items.start;
- if(n < 3) {
- log_err(parser, vertices, "expect at least 3 vertices.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- res = darray_double_resize(coords, (size_t)n*3/*#coords per vertex*/);
- if(res != RES_OK) {
- log_err(parser, vertices, "could not allocate the array of vertices.\n");
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- yaml_node_t* vertex;
- double* real3 = darray_double_data_get(coords) + i*3/*#coords per vertex*/;
-
- vertex = yaml_document_get_node(doc, vertices->data.sequence.items.start[i]);
- res = parse_real3(parser, doc, vertex, -DBL_MAX, DBL_MAX, real3);
- if(res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- darray_double_clear(coords);
- goto exit;
-}
-
-static res_T
-parse_polyclip
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* polyclip,
- struct solstice_polyclip* clip)
-{
- enum { OPERATION, VERTICES };
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && polyclip && clip);
-
- if(polyclip->type != YAML_MAPPING_NODE) {
- log_err(parser, polyclip,
- "expect a mapping of clipping polygon parameters.\n");
- res = RES_OK;
- goto error;
- }
-
- n = polyclip->data.mapping.pairs.top - polyclip->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, polyclip->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, polyclip->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a clipping polygon parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the clipping polygon parameter `"Name"' is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "operation")) {
- SETUP_MASK(OPERATION, "operation");
- res = parse_clip_op(parser, val, &clip->op);
- } else if(!strcmp((char*)key->data.scalar.value, "vertices")) {
- SETUP_MASK(VERTICES, "vertices");
- res = parse_vertices(parser, doc, val, &clip->vertices);
- } else {
- log_err(parser, key, "unknown clipping polygon parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, polyclip, \
- "the clipping polygon parameter `"Name"' is missing"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(OPERATION, "operation");
- CHECK_PARAM(VERTICES, "vertices");
- #undef CHECK_PARAM
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_clip
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* clip,
- struct darray_polyclip* polyclips)
-{
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && clip && polyclips);
-
- if(clip->type != YAML_SEQUENCE_NODE) {
- log_err(parser, clip, "expect a list of clipping polygons.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = clip->data.sequence.items.top - clip->data.sequence.items.start;
-
- /* Allocate the clipping polygons */
- res = darray_polyclip_resize(polyclips, (size_t)n);
- if(res != RES_OK) {
- log_err(parser, clip, "could not allocate the list of clipping polygons.\n");
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- yaml_node_t* node;
- struct solstice_polyclip* polyclip = darray_polyclip_data_get(polyclips) + i;
-
- node = yaml_document_get_node(doc, clip->data.sequence.items.start[i]);
- res = parse_polyclip(parser, doc, node, polyclip);
- if(res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * Shapes
- ******************************************************************************/
-static res_T
-parse_cuboid
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* cuboid,
- struct solstice_shape_cuboid_id* out_ishape)
-{
- enum { SIZE };
- struct solstice_shape_cuboid* shape = NULL;
- size_t ishape = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && cuboid && out_ishape);
-
- if(cuboid->type != YAML_MAPPING_NODE) {
- log_err(parser, cuboid, "expect a mapping of cuboid parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate a cuboid */
- ishape = darray_cuboid_size_get(&parser->cuboids);
- res = darray_cuboid_resize(&parser->cuboids, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, cuboid, "could not allocate the cuboid shape.\n");
- goto exit;
- }
- shape = darray_cuboid_data_get(&parser->cuboids) + ishape;
-
- n = cuboid->data.mapping.pairs.top - cuboid->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, cuboid->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, cuboid->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect cuboid parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- if(!strcmp((char*)key->data.scalar.value, "size")) {
- if(mask & BIT(SIZE)) {
- log_err(parser, key, "the cuboid size is already defined.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- mask |= BIT(SIZE);
- res = parse_real3(parser, doc, val, 0, DBL_MAX, shape->size);
- } else {
- log_err(parser, key, "unknown cuboid parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- }
-
- if(!(mask & BIT(SIZE))) {
- log_err(parser, cuboid, "the size of the cuboid is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- out_ishape->i = ishape;
- return res;
-error:
- if(shape) {
- darray_cuboid_pop_back(&parser->cuboids);
- ishape = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_cylinder
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* cylinder,
- struct solstice_shape_cylinder_id* out_ishape)
-{
- enum { HEIGHT, RADIUS, SLICES };
- struct solstice_shape_cylinder* shape = NULL;
- size_t ishape = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && cylinder && out_ishape);
-
- if(cylinder->type != YAML_MAPPING_NODE) {
- log_err(parser, cylinder, "expect a mapping of cylinder parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate a cylinder */
- ishape = darray_cylinder_size_get(&parser->cylinders);
- res = darray_cylinder_resize(&parser->cylinders, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, cylinder, "could not alocate the cylinder shape.\n");
- goto exit;
- }
- shape = darray_cylinder_data_get(&parser->cylinders) + ishape;
-
- n = cylinder->data.mapping.pairs.top - cylinder->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, cylinder->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, cylinder->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect cylinder parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the cylinder parameter `"Name"' is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "height")) {
- SETUP_MASK(HEIGHT, "height");
- res = parse_real(parser, val, 0, DBL_MAX, &shape->height);
- } else if(!strcmp((char*)key->data.scalar.value, "radius")) {
- SETUP_MASK(RADIUS, "radius");
- res = parse_real(parser, val, 0, DBL_MAX, &shape->radius);
- } else if(!strcmp((char*)key->data.scalar.value, "slices")) {
- SETUP_MASK(SLICES, "slices");
- res = parse_integer(parser, val, 4, 4096, &shape->nslices);
- } else {
- log_err(parser, key, "unknown cylinder parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, cylinder, \
- "the cylinder parameter `"Name"' is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(HEIGHT, "height");
- CHECK_PARAM(RADIUS, "radius");
- #undef CHECK_PARAM
-
-exit:
- out_ishape->i = ishape;
- return res;
-error:
- if(shape) {
- darray_cylinder_pop_back(&parser->cylinders);
- ishape = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_imported_geometry
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* geom,
- const enum solstice_shape_type type,
- struct solstice_shape_imported_geometry_id* out_ishape)
-{
- enum { PATH };
- struct solstice_shape_imported_geometry* shape = NULL;
- size_t ishape = SIZE_MAX;
- const char* name;
- struct darray_impgeom* impgeoms;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && geom && out_ishape);
-
- switch(type) {
- case SOLSTICE_SHAPE_OBJ: name = "obj"; impgeoms = &parser->objs; break;
- case SOLSTICE_SHAPE_STL: name = "stl"; impgeoms = &parser->stls; break;
- default: FATAL("Unreachable code.\n"); break;
- }
-
- if(geom->type != YAML_MAPPING_NODE) {
- log_err(parser, geom, "expect a mapping of %s parameters.\n", name);
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate an imported geometry */
- ishape = darray_impgeom_size_get(impgeoms);
- res = darray_impgeom_resize(impgeoms, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, geom, "could not allocate the %s shape.\n", name);
- goto error;
- }
- shape = darray_impgeom_data_get(impgeoms) + ishape;
-
- n = geom->data.mapping.pairs.top - geom->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, geom->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, geom->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect %s parameters.\n", name);
- res = RES_BAD_ARG;
- goto error;
- }
- if(!strcmp((char*)key->data.scalar.value, "path")) {
- if(mask & BIT(PATH)) {
- log_err(parser, key, "the %s path is already defined.\n", name);
- res = RES_BAD_ARG;
- goto error;
- }
- mask |= BIT(PATH);
- res = parse_string(parser, val, &shape->filename);
- } else {
- log_err(parser, key, "unknown %s parameter `%s'.\n",
- name, key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- }
-
- if(!(mask & BIT(PATH))) {
- log_err(parser, geom, "the path of the %s geometry is missing.\n", name);
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- out_ishape->i = ishape;
- return res;
-error:
- if(shape) {
- darray_impgeom_pop_back(impgeoms);
- ishape = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_paraboloid
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* paraboloid,
- const enum solstice_shape_type type,
- struct solstice_shape_paraboloid_id* out_ishape)
-{
- enum { CLIP, FOCAL };
- struct solstice_shape_paraboloid* shape = NULL;
- struct darray_paraboloid* paraboloids;
- const char* name;
- size_t ishape = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && paraboloid && out_ishape);
-
- switch(type) {
- case SOLSTICE_SHAPE_PARABOL:
- name = "parabol";
- paraboloids = &parser->parabols;
- break;
- case SOLSTICE_SHAPE_PARABOLIC_CYLINDER:
- name = "parabolic cylinder";
- paraboloids = &parser->parabolic_cylinders;
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
-
- if(paraboloid->type != YAML_MAPPING_NODE) {
- log_err(parser, paraboloid, "expect a mapping of %s parameters.\n", name);
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate a paraboloid shape */
- ishape = darray_paraboloid_size_get(paraboloids);
- res = darray_paraboloid_resize(paraboloids, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, paraboloid, "could not allocate the %s shape.\n", name);
- goto error;
- }
- shape = darray_paraboloid_data_get(paraboloids) + ishape;
-
- n = paraboloid->data.mapping.pairs.top - paraboloid->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, paraboloid->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, paraboloid->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect %s parameters.\n", name);
- res = RES_BAD_ARG;
- goto error;
- }
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the %s parameter `"Name"' is already defined.\n", name); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "clip")) {
- SETUP_MASK(CLIP, "clip");
- res = parse_clip(parser, doc, val, &shape->polyclips);
- } else if(!strcmp((char*)key->data.scalar.value, "focal")) {
- SETUP_MASK(FOCAL, "focal");
- res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &shape->focal);
- } else {
- log_err(parser, key, "unknown %s parameter `%s'.\n",
- name, key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, paraboloid, \
- "the %s parameter `"Name"' is missing.\n", name); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(CLIP, "clip");
- CHECK_PARAM(FOCAL, "focal");
- #undef CHECK_PARAM
-
-exit:
- out_ishape->i = ishape;
- return res;
-error:
- if(shape) {
- darray_paraboloid_pop_back(paraboloids);
- ishape = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_plane
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* plane,
- struct solstice_shape_plane_id* out_ishape)
-{
- enum { CLIP };
- struct solstice_shape_plane* shape = NULL;
- size_t ishape = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && plane && out_ishape);
-
- if(plane->type != YAML_MAPPING_NODE) {
- log_err(parser, plane, "expect a mapping of plane parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate a plane shape */
- ishape = darray_plane_size_get(&parser->planes);
- res = darray_plane_resize(&parser->planes, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, plane, "could not allocate the plane shape.\n");
- goto error;
- }
- shape = darray_plane_data_get(&parser->planes) + ishape;
-
- n = plane->data.mapping.pairs.top - plane->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, plane->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, plane->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect plane parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- if(!strcmp((char*)key->data.scalar.value, "clip")) {
- if(mask & BIT(CLIP)) {
- log_err(parser, key, "the plane clipping is already defined.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- mask |= BIT(CLIP);
- res = parse_clip(parser, doc, val, &shape->polyclips);
- } else {
- log_err(parser, key, "unknown plane parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- }
- if(!(mask & BIT(CLIP))) {
- log_err(parser, plane, "the plane parameter `clip' is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- out_ishape->i = ishape;
- return res;
-error:
- if(shape) {
- darray_plane_pop_back(&parser->planes);
- ishape = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_sphere
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* sphere,
- struct solstice_shape_sphere_id* out_ishape)
-{
- enum { RADIUS, SLICES };
- struct solstice_shape_sphere* shape = NULL;
- size_t ishape = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && sphere && out_ishape);
-
- if(sphere->type != YAML_MAPPING_NODE) {
- log_err(parser, sphere, "expect a mapping of sphere parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate a shpere shape */
- ishape = darray_sphere_size_get(&parser->spheres);
- res = darray_sphere_resize(&parser->spheres, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, sphere, "could not allocate the sphere shape.\n");
- goto error;
- }
- shape = darray_sphere_data_get(&parser->spheres) + ishape;
-
- n = sphere->data.mapping.pairs.top - sphere->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, sphere->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, sphere->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect sphere parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the sphere parameter `"Name"' is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "radius")) {
- SETUP_MASK(RADIUS, "radius");
- res = parse_real(parser, val, 0, DBL_MAX, &shape->radius);
- } else if(!strcmp((char*)key->data.scalar.value, "slices")) {
- SETUP_MASK(SLICES, "slices");
- res = parse_integer(parser, val, 4, 4096, &shape->nslices);
- } else {
- log_err(parser, key, "unknown sphere parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- if(!(mask & BIT(RADIUS))) {
- log_err(parser, sphere, "the sphere radius is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- out_ishape->i = ishape;
- return res;
-error:
- if(shape) {
- darray_sphere_pop_back(&parser->spheres);
- ishape = SIZE_MAX;
- }
- goto exit;
-}
-
-/*******************************************************************************
- * Geometry
- ******************************************************************************/
-static res_T
-parse_object
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* object,
- struct solstice_object_id* out_iobj)
-{
- enum { MATERIAL, SHAPE, TRANSFORM };
- struct solstice_object* obj = NULL;
- struct solstice_shape* shape = NULL;
- size_t iobj = SIZE_MAX;
- size_t ishape = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && object && out_iobj);
-
- if(object->type != YAML_MAPPING_NODE) {
- log_err(parser, object, "expect an object definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate an object */
- iobj = darray_object_size_get(&parser->objects);
- res = darray_object_resize(&parser->objects, iobj + 1);
- if(res != RES_OK) {
- log_err(parser, object, "could not allocate the object.\n");
- goto error;
- }
- obj = darray_object_data_get(&parser->objects) + iobj;
-
- /* Allocate a shape */
- ishape = darray_shape_size_get(&parser->shapes);
- res = darray_shape_resize(&parser->shapes, ishape + 1);
- if(res != RES_OK) {
- log_err(parser, object, "could not allocate the object shape.\n");
- goto error;
- }
- shape = darray_shape_data_get(&parser->shapes) + ishape;
- obj->shape.i = ishape;
-
- /* Setup default object transformation */
- d3_splat(obj->translation, 0);
- d3_splat(obj->rotation, 0);
-
- n = object->data.mapping.pairs.top - object->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, object->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, object->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect an object parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the object "Name" is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "material")) {
- SETUP_MASK(MATERIAL, "material");
- res = parse_material(parser, doc, val, &obj->mtl2);
- } else if(!strcmp((char*)key->data.scalar.value, "cuboid")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_CUBOID;
- res = parse_cuboid(parser, doc, val, &shape->data.cuboid);
- } else if(!strcmp((char*)key->data.scalar.value, "cylinder")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_CYLINDER;
- res = parse_cylinder(parser, doc, val, &shape->data.cylinder);
- } else if(!strcmp((char*)key->data.scalar.value, "obj")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_OBJ;
- res = parse_imported_geometry
- (parser, doc, val, shape->type, &shape->data.obj);
- } else if(!strcmp((char*)key->data.scalar.value, "parabol")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_PARABOL;
- res = parse_paraboloid
- (parser, doc, val, shape->type, &shape->data.parabol);
- } else if(!strcmp((char*)key->data.scalar.value, "parabolic-cylinder")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_PARABOLIC_CYLINDER;
- res = parse_paraboloid
- (parser, doc, val, shape->type, &shape->data.parabolic_cylinder);
- } else if(!strcmp((char*)key->data.scalar.value, "plane")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_PLANE;
- res = parse_plane(parser, doc, val, &shape->data.plane);
- } else if(!strcmp((char*)key->data.scalar.value, "sphere")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_SPHERE;
- res = parse_sphere(parser, doc, val, &shape->data.sphere);
- } else if(!strcmp((char*)key->data.scalar.value, "stl")) {
- SETUP_MASK(SHAPE, "shape");
- shape->type = SOLSTICE_SHAPE_STL;
- res = parse_imported_geometry
- (parser, doc, val, shape->type, &shape->data.stl);
- } else if(!strcmp((char*)key->data.scalar.value, "transform")) {
- SETUP_MASK(TRANSFORM, "transform");
- res = parse_transform(parser, doc, val, obj->translation, obj->rotation);
- } else {
- log_err(parser, key, "unknown object parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, object, "the object "Name" is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(MATERIAL, "material");
- CHECK_PARAM(SHAPE, "shape");
- #undef CHECK_PARAM
-
-exit:
- out_iobj->i = iobj;
- return res;
-error:
- if(obj) {
- if(shape) darray_shape_pop_back(&parser->shapes);
- darray_object_pop_back(&parser->objects);
- obj = NULL;
- }
- goto exit;
-}
-
-static res_T
-parse_geometry
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* geometry,
- struct solstice_geometry_id* out_isolgeom)
-{
- struct solstice_geometry* solgeom = NULL;
- size_t* pisolgeom;
- size_t isolgeom = SIZE_MAX;
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && geometry && out_isolgeom);
-
- if(geometry->type != YAML_SEQUENCE_NODE) {
- log_err(parser, geometry, "expect a list of objects.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Check whether or not the YAML descriptor alias an already created Solstice
- * geometry */
- pisolgeom = htable_yaml2sols_find(&parser->yaml2geoms, &geometry);
- if(pisolgeom) {
- isolgeom = *pisolgeom;
- goto exit;
- }
-
- /* Allocate the geometry */
- isolgeom = darray_geometry_size_get(&parser->geometries);
- res = darray_geometry_resize(&parser->geometries, isolgeom + 1);
- if(res != RES_OK) {
- log_err(parser, geometry, "could not allocate the geometry.\n");
- goto error;
- }
- solgeom = darray_geometry_data_get(&parser->geometries) + isolgeom;
-
- n = geometry->data.sequence.items.top - geometry->data.sequence.items.start;
- res = darray_object_id_resize(&solgeom->objects, (size_t)n);
- if(res != RES_OK) {
- log_err(parser, geometry, "could not allocate the objects list.\n");
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- struct solstice_object_id* obj_id;
- yaml_node_t* obj;
-
- obj_id = darray_object_id_data_get(&solgeom->objects) + i;
- obj = yaml_document_get_node(doc, geometry->data.sequence.items.start[i]);
- res = parse_object(parser, doc, obj, obj_id);
- if(res != RES_OK) goto error;
- }
-
- /* Cache the geometry */
- res = htable_yaml2sols_set(&parser->yaml2geoms, &geometry, &isolgeom);
- if(res != RES_OK) {
- log_err(parser, geometry, "could not register the geometry.\n");
- goto error;
- }
-
-exit:
- out_isolgeom->i = isolgeom;
- return res;
-error:
- if(solgeom) {
- darray_geometry_pop_back(&parser->geometries);
- isolgeom = SIZE_MAX;
- }
- goto exit;
-}
-
-
-/*******************************************************************************
- * Entity
- ******************************************************************************/
-static res_T
-entity_register_name
- (struct solstice_parser* parser,
- const yaml_node_t* entity,
- struct htable_str2sols* htable,
- const size_t isolent)
-{
- struct solstice_entity* solent;
- size_t* pisolent;
- res_T res = RES_OK;
- ASSERT(parser && htable);
- ASSERT(isolent < darray_entity_size_get(&parser->entities));
-
- solent = darray_entity_data_get(&parser->entities) + isolent;
-
- pisolent = htable_str2sols_find(htable, &solent->name);
- if(pisolent) {
- log_err(parser, entity,
- "an entity with the name `%s' is already defined in the current context.\n",
- str_cget(&solent->name));
- return RES_BAD_ARG;
- }
-
- res = htable_str2sols_set(htable, &solent->name, &isolent);
- if(res != RES_OK) {
- log_err(parser, entity, "could not register the entity.\n");
- return res;
- }
- return RES_OK;
-}
-
-static res_T
-anchor_register_name
- (struct solstice_parser* parser,
- const yaml_node_t* anchor,
- struct htable_str2sols* htable,
- const size_t isolanchor)
-{
- struct solstice_anchor* solanchor;
- size_t* pisolanchor;
- res_T res = RES_OK;
- ASSERT(parser && htable);
- ASSERT(isolanchor < darray_anchor_size_get(&parser->anchors));
-
- solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor;
-
- pisolanchor = htable_str2sols_find(htable, &solanchor->name);
- if(pisolanchor) {
- log_err(parser, anchor,
- "an anchor with the name `%s' is already defined in the cunrrent context.\n",
- str_cget(&solanchor->name));
- return RES_BAD_ARG;
- }
-
- res = htable_str2sols_set(htable, &solanchor->name, &isolanchor);
- if(res != RES_OK) {
- log_err(parser, anchor, "could not register the anchor.\n");
- return res;
- }
- return RES_OK;
-}
-
-static res_T
-parse_identifier_string
- (struct solstice_parser* parser,
- yaml_node_t* name,
- struct str* str)
-{
- res_T res = RES_OK;
- ASSERT(parser && name && str);
-
- res = parse_string(parser, name, str);
- if(res != RES_OK) goto error;
-
- if(strchr(str_cget(str), '.')) {
- log_err(parser, name, "invalid character `.' in the name `%s'.\n",
- str_cget(str));
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_anchor
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* anchor,
- struct htable_str2sols* htable,
- struct solstice_anchor_id* out_isolanchor)
-{
- enum { NAME, POSITION };
- struct solstice_anchor* solanchor = NULL;
- size_t isolanchor = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(parser && anchor && out_isolanchor);
-
- if(anchor->type != YAML_MAPPING_NODE) {
- log_err(parser, anchor, "expect an anchor definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate the anchor */
- isolanchor = darray_anchor_size_get(&parser->anchors);
- res = darray_anchor_resize(&parser->anchors, isolanchor + 1);
- if(res != RES_OK) {
- log_err(parser, anchor, "could not allocate the anchor.\n");
- goto error;
- }
- solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor;
-
- n = anchor->data.mapping.pairs.top - anchor->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect an anchor attribute.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, "the anchor "Name" is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "name")) {
- SETUP_MASK(NAME, "name");
- res = parse_identifier_string(parser, val, &solanchor->name);
- } else if(!strcmp((char*)key->data.scalar.value, "position")) {
- SETUP_MASK(POSITION, "position");
- res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solanchor->position);
- } else {
- log_err(parser, key, "unknown anchor parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, anchor, "the anchor "Name" is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(NAME, "name");
- CHECK_PARAM(POSITION, "position");
- #undef CHECK_PARAM
-
- res = anchor_register_name(parser, anchor, htable, isolanchor);
- if(res != RES_OK) goto error;
-
-exit:
- out_isolanchor->i = isolanchor;
- return res;
-error:
- if(solanchor) {
- darray_anchor_pop_back(&parser->anchors);
- isolanchor = SIZE_MAX;
- }
- goto exit;
-}
-
-static res_T
-parse_anchors
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* anchors,
- struct htable_str2sols* htable,
- struct darray_anchor_id* solanchors)
-{
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(parser && anchors);
-
- if(anchors->type != YAML_SEQUENCE_NODE) {
- log_err(parser, anchors, "expect a list of anchors.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = anchors->data.sequence.items.top - anchors->data.sequence.items.start;
- res = darray_anchor_id_resize(solanchors, (size_t)n);
- if(res != RES_OK) {
- log_err(parser, anchors, "could not allocate the anchors list.\n");
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- struct solstice_anchor_id* anchor_id;
- yaml_node_t* anchor;
-
- anchor_id = darray_anchor_id_data_get(solanchors)+i;
- anchor = yaml_document_get_node(doc, anchors->data.sequence.items.start[i]);
- res = parse_anchor(parser, doc, anchor, htable, anchor_id);
- if(res != RES_OK) goto error;
- }
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_children
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* children,
- struct htable_str2sols* htable,
- struct darray_child_id* entities)
-{
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(parser && children && htable && entities);
-
- if(children->type != YAML_SEQUENCE_NODE) {
- log_err(parser, children, "expect a list of entities.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = children->data.sequence.items.top - children->data.sequence.items.start;
- res = darray_child_id_resize(entities, (size_t)n);
- if(res != RES_OK) {
- log_err(parser, children, "could not allocate the children list.\n");
- goto error;
- }
-
- FOR_EACH(i, 0, n) {
- struct solstice_entity_id* entity_id = darray_child_id_data_get(entities) + i;
- yaml_node_t* child;
-
- child = yaml_document_get_node(doc, children->data.sequence.items.start[i]);
- res = parse_entity(parser, doc, child, htable, entity_id);
- if(res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- darray_child_id_clear(entities);
- goto exit;
-}
-
-res_T
-parse_entity
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- yaml_node_t* entity,
- struct htable_str2sols* htable,
- struct solstice_entity_id* out_isolent)
-{
- enum { ANCHORS, CHILDREN, DATA, NAME, TRANSFORM };
- struct solstice_entity solent;
- struct solstice_entity* psolent;
- const size_t *pisolent;
- size_t isolent = SIZE_MAX;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && entity && htable && out_isolent);
-
- solstice_entity_init(parser->allocator, &solent);
-
- pisolent = htable_yaml2sols_find(&parser->yaml2entities, &entity);
- if(pisolent) {
- isolent = *pisolent;
- res = entity_register_name(parser, entity, htable, *pisolent);
- if(res != RES_OK) goto error;
- goto exit;
- }
-
- if(entity->type != YAML_MAPPING_NODE) {
- log_err(parser, entity, "expect an entity definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate the entity but *DO NOT* retrieve a pointer onto it since the
- * allocation of its children may update its memory location. Use the "on
- * stack" entity `solent' instead. */
- isolent = darray_entity_size_get(&parser->entities);
- res = darray_entity_resize(&parser->entities, isolent + 1);
- if(res != RES_OK) {
- log_err(parser, entity, "could not allocate the entity.\n");
- goto error;
- }
-
- n = entity->data.mapping.pairs.top - entity->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, entity->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, entity->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect an entity attribute.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the entity "Name" is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "anchors")) {
- SETUP_MASK(ANCHORS, "anchors");
- res = parse_anchors
- (parser, doc, val, &solent.str2anchors, &solent.anchors);
- } else if(!strcmp((char*)key->data.scalar.value, "children")) {
- SETUP_MASK(CHILDREN, "children");
- res = parse_children
- (parser, doc, val, &solent.str2children, &solent.children);
- } else if(!strcmp((char*)key->data.scalar.value, "geometry")) {
- SETUP_MASK(DATA, "data");
- solent.type = SOLSTICE_ENTITY_GEOMETRY;
- res = parse_geometry(parser, doc, val, &solent.data.geometry);
- } else if(!strcmp((char*)key->data.scalar.value, "name")) {
- SETUP_MASK(NAME, "name");
- res = parse_identifier_string(parser, val, &solent.name);
- } else if(!strcmp((char*)key->data.scalar.value, "pivot")) {
- SETUP_MASK(DATA, "data");
- solent.type = SOLSTICE_ENTITY_PIVOT;
- res = parse_pivot(parser, doc, val, &solent.data.pivot);
- } else if(!strcmp((char*)key->data.scalar.value, "transform")) {
- SETUP_MASK(TRANSFORM, "transform");
- res = parse_transform
- (parser, doc, val, solent.translation, solent.rotation);
- } else {
- log_err(parser, key, "unknown entity parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- if(!(mask & BIT(DATA))) {
- solent.type = SOLSTICE_ENTITY_EMPTY;
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, entity, "the entity "Name" is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(NAME, "name");
- #undef CHECK_PARAM
-
- psolent = darray_entity_data_get(&parser->entities) + isolent;
- res = solstice_entity_copy_and_clear(psolent, &solent);
- if(res != RES_OK) {
- log_err(parser, entity,
- "could not copy the loaded entity into the parser data structures.\n");
- goto error;
- }
- res = entity_register_name(parser, entity, htable, isolent);
- if(res != RES_OK) goto error;
-
- res = htable_yaml2sols_set(&parser->yaml2entities, &entity, &isolent);
- if(res != RES_OK) {
- log_err(parser, entity, "could not register the entity.\n");
- goto error;
- }
-
-exit:
- solstice_entity_release(&solent);
- out_isolent->i = isolent;
- return res;
-error:
- if(isolent != SIZE_MAX) {
- htable_str2sols_erase(htable, &solent.name);
- darray_entity_pop_back(&parser->entities);
- isolent = SIZE_MAX;
- }
- goto exit;
-}
-
-/*******************************************************************************
- * Pivot
- ******************************************************************************/
-static res_T
-parse_anchor_alias
- (struct solstice_parser* parser,
- const yaml_node_t* alias,
- struct solstice_anchor_id* out_ianchor)
-{
- const struct solstice_anchor* anchor = NULL;
- intptr_t ianchor = INTPTR_MAX;
- res_T res = RES_OK;
- ASSERT(parser && alias && out_ianchor);
-
- if(alias->type != YAML_SCALAR_NODE) {
- log_err(parser, alias, "expect an anchor idententifier.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- anchor = solstice_parser_find_anchor(parser, (char*)alias->data.scalar.value);
- if(!anchor) {
- log_err(parser, alias, "undefined anchor `%s'.\n",
- alias->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
-
- ianchor = anchor - darray_anchor_cdata_get(&parser->anchors);
- ASSERT(ianchor >= 0);
- ASSERT((size_t)ianchor < darray_anchor_size_get(&parser->anchors));
-
-exit:
- out_ianchor->i = (size_t)ianchor;
- return res;
-error:
- ianchor = INTPTR_MAX;
- goto exit;
-}
-
-static res_T
-parse_target
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* target,
- struct solstice_pivot* pivot)
-{
- enum { POLICY };
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && target && pivot);
-
- if(target->type != YAML_MAPPING_NODE) {
- log_err(parser, target, "expect a target definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = target->data.mapping.pairs.top - target->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, target->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, target->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a target parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, "the target "Name" is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "anchor")) {
- SETUP_MASK(POLICY, "policy");
- pivot->target_type = SOLSTICE_TARGET_ANCHOR;
- res = parse_anchor_alias(parser, val, &pivot->target.anchor);
- } else if(!strcmp((char*)key->data.scalar.value, "direction")) {
- SETUP_MASK(POLICY, "policy");
- pivot->target_type = SOLSTICE_TARGET_DIRECTION;
- res = parse_real3
- (parser, doc, val, -DBL_MAX, DBL_MAX, pivot->target.direction);
- } else if(!strcmp((char*)key->data.scalar.value, "position")) {
- SETUP_MASK(POLICY, "policy");
- pivot->target_type = SOLSTICE_TARGET_POSITION;
- res = parse_real3
- (parser, doc, val, -DBL_MAX, DBL_MAX, pivot->target.position);
- } else if(!strcmp((char*)key->data.scalar.value, "sun")) {
- /* There is only one sun per YAML file. It is thus sufficient to define
- * the target_type to SOLSTICE_TARGET_SUN to indentify which data is
- * targeted, i.e. it is not necessary to store the identifier of the sun
- * to target */
- struct solstice_sun* sun;
- SETUP_MASK(POLICY, "policy");
- pivot->target_type = SOLSTICE_TARGET_SUN;
- res = parse_sun(parser, doc, val, &sun);
- } else {
- log_err(parser, key, "unknown target parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- goto error;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- if(!(mask & BIT(POLICY))) {
- log_err(parser, target, "the target policy is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_pivot
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* pivot,
- struct solstice_pivot_id* out_isolpivot)
-{
- enum { NORMAL, POINT, TARGET, TRANSFORM };
- struct solstice_pivot* solpivot = NULL;
- size_t isolpivot = SIZE_MAX;
- int mask = 0; /* Register the parsed attributes */
- intptr_t i, n;
- res_T res = RES_OK;
- ASSERT(doc && pivot && out_isolpivot);
-
- if(pivot->type != YAML_MAPPING_NODE) {
- log_err(parser, pivot, "expect a pivot definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- /* Allocate the solstice pivot */
- isolpivot = darray_pivot_size_get(&parser->pivots);
- res = darray_pivot_resize(&parser->pivots, isolpivot + 1);
- if(res != RES_OK) {
- log_err(parser, pivot, "could not allocate the pivot.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- solpivot = darray_pivot_data_get(&parser->pivots) + isolpivot;
-
- n = pivot->data.mapping.pairs.top - pivot->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, pivot->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, pivot->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect pivot parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, \
- "the pivot parameter `"Name"' is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "point")) {
- SETUP_MASK(POINT, "point");
- res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solpivot->point);
- } else if(!strcmp((char*)key->data.scalar.value, "normal")) {
- SETUP_MASK(NORMAL, "normal");
- res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solpivot->normal);
- } else if(!strcmp((char*)key->data.scalar.value, "target")) {
- SETUP_MASK(TARGET, "target");
- res = parse_target(parser, doc, val, solpivot);
- } else if(!strcmp((char*)key->data.scalar.value, "transform")) {
- SETUP_MASK(TRANSFORM, "transform");
- res = parse_transform
- (parser, doc, val, solpivot->translation, solpivot->rotation);
- } else {
- log_err(parser, key, "unknown pivot parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, pivot, "the pivot parameter `"Name"' is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(POINT, "point");
- CHECK_PARAM(NORMAL, "normal");
- CHECK_PARAM(TARGET, "target");
- #undef CHECK_PARAM
-
-exit:
- out_isolpivot->i = isolpivot;
- return res;
-error:
- if(solpivot) {
- darray_pivot_pop_back(&parser->pivots);
- isolpivot = SIZE_MAX;
- }
- goto exit;
-}
-
-/*******************************************************************************
- * Sun
- ******************************************************************************/
-static res_T
-parse_buie
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* buie,
- struct solstice_sun_buie* sun)
-{
- enum { CSR };
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && buie && sun);
-
- if(buie->type != YAML_MAPPING_NODE) {
- log_err(parser, buie,
- "expect a buie definition of the sun radial angular distribution.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = buie->data.mapping.pairs.top - buie->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, buie->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, buie->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a buie parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!strcmp((char*)key->data.scalar.value, "csr")) {
- if(mask & BIT(CSR)) {
- log_err(parser, key, "the buie `csr' is already defined.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- mask |= BIT(CSR);
- res = parse_real(parser, val, nextafter(0, 1), nextafter(1, 0), &sun->csr);
- } else {
- log_err(parser, key, "unknown buie parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- }
-
- if(!(mask & BIT(CSR))) {
- log_err(parser, buie, "the buie csr parameter is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_pillbox
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* pillbox,
- struct solstice_sun_pillbox* sun)
-{
- enum { APERTURE };
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && pillbox && sun);
-
- if(pillbox->type != YAML_MAPPING_NODE) {
- log_err(parser, pillbox,
- "expect a pillbox definition of the sun radial angular distribution.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = pillbox->data.mapping.pairs.top - pillbox->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, pillbox->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, pillbox->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect a pillbox parameter.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- if(!strcmp((char*)key->data.scalar.value, "aperture")) {
- if(mask & BIT(APERTURE)) {
- log_err(parser, key, "the pillbox `aperture' is already defined.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- mask |= BIT(APERTURE);
- res = parse_real(parser, val, nextafter(0, 1), PI/2.0, &sun->aperture);
- } else {
- log_err(parser, pillbox, "unknown pillbox parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- }
-
- if(!(mask & BIT(APERTURE))) {
- log_err(parser, pillbox, "the pillbox aperture parameter is missing.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-res_T
-parse_sun
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* sun,
- struct solstice_sun** out_solsun)
-{
- enum { DNI, RADIAL_ANGULAR_DISTRIB, SPECTRUM };
- struct solstice_sun* solsun = NULL;
- intptr_t i, n;
- int mask = 0; /* Register the parsed attributes */
- res_T res = RES_OK;
- ASSERT(doc && sun && out_solsun);
-
- if(sun == parser->sun_key) {
- solsun = &parser->sun;
- goto exit;
- } else if(parser->sun_key != 0) {
- log_err(parser, sun,
- "a sun is already defined. Previous definition is here %lu:%lu.\n",
- (unsigned long)parser->sun_key->start_mark.line+1,
- (unsigned long)parser->sun_key->start_mark.column+1);
- res = RES_BAD_ARG;
- goto error;
- } else {
- solsun = &parser->sun;
- parser->sun_key = sun;
- solsun->radang_distrib_type = SOLSTICE_SUN_RADANG_DISTRIB_DIRECTIONAL;
- }
-
- if(sun->type != YAML_MAPPING_NODE) {
- log_err(parser, sun, "expect a sun definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = sun->data.mapping.pairs.top - sun->data.mapping.pairs.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* key;
- yaml_node_t* val;
-
- key = yaml_document_get_node(doc, sun->data.mapping.pairs.start[i].key);
- val = yaml_document_get_node(doc, sun->data.mapping.pairs.start[i].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expect sun parameters.\n");
- res = RES_BAD_ARG;
- goto error;
- }
- #define SETUP_MASK(Flag, Name) { \
- if(mask & BIT(Flag)) { \
- log_err(parser, key, "the sun "Name" is already defined.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } \
- mask |= BIT(Flag); \
- } (void)0
- if(!strcmp((char*)key->data.scalar.value, "dni")) {
- SETUP_MASK(DNI, "dni");
- res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &solsun->dni);
- } else if(!strcmp((char*)key->data.scalar.value, "buie")) {
- SETUP_MASK(RADIAL_ANGULAR_DISTRIB, "radial angular distribution");
- solsun->radang_distrib_type = SOLSTICE_SUN_RADANG_DISTRIB_BUIE;
- res = parse_buie(parser, doc, val, &solsun->radang_distrib.buie);
- } else if(!strcmp((char*)key->data.scalar.value, "pillbox")) {
- SETUP_MASK(RADIAL_ANGULAR_DISTRIB, "radial angular distribution");
- solsun->radang_distrib_type = SOLSTICE_SUN_RADANG_DISTRIB_PILLBOX;
- res = parse_pillbox(parser, doc, val, &solsun->radang_distrib.pillbox);
- } else if(!strcmp((char*)key->data.scalar.value, "spectrum")) {
- SETUP_MASK(SPECTRUM, "spectrum");
- res = parse_spectrum(parser, doc, 0, DBL_MAX, val, &solsun->spectrum);
- } else {
- log_err(parser, key, "unknown sun parameter `%s'.\n",
- key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
- #undef SETUP_MASK
- }
-
- #define CHECK_PARAM(Flag, Name) \
- if(!(mask & BIT(Flag))) { \
- log_err(parser, sun, "the sun "Name" is missing.\n"); \
- res = RES_BAD_ARG; \
- goto error; \
- } (void)0
- CHECK_PARAM(DNI, "dni");
- CHECK_PARAM(SPECTRUM, "spectrum");
- #undef CHECK_PARAM
-
-exit:
- *out_solsun = solsun;
- return res;
-error:
- if(solsun) {
- solstice_sun_clear(solsun);
- solsun = NULL;
- parser->sun_key = 0;
- }
- goto exit;
-}
-
-/*******************************************************************************
- * Item
- ******************************************************************************/
-static res_T
-parse_item
- (struct solstice_parser* parser,
- yaml_document_t* doc,
- const yaml_node_t* item)
-{
- yaml_node_t* key;
- yaml_node_t* val;
- struct solstice_material_double_sided_id mtl2; /* TODO */
- struct solstice_entity_id entity; /* TODO */
- struct solstice_geometry_id geometry; /* TODO */
- struct solstice_sun* sun; /* TODO */
- intptr_t n;
- res_T res = RES_OK;
- ASSERT(doc && item);
-
- if(item->type != YAML_MAPPING_NODE) {
- log_err(parser, item, "expect an item definition.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = item->data.mapping.pairs.top - item->data.mapping.pairs.start;
- if(n != 1) {
- log_err(parser, item,
- "expect only one \"key:value\" pair while %li are provided.\n", n);
- res = RES_BAD_ARG;
- goto error;
- }
-
- key = yaml_document_get_node(doc, item->data.mapping.pairs.start[0].key);
- val = yaml_document_get_node(doc, item->data.mapping.pairs.start[0].value);
- if(key->type != YAML_SCALAR_NODE) {
- log_err(parser, key, "expecting an item name.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!strcmp((char*)key->data.scalar.value, "material")) {
- res = parse_material(parser, doc, val, &mtl2);
- } else if(!strcmp((char*)key->data.scalar.value, "entity")) {
- res = parse_entity(parser, doc, val, &parser->str2entities, &entity);
- } else if(!strcmp((char*)key->data.scalar.value, "template")) {
- /* The parsing of the template data is deferred to its explicit used in the
- * definition of an entity. If the parsing of the template becomes a
- * bottleneck, parse the data only once here and cache them for reuse. */
- } else if(!strcmp((char*)key->data.scalar.value, "geometry")) {
- res = parse_geometry(parser, doc, val, &geometry);
- } else if(!strcmp((char*)key->data.scalar.value, "sun")) {
- res = parse_sun(parser, doc, val, &sun);
- } else {
- log_err(parser, key, "unknown item `%s'.\n", key->data.scalar.value);
- res = RES_BAD_ARG;
- }
- if(res != RES_OK) goto error;
-
-exit:
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * Local functions
- ******************************************************************************/
-res_T
-solstice_parser_create
- (struct mem_allocator* allocator, struct solstice_parser** out_parser)
-{
- struct solstice_parser* parser = NULL;
- struct mem_allocator* mem_allocator;
- res_T res = RES_OK;
- ASSERT(out_parser);
-
- mem_allocator = allocator ? allocator : &mem_default_allocator;
- parser = MEM_CALLOC(mem_allocator, 1, sizeof(struct solstice_parser));
- if(!parser) {
- fprintf(stderr, "Could not allocat the Solstice parser.\n");
- res = RES_MEM_ERR;
- goto error;
- }
- parser->allocator = mem_allocator;
- ref_init(&parser->ref);
- str_init(mem_allocator, &parser->stream_name);
-
- /* Materials */
- htable_yaml2sols_init(mem_allocator, &parser->yaml2mtls);
- darray_material_init(mem_allocator, &parser->mtls);
- darray_material2_init(mem_allocator, &parser->mtls2);
- darray_matte_init(mem_allocator, &parser->mattes);
- darray_mirror_init(mem_allocator, &parser->mirrors);
-
- /* Shapes */
- darray_shape_init(mem_allocator, &parser->shapes);
- darray_cuboid_init(mem_allocator, &parser->cuboids);
- darray_cylinder_init(mem_allocator, &parser->cylinders);
- darray_impgeom_init(mem_allocator, &parser->objs);
- darray_paraboloid_init(mem_allocator, &parser->parabols);
- darray_paraboloid_init(mem_allocator, &parser->parabolic_cylinders);
- darray_plane_init(mem_allocator, &parser->planes);
- darray_sphere_init(mem_allocator, &parser->spheres);
- darray_impgeom_init(mem_allocator, &parser->stls);
-
- /* Geometries */
- htable_yaml2sols_init(mem_allocator, &parser->yaml2geoms);
- darray_object_init(mem_allocator, &parser->objects);
- darray_geometry_init(mem_allocator, &parser->geometries);
-
- /* Sun */
- solstice_sun_init(mem_allocator, &parser->sun);
-
- /* Entities */
- htable_yaml2sols_init(mem_allocator, &parser->yaml2entities);
- htable_str2sols_init(mem_allocator, &parser->str2entities);
- darray_entity_init(mem_allocator, &parser->entities);
-
- /* Anchors */
- darray_anchor_init(mem_allocator, &parser->anchors);
- darray_pivot_init(mem_allocator, &parser->pivots);
-
-exit:
- *out_parser = parser;
- return res;
-error:
- if(parser) {
- solstice_parser_ref_put(parser);
- parser = NULL;
- }
- goto exit;
-}
-
-void
-solstice_parser_ref_get(struct solstice_parser* parser)
-{
- ASSERT(parser);
- ref_get(&parser->ref);
-}
-
-void
-solstice_parser_ref_put(struct solstice_parser* parser)
-{
- ASSERT(parser);
- ref_put(&parser->ref, parser_release);
-}
-
-res_T
-solstice_parser_setup
- (struct solstice_parser* parser,
- const char* stream_name,
- FILE* stream)
-{
- res_T res = RES_OK;
- ASSERT(parser && stream );
-
- if(parser->parser_is_init) {
- yaml_parser_delete(&parser->parser);
- parser->parser_is_init = 0;
- }
- res = str_set(&parser->stream_name, stream_name ? stream_name : "<stream>");
- if(res != RES_OK) {
- fprintf(stderr, "Could not register the filename.\n");
- goto error;
- }
- if(!yaml_parser_initialize(&parser->parser)) {
- fprintf(stderr, "Could not initialise the YAML parser.\n");
- res = RES_UNKNOWN_ERR;
- goto error;
- }
- parser->parser_is_init = 1;
- yaml_parser_set_input_file(&parser->parser, stream);
-
-exit:
- return res;
-error:
- str_clear(&parser->stream_name);
- if(parser->parser_is_init) {
- yaml_parser_delete(&parser->parser);
- parser->parser_is_init = 0;
- }
- goto exit;
-}
-
-res_T
-solstice_parser_load(struct solstice_parser* parser)
-{
- yaml_document_t doc;
- yaml_node_t* root;
- const char* filename;
- intptr_t i, n;
- int doc_is_init = 0;
- res_T res = RES_OK;
- ASSERT(parser);
-
- filename = str_cget(&parser->stream_name);
-
- parser_clear(parser); /* Clean up previously loaded data */
-
- if(!parser->parser_is_init) {
- res = RES_BAD_OP;
- goto error;
- }
-
- if(!yaml_parser_load(&parser->parser, &doc)) {
- fprintf(stderr, "%s:%lu:%lu: %s.\n",
- filename,
- (unsigned long)parser->parser.problem_mark.line+1,
- (unsigned long)parser->parser.problem_mark.column+1,
- parser->parser.problem);
- yaml_parser_delete(&parser->parser);
- parser->parser_is_init = 0;
- res = RES_BAD_OP;
- goto error;
- }
- doc_is_init = 1;
-
- root = yaml_document_get_root_node(&doc);
- if(!root) {
- yaml_parser_delete(&parser->parser);
- parser->parser_is_init = 0;
- res = RES_BAD_OP;
- goto error;
- }
-
- if(root->type != YAML_SEQUENCE_NODE) {
- log_err(parser, root, "expect a list of items.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- n = root->data.sequence.items.top - root->data.sequence.items.start;
- FOR_EACH(i, 0, n) {
- yaml_node_t* item;
-
- item = yaml_document_get_node(&doc, root->data.sequence.items.start[i]);
- res = parse_item(parser, &doc, item);
- if(res != RES_OK) goto error;
- }
-
- if(!parser->sun_key) {
- log_err(parser, root, "%s: no sun definition in the document.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
-exit:
- if(doc_is_init) yaml_document_delete(&doc);
- return res;
-error:
- parser_clear(parser);
- goto exit;
-}
-
-const struct solstice_anchor*
-solstice_parser_find_anchor
- (struct solstice_parser* parser, const char* name)
-{
- struct str str;
- struct str str_tk;
- struct htable_str2sols* htable = NULL;
- struct solstice_entity* entity = NULL;
- struct solstice_anchor* anchor = NULL;
- char* cstr;
- char* tk;
- char* tk_anchor;
- res_T res = RES_OK;
- ASSERT(parser && name);
-
- str_init(parser->allocator, &str);
- str_init(parser->allocator, &str_tk);
-
- res = str_set(&str, name);
- if(res != RES_OK) {
- fprintf(stderr, "%s: could not copy the input string.\n", FUNC_NAME);
- goto error;
- }
- res = str_reserve(&str_tk, str_len(&str));
- if(res != RES_OK) {
- fprintf(stderr, "%s: could not allocate the temporary token string.\n",
- FUNC_NAME);
- goto error;
- }
-
- cstr = str_get(&str);
- tk_anchor = strrchr(cstr, '.');
- if(!tk_anchor) goto exit;
- *tk_anchor='\0';
- ++tk_anchor;
-
- tk = strtok(cstr, ".");
- htable = &parser->str2entities;
- while(tk) {
- size_t* pientity;
- str_set(&str_tk, tk);
- pientity = htable_str2sols_find(htable, &str_tk);
- if(!pientity) {
- tk = NULL;
- entity = NULL;
- } else {
- tk = strtok(NULL, ".");
- entity = darray_entity_data_get(&parser->entities) + *pientity;
- htable = &entity->str2children;
- }
- }
-
- if(entity) {
- size_t* pianchor;
- str_set(&str_tk, tk_anchor);
- pianchor = htable_str2sols_find(&entity->str2anchors, &str_tk);
- if(pianchor) {
- anchor = darray_anchor_data_get(&parser->anchors) + *pianchor;
- }
- }
-
-exit:
- str_release(&str);
- str_release(&str_tk);
- return anchor;
-error:
- anchor = NULL;
- goto exit;
-}
-
-const struct solstice_entity*
-solstice_parser_find_entity
- (struct solstice_parser* parser, const char* name)
-{
- struct htable_str2sols* htable = NULL;
- struct solstice_entity* entity = NULL;
- struct str str;
- struct str str_tk;
- char* cstr;
- char* tk;
- res_T res = RES_OK;
- ASSERT(parser && name);
-
- str_init(parser->allocator, &str);
- str_init(parser->allocator, &str_tk);
-
- res = str_set(&str, name);
- if(res != RES_OK) {
- fprintf(stderr, "%s: could not copy the input string.\n", FUNC_NAME);
- goto error;
- }
- res = str_reserve(&str_tk, str_len(&str));
- if(res != RES_OK) {
- fprintf(stderr, "%s: could not allocate the temporary token sting.\n",
- FUNC_NAME);
- goto error;
- }
-
- cstr = str_get(&str);
- tk = strtok(cstr, ".");
- htable = &parser->str2entities;
- while(tk) {
- size_t* pientity;
- str_set(&str_tk, tk);
- pientity = htable_str2sols_find(htable, &str_tk);
- if(!pientity) {
- tk = NULL;
- entity = NULL;
- } else {
- tk = strtok(NULL, ".");
- entity = darray_entity_data_get(&parser->entities) + *pientity;
- htable = &entity->str2children;
- }
- }
-
-exit:
- str_release(&str);
- str_release(&str_tk);
- return entity;
-error:
- entity = NULL;
- goto exit;
-}
-
-const struct solstice_anchor*
-solstice_parser_get_anchor
- (const struct solstice_parser* parser,
- const struct solstice_anchor_id anchor)
-{
- ASSERT(parser && anchor.i < darray_anchor_size_get(&parser->anchors));
- return darray_anchor_cdata_get(&parser->anchors) + anchor.i;
-}
-
-const struct solstice_entity*
-solstice_parser_get_entity
- (const struct solstice_parser* parser,
- const struct solstice_entity_id entity)
-{
- ASSERT(parser && entity.i < darray_entity_size_get(&parser->entities));
- return darray_entity_cdata_get(&parser->entities) + entity.i;
-}
-
-const struct solstice_geometry*
-solstice_parser_get_geometry
- (const struct solstice_parser* parser,
- const struct solstice_geometry_id geom)
-{
- ASSERT(parser && geom.i < darray_geometry_size_get(&parser->geometries));
- return darray_geometry_cdata_get(&parser->geometries) + geom.i;
-}
-
-const struct solstice_material*
-solstice_parser_get_material
- (const struct solstice_parser* parser,
- const struct solstice_material_id mtl)
-{
- ASSERT(parser && mtl.i < darray_material_size_get(&parser->mtls));
- return darray_material_cdata_get(&parser->mtls) + mtl.i;
-}
-
-const struct solstice_material_double_sided*
-solstice_parser_get_material_double_sided
- (const struct solstice_parser* parser,
- const struct solstice_material_double_sided_id mtl2)
-{
- ASSERT(parser && mtl2.i < darray_material2_size_get(&parser->mtls2));
- return darray_material2_cdata_get(&parser->mtls2) + mtl2.i;
-}
-
-const struct solstice_material_matte*
-solstice_parser_get_material_matte
- (const struct solstice_parser* parser,
- const struct solstice_material_matte_id matte)
-{
- ASSERT(parser && matte.i < darray_matte_size_get(&parser->mattes));
- return darray_matte_cdata_get(&parser->mattes) + matte.i;
-}
-
-const struct solstice_material_mirror*
-solstice_parser_get_material_mirror
- (const struct solstice_parser* parser,
- const struct solstice_material_mirror_id mirror)
-{
- ASSERT(parser && mirror.i < darray_mirror_size_get(&parser->mirrors));
- return darray_mirror_cdata_get(&parser->mirrors) + mirror.i;
-}
-
-const struct solstice_object*
-solstice_parser_get_object
- (const struct solstice_parser* parser,
- const struct solstice_object_id obj)
-{
- ASSERT(parser && obj.i < darray_object_size_get(&parser->objects));
- return darray_object_cdata_get(&parser->objects) + obj.i;
-}
-
-const struct solstice_pivot*
-solstice_parser_get_pivot
- (const struct solstice_parser* parser,
- const struct solstice_pivot_id pivot)
-{
- ASSERT(parser && pivot.i < darray_pivot_size_get(&parser->pivots));
- return darray_pivot_cdata_get(&parser->pivots) + pivot.i;
-}
-
-const struct solstice_shape*
-solstice_parser_get_shape
- (const struct solstice_parser* parser,
- const struct solstice_shape_id shape)
-{
- ASSERT(parser && shape.i < darray_shape_size_get(&parser->shapes));
- return darray_shape_cdata_get(&parser->shapes) + shape.i;
-}
-
-const struct solstice_shape_cuboid*
-solstice_parser_get_shape_cuboid
- (const struct solstice_parser* parser,
- const struct solstice_shape_cuboid_id cuboid)
-{
- ASSERT(parser && cuboid.i < darray_cuboid_size_get(&parser->cuboids));
- return darray_cuboid_cdata_get(&parser->cuboids) + cuboid.i;
-}
-
-const struct solstice_shape_cylinder*
-solstice_parser_get_shape_cylinder
- (const struct solstice_parser* parser,
- const struct solstice_shape_cylinder_id cylinder)
-{
- ASSERT(parser && cylinder.i < darray_cylinder_size_get(&parser->cylinders));
- return darray_cylinder_cdata_get(&parser->cylinders) + cylinder.i;
-}
-
-const struct solstice_shape_imported_geometry*
-solstice_parser_get_shape_obj
- (const struct solstice_parser* parser,
- const struct solstice_shape_imported_geometry_id impgeom)
-{
- ASSERT(parser && impgeom.i < darray_impgeom_size_get(&parser->objs));
- return darray_impgeom_cdata_get(&parser->objs) + impgeom.i;
-}
-
-const struct solstice_shape_paraboloid*
-solstice_parser_get_shape_parabol
- (const struct solstice_parser* parser,
- const struct solstice_shape_paraboloid_id paraboloid)
-{
- ASSERT(parser && paraboloid.i < darray_paraboloid_size_get(&parser->parabols));
- return darray_paraboloid_cdata_get(&parser->parabols) + paraboloid.i;
-}
-
-const struct solstice_shape_paraboloid*
-solstice_parser_get_shape_parabolic_cylinder
- (const struct solstice_parser* parser,
- const struct solstice_shape_paraboloid_id paraboloid)
-{
- ASSERT(parser);
- ASSERT(paraboloid.i<darray_paraboloid_size_get(&parser->parabolic_cylinders));
- return darray_paraboloid_cdata_get(&parser->parabolic_cylinders)+paraboloid.i;
-}
-
-const struct solstice_shape_plane*
-solstice_parser_get_shape_plane
- (const struct solstice_parser* parser,
- const struct solstice_shape_plane_id plane)
-{
- ASSERT(parser && plane.i < darray_plane_size_get(&parser->planes));
- return darray_plane_cdata_get(&parser->planes) + plane.i;
-}
-
-const struct solstice_shape_sphere*
-solstice_parser_get_shape_sphere
- (const struct solstice_parser* parser,
- const struct solstice_shape_sphere_id sphere)
-{
- ASSERT(parser && sphere.i < darray_sphere_size_get(&parser->spheres));
- return darray_sphere_cdata_get(&parser->spheres) + sphere.i;
-}
-
-const struct solstice_shape_imported_geometry*
-solstice_parser_get_shape_stl
- (const struct solstice_parser* parser,
- const struct solstice_shape_imported_geometry_id impgeom)
-{
- ASSERT(parser && impgeom.i < darray_impgeom_size_get(&parser->stls));
- return darray_impgeom_cdata_get(&parser->stls) + impgeom.i;
-}
-
-const struct solstice_sun*
-solstice_parser_get_sun(const struct solstice_parser* parser)
-{
- ASSERT(parser && parser->sun_key);
- return &parser->sun;
-}
-
-void
-solstice_parser_entity_iterator_begin
- (struct solstice_parser* parser,
- struct solstice_entity_iterator* it)
-{
- ASSERT(parser && it);
- htable_str2sols_begin(&parser->str2entities, &it->it__);
-}
-
-void
-solstice_parser_entity_iterator_end
- (struct solstice_parser* parser,
- struct solstice_entity_iterator* it)
-{
- ASSERT(parser && it);
- htable_str2sols_end(&parser->str2entities, &it->it__);
-}
-
-void
-solstice_parser_material_iterator_begin
- (struct solstice_parser* parser, struct solstice_material_iterator* it)
-{
- ASSERT(parser && it);
- it->mtls__ = darray_material_cdata_get(&parser->mtls);
- it->imtl__ = 0;
-}
-
-void
-solstice_parser_material_iterator_end
- (struct solstice_parser* parser, struct solstice_material_iterator* it)
-{
- ASSERT(parser && it);
- it->mtls__ = darray_material_cdata_get(&parser->mtls);
- it->imtl__ = darray_material_size_get(&parser->mtls);
-}
-
-void
-solstice_parser_geometry_iterator_begin
- (struct solstice_parser* parser, struct solstice_geometry_iterator* it)
-{
- ASSERT(parser && it);
- it->geoms__ = darray_geometry_cdata_get(&parser->geometries);
- it->igeom__ = 0;
-}
-
-void
-solstice_parser_geometry_iterator_end
- (struct solstice_parser* parser, struct solstice_geometry_iterator* it)
-{
- ASSERT(parser && it);
- it->geoms__ = darray_geometry_cdata_get(&parser->geometries);
- it->igeom__ = darray_geometry_size_get(&parser->geometries);
-}
-
diff --git a/src/parser/solstice_parser.h b/src/parser/solstice_parser.h
@@ -1,289 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_PARSER_H
-#define SOLSTICE_PARSER_H
-
-#include "solstice_entity.h"
-#include <rsys/rsys.h>
-
-struct mem_allocator;
-struct solstice_parser;
-
-struct solstice_entity_iterator {
- struct htable_str2sols_iterator it__; /* Internal data */
-};
-
-struct solstice_material_iterator {
- /* Internal data */
- const struct solstice_material* mtls__;
- size_t imtl__;
-};
-
-struct solstice_geometry_iterator {
- /* Internal data */
- const struct solstice_geometry* geoms__;
- size_t igeom__;
-};
-
-/*******************************************************************************
- * Solstice parser API.
- ******************************************************************************/
-extern LOCAL_SYM res_T
-solstice_parser_create
- (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
- struct solstice_parser** parser);
-
-extern LOCAL_SYM void
-solstice_parser_ref_get
- (struct solstice_parser* parser);
-
-extern LOCAL_SYM void
-solstice_parser_ref_put
- (struct solstice_parser* parser);
-
-extern LOCAL_SYM res_T
-solstice_parser_setup
- (struct solstice_parser* parser,
- const char* stream_name, /* May be NULL */
- FILE* stream);
-
-/* Return RES_BAD_OP if there is no more YAML document to parse */
-extern LOCAL_SYM res_T
-solstice_parser_load
- (struct solstice_parser* parser);
-
-/* Return NULL if no entity is found */
-extern LOCAL_SYM const struct solstice_anchor*
-solstice_parser_find_anchor
- (struct solstice_parser* parser,
- const char* anchor_name);
-
-/* Return NULL if no entity is found */
-extern LOCAL_SYM const struct solstice_entity*
-solstice_parser_find_entity
- (struct solstice_parser* parser,
- const char* entity_name);
-
-extern LOCAL_SYM const struct solstice_anchor*
-solstice_parser_get_anchor
- (const struct solstice_parser* parser,
- const struct solstice_anchor_id anchor);
-
-extern LOCAL_SYM const struct solstice_entity*
-solstice_parser_get_entity
- (const struct solstice_parser* parser,
- const struct solstice_entity_id entity);
-
-extern LOCAL_SYM const struct solstice_geometry*
-solstice_parser_get_geometry
- (const struct solstice_parser* parser,
- const struct solstice_geometry_id geom);
-
-extern LOCAL_SYM const struct solstice_material*
-solstice_parser_get_material
- (const struct solstice_parser* parser,
- const struct solstice_material_id mtl);
-
-extern LOCAL_SYM const struct solstice_material_double_sided*
-solstice_parser_get_material_double_sided
- (const struct solstice_parser* parser,
- const struct solstice_material_double_sided_id mtl2);
-
-extern LOCAL_SYM const struct solstice_material_matte*
-solstice_parser_get_material_matte
- (const struct solstice_parser* parser,
- const struct solstice_material_matte_id matte);
-
-extern LOCAL_SYM const struct solstice_material_mirror*
-solstice_parser_get_material_mirror
- (const struct solstice_parser* parser,
- const struct solstice_material_mirror_id mirror);
-
-extern LOCAL_SYM const struct solstice_object*
-solstice_parser_get_object
- (const struct solstice_parser* parser,
- const struct solstice_object_id obj);
-
-extern LOCAL_SYM const struct solstice_pivot*
-solstice_parser_get_pivot
- (const struct solstice_parser* parser,
- const struct solstice_pivot_id pivot);
-
-extern LOCAL_SYM const struct solstice_shape*
-solstice_parser_get_shape
- (const struct solstice_parser* parser,
- const struct solstice_shape_id shape);
-
-extern LOCAL_SYM const struct solstice_shape_cuboid*
-solstice_parser_get_shape_cuboid
- (const struct solstice_parser* parser,
- const struct solstice_shape_cuboid_id cuboid);
-
-extern LOCAL_SYM const struct solstice_shape_cylinder*
-solstice_parser_get_shape_cylinder
- (const struct solstice_parser* parser,
- const struct solstice_shape_cylinder_id cylinder);
-
-extern LOCAL_SYM const struct solstice_shape_imported_geometry*
-solstice_parser_get_shape_obj
- (const struct solstice_parser* parser,
- const struct solstice_shape_imported_geometry_id impgeom);
-
-extern LOCAL_SYM const struct solstice_shape_paraboloid*
-solstice_parser_get_shape_parabol
- (const struct solstice_parser* parser,
- const struct solstice_shape_paraboloid_id paraboloid);
-
-extern LOCAL_SYM const struct solstice_shape_paraboloid*
-solstice_parser_get_shape_parabolic_cylinder
- (const struct solstice_parser* parser,
- const struct solstice_shape_paraboloid_id paraboloid);
-
-extern LOCAL_SYM const struct solstice_shape_plane*
-solstice_parser_get_shape_plane
- (const struct solstice_parser* parser,
- const struct solstice_shape_plane_id plane);
-
-extern LOCAL_SYM const struct solstice_shape_sphere*
-solstice_parser_get_shape_sphere
- (const struct solstice_parser* parser,
- const struct solstice_shape_sphere_id sphere);
-
-extern LOCAL_SYM const struct solstice_shape_imported_geometry*
-solstice_parser_get_shape_stl
- (const struct solstice_parser* parser,
- const struct solstice_shape_imported_geometry_id impgeom);
-
-extern LOCAL_SYM const struct solstice_sun*
-solstice_parser_get_sun
- (const struct solstice_parser* parser);
-
-/*******************************************************************************
- * Entity interator
- ******************************************************************************/
-extern LOCAL_SYM void
-solstice_parser_entity_iterator_begin
- (struct solstice_parser* parser,
- struct solstice_entity_iterator* it);
-
-extern LOCAL_SYM void
-solstice_parser_entity_iterator_end
- (struct solstice_parser* parser,
- struct solstice_entity_iterator* it);
-
-static FINLINE void
-solstice_entity_iterator_next(struct solstice_entity_iterator* it)
-{
- ASSERT(it);
- htable_str2sols_iterator_next(&it->it__);
-}
-
-static FINLINE int
-solstice_entity_iterator_eq
- (const struct solstice_entity_iterator* a,
- const struct solstice_entity_iterator* b)
-{
- ASSERT(a && b);
- return htable_str2sols_iterator_eq(&a->it__, &b->it__);
-}
-
-static FINLINE struct solstice_entity_id
-solstice_entity_iterator_get(struct solstice_entity_iterator* it)
-{
- struct solstice_entity_id id;
- ASSERT(it);
- id.i = *htable_str2sols_iterator_data_get(&it->it__);
- return id;
-}
-
-/*******************************************************************************
- * Material iterator
- ******************************************************************************/
-extern LOCAL_SYM void
-solstice_parser_material_iterator_begin
- (struct solstice_parser* parser,
- struct solstice_material_iterator* it);
-
-extern LOCAL_SYM void
-solstice_parser_material_iterator_end
- (struct solstice_parser* parser,
- struct solstice_material_iterator* it);
-
-static FINLINE void
-solstice_material_iterator_next(struct solstice_material_iterator* it)
-{
- ASSERT(it);
- ++it->imtl__;
-}
-
-static FINLINE int
-solstice_material_iterator_eq
- (const struct solstice_material_iterator* a,
- const struct solstice_material_iterator* b)
-{
- ASSERT(a && b);
- return a->mtls__ == b->mtls__ && a->imtl__ == b->imtl__;
-}
-
-static FINLINE struct solstice_material_id
-solstice_material_iterator_get(struct solstice_material_iterator* it)
-{
- struct solstice_material_id id;
- ASSERT(it);
- id.i = it->imtl__;
- return id;
-}
-
-/*******************************************************************************
- * Geometry iterator
- ******************************************************************************/
-extern LOCAL_SYM void
-solstice_parser_geometry_iterator_begin
- (struct solstice_parser* parser,
- struct solstice_geometry_iterator* it);
-
-extern LOCAL_SYM void
-solstice_parser_geometry_iterator_end
- (struct solstice_parser* parser,
- struct solstice_geometry_iterator* it);
-
-static FINLINE void
-solstice_geometry_iterator_next(struct solstice_geometry_iterator* it)
-{
- ASSERT(it);
- ++it->igeom__;
-}
-
-static FINLINE int
-solstice_geometry_iterator_eq
- (const struct solstice_geometry_iterator* a,
- const struct solstice_geometry_iterator* b)
-{
- ASSERT(a && b);
- return a->geoms__ == b->geoms__ && a->igeom__ == b->igeom__;
-}
-
-static FINLINE struct solstice_geometry_id
-solstice_geometry_iterator_get(struct solstice_geometry_iterator* it)
-{
- struct solstice_geometry_id id;
- ASSERT(it);
- id.i = it->igeom__;
- return id;
-}
-
-#endif /* SOLSTICE_PARSER_H */
-
diff --git a/src/parser/solstice_pivot.h b/src/parser/solstice_pivot.h
@@ -1,84 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_PIVOT_H
-#define SOLSTICE_PIVOT_H
-
-#include <rsys/double3.h>
-
-enum solstice_target_type {
- SOLSTICE_TARGET_ANCHOR,
- SOLSTICE_TARGET_DIRECTION,
- SOLSTICE_TARGET_POSITION,
- SOLSTICE_TARGET_SUN
-};
-
-struct solstice_anchor_id { size_t i; };
-
-struct solstice_anchor {
- struct str name;
- double position[3];
-};
-
-static INLINE void
-solstice_anchor_init
- (struct mem_allocator* allocator, struct solstice_anchor* anchor)
-{
- ASSERT(anchor);
- str_init(allocator, &anchor->name);
-}
-
-static INLINE void
-solstice_anchor_release(struct solstice_anchor* anchor)
-{
- ASSERT(anchor);
- str_release(&anchor->name);
-}
-
-static INLINE res_T
-solstice_anchor_copy
- (struct solstice_anchor* dst, const struct solstice_anchor* src)
-{
- ASSERT(dst && src);
- d3_set(dst->position, src->position);
- return str_copy(&dst->name, &src->name);
-}
-
-static INLINE res_T
-solstice_anchor_copy_and_release
- (struct solstice_anchor* dst, struct solstice_anchor* src)
-{
- ASSERT(dst && src);
- d3_set(dst->position, src->position);
- return str_copy_and_release(&dst->name, &src->name);
-}
-
-struct solstice_pivot {
- double point[3];
- double normal[3];
- double rotation[3];
- double translation[3];
- enum solstice_target_type target_type;
- union {
- double position[3]; /* World space position */
- double direction[3]; /* World space direction */
- struct solstice_anchor_id anchor;
- } target;
-};
-
-struct solstice_pivot_id { size_t i; };
-
-#endif /* SOLSTICE_PIVOT_H */
-
diff --git a/src/parser/solstice_shape.h b/src/parser/solstice_shape.h
@@ -1,260 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_SHAPE_H
-#define SOLSTICE_SHAPE_H
-
-#include "solstice_material.h"
-
-#include <rsys/dynamic_array_double.h>
-#include <rsys/str.h>
-
-enum solstice_clip_op {
- SOLSTICE_CLIP_OP_AND,
- SOLSTICE_CLIP_OP_SUB
-};
-
-enum solstice_shape_type {
- SOLSTICE_SHAPE_CUBOID,
- SOLSTICE_SHAPE_CYLINDER,
- SOLSTICE_SHAPE_OBJ, /* Imported Alias Wavefront obj */
- SOLSTICE_SHAPE_PARABOL,
- SOLSTICE_SHAPE_PARABOLIC_CYLINDER,
- SOLSTICE_SHAPE_PLANE,
- SOLSTICE_SHAPE_SPHERE,
- SOLSTICE_SHAPE_STL /* Imported STereo Lithography */
-};
-
-/*******************************************************************************
- * Clipping polygon
- ******************************************************************************/
-struct solstice_polyclip {
- enum solstice_clip_op op;
- struct darray_double vertices;
-};
-
-static INLINE void
-solstice_polyclip_init
- (struct mem_allocator* allocator,
- struct solstice_polyclip* polyclip)
-{
- ASSERT(polyclip);
- darray_double_init(allocator, &polyclip->vertices);
-}
-
-static INLINE void
-solstice_polyclip_release(struct solstice_polyclip* polyclip)
-{
- ASSERT(polyclip);
- darray_double_release(&polyclip->vertices);
-}
-
-static INLINE res_T
-solstice_polyclip_copy
- (struct solstice_polyclip* dst, const struct solstice_polyclip* src)
-{
- ASSERT(dst && src);
- dst->op = src->op;
- return darray_double_copy(&dst->vertices, &src->vertices);
-}
-
-static INLINE res_T
-solstice_polyclip_copy_and_release
- (struct solstice_polyclip* dst, struct solstice_polyclip* src)
-{
- ASSERT(dst && src);
- dst->op = src->op;
- return darray_double_copy_and_release(&dst->vertices, &src->vertices);
-}
-
-/* Declare the array of clipping polygons */
-#define DARRAY_NAME polyclip
-#define DARRAY_DATA struct solstice_polyclip
-#define DARRAY_FUNCTOR_INIT solstice_polyclip_init
-#define DARRAY_FUNCTOR_RELEASE solstice_polyclip_release
-#define DARRAY_FUNCTOR_COPY solstice_polyclip_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_polyclip_copy_and_release
-#include <rsys/dynamic_array.h>
-
-/*******************************************************************************
- * Imported geometry shape
- ******************************************************************************/
-struct solstice_shape_imported_geometry {
- struct str filename;
-};
-
-static INLINE void
-solstice_shape_imported_geometry_init
- (struct mem_allocator* allocator,
- struct solstice_shape_imported_geometry* impgeom)
-{
- ASSERT(impgeom);
- str_init(allocator, &impgeom->filename);
-}
-
-static INLINE void
-solstice_shape_imported_geometry_release
- (struct solstice_shape_imported_geometry* impgeom)
-{
- ASSERT(impgeom);
- str_release(&impgeom->filename);
-}
-
-static INLINE res_T
-solstice_shape_imported_geometry_copy
- (struct solstice_shape_imported_geometry* dst,
- const struct solstice_shape_imported_geometry* src)
-{
- ASSERT(dst && src);
- return str_copy(&dst->filename, &src->filename);
-}
-
-static INLINE res_T
-solstice_shape_imported_geometry_copy_and_release
- (struct solstice_shape_imported_geometry* dst,
- struct solstice_shape_imported_geometry* src)
-{
- ASSERT(dst && src);
- return str_copy_and_release(&dst->filename, &src->filename);
-}
-
-/*******************************************************************************
- * Paraboloid shape
- ******************************************************************************/
-struct solstice_shape_paraboloid {
- double focal;
- struct darray_polyclip polyclips;
-};
-
-static INLINE void
-solstice_shape_paraboloid_init
- (struct mem_allocator* allocator,
- struct solstice_shape_paraboloid* paraboloid)
-{
- ASSERT(paraboloid);
- darray_polyclip_init(allocator, ¶boloid->polyclips);
-}
-
-static INLINE void
-solstice_shape_paraboloid_release(struct solstice_shape_paraboloid* paraboloid)
-{
- ASSERT(paraboloid);
- darray_polyclip_release(¶boloid->polyclips);
-}
-
-static INLINE res_T
-solstice_shape_paraboloid_copy
- (struct solstice_shape_paraboloid* dst,
- const struct solstice_shape_paraboloid* src)
-{
- ASSERT(dst && src);
- dst->focal = src->focal;
- return darray_polyclip_copy(&dst->polyclips, &src->polyclips);
-}
-
-static INLINE res_T
-solstice_shape_paraboloid_copy_and_release
- (struct solstice_shape_paraboloid* dst,
- struct solstice_shape_paraboloid* src)
-{
- ASSERT(dst && src);
- dst->focal = src->focal;
- return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips);
-}
-
-/*******************************************************************************
- * Plane shape
- ******************************************************************************/
-struct solstice_shape_plane {
- struct darray_polyclip polyclips;
-};
-
-static INLINE void
-solstice_shape_plane_init
- (struct mem_allocator* allocator,
- struct solstice_shape_plane* plane)
-{
- ASSERT(plane);
- darray_polyclip_init(allocator, &plane->polyclips);
-}
-
-static INLINE void
-solstice_shape_plane_release(struct solstice_shape_plane* plane)
-{
- ASSERT(plane);
- darray_polyclip_release(&plane->polyclips);
-}
-
-static INLINE res_T
-solstice_shape_plane_copy
- (struct solstice_shape_plane* dst,
- const struct solstice_shape_plane* src)
-{
- ASSERT(dst && src);
- return darray_polyclip_copy(&dst->polyclips, &src->polyclips);
-}
-
-static INLINE res_T
-solstice_shape_plane_copy_and_release
- (struct solstice_shape_plane* dst,
- struct solstice_shape_plane* src)
-{
- ASSERT(dst && src);
- return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips);
-}
-
-/*******************************************************************************
- * POD shape data
- ******************************************************************************/
-struct solstice_shape_cuboid {
- double size[3]; /* Size along the X, Y and Z dimension */
-};
-
-struct solstice_shape_cylinder {
- double height;
- double radius;
- long nslices;
-};
-
-struct solstice_shape_sphere {
- double radius;
- long nslices;
-};
-
-struct solstice_shape_cuboid_id { size_t i; };
-struct solstice_shape_cylinder_id { size_t i; };
-struct solstice_shape_imported_geometry_id { size_t i; };
-struct solstice_shape_paraboloid_id { size_t i; };
-struct solstice_shape_plane_id { size_t i; };
-struct solstice_shape_sphere_id { size_t i; };
-
-struct solstice_shape {
- enum solstice_shape_type type;
- union {
- struct solstice_shape_cuboid_id cuboid;
- struct solstice_shape_cylinder_id cylinder;
- struct solstice_shape_imported_geometry_id obj;
- struct solstice_shape_paraboloid_id parabol;
- struct solstice_shape_paraboloid_id parabolic_cylinder;
- struct solstice_shape_plane_id plane;
- struct solstice_shape_sphere_id sphere;
- struct solstice_shape_imported_geometry_id stl;
- } data;
-};
-
-struct solstice_shape_id { size_t i; };
-
-#endif /* SOLSTICE_SHAPE_H */
-
diff --git a/src/parser/solstice_sun.h b/src/parser/solstice_sun.h
@@ -1,88 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef SOLSTICE_SUN_H
-#define SOLSTICE_SUN_H
-
-#include <rsys/dynamic_array.h>
-
-enum solstice_sun_radang_distrib_type { /* Radial Angular distribution */
- SOLSTICE_SUN_RADANG_DISTRIB_BUIE,
- SOLSTICE_SUN_RADANG_DISTRIB_DIRECTIONAL,
- SOLSTICE_SUN_RADANG_DISTRIB_PILLBOX
-};
-
-struct solstice_spectrum_data {
- double wavelength;
- double data;
-};
-
-#define DARRAY_NAME spectrum_data
-#define DARRAY_DATA struct solstice_spectrum_data
-#include <rsys/dynamic_array.h>
-
-struct solstice_sun_buie { double csr; };
-struct solstice_sun_pillbox { double aperture; };
-
-struct solstice_sun {
- double dni; /* In ]0, INF) */
- struct darray_spectrum_data spectrum;
- enum solstice_sun_radang_distrib_type radang_distrib_type;
- union {
- struct solstice_sun_buie buie;
- struct solstice_sun_pillbox pillbox;
- } radang_distrib;
-};
-
-static INLINE void
-solstice_sun_init(struct mem_allocator* allocator, struct solstice_sun* sun)
-{
- ASSERT(sun);
- sun->dni = 1.0;
- sun->radang_distrib_type = SOLSTICE_SUN_RADANG_DISTRIB_DIRECTIONAL;
- darray_spectrum_data_init(allocator, &sun->spectrum);
-}
-
-static INLINE void
-solstice_sun_release(struct solstice_sun* sun)
-{
- ASSERT(sun);
- darray_spectrum_data_release(&sun->spectrum);
-}
-
-static INLINE res_T
-solstice_sun_copy(struct solstice_sun* dst, const struct solstice_sun* src)
-{
- ASSERT(dst && src);
- return darray_spectrum_data_copy(&dst->spectrum, &src->spectrum);
-}
-
-static INLINE res_T
-solstice_sun_copy_and_release
- (struct solstice_sun* dst, struct solstice_sun* src)
-{
- ASSERT(dst && src);
- return darray_spectrum_data_copy_and_release(&dst->spectrum, &src->spectrum);
-}
-
-static INLINE void
-solstice_sun_clear(struct solstice_sun* sun)
-{
- ASSERT(sun);
- darray_spectrum_data_clear(&sun->spectrum);
-}
-
-#endif /* SOLSTICE_SUN_H */
-
diff --git a/src/parser/test_solparser.c b/src/parser/test_solparser.c
@@ -0,0 +1,80 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "solparser.h"
+#include "test_solstice_utils.h"
+
+#include <string.h>
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct solparser* parser;
+ int ifile = 1;
+ int i;
+ res_T load_res = RES_OK;
+ (void)argc, (void)argv;
+
+ if(argc > 1) {
+ if(!strcmp(argv[1], "-e")) {
+ load_res = RES_BAD_ARG;
+ ifile = 2;
+ } else if(!strcmp(argv[1], "-h")) {
+ printf("Usage: %s [OPTIONS] [FILE ... ]\n", argv[0]);
+ printf(
+"Check the parser API and that the submitted FILEs are valid. Use the `-e'\n"
+"option to check that the FILEs are invalid.\n\n");
+ printf("OPTIONS:\n");
+ printf(" -h print this help and exit.\n");
+ printf(" -e check that the submitted FILEs have errors.\n");
+ return 0;
+ }
+ }
+
+ CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
+ solparser_create(&allocator, &parser);
+
+ CHECK(solparser_setup(parser, NULL, tmpfile()), RES_OK);
+ CHECK(solparser_setup(parser, "yop", tmpfile()), RES_OK);
+ CHECK(solparser_load(parser), RES_BAD_OP); /* Empty stream */
+
+ FOR_EACH(i, ifile, argc) {
+ FILE* file = fopen(argv[i], "rb");
+ int count = 0;
+ NCHECK(file, NULL);
+ CHECK(solparser_setup(parser, argv[i], file), RES_OK);
+ for(;;) {
+ const res_T res = solparser_load(parser);
+ if(count == 0 && load_res == RES_OK) {
+ CHECK(res, RES_OK);
+ } else if(res == RES_BAD_OP) {
+ break;
+ }
+ CHECK(res, load_res);
+ ++count;
+ }
+ fclose(file);
+ }
+
+ solparser_ref_get(parser);
+ solparser_ref_put(parser);
+ solparser_ref_put(parser);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
diff --git a/src/parser/test_solparser2.c b/src/parser/test_solparser2.c
@@ -0,0 +1,215 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "solparser.h"
+#include "solparser_sun.h"
+#include "test_solstice_utils.h"
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct solparser* parser;
+ struct solparser_entity_iterator it, end;
+ struct solparser_geometry_iterator geom_it, geom_it_end;
+ struct solparser_material_iterator mtl_it, mtl_it_end;
+ struct solparser_entity_id entity_id;
+ struct solparser_object_id obj_id;
+ struct solparser_geometry_id geom_id;
+ const struct solparser_geometry* geoms[2] = { NULL, NULL };
+ const struct solparser_material* mtls[2] = { NULL, NULL };
+ const struct solparser_entity* entity, *entity1a, *entity1b, *entity2, *entity3;
+ const struct solparser_geometry* geom;
+ const struct solparser_object* obj;
+ const struct solparser_shape* shape;
+ const struct solparser_material_double_sided* mtl2;
+ const struct solparser_material* mtl;
+ const struct solparser_material_matte* matte;
+ const struct solparser_material_mirror* mirror;
+ const struct solparser_shape_sphere* sphere;
+ const struct solparser_sun* sun;
+ size_t nmtls = 0;
+ size_t ngeoms = 0;
+ double tmp[3];
+ FILE* stream;
+ (void)argc, (void)argv;
+
+ CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
+ solparser_create(&allocator, &parser);
+
+ stream = tmpfile();
+ NCHECK(stream, NULL);
+
+ fprintf(stream, "- geometry: &sphere\n");
+ fprintf(stream, " - sphere: { radius: 1 }\n");
+ fprintf(stream, " material: { matte: { reflectivity: 1 } }\n");
+ fprintf(stream, "- entity:\n");
+ fprintf(stream, " name: lvl 0\n");
+ fprintf(stream, " geometry: *sphere\n");
+ fprintf(stream, " transform: { translation: [1,2,3], rotation: [4,5,6]}\n");
+ fprintf(stream, " children:\n");
+ fprintf(stream, " - name: lvl1a\n");
+ fprintf(stream, " geometry: \n");
+ fprintf(stream, " - sphere: {radius: 2}\n");
+ fprintf(stream, " material:\n");
+ fprintf(stream, " mirror: { reflectivity: 0.9, roughness: 0.1 }\n");
+ fprintf(stream, " - name: lvl1b\n");
+ fprintf(stream, " geometry: *sphere\n");
+ fprintf(stream, " transform: { rotation: [3.14, 0, -1] }\n");
+ fprintf(stream, " children:\n");
+ fprintf(stream, " - name: lvl2\n");
+ fprintf(stream, " geometry: *sphere\n");
+ fprintf(stream, "- sun:\n");
+ fprintf(stream, " dni: 1\n");
+ fprintf(stream, " spectrum: [ { wavelength: 1, data: 1} ]\n");
+ rewind(stream);
+
+ CHECK(solparser_setup(parser, NULL, stream), RES_OK);
+ CHECK(solparser_load(parser), RES_OK);
+
+ solparser_geometry_iterator_begin(parser, &geom_it);
+ solparser_geometry_iterator_end(parser, &geom_it_end);
+ ngeoms = 0;
+ while(!solparser_geometry_iterator_eq(&geom_it, &geom_it_end)) {
+ CHECK(ngeoms < 2, 1);
+ geom_id = solparser_geometry_iterator_get(&geom_it);
+ solparser_geometry_iterator_next(&geom_it);
+ geoms[ngeoms] = solparser_get_geometry(parser, geom_id);
+ ++ngeoms;
+ }
+ CHECK(ngeoms, 2);
+
+ solparser_material_iterator_begin(parser, &mtl_it);
+ solparser_material_iterator_end(parser, &mtl_it_end);
+ nmtls = 0;
+ while(!solparser_material_iterator_eq(&mtl_it, &mtl_it_end)) {
+ struct solparser_material_id mtl_id;
+ CHECK(nmtls < 2, 1);
+ mtl_id = solparser_material_iterator_get(&mtl_it);
+ solparser_material_iterator_next(&mtl_it);
+ mtls[nmtls] = solparser_get_material(parser, mtl_id);
+ ++nmtls;
+ }
+ CHECK(nmtls, 2);
+
+ solparser_entity_iterator_begin(parser, &it);
+ solparser_entity_iterator_end(parser, &end);
+ CHECK(solparser_entity_iterator_eq(&it, &end), 0);
+
+ entity_id = solparser_entity_iterator_get(&it);
+ entity = solparser_get_entity(parser, entity_id);
+
+
+ CHECK(strcmp("lvl 0", str_cget(&entity->name)), 0);
+ CHECK(solparser_entity_get_children_count(entity), 2);
+ CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY);
+ geom_id = entity->data.geometry;
+ geom = solparser_get_geometry(parser, entity->data.geometry);
+ CHECK(geom == geoms[0] || geom == geoms[1], 1);
+ CHECK(solparser_geometry_get_objects_count(geom), 1);
+ obj_id = solparser_geometry_get_object(geom, 0);
+ obj = solparser_get_object(parser, obj_id);
+ CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_SPHERE);
+ sphere = solparser_get_shape_sphere(parser, shape->data.sphere);
+ CHECK(sphere->radius, 1);
+ mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
+ CHECK(mtl2->front.i, mtl2->back.i);
+ mtl = solparser_get_material(parser, mtl2->front);
+ CHECK(mtl == mtls[0] || mtl == mtls[1], 1);
+ CHECK(mtl->type, SOLPARSER_MATERIAL_MATTE);
+ matte = solparser_get_material_matte(parser, mtl->data.matte);
+ CHECK(matte->reflectivity, 1);
+
+ entity_id = solparser_entity_get_child(entity, 0);
+ entity1a = solparser_get_entity(parser, entity_id);
+ CHECK(d3_eq(entity1a->translation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity1a->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(strcmp("lvl1a", str_cget(&entity1a->name)), 0);
+ CHECK(solparser_entity_get_children_count(entity1a), 0);
+ CHECK(entity1a->type, SOLPARSER_ENTITY_GEOMETRY);
+ NCHECK(entity1a->data.geometry.i, geom_id.i);
+ geom = solparser_get_geometry(parser, entity1a->data.geometry);
+ CHECK(geom == geoms[0] || geom == geoms[1], 1);
+ CHECK(solparser_geometry_get_objects_count(geom), 1);
+ obj_id = solparser_geometry_get_object(geom, 0);
+ obj = solparser_get_object(parser, obj_id);
+ CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_SPHERE);
+ sphere = solparser_get_shape_sphere(parser, shape->data.sphere);
+ CHECK(sphere->radius, 2);
+ mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
+ CHECK(mtl2->front.i, mtl2->back.i);
+ mtl = solparser_get_material(parser, mtl2->front);
+ CHECK(mtl == mtls[0] || mtl == mtls[1], 1);
+ CHECK(mtl->type, SOLPARSER_MATERIAL_MIRROR);
+ mirror = solparser_get_material_mirror(parser, mtl->data.mirror);
+ CHECK(mirror->reflectivity, 0.9);
+ CHECK(mirror->roughness, 0.1);
+
+ entity_id = solparser_entity_get_child(entity, 1);
+ entity1b = solparser_get_entity(parser, entity_id);
+ CHECK(d3_eq(entity1b->translation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity1b->rotation, d3(tmp, 3.14, 0, -1)), 1);
+ CHECK(strcmp("lvl1b", str_cget(&entity1b->name)), 0);
+ CHECK(solparser_entity_get_children_count(entity1b), 1);
+ CHECK(entity1b->type, SOLPARSER_ENTITY_GEOMETRY);
+ CHECK(entity1b->data.geometry.i, geom_id.i);
+
+ entity_id = solparser_entity_get_child(entity1b, 0);
+ entity2 = solparser_get_entity(parser, entity_id);
+ CHECK(d3_eq(entity2->translation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity2->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(strcmp("lvl2", str_cget(&entity2->name)), 0);
+ CHECK(solparser_entity_get_children_count(entity2), 0);
+ CHECK(entity2->type, SOLPARSER_ENTITY_GEOMETRY);
+ CHECK(entity2->data.geometry.i, geom_id.i);
+
+ entity3 = solparser_find_entity(parser, "lvl 0");
+ CHECK(entity3, entity);
+ entity3 = solparser_find_entity(parser, "lvl1a");
+ CHECK(entity3, NULL);
+ entity3 = solparser_find_entity(parser, "lvl 0.lvl1a");
+ CHECK(entity3, entity1a);
+ entity3 = solparser_find_entity(parser, "lvl 0.lvl1b");
+ CHECK(entity3, entity1b);
+ entity3 = solparser_find_entity(parser, "lvl 0.lvl1b.lvl2");
+ CHECK(entity3, entity2);
+ entity3 = solparser_find_entity(parser,"lvl 0.lvl1b.bad_name");
+ CHECK(entity3, NULL);
+
+ sun = solparser_get_sun(parser);
+ NCHECK(sun, NULL);
+ CHECK(sun->dni, 1.0);
+ CHECK(sun->radang_distrib_type, SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL);
+ CHECK(darray_spectrum_data_size_get(&sun->spectrum), 1);
+ CHECK(darray_spectrum_data_cdata_get(&sun->spectrum)[0].wavelength, 1.0);
+ CHECK(darray_spectrum_data_cdata_get(&sun->spectrum)[0].data, 1.0);
+
+ CHECK(solparser_load(parser), RES_BAD_OP);
+ solparser_ref_put(parser);
+
+ fclose(stream);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
+
diff --git a/src/parser/test_solparser3.c b/src/parser/test_solparser3.c
@@ -0,0 +1,246 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "solparser.h"
+#include "test_solstice_utils.h"
+
+static const char* input[] = {
+ "- material: &lambertian\n",
+ " matte: { reflectivity: 0.5 }\n",
+ "- geometry: &cylinder\n",
+ " - cylinder: { radius: 1, height: 10, slices: 128 }\n",
+ " material: *lambertian\n",
+ "- sun: \n",
+ " dni: 1\n",
+ " spectrum: [{wavelength: 1, data: 1}]\n",
+ "- entity:\n",
+ " name: entity0\n",
+ " geometry: *cylinder\n",
+ " anchors:\n",
+ " - name: anchor0\n",
+ " position: [1, 2, 3]\n",
+ " - name: anchor1\n",
+ " position: [4, 5, 6]\n",
+ " children:\n",
+ " - name: entity0a\n",
+ " geometry: *cylinder\n",
+ " - name: entity0b\n",
+ " geometry: *cylinder\n",
+ " anchors:\n\n",
+ " - name: anchor0\n",
+ " position: [4, 5, 6]\n",
+ " - name: entity0b\n",
+ " position: [7, 8, 9]\n",
+ "- entity:\n",
+ " name: entity1\n",
+ " pivot:\n",
+ " point: [1, 2, 3]\n",
+ " normal: [4, 5, 6]\n",
+ " target: { anchor: \"entity0.entity0b.anchor0\" }\n",
+ NULL
+};
+
+const struct solparser_anchor* entity0_anchor0;
+const struct solparser_anchor* entity0_anchor1;
+const struct solparser_anchor* entity0_entity0b_anchor0;
+const struct solparser_anchor* entity0_entity0b_entity0b;
+const struct solparser_geometry* geom;
+const struct solparser_pivot* pivot;
+
+static void
+check_entity0
+ (struct solparser* parser, const struct solparser_entity* entity0)
+{
+ struct solparser_anchor_id anchor_id;
+ struct solparser_entity_id entity_id;
+ struct solparser_object_id obj_id;
+ const struct solparser_entity *entity0a, *entity0b;
+ const struct solparser_material_matte* matte;
+ const struct solparser_material* mtl;
+ const struct solparser_material_double_sided* mtl2;
+ const struct solparser_object* obj;
+ const struct solparser_shape* shape;
+ const struct solparser_shape_cylinder* cylinder;
+ double tmp[3];
+
+ NCHECK(parser, NULL);
+ NCHECK(entity0, NULL);
+
+ CHECK(strcmp(str_cget(&entity0->name), "entity0"), 0);
+ CHECK(d3_eq(entity0->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity0->translation, d3_splat(tmp, 0)), 1);
+ CHECK(entity0->type, SOLPARSER_ENTITY_GEOMETRY);
+
+ geom = solparser_get_geometry(parser, entity0->data.geometry);
+ CHECK(solparser_geometry_get_objects_count(geom), 1);
+
+ obj_id = solparser_geometry_get_object(geom, 0);
+ obj = solparser_get_object(parser, obj_id);
+ CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
+
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_CYLINDER);
+
+ cylinder = solparser_get_shape_cylinder(parser, shape->data.cylinder);
+ CHECK(cylinder->height, 10);
+ CHECK(cylinder->radius, 1);
+ CHECK(cylinder->nslices, 128);
+
+ mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
+ CHECK(mtl2->front.i, mtl2->back.i);
+
+ mtl = solparser_get_material(parser, mtl2->front);
+ CHECK(mtl->type, SOLPARSER_MATERIAL_MATTE);
+
+ matte = solparser_get_material_matte(parser, mtl->data.matte);
+ CHECK(matte->reflectivity, 0.5);
+
+ CHECK(solparser_entity_get_children_count(entity0), 2);
+ CHECK(solparser_entity_get_anchors_count(entity0), 2);
+
+ anchor_id = solparser_entity_get_anchor(entity0, 0);
+ entity0_anchor0 = solparser_get_anchor(parser, anchor_id);
+ CHECK(strcmp(str_cget(&entity0_anchor0->name), "anchor0"), 0);
+ CHECK(d3_eq(entity0_anchor0->position, d3(tmp, 1, 2, 3)), 1);
+
+ anchor_id = solparser_entity_get_anchor(entity0, 1);
+ entity0_anchor1 = solparser_get_anchor(parser, anchor_id);
+ CHECK(strcmp(str_cget(&entity0_anchor1->name), "anchor1"), 0);
+ CHECK(d3_eq(entity0_anchor1->position, d3(tmp, 4, 5, 6)), 1);
+
+ entity_id = solparser_entity_get_child(entity0, 0);
+ entity0a = solparser_get_entity(parser, entity_id);
+ CHECK(strcmp(str_cget(&entity0a->name), "entity0a"), 0);
+ CHECK(entity0a->type, SOLPARSER_ENTITY_GEOMETRY);
+ CHECK(entity0->data.geometry.i, entity0a->data.geometry.i);
+ CHECK(solparser_entity_get_anchors_count(entity0a), 0);
+ CHECK(solparser_entity_get_children_count(entity0a), 0);
+
+ entity_id = solparser_entity_get_child(entity0, 1);
+ entity0b = solparser_get_entity(parser, entity_id);
+ CHECK(strcmp(str_cget(&entity0b->name), "entity0b"), 0);
+ CHECK(entity0b->type, SOLPARSER_ENTITY_GEOMETRY);
+ CHECK(entity0->data.geometry.i, entity0b->data.geometry.i);
+ CHECK(solparser_entity_get_anchors_count(entity0b), 2);
+ CHECK(solparser_entity_get_children_count(entity0b), 0);
+
+ anchor_id = solparser_entity_get_anchor(entity0b, 0);
+ entity0_entity0b_anchor0 = solparser_get_anchor(parser, anchor_id);
+ CHECK(strcmp(str_cget(&entity0_entity0b_anchor0->name), "anchor0"), 0);
+ CHECK(d3_eq(entity0_entity0b_anchor0->position, d3(tmp, 4, 5, 6)), 1);
+
+ anchor_id = solparser_entity_get_anchor(entity0b, 1);
+ entity0_entity0b_entity0b = solparser_get_anchor(parser, anchor_id);
+ CHECK(strcmp(str_cget(&entity0_entity0b_entity0b->name), "entity0b"), 0);
+ CHECK(d3_eq(entity0_entity0b_entity0b->position, d3(tmp, 7, 8, 9)), 1);
+}
+
+static void
+check_entity1
+ (struct solparser* parser, const struct solparser_entity* entity1)
+{
+ double tmp[3];
+
+ NCHECK(parser, NULL);
+ NCHECK(entity1, NULL);
+
+ CHECK(strcmp(str_cget(&entity1->name), "entity1"), 0);
+ CHECK(entity1->type, SOLPARSER_ENTITY_PIVOT);
+ CHECK(solparser_entity_get_anchors_count(entity1), 0);
+ CHECK(solparser_entity_get_children_count(entity1), 0);
+
+ pivot = solparser_get_pivot(parser, entity1->data.pivot);
+ CHECK(d3_eq(pivot->point, d3(tmp, 1, 2, 3)), 1);
+ CHECK(d3_eq(pivot->normal, d3(tmp, 4, 5, 6)), 1);
+ CHECK(pivot->target_type, SOLPARSER_TARGET_ANCHOR);
+}
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct solparser* parser;
+ struct solparser_entity_iterator it, it_end;
+ const struct solparser_anchor* anchor;
+ FILE* stream;
+ size_t i;
+ (void)argc, (void)argv;
+
+ CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
+ solparser_create(&allocator, &parser);
+
+ stream = tmpfile();
+ NCHECK(stream, NULL);
+ i = 0;
+ while(input[i]) {
+ const size_t len = strlen(input[i]);
+ CHECK(fwrite(input[i], 1, len, stream), len);
+ ++i;
+ }
+ rewind(stream);
+
+ CHECK(solparser_setup(parser, NULL, stream), RES_OK);
+ CHECK(solparser_load(parser), RES_OK);
+
+ solparser_entity_iterator_begin(parser, &it);
+ solparser_entity_iterator_end(parser, &it_end);
+ CHECK(solparser_entity_iterator_eq(&it, &it_end), 0);
+
+ while(!solparser_entity_iterator_eq(&it, &it_end)) {
+ struct solparser_entity_id entity_id;
+ const struct solparser_entity* entity;
+
+ entity_id = solparser_entity_iterator_get(&it);
+ entity = solparser_get_entity(parser, entity_id);
+
+ if(!strcmp(str_cget(&entity->name), "entity0")) {
+ check_entity0(parser, entity);
+ } else if(!strcmp(str_cget(&entity->name), "entity1")) {
+ check_entity1(parser, entity);
+ } else {
+ FATAL("Unexpected entity name.\n");
+ }
+
+ solparser_entity_iterator_next(&it);
+ }
+
+ anchor = solparser_get_anchor(parser, pivot->target.anchor);
+ CHECK(anchor, entity0_entity0b_anchor0);
+
+ anchor = solparser_find_anchor(parser, "entity0");
+ CHECK(anchor, NULL);
+ anchor = solparser_find_anchor(parser, "entity0.anchor0");
+ CHECK(anchor, entity0_anchor0);
+ anchor = solparser_find_anchor(parser, "entity0.anchor1");
+ CHECK(anchor, entity0_anchor1);
+ anchor = solparser_find_anchor(parser, "entity0.entity0a.anchor0");
+ CHECK(anchor, NULL);
+ anchor = solparser_find_anchor(parser, "entity0.entity0b.anchor0");
+ CHECK(anchor, entity0_entity0b_anchor0);
+ anchor = solparser_find_anchor(parser, "entity0.entity0b.entity0b");
+ CHECK(anchor, entity0_entity0b_entity0b);
+ anchor = solparser_find_anchor(parser, "entity1.entity0b.anchor1");
+ CHECK(anchor, NULL);
+
+ CHECK(solparser_load(parser), RES_BAD_OP);
+ solparser_ref_put(parser);
+ fclose(stream);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
diff --git a/src/parser/test_solparser4.c b/src/parser/test_solparser4.c
@@ -0,0 +1,208 @@
+/* Copyright (C) CNRS 2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "solparser.h"
+#include "test_solstice_utils.h"
+
+const struct solparser_geometry* geometry;
+
+static const char* input[] = {
+ "- sun: \n",
+ " dni: 1\n",
+ " spectrum: [{wavelength: 1, data: 1}]\n",
+ "- material: &lambertian\n",
+ " mirror: { reflectivity: 0.2, roughness: 0.1 }\n",
+ "- geometry: &cuboid\n",
+ " - cuboid: { size: [1, 2, 3] }\n",
+ " material: *lambertian\n",
+ "- template: &template\n",
+ " name: template0\n",
+ " geometry: *cuboid\n",
+ "- entity:\n",
+ " name: entity0\n",
+ " transform: { translation: [1, 2, 3] }\n",
+ " children: [ *template ]\n",
+ "- entity:\n",
+ " name: entity1\n",
+ " transform: { translation: [3, 4, 5] }\n",
+ " children: [ *template ]\n",
+ NULL
+};
+
+static void
+check_entity0
+ (struct solparser* parser, const struct solparser_entity* entity0)
+{
+ const struct solparser_entity* entity;
+ struct solparser_entity_id entity_id;
+ double tmp[3];
+
+ NCHECK(parser, NULL);
+ NCHECK(entity0, NULL);
+
+ CHECK(strcmp(str_cget(&entity0->name), "entity0"), 0);
+ CHECK(d3_eq(entity0->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity0->translation, d3(tmp, 1, 2, 3)), 1);
+ CHECK(entity0->type, SOLPARSER_ENTITY_EMPTY);
+
+ CHECK(solparser_entity_get_children_count(entity0), 1);
+ CHECK(solparser_entity_get_anchors_count(entity0), 0);
+
+ entity_id = solparser_entity_get_child(entity0, 0);
+ entity = solparser_get_entity(parser, entity_id);
+ CHECK(strcmp(str_cget(&entity->name), "template0"), 0);
+ CHECK(d3_eq(entity->translation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity->rotation, d3_splat(tmp, 0)), 1);
+
+ CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY);
+ CHECK(solparser_get_geometry(parser, entity->data.geometry), geometry);
+ CHECK(solparser_find_entity(parser, "entity0.template0"), entity);
+}
+
+static void
+check_entity1
+ (struct solparser* parser, const struct solparser_entity* entity1)
+{
+ const struct solparser_entity* entity;
+ struct solparser_entity_id entity_id;
+ double tmp[3];
+
+ NCHECK(parser, NULL);
+ NCHECK(entity1, NULL);
+
+ CHECK(strcmp(str_cget(&entity1->name), "entity1"), 0);
+ CHECK(d3_eq(entity1->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity1->translation, d3(tmp, 3, 4, 5)), 1);
+ CHECK(entity1->type, SOLPARSER_ENTITY_EMPTY);
+
+ CHECK(solparser_entity_get_children_count(entity1), 1);
+ CHECK(solparser_entity_get_anchors_count(entity1), 0);
+
+ entity_id = solparser_entity_get_child(entity1, 0);
+ entity = solparser_get_entity(parser, entity_id);
+ CHECK(strcmp(str_cget(&entity->name), "template0"), 0);
+ CHECK(d3_eq(entity->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(entity->translation, d3_splat(tmp, 0)), 1);
+
+ CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY);
+ CHECK(solparser_get_geometry(parser, entity->data.geometry), geometry);
+ CHECK(solparser_find_entity(parser, "entity1.template0"), entity);
+}
+
+int
+main(int argc, char** argv)
+{
+ struct solparser_entity_iterator it, it_end;
+ struct solparser_geometry_iterator it_geom, it_end_geom;
+ struct mem_allocator allocator;
+ struct solparser* parser;
+ const struct solparser_material* mtl;
+ const struct solparser_material_double_sided* mtl2;
+ const struct solparser_material_mirror* mirror;
+ const struct solparser_object* obj;
+ const struct solparser_shape* shape;
+ const struct solparser_shape_cuboid* cuboid;
+ struct solparser_geometry_id geom_id;
+ struct solparser_object_id obj_id;
+ double tmp[3];
+ FILE* stream;
+ size_t i;
+ int entity0 = 0;
+ int entity1 = 0;
+ (void)argc, (void)argv;
+
+ CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
+ solparser_create(&allocator, &parser);
+
+ stream = tmpfile();
+ NCHECK(stream, NULL);
+ i = 0;
+ while(input[i]) {
+ const size_t len = strlen(input[i]);
+ CHECK(fwrite(input[i], 1, len, stream), len);
+ ++i;
+ }
+ rewind(stream);
+
+ CHECK(solparser_setup(parser, NULL, stream), RES_OK);
+ CHECK(solparser_load(parser), RES_OK);
+
+ solparser_geometry_iterator_begin(parser, &it_geom);
+ solparser_geometry_iterator_end(parser, &it_end_geom);
+ CHECK(solparser_geometry_iterator_eq(&it_geom, &it_end_geom), 0);
+ geom_id = solparser_geometry_iterator_get(&it_geom);
+ geometry = solparser_get_geometry(parser, geom_id);
+ solparser_geometry_iterator_next(&it_geom);
+ CHECK(solparser_geometry_iterator_eq(&it_geom, &it_end_geom), 1);
+
+ CHECK(solparser_geometry_get_objects_count(geometry), 1);
+ obj_id = solparser_geometry_get_object(geometry, 0);
+ obj = solparser_get_object(parser, obj_id);
+ CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
+ CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
+
+ mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
+ CHECK(mtl2->front.i, mtl2->back.i);
+ mtl = solparser_get_material(parser, mtl2->front);
+ CHECK(mtl->type, SOLPARSER_MATERIAL_MIRROR);
+ mirror = solparser_get_material_mirror(parser, mtl->data.mirror);
+ CHECK(mirror->reflectivity, 0.2);
+ CHECK(mirror->roughness, 0.1);
+
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_CUBOID);
+ cuboid = solparser_get_shape_cuboid(parser, shape->data.cuboid);
+ CHECK(cuboid->size[0], 1);
+ CHECK(cuboid->size[1], 2);
+ CHECK(cuboid->size[2], 3);
+
+ solparser_entity_iterator_begin(parser, &it);
+ solparser_entity_iterator_end(parser, &it_end);
+ CHECK(solparser_entity_iterator_eq(&it, &it_end), 0);
+
+ while(!solparser_entity_iterator_eq(&it, &it_end)) {
+ struct solparser_entity_id entity_id;
+ const struct solparser_entity* entity;
+
+ entity_id = solparser_entity_iterator_get(&it);
+ entity = solparser_get_entity(parser, entity_id);
+
+ if(!strcmp(str_cget(&entity->name), "entity0")) {
+ CHECK(entity0, 0);
+ entity0 = 1;
+ check_entity0(parser, entity);
+ } else if(!strcmp(str_cget(&entity->name), "entity1")) {
+ CHECK(entity1, 0);
+ entity1 = 1;
+ check_entity1(parser, entity);
+ } else {
+ FATAL("Unexpected entity name.\n");
+ }
+
+ solparser_entity_iterator_next(&it);
+ }
+ CHECK(entity0, 1);
+ CHECK(entity1, 1);
+
+ CHECK(solparser_load(parser), RES_BAD_OP);
+ solparser_ref_put(parser);
+ fclose(stream);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}
+
diff --git a/src/parser/test_solstice_parser.c b/src/parser/test_solstice_parser.c
@@ -1,80 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "solstice_parser.h"
-#include "test_solstice_utils.h"
-
-#include <string.h>
-
-int
-main(int argc, char** argv)
-{
- struct mem_allocator allocator;
- struct solstice_parser* parser;
- int ifile = 1;
- int i;
- res_T load_res = RES_OK;
- (void)argc, (void)argv;
-
- if(argc > 1) {
- if(!strcmp(argv[1], "-e")) {
- load_res = RES_BAD_ARG;
- ifile = 2;
- } else if(!strcmp(argv[1], "-h")) {
- printf("Usage: %s [OPTIONS] [FILE ... ]\n", argv[0]);
- printf(
-"Check the parser API and that the submitted FILEs are valid. Use the `-e'\n"
-"option to check that the FILEs are invalid.\n\n");
- printf("OPTIONS:\n");
- printf(" -h print this help and exit.\n");
- printf(" -e check that the submitted FILEs have errors.\n");
- return 0;
- }
- }
-
- CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
- solstice_parser_create(&allocator, &parser);
-
- CHECK(solstice_parser_setup(parser, NULL, tmpfile()), RES_OK);
- CHECK(solstice_parser_setup(parser, "yop", tmpfile()), RES_OK);
- CHECK(solstice_parser_load(parser), RES_BAD_OP); /* Empty stream */
-
- FOR_EACH(i, ifile, argc) {
- FILE* file = fopen(argv[i], "rb");
- int count = 0;
- NCHECK(file, NULL);
- CHECK(solstice_parser_setup(parser, argv[i], file), RES_OK);
- for(;;) {
- const res_T res = solstice_parser_load(parser);
- if(count == 0 && load_res == RES_OK) {
- CHECK(res, RES_OK);
- } else if(res == RES_BAD_OP) {
- break;
- }
- CHECK(res, load_res);
- ++count;
- }
- fclose(file);
- }
-
- solstice_parser_ref_get(parser);
- solstice_parser_ref_put(parser);
- solstice_parser_ref_put(parser);
-
- check_memory_allocator(&allocator);
- mem_shutdown_proxy_allocator(&allocator);
- CHECK(mem_allocated_size(), 0);
- return 0;
-}
diff --git a/src/parser/test_solstice_parser2.c b/src/parser/test_solstice_parser2.c
@@ -1,215 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "solstice_parser.h"
-#include "solstice_sun.h"
-#include "test_solstice_utils.h"
-
-int
-main(int argc, char** argv)
-{
- struct mem_allocator allocator;
- struct solstice_parser* parser;
- struct solstice_entity_iterator it, end;
- struct solstice_geometry_iterator geom_it, geom_it_end;
- struct solstice_material_iterator mtl_it, mtl_it_end;
- struct solstice_entity_id entity_id;
- struct solstice_object_id obj_id;
- struct solstice_geometry_id geom_id;
- const struct solstice_geometry* geoms[2] = { NULL, NULL };
- const struct solstice_material* mtls[2] = { NULL, NULL };
- const struct solstice_entity* entity, *entity1a, *entity1b, *entity2, *entity3;
- const struct solstice_geometry* geom;
- const struct solstice_object* obj;
- const struct solstice_shape* shape;
- const struct solstice_material_double_sided* mtl2;
- const struct solstice_material* mtl;
- const struct solstice_material_matte* matte;
- const struct solstice_material_mirror* mirror;
- const struct solstice_shape_sphere* sphere;
- const struct solstice_sun* sun;
- size_t nmtls = 0;
- size_t ngeoms = 0;
- double tmp[3];
- FILE* stream;
- (void)argc, (void)argv;
-
- CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
- solstice_parser_create(&allocator, &parser);
-
- stream = tmpfile();
- NCHECK(stream, NULL);
-
- fprintf(stream, "- geometry: &sphere\n");
- fprintf(stream, " - sphere: { radius: 1 }\n");
- fprintf(stream, " material: { matte: { reflectivity: 1 } }\n");
- fprintf(stream, "- entity:\n");
- fprintf(stream, " name: lvl 0\n");
- fprintf(stream, " geometry: *sphere\n");
- fprintf(stream, " transform: { translation: [1,2,3], rotation: [4,5,6]}\n");
- fprintf(stream, " children:\n");
- fprintf(stream, " - name: lvl1a\n");
- fprintf(stream, " geometry: \n");
- fprintf(stream, " - sphere: {radius: 2}\n");
- fprintf(stream, " material:\n");
- fprintf(stream, " mirror: { reflectivity: 0.9, roughness: 0.1 }\n");
- fprintf(stream, " - name: lvl1b\n");
- fprintf(stream, " geometry: *sphere\n");
- fprintf(stream, " transform: { rotation: [3.14, 0, -1] }\n");
- fprintf(stream, " children:\n");
- fprintf(stream, " - name: lvl2\n");
- fprintf(stream, " geometry: *sphere\n");
- fprintf(stream, "- sun:\n");
- fprintf(stream, " dni: 1\n");
- fprintf(stream, " spectrum: [ { wavelength: 1, data: 1} ]\n");
- rewind(stream);
-
- CHECK(solstice_parser_setup(parser, NULL, stream), RES_OK);
- CHECK(solstice_parser_load(parser), RES_OK);
-
- solstice_parser_geometry_iterator_begin(parser, &geom_it);
- solstice_parser_geometry_iterator_end(parser, &geom_it_end);
- ngeoms = 0;
- while(!solstice_geometry_iterator_eq(&geom_it, &geom_it_end)) {
- CHECK(ngeoms < 2, 1);
- geom_id = solstice_geometry_iterator_get(&geom_it);
- solstice_geometry_iterator_next(&geom_it);
- geoms[ngeoms] = solstice_parser_get_geometry(parser, geom_id);
- ++ngeoms;
- }
- CHECK(ngeoms, 2);
-
- solstice_parser_material_iterator_begin(parser, &mtl_it);
- solstice_parser_material_iterator_end(parser, &mtl_it_end);
- nmtls = 0;
- while(!solstice_material_iterator_eq(&mtl_it, &mtl_it_end)) {
- struct solstice_material_id mtl_id;
- CHECK(nmtls < 2, 1);
- mtl_id = solstice_material_iterator_get(&mtl_it);
- solstice_material_iterator_next(&mtl_it);
- mtls[nmtls] = solstice_parser_get_material(parser, mtl_id);
- ++nmtls;
- }
- CHECK(nmtls, 2);
-
- solstice_parser_entity_iterator_begin(parser, &it);
- solstice_parser_entity_iterator_end(parser, &end);
- CHECK(solstice_entity_iterator_eq(&it, &end), 0);
-
- entity_id = solstice_entity_iterator_get(&it);
- entity = solstice_parser_get_entity(parser, entity_id);
-
-
- CHECK(strcmp("lvl 0", str_cget(&entity->name)), 0);
- CHECK(solstice_entity_get_children_count(entity), 2);
- CHECK(entity->type, SOLSTICE_ENTITY_GEOMETRY);
- geom_id = entity->data.geometry;
- geom = solstice_parser_get_geometry(parser, entity->data.geometry);
- CHECK(geom == geoms[0] || geom == geoms[1], 1);
- CHECK(solstice_geometry_get_objects_count(geom), 1);
- obj_id = solstice_geometry_get_object(geom, 0);
- obj = solstice_parser_get_object(parser, obj_id);
- CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
- shape = solstice_parser_get_shape(parser, obj->shape);
- CHECK(shape->type, SOLSTICE_SHAPE_SPHERE);
- sphere = solstice_parser_get_shape_sphere(parser, shape->data.sphere);
- CHECK(sphere->radius, 1);
- mtl2 = solstice_parser_get_material_double_sided(parser, obj->mtl2);
- CHECK(mtl2->front.i, mtl2->back.i);
- mtl = solstice_parser_get_material(parser, mtl2->front);
- CHECK(mtl == mtls[0] || mtl == mtls[1], 1);
- CHECK(mtl->type, SOLSTICE_MATERIAL_MATTE);
- matte = solstice_parser_get_material_matte(parser, mtl->data.matte);
- CHECK(matte->reflectivity, 1);
-
- entity_id = solstice_entity_get_child(entity, 0);
- entity1a = solstice_parser_get_entity(parser, entity_id);
- CHECK(d3_eq(entity1a->translation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity1a->rotation, d3_splat(tmp, 0)), 1);
- CHECK(strcmp("lvl1a", str_cget(&entity1a->name)), 0);
- CHECK(solstice_entity_get_children_count(entity1a), 0);
- CHECK(entity1a->type, SOLSTICE_ENTITY_GEOMETRY);
- NCHECK(entity1a->data.geometry.i, geom_id.i);
- geom = solstice_parser_get_geometry(parser, entity1a->data.geometry);
- CHECK(geom == geoms[0] || geom == geoms[1], 1);
- CHECK(solstice_geometry_get_objects_count(geom), 1);
- obj_id = solstice_geometry_get_object(geom, 0);
- obj = solstice_parser_get_object(parser, obj_id);
- CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
- shape = solstice_parser_get_shape(parser, obj->shape);
- CHECK(shape->type, SOLSTICE_SHAPE_SPHERE);
- sphere = solstice_parser_get_shape_sphere(parser, shape->data.sphere);
- CHECK(sphere->radius, 2);
- mtl2 = solstice_parser_get_material_double_sided(parser, obj->mtl2);
- CHECK(mtl2->front.i, mtl2->back.i);
- mtl = solstice_parser_get_material(parser, mtl2->front);
- CHECK(mtl == mtls[0] || mtl == mtls[1], 1);
- CHECK(mtl->type, SOLSTICE_MATERIAL_MIRROR);
- mirror = solstice_parser_get_material_mirror(parser, mtl->data.mirror);
- CHECK(mirror->reflectivity, 0.9);
- CHECK(mirror->roughness, 0.1);
-
- entity_id = solstice_entity_get_child(entity, 1);
- entity1b = solstice_parser_get_entity(parser, entity_id);
- CHECK(d3_eq(entity1b->translation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity1b->rotation, d3(tmp, 3.14, 0, -1)), 1);
- CHECK(strcmp("lvl1b", str_cget(&entity1b->name)), 0);
- CHECK(solstice_entity_get_children_count(entity1b), 1);
- CHECK(entity1b->type, SOLSTICE_ENTITY_GEOMETRY);
- CHECK(entity1b->data.geometry.i, geom_id.i);
-
- entity_id = solstice_entity_get_child(entity1b, 0);
- entity2 = solstice_parser_get_entity(parser, entity_id);
- CHECK(d3_eq(entity2->translation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity2->rotation, d3_splat(tmp, 0)), 1);
- CHECK(strcmp("lvl2", str_cget(&entity2->name)), 0);
- CHECK(solstice_entity_get_children_count(entity2), 0);
- CHECK(entity2->type, SOLSTICE_ENTITY_GEOMETRY);
- CHECK(entity2->data.geometry.i, geom_id.i);
-
- entity3 = solstice_parser_find_entity(parser, "lvl 0");
- CHECK(entity3, entity);
- entity3 = solstice_parser_find_entity(parser, "lvl1a");
- CHECK(entity3, NULL);
- entity3 = solstice_parser_find_entity(parser, "lvl 0.lvl1a");
- CHECK(entity3, entity1a);
- entity3 = solstice_parser_find_entity(parser, "lvl 0.lvl1b");
- CHECK(entity3, entity1b);
- entity3 = solstice_parser_find_entity(parser, "lvl 0.lvl1b.lvl2");
- CHECK(entity3, entity2);
- entity3 = solstice_parser_find_entity(parser,"lvl 0.lvl1b.bad_name");
- CHECK(entity3, NULL);
-
- sun = solstice_parser_get_sun(parser);
- NCHECK(sun, NULL);
- CHECK(sun->dni, 1.0);
- CHECK(sun->radang_distrib_type, SOLSTICE_SUN_RADANG_DISTRIB_DIRECTIONAL);
- CHECK(darray_spectrum_data_size_get(&sun->spectrum), 1);
- CHECK(darray_spectrum_data_cdata_get(&sun->spectrum)[0].wavelength, 1.0);
- CHECK(darray_spectrum_data_cdata_get(&sun->spectrum)[0].data, 1.0);
-
- CHECK(solstice_parser_load(parser), RES_BAD_OP);
- solstice_parser_ref_put(parser);
-
- fclose(stream);
-
- check_memory_allocator(&allocator);
- mem_shutdown_proxy_allocator(&allocator);
- CHECK(mem_allocated_size(), 0);
- return 0;
-}
-
diff --git a/src/parser/test_solstice_parser3.c b/src/parser/test_solstice_parser3.c
@@ -1,246 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "solstice_parser.h"
-#include "test_solstice_utils.h"
-
-static const char* input[] = {
- "- material: &lambertian\n",
- " matte: { reflectivity: 0.5 }\n",
- "- geometry: &cylinder\n",
- " - cylinder: { radius: 1, height: 10, slices: 128 }\n",
- " material: *lambertian\n",
- "- sun: \n",
- " dni: 1\n",
- " spectrum: [{wavelength: 1, data: 1}]\n",
- "- entity:\n",
- " name: entity0\n",
- " geometry: *cylinder\n",
- " anchors:\n",
- " - name: anchor0\n",
- " position: [1, 2, 3]\n",
- " - name: anchor1\n",
- " position: [4, 5, 6]\n",
- " children:\n",
- " - name: entity0a\n",
- " geometry: *cylinder\n",
- " - name: entity0b\n",
- " geometry: *cylinder\n",
- " anchors:\n\n",
- " - name: anchor0\n",
- " position: [4, 5, 6]\n",
- " - name: entity0b\n",
- " position: [7, 8, 9]\n",
- "- entity:\n",
- " name: entity1\n",
- " pivot:\n",
- " point: [1, 2, 3]\n",
- " normal: [4, 5, 6]\n",
- " target: { anchor: \"entity0.entity0b.anchor0\" }\n",
- NULL
-};
-
-const struct solstice_anchor* entity0_anchor0;
-const struct solstice_anchor* entity0_anchor1;
-const struct solstice_anchor* entity0_entity0b_anchor0;
-const struct solstice_anchor* entity0_entity0b_entity0b;
-const struct solstice_geometry* geom;
-const struct solstice_pivot* pivot;
-
-static void
-check_entity0
- (struct solstice_parser* parser, const struct solstice_entity* entity0)
-{
- struct solstice_anchor_id anchor_id;
- struct solstice_entity_id entity_id;
- struct solstice_object_id obj_id;
- const struct solstice_entity *entity0a, *entity0b;
- const struct solstice_material_matte* matte;
- const struct solstice_material* mtl;
- const struct solstice_material_double_sided* mtl2;
- const struct solstice_object* obj;
- const struct solstice_shape* shape;
- const struct solstice_shape_cylinder* cylinder;
- double tmp[3];
-
- NCHECK(parser, NULL);
- NCHECK(entity0, NULL);
-
- CHECK(strcmp(str_cget(&entity0->name), "entity0"), 0);
- CHECK(d3_eq(entity0->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity0->translation, d3_splat(tmp, 0)), 1);
- CHECK(entity0->type, SOLSTICE_ENTITY_GEOMETRY);
-
- geom = solstice_parser_get_geometry(parser, entity0->data.geometry);
- CHECK(solstice_geometry_get_objects_count(geom), 1);
-
- obj_id = solstice_geometry_get_object(geom, 0);
- obj = solstice_parser_get_object(parser, obj_id);
- CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
-
- shape = solstice_parser_get_shape(parser, obj->shape);
- CHECK(shape->type, SOLSTICE_SHAPE_CYLINDER);
-
- cylinder = solstice_parser_get_shape_cylinder(parser, shape->data.cylinder);
- CHECK(cylinder->height, 10);
- CHECK(cylinder->radius, 1);
- CHECK(cylinder->nslices, 128);
-
- mtl2 = solstice_parser_get_material_double_sided(parser, obj->mtl2);
- CHECK(mtl2->front.i, mtl2->back.i);
-
- mtl = solstice_parser_get_material(parser, mtl2->front);
- CHECK(mtl->type, SOLSTICE_MATERIAL_MATTE);
-
- matte = solstice_parser_get_material_matte(parser, mtl->data.matte);
- CHECK(matte->reflectivity, 0.5);
-
- CHECK(solstice_entity_get_children_count(entity0), 2);
- CHECK(solstice_entity_get_anchors_count(entity0), 2);
-
- anchor_id = solstice_entity_get_anchor(entity0, 0);
- entity0_anchor0 = solstice_parser_get_anchor(parser, anchor_id);
- CHECK(strcmp(str_cget(&entity0_anchor0->name), "anchor0"), 0);
- CHECK(d3_eq(entity0_anchor0->position, d3(tmp, 1, 2, 3)), 1);
-
- anchor_id = solstice_entity_get_anchor(entity0, 1);
- entity0_anchor1 = solstice_parser_get_anchor(parser, anchor_id);
- CHECK(strcmp(str_cget(&entity0_anchor1->name), "anchor1"), 0);
- CHECK(d3_eq(entity0_anchor1->position, d3(tmp, 4, 5, 6)), 1);
-
- entity_id = solstice_entity_get_child(entity0, 0);
- entity0a = solstice_parser_get_entity(parser, entity_id);
- CHECK(strcmp(str_cget(&entity0a->name), "entity0a"), 0);
- CHECK(entity0a->type, SOLSTICE_ENTITY_GEOMETRY);
- CHECK(entity0->data.geometry.i, entity0a->data.geometry.i);
- CHECK(solstice_entity_get_anchors_count(entity0a), 0);
- CHECK(solstice_entity_get_children_count(entity0a), 0);
-
- entity_id = solstice_entity_get_child(entity0, 1);
- entity0b = solstice_parser_get_entity(parser, entity_id);
- CHECK(strcmp(str_cget(&entity0b->name), "entity0b"), 0);
- CHECK(entity0b->type, SOLSTICE_ENTITY_GEOMETRY);
- CHECK(entity0->data.geometry.i, entity0b->data.geometry.i);
- CHECK(solstice_entity_get_anchors_count(entity0b), 2);
- CHECK(solstice_entity_get_children_count(entity0b), 0);
-
- anchor_id = solstice_entity_get_anchor(entity0b, 0);
- entity0_entity0b_anchor0 = solstice_parser_get_anchor(parser, anchor_id);
- CHECK(strcmp(str_cget(&entity0_entity0b_anchor0->name), "anchor0"), 0);
- CHECK(d3_eq(entity0_entity0b_anchor0->position, d3(tmp, 4, 5, 6)), 1);
-
- anchor_id = solstice_entity_get_anchor(entity0b, 1);
- entity0_entity0b_entity0b = solstice_parser_get_anchor(parser, anchor_id);
- CHECK(strcmp(str_cget(&entity0_entity0b_entity0b->name), "entity0b"), 0);
- CHECK(d3_eq(entity0_entity0b_entity0b->position, d3(tmp, 7, 8, 9)), 1);
-}
-
-static void
-check_entity1
- (struct solstice_parser* parser, const struct solstice_entity* entity1)
-{
- double tmp[3];
-
- NCHECK(parser, NULL);
- NCHECK(entity1, NULL);
-
- CHECK(strcmp(str_cget(&entity1->name), "entity1"), 0);
- CHECK(entity1->type, SOLSTICE_ENTITY_PIVOT);
- CHECK(solstice_entity_get_anchors_count(entity1), 0);
- CHECK(solstice_entity_get_children_count(entity1), 0);
-
- pivot = solstice_parser_get_pivot(parser, entity1->data.pivot);
- CHECK(d3_eq(pivot->point, d3(tmp, 1, 2, 3)), 1);
- CHECK(d3_eq(pivot->normal, d3(tmp, 4, 5, 6)), 1);
- CHECK(pivot->target_type, SOLSTICE_TARGET_ANCHOR);
-}
-
-int
-main(int argc, char** argv)
-{
- struct mem_allocator allocator;
- struct solstice_parser* parser;
- struct solstice_entity_iterator it, it_end;
- const struct solstice_anchor* anchor;
- FILE* stream;
- size_t i;
- (void)argc, (void)argv;
-
- CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
- solstice_parser_create(&allocator, &parser);
-
- stream = tmpfile();
- NCHECK(stream, NULL);
- i = 0;
- while(input[i]) {
- const size_t len = strlen(input[i]);
- CHECK(fwrite(input[i], 1, len, stream), len);
- ++i;
- }
- rewind(stream);
-
- CHECK(solstice_parser_setup(parser, NULL, stream), RES_OK);
- CHECK(solstice_parser_load(parser), RES_OK);
-
- solstice_parser_entity_iterator_begin(parser, &it);
- solstice_parser_entity_iterator_end(parser, &it_end);
- CHECK(solstice_entity_iterator_eq(&it, &it_end), 0);
-
- while(!solstice_entity_iterator_eq(&it, &it_end)) {
- struct solstice_entity_id entity_id;
- const struct solstice_entity* entity;
-
- entity_id = solstice_entity_iterator_get(&it);
- entity = solstice_parser_get_entity(parser, entity_id);
-
- if(!strcmp(str_cget(&entity->name), "entity0")) {
- check_entity0(parser, entity);
- } else if(!strcmp(str_cget(&entity->name), "entity1")) {
- check_entity1(parser, entity);
- } else {
- FATAL("Unexpected entity name.\n");
- }
-
- solstice_entity_iterator_next(&it);
- }
-
- anchor = solstice_parser_get_anchor(parser, pivot->target.anchor);
- CHECK(anchor, entity0_entity0b_anchor0);
-
- anchor = solstice_parser_find_anchor(parser, "entity0");
- CHECK(anchor, NULL);
- anchor = solstice_parser_find_anchor(parser, "entity0.anchor0");
- CHECK(anchor, entity0_anchor0);
- anchor = solstice_parser_find_anchor(parser, "entity0.anchor1");
- CHECK(anchor, entity0_anchor1);
- anchor = solstice_parser_find_anchor(parser, "entity0.entity0a.anchor0");
- CHECK(anchor, NULL);
- anchor = solstice_parser_find_anchor(parser, "entity0.entity0b.anchor0");
- CHECK(anchor, entity0_entity0b_anchor0);
- anchor = solstice_parser_find_anchor(parser, "entity0.entity0b.entity0b");
- CHECK(anchor, entity0_entity0b_entity0b);
- anchor = solstice_parser_find_anchor(parser, "entity1.entity0b.anchor1");
- CHECK(anchor, NULL);
-
- CHECK(solstice_parser_load(parser), RES_BAD_OP);
- solstice_parser_ref_put(parser);
- fclose(stream);
-
- check_memory_allocator(&allocator);
- mem_shutdown_proxy_allocator(&allocator);
- CHECK(mem_allocated_size(), 0);
- return 0;
-}
diff --git a/src/parser/test_solstice_parser4.c b/src/parser/test_solstice_parser4.c
@@ -1,208 +0,0 @@
-/* Copyright (C) CNRS 2016
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "solstice_parser.h"
-#include "test_solstice_utils.h"
-
-const struct solstice_geometry* geometry;
-
-static const char* input[] = {
- "- sun: \n",
- " dni: 1\n",
- " spectrum: [{wavelength: 1, data: 1}]\n",
- "- material: &lambertian\n",
- " mirror: { reflectivity: 0.2, roughness: 0.1 }\n",
- "- geometry: &cuboid\n",
- " - cuboid: { size: [1, 2, 3] }\n",
- " material: *lambertian\n",
- "- template: &template\n",
- " name: template0\n",
- " geometry: *cuboid\n",
- "- entity:\n",
- " name: entity0\n",
- " transform: { translation: [1, 2, 3] }\n",
- " children: [ *template ]\n",
- "- entity:\n",
- " name: entity1\n",
- " transform: { translation: [3, 4, 5] }\n",
- " children: [ *template ]\n",
- NULL
-};
-
-static void
-check_entity0
- (struct solstice_parser* parser, const struct solstice_entity* entity0)
-{
- const struct solstice_entity* entity;
- struct solstice_entity_id entity_id;
- double tmp[3];
-
- NCHECK(parser, NULL);
- NCHECK(entity0, NULL);
-
- CHECK(strcmp(str_cget(&entity0->name), "entity0"), 0);
- CHECK(d3_eq(entity0->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity0->translation, d3(tmp, 1, 2, 3)), 1);
- CHECK(entity0->type, SOLSTICE_ENTITY_EMPTY);
-
- CHECK(solstice_entity_get_children_count(entity0), 1);
- CHECK(solstice_entity_get_anchors_count(entity0), 0);
-
- entity_id = solstice_entity_get_child(entity0, 0);
- entity = solstice_parser_get_entity(parser, entity_id);
- CHECK(strcmp(str_cget(&entity->name), "template0"), 0);
- CHECK(d3_eq(entity->translation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity->rotation, d3_splat(tmp, 0)), 1);
-
- CHECK(entity->type, SOLSTICE_ENTITY_GEOMETRY);
- CHECK(solstice_parser_get_geometry(parser, entity->data.geometry), geometry);
- CHECK(solstice_parser_find_entity(parser, "entity0.template0"), entity);
-}
-
-static void
-check_entity1
- (struct solstice_parser* parser, const struct solstice_entity* entity1)
-{
- const struct solstice_entity* entity;
- struct solstice_entity_id entity_id;
- double tmp[3];
-
- NCHECK(parser, NULL);
- NCHECK(entity1, NULL);
-
- CHECK(strcmp(str_cget(&entity1->name), "entity1"), 0);
- CHECK(d3_eq(entity1->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity1->translation, d3(tmp, 3, 4, 5)), 1);
- CHECK(entity1->type, SOLSTICE_ENTITY_EMPTY);
-
- CHECK(solstice_entity_get_children_count(entity1), 1);
- CHECK(solstice_entity_get_anchors_count(entity1), 0);
-
- entity_id = solstice_entity_get_child(entity1, 0);
- entity = solstice_parser_get_entity(parser, entity_id);
- CHECK(strcmp(str_cget(&entity->name), "template0"), 0);
- CHECK(d3_eq(entity->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(entity->translation, d3_splat(tmp, 0)), 1);
-
- CHECK(entity->type, SOLSTICE_ENTITY_GEOMETRY);
- CHECK(solstice_parser_get_geometry(parser, entity->data.geometry), geometry);
- CHECK(solstice_parser_find_entity(parser, "entity1.template0"), entity);
-}
-
-int
-main(int argc, char** argv)
-{
- struct solstice_entity_iterator it, it_end;
- struct solstice_geometry_iterator it_geom, it_end_geom;
- struct mem_allocator allocator;
- struct solstice_parser* parser;
- const struct solstice_material* mtl;
- const struct solstice_material_double_sided* mtl2;
- const struct solstice_material_mirror* mirror;
- const struct solstice_object* obj;
- const struct solstice_shape* shape;
- const struct solstice_shape_cuboid* cuboid;
- struct solstice_geometry_id geom_id;
- struct solstice_object_id obj_id;
- double tmp[3];
- FILE* stream;
- size_t i;
- int entity0 = 0;
- int entity1 = 0;
- (void)argc, (void)argv;
-
- CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK);
- solstice_parser_create(&allocator, &parser);
-
- stream = tmpfile();
- NCHECK(stream, NULL);
- i = 0;
- while(input[i]) {
- const size_t len = strlen(input[i]);
- CHECK(fwrite(input[i], 1, len, stream), len);
- ++i;
- }
- rewind(stream);
-
- CHECK(solstice_parser_setup(parser, NULL, stream), RES_OK);
- CHECK(solstice_parser_load(parser), RES_OK);
-
- solstice_parser_geometry_iterator_begin(parser, &it_geom);
- solstice_parser_geometry_iterator_end(parser, &it_end_geom);
- CHECK(solstice_geometry_iterator_eq(&it_geom, &it_end_geom), 0);
- geom_id = solstice_geometry_iterator_get(&it_geom);
- geometry = solstice_parser_get_geometry(parser, geom_id);
- solstice_geometry_iterator_next(&it_geom);
- CHECK(solstice_geometry_iterator_eq(&it_geom, &it_end_geom), 1);
-
- CHECK(solstice_geometry_get_objects_count(geometry), 1);
- obj_id = solstice_geometry_get_object(geometry, 0);
- obj = solstice_parser_get_object(parser, obj_id);
- CHECK(d3_eq(obj->rotation, d3_splat(tmp, 0)), 1);
- CHECK(d3_eq(obj->translation, d3_splat(tmp, 0)), 1);
-
- mtl2 = solstice_parser_get_material_double_sided(parser, obj->mtl2);
- CHECK(mtl2->front.i, mtl2->back.i);
- mtl = solstice_parser_get_material(parser, mtl2->front);
- CHECK(mtl->type, SOLSTICE_MATERIAL_MIRROR);
- mirror = solstice_parser_get_material_mirror(parser, mtl->data.mirror);
- CHECK(mirror->reflectivity, 0.2);
- CHECK(mirror->roughness, 0.1);
-
- shape = solstice_parser_get_shape(parser, obj->shape);
- CHECK(shape->type, SOLSTICE_SHAPE_CUBOID);
- cuboid = solstice_parser_get_shape_cuboid(parser, shape->data.cuboid);
- CHECK(cuboid->size[0], 1);
- CHECK(cuboid->size[1], 2);
- CHECK(cuboid->size[2], 3);
-
- solstice_parser_entity_iterator_begin(parser, &it);
- solstice_parser_entity_iterator_end(parser, &it_end);
- CHECK(solstice_entity_iterator_eq(&it, &it_end), 0);
-
- while(!solstice_entity_iterator_eq(&it, &it_end)) {
- struct solstice_entity_id entity_id;
- const struct solstice_entity* entity;
-
- entity_id = solstice_entity_iterator_get(&it);
- entity = solstice_parser_get_entity(parser, entity_id);
-
- if(!strcmp(str_cget(&entity->name), "entity0")) {
- CHECK(entity0, 0);
- entity0 = 1;
- check_entity0(parser, entity);
- } else if(!strcmp(str_cget(&entity->name), "entity1")) {
- CHECK(entity1, 0);
- entity1 = 1;
- check_entity1(parser, entity);
- } else {
- FATAL("Unexpected entity name.\n");
- }
-
- solstice_entity_iterator_next(&it);
- }
- CHECK(entity0, 1);
- CHECK(entity1, 1);
-
- CHECK(solstice_parser_load(parser), RES_BAD_OP);
- solstice_parser_ref_put(parser);
- fclose(stream);
-
- check_memory_allocator(&allocator);
- mem_shutdown_proxy_allocator(&allocator);
- CHECK(mem_allocated_size(), 0);
- return 0;
-}
-
diff --git a/src/solstice.c b/src/solstice.c
@@ -13,14 +13,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "parser/solstice_parser.h"
+#include "parser/solparser.h"
#include <rsys/rsys.h>
int
main(int argc, char** argv)
{
FILE* file = NULL;
- struct solstice_parser* parser = NULL;
+ struct solparser* parser = NULL;
res_T res;
int err = 0;
int i;
@@ -31,7 +31,7 @@ main(int argc, char** argv)
goto error;
}
- res = solstice_parser_create(NULL, &parser);
+ res = solparser_create(NULL, &parser);
if(res != RES_OK) goto error;
FOR_EACH(i, 1, argc) {
@@ -41,11 +41,11 @@ main(int argc, char** argv)
goto error;
}
- res = solstice_parser_setup(parser, argv[i], file);
+ res = solparser_setup(parser, argv[i], file);
if(res != RES_OK) break;
do {
- res = solstice_parser_load(parser);
+ res = solparser_load(parser);
} while(res != RES_BAD_OP);
fclose(file);
@@ -53,7 +53,7 @@ main(int argc, char** argv)
}
exit:
- if(parser) solstice_parser_ref_put(parser);
+ if(parser) solparser_ref_put(parser);
if(file) fclose(file);
return err;
error: