solparser_pivot.c (12975B)
1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com) 2 * Copyright (C) 2016-2018 CNRS 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17 #include "solparser_c.h" 18 19 /******************************************************************************* 20 * Helper functions 21 ******************************************************************************/ 22 static res_T 23 parse_anchor_alias 24 (struct solparser* parser, 25 const yaml_node_t* alias, 26 const struct solparser_pivot_id pivot, 27 struct solparser_anchor_id* out_ianchor) 28 { 29 const struct solparser_anchor* anchor = NULL; 30 intptr_t ianchor = INTPTR_MAX; 31 res_T res = RES_OK; 32 ASSERT(parser && alias && out_ianchor); 33 34 if(alias->type != YAML_SCALAR_NODE) { 35 log_err(parser, alias, "expect an anchor idententifier.\n"); 36 res = RES_BAD_ARG; 37 goto error; 38 } 39 40 if(!strncmp((char*)alias->data.scalar.value, "self.", 5)) { 41 struct target_alias tgt; 42 tgt.pivot = pivot; 43 tgt.alias = alias; 44 res = darray_tgtalias_push_back(&parser->tgtaliases, &tgt); 45 if(res != RES_OK) { 46 log_err(parser, alias, "could not register the anchor alias.\n"); 47 goto error; 48 } 49 } else { 50 anchor = solparser_find_anchor(parser, (char*)alias->data.scalar.value); 51 if(!anchor) { 52 log_err(parser, alias, "undefined anchor `%s'.\n", 53 alias->data.scalar.value); 54 res = RES_BAD_ARG; 55 goto error; 56 } 57 58 ianchor = anchor - darray_anchor_cdata_get(&parser->anchors); 59 ASSERT(ianchor >= 0); 60 ASSERT((size_t)ianchor < darray_anchor_size_get(&parser->anchors)); 61 } 62 63 exit: 64 out_ianchor->i = (size_t)ianchor; 65 return res; 66 error: 67 ianchor = INTPTR_MAX; 68 goto exit; 69 } 70 71 static res_T 72 parse_target 73 (struct solparser* parser, 74 yaml_document_t* doc, 75 const yaml_node_t* target_node, 76 struct solparser_target* target, 77 struct solparser_pivot_id pivot_id) 78 { 79 enum { POLICY }; 80 intptr_t i, n; 81 int mask = 0; /* Register the parsed attributes */ 82 res_T res = RES_OK; 83 ASSERT(doc && target_node && target); 84 85 if(target_node->type != YAML_MAPPING_NODE) { 86 log_err(parser, target_node, "expect a target definition.\n"); 87 res = RES_BAD_ARG; 88 goto error; 89 } 90 91 n = target_node->data.mapping.pairs.top - target_node->data.mapping.pairs.start; 92 FOR_EACH(i, 0, n) { 93 yaml_node_t* key; 94 yaml_node_t* val; 95 96 key = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].key); 97 val = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].value); 98 if(key->type != YAML_SCALAR_NODE) { 99 log_err(parser, key, "expect a target parameter.\n"); 100 res = RES_BAD_ARG; 101 goto error; 102 } 103 104 #define SETUP_MASK(Flag, Name) { \ 105 if(mask & BIT(Flag)) { \ 106 log_err(parser, key, "the target "Name" is already defined.\n"); \ 107 res = RES_BAD_ARG; \ 108 goto error; \ 109 } \ 110 mask |= BIT(Flag); \ 111 } (void)0 112 if(!strcmp((char*)key->data.scalar.value, "anchor")) { 113 SETUP_MASK(POLICY, "policy"); 114 target->type = SOLPARSER_TARGET_ANCHOR; 115 res = parse_anchor_alias(parser, val, pivot_id, &target->data.anchor); 116 } else if(!strcmp((char*)key->data.scalar.value, "direction")) { 117 SETUP_MASK(POLICY, "policy"); 118 target->type = SOLPARSER_TARGET_DIRECTION; 119 res = parse_real3 120 (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.direction); 121 } else if(!strcmp((char*)key->data.scalar.value, "position")) { 122 SETUP_MASK(POLICY, "policy"); 123 target->type = SOLPARSER_TARGET_POSITION; 124 res = parse_real3 125 (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.position); 126 } else if(!strcmp((char*)key->data.scalar.value, "sun")) { 127 /* There is only one sun per YAML file. It is thus sufficient to define 128 * the target_type to SOLPARSER_TARGET_SUN to indentify which data is 129 * targeted, i.e. it is not necessary to store the identifier of the sun 130 * to target */ 131 struct solparser_sun* sun; 132 SETUP_MASK(POLICY, "policy"); 133 target->type = SOLPARSER_TARGET_SUN; 134 res = parse_sun(parser, doc, val, &sun); 135 } else { 136 log_err(parser, key, "unknown target parameter `%s'.\n", 137 key->data.scalar.value); 138 res = RES_BAD_ARG; 139 goto error; 140 } 141 if(res != RES_OK) { 142 log_node(parser, key); 143 goto error; 144 } 145 #undef SETUP_MASK 146 } 147 148 if(!(mask & BIT(POLICY))) { 149 log_err(parser, target_node, "the target policy is missing.\n"); 150 res = RES_BAD_ARG; 151 goto error; 152 } 153 154 exit: 155 return res; 156 error: 157 goto exit; 158 } 159 160 /******************************************************************************* 161 * Local functions 162 ******************************************************************************/ 163 res_T 164 parse_x_pivot 165 (struct solparser* parser, 166 yaml_document_t* doc, 167 const yaml_node_t* x_pivot, 168 struct solparser_pivot_id* out_isolpivot) 169 { 170 enum { REF_POINT, TARGET }; 171 struct solparser_x_pivot* solxpivot = NULL; 172 size_t isolpivot = SIZE_MAX; 173 int mask = 0; /* Register the parsed attributes */ 174 intptr_t i, n; 175 res_T res = RES_OK; 176 ASSERT(doc && x_pivot && out_isolpivot); 177 178 if(x_pivot->type != YAML_MAPPING_NODE) { 179 log_err(parser, x_pivot, "expect a x_pivot definition.\n"); 180 res = RES_BAD_ARG; 181 goto error; 182 } 183 184 /* Allocate the solstice pivot */ 185 isolpivot = darray_x_pivot_size_get(&parser->x_pivots); 186 res = darray_x_pivot_resize(&parser->x_pivots, isolpivot + 1); 187 if(res != RES_OK) { 188 log_err(parser, x_pivot, "could not allocate the x_pivot.\n"); 189 res = RES_BAD_ARG; 190 goto error; 191 } 192 solxpivot = darray_x_pivot_data_get(&parser->x_pivots) + isolpivot; 193 194 n = x_pivot->data.mapping.pairs.top - x_pivot->data.mapping.pairs.start; 195 d3_splat(solxpivot->ref_point, 0); /* default value */ 196 FOR_EACH(i, 0, n) { 197 yaml_node_t* key; 198 yaml_node_t* val; 199 200 key = yaml_document_get_node(doc, x_pivot->data.mapping.pairs.start[i].key); 201 val = yaml_document_get_node(doc, x_pivot->data.mapping.pairs.start[i].value); 202 if(key->type != YAML_SCALAR_NODE) { 203 log_err(parser, key, "expect x_pivot parameters.\n"); 204 res = RES_BAD_ARG; 205 goto error; 206 } 207 #define SETUP_MASK(Flag, Name) { \ 208 if(mask & BIT(Flag)) { \ 209 log_err(parser, key, \ 210 "the x_pivot parameter `"Name"' is already defined.\n"); \ 211 res = RES_BAD_ARG; \ 212 goto error; \ 213 } \ 214 mask |= BIT(Flag); \ 215 } (void)0 216 if(!strcmp((char*)key->data.scalar.value, "ref_point")) { 217 SETUP_MASK(REF_POINT, "point"); 218 res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solxpivot->ref_point); 219 } else if(!strcmp((char*)key->data.scalar.value, "target")) { 220 struct solparser_pivot_id pivot_id; 221 pivot_id.i = (size_t) (solxpivot - darray_x_pivot_cdata_get(&parser->x_pivots)); 222 SETUP_MASK(TARGET, "target"); 223 res = parse_target(parser, doc, val, &solxpivot->target, pivot_id); 224 } else { 225 log_err(parser, key, "unknown x_pivot parameter `%s'.\n", 226 key->data.scalar.value); 227 res = RES_BAD_ARG; 228 goto error; 229 } 230 if(res != RES_OK) { 231 log_node(parser, key); 232 goto error; 233 } 234 #undef SETUP_MASK 235 } 236 #define CHECK_PARAM(Flag, Name) \ 237 if(!(mask & BIT(Flag))) { \ 238 log_err(parser, x_pivot, "the x_pivot parameter `"Name"' is missing.\n");\ 239 res = RES_BAD_ARG; \ 240 goto error; \ 241 } (void)0 242 CHECK_PARAM(TARGET, "target"); 243 #undef CHECK_PARAM 244 245 exit: 246 out_isolpivot->i = isolpivot; 247 return res; 248 error: 249 if(solxpivot) { 250 darray_x_pivot_pop_back(&parser->x_pivots); 251 isolpivot = SIZE_MAX; 252 } 253 goto exit; 254 } 255 256 res_T 257 parse_zx_pivot 258 (struct solparser* parser, 259 yaml_document_t* doc, 260 const yaml_node_t* zx_pivot, 261 struct solparser_pivot_id* out_isolpivot) 262 { 263 enum { SPACING, REF_POINT, TARGET }; 264 struct solparser_zx_pivot* solxzpivot = NULL; 265 size_t isolpivot = SIZE_MAX; 266 int mask = 0; /* Register the parsed attributes */ 267 intptr_t i, n; 268 res_T res = RES_OK; 269 ASSERT(doc && zx_pivot && out_isolpivot); 270 271 if(zx_pivot->type != YAML_MAPPING_NODE) { 272 log_err(parser, zx_pivot, "expect a zx_pivot definition.\n"); 273 res = RES_BAD_ARG; 274 goto error; 275 } 276 277 /* Allocate the solstice pivot */ 278 isolpivot = darray_zx_pivot_size_get(&parser->zx_pivots); 279 res = darray_zx_pivot_resize(&parser->zx_pivots, isolpivot + 1); 280 if(res != RES_OK) { 281 log_err(parser, zx_pivot, "could not allocate the zx_pivot.\n"); 282 res = RES_BAD_ARG; 283 goto error; 284 } 285 solxzpivot = darray_zx_pivot_data_get(&parser->zx_pivots) + isolpivot; 286 287 n = zx_pivot->data.mapping.pairs.top - zx_pivot->data.mapping.pairs.start; 288 solxzpivot->spacing = 0; /* default value */ 289 d3_splat(solxzpivot->ref_point, 0); /* default value */ 290 FOR_EACH(i, 0, n) { 291 yaml_node_t* key; 292 yaml_node_t* val; 293 294 key = yaml_document_get_node(doc, zx_pivot->data.mapping.pairs.start[i].key); 295 val = yaml_document_get_node( 296 doc, zx_pivot->data.mapping.pairs.start[i].value); 297 if(key->type != YAML_SCALAR_NODE) { 298 log_err(parser, key, "expect zx_pivot parameters.\n"); 299 res = RES_BAD_ARG; 300 goto error; 301 } 302 #define SETUP_MASK(Flag, Name) { \ 303 if(mask & BIT(Flag)) { \ 304 log_err(parser, key, \ 305 "the zx_pivot parameter `"Name"' is already defined.\n"); \ 306 res = RES_BAD_ARG; \ 307 goto error; \ 308 } \ 309 mask |= BIT(Flag); \ 310 } (void)0 311 if(!strcmp((char*) key->data.scalar.value, "spacing")) { 312 SETUP_MASK(SPACING, "spacing"); 313 res = parse_real(parser, val, 0, DBL_MAX, &solxzpivot->spacing); 314 } else if(!strcmp((char*) key->data.scalar.value, "ref_point")) { 315 SETUP_MASK(REF_POINT, "ref_point"); 316 res = parse_real3( 317 parser, doc, val, -DBL_MAX, DBL_MAX, solxzpivot->ref_point); 318 } else if(!strcmp((char*) key->data.scalar.value, "target")) { 319 struct solparser_pivot_id pivot_id; 320 pivot_id.i = 321 (size_t) (solxzpivot - darray_zx_pivot_cdata_get(&parser->zx_pivots)); 322 SETUP_MASK(TARGET, "target"); 323 res = parse_target(parser, doc, val, &solxzpivot->target, pivot_id); 324 } else { 325 log_err(parser, key, "unknown zx_pivot parameter `%s'.\n", 326 key->data.scalar.value); 327 res = RES_BAD_ARG; 328 goto error; 329 } 330 if(res != RES_OK) { 331 log_node(parser, key); 332 goto error; 333 } 334 #undef SETUP_MASK 335 } 336 #define CHECK_PARAM(Flag, Name) \ 337 if(!(mask & BIT(Flag))) { \ 338 log_err(parser, zx_pivot, \ 339 "the zx_pivot parameter `"Name"' is missing.\n"); \ 340 res = RES_BAD_ARG; \ 341 goto error; \ 342 } (void)0 343 CHECK_PARAM(TARGET, "target"); 344 #undef CHECK_PARAM 345 346 exit: 347 out_isolpivot->i = isolpivot; 348 return res; 349 error: 350 if(solxzpivot) { 351 darray_zx_pivot_pop_back(&parser->zx_pivots); 352 isolpivot = SIZE_MAX; 353 } 354 goto exit; 355 } 356 357