srcvl.c (12543B)
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 "srcvl.h" 18 19 #include <rsys/cstr.h> 20 #include <rsys/dynamic_array.h> 21 #include <rsys/mem_allocator.h> 22 #include <rsys/ref_count.h> 23 #include <rsys/str.h> 24 25 #include <stdio.h> 26 #include <stdarg.h> 27 #include <yaml.h> 28 29 struct receiver { 30 struct str name; 31 enum srcvl_side side; 32 enum srcvl_pp_output per_primitive_output; 33 }; 34 35 static INLINE void 36 receiver_init(struct mem_allocator* allocator, struct receiver* receiver) 37 { 38 ASSERT(receiver); 39 str_init(allocator, &receiver->name); 40 receiver->side = SRCVL_FRONT_AND_BACK; 41 receiver->per_primitive_output = SRCVL_PP_NONE; 42 } 43 44 static INLINE void 45 receiver_release(struct receiver* receiver) 46 { 47 ASSERT(receiver); 48 str_release(&receiver->name); 49 } 50 51 static INLINE res_T 52 receiver_copy(struct receiver* dst, const struct receiver* src) 53 { 54 ASSERT(dst && src); 55 dst->side = src->side; 56 dst->per_primitive_output = src->per_primitive_output; 57 return str_copy(&dst->name, &src->name); 58 } 59 60 static INLINE res_T 61 receiver_copy_and_release(struct receiver* dst, struct receiver* src) 62 { 63 ASSERT(dst && src); 64 dst->side = src->side; 65 dst->per_primitive_output = src->per_primitive_output; 66 return str_copy_and_release(&dst->name, &src->name); 67 } 68 69 #define DARRAY_NAME receiver 70 #define DARRAY_DATA struct receiver 71 #define DARRAY_FUNCTOR_INIT receiver_init 72 #define DARRAY_FUNCTOR_RELEASE receiver_release 73 #define DARRAY_FUNCTOR_COPY receiver_copy 74 #define DARRAY_FUNCTOR_COPY_AND_RELEASE receiver_copy_and_release 75 #include <rsys/dynamic_array.h> 76 77 struct srcvl { 78 yaml_parser_t parser; 79 int parser_is_init; 80 struct darray_receiver receivers; 81 82 struct str stream_name; 83 84 ref_T ref; 85 struct mem_allocator* allocator; 86 }; 87 88 /******************************************************************************* 89 * Helper functions 90 ******************************************************************************/ 91 static INLINE void 92 log_err 93 (const struct srcvl* srcvl, 94 const yaml_node_t* node, 95 const char* fmt, 96 ...) 97 { 98 va_list vargs_list; 99 ASSERT(srcvl && node && fmt); 100 101 fprintf(stderr, "%s:%lu:%lu: ", 102 str_cget(&srcvl->stream_name), 103 (unsigned long)node->start_mark.line+1, 104 (unsigned long)node->start_mark.column+1); 105 va_start(vargs_list, fmt); 106 vfprintf(stderr, fmt, vargs_list); 107 va_end(vargs_list); 108 } 109 110 static res_T 111 parse_string 112 (struct srcvl* srcvl, 113 yaml_node_t* string, 114 struct str* str) 115 { 116 res_T res = RES_OK; 117 ASSERT(string && str); 118 119 if(string->type != YAML_SCALAR_NODE 120 || !strlen((char*)string->data.scalar.value)) { 121 log_err(srcvl, string, "expect a character string.\n"); 122 res = RES_BAD_ARG; 123 goto error; 124 } 125 res = str_set(str, (char*)string->data.scalar.value); 126 if(res != RES_OK) { 127 log_err(srcvl, string, "could not register the string `%s'.\n", 128 string->data.scalar.value); 129 goto error; 130 } 131 132 exit: 133 return res; 134 error: 135 goto exit; 136 } 137 138 static res_T 139 parse_side 140 (struct srcvl* srcvl, 141 yaml_node_t* side, 142 enum srcvl_side* out_side) 143 { 144 res_T res = RES_OK; 145 ASSERT(side && out_side); 146 147 if(side->type != YAML_SCALAR_NODE) { 148 log_err(srcvl, side, "expect a character string.\n"); 149 res = RES_BAD_ARG; 150 goto error; 151 } 152 153 if(!strcmp((char*)side->data.scalar.value, "FRONT")) { 154 *out_side = SRCVL_FRONT; 155 } else if(!strcmp((char*)side->data.scalar.value, "BACK")) { 156 *out_side = SRCVL_BACK; 157 } else if(!strcmp((char*)side->data.scalar.value, "FRONT_AND_BACK")) { 158 *out_side = SRCVL_FRONT_AND_BACK; 159 } else { 160 log_err(srcvl, side, "unknown side value `%s'.\n", 161 side->data.scalar.value); 162 res = RES_BAD_ARG; 163 goto error; 164 } 165 exit: 166 return res; 167 error: 168 goto exit; 169 } 170 171 static res_T 172 parse_pp_output 173 (struct srcvl* srcvl, 174 yaml_node_t* side, 175 enum srcvl_pp_output* out_side) 176 { 177 res_T res = RES_OK; 178 ASSERT(side && out_side); 179 180 if(side->type != YAML_SCALAR_NODE) { 181 log_err(srcvl, side, "expect a character string.\n"); 182 res = RES_BAD_ARG; 183 goto error; 184 } 185 186 if(!strcmp((char*) side->data.scalar.value, "NONE")) { 187 *out_side = SRCVL_PP_NONE; 188 } else if(!strcmp((char*) side->data.scalar.value, "INCOMING")) { 189 *out_side = SRCVL_PP_INCOMING; 190 } else if(!strcmp((char*) side->data.scalar.value, "ABSORBED")) { 191 *out_side = SRCVL_PP_ABSORBED; 192 } else if(!strcmp((char*) side->data.scalar.value, "INCOMING_AND_ABSORBED")) { 193 *out_side = SRCVL_PP_INCOMING_AND_ABSORBED; 194 } else { 195 log_err(srcvl, side, "unknown per primitive output type value `%s'.\n", 196 side->data.scalar.value); 197 res = RES_BAD_ARG; 198 goto error; 199 } 200 exit: 201 return res; 202 error: 203 goto exit; 204 } 205 206 static res_T 207 parse_receiver 208 (struct srcvl* srcvl, 209 yaml_document_t* doc, 210 const yaml_node_t* receiver) 211 { 212 enum { NAME, PER_PRIMITIVE, SIDE }; 213 struct receiver* solreceiver = NULL; 214 size_t isolreceiver; 215 intptr_t i, n; 216 int mask = 0; /* Register the parsed attributes */ 217 res_T res = RES_OK; 218 ASSERT(srcvl && doc && receiver); 219 220 if(receiver->type != YAML_MAPPING_NODE) { 221 log_err(srcvl, receiver, "expect a receiver definition.\n"); 222 res = RES_BAD_ARG; 223 goto error; 224 } 225 226 /* Allocate the receiver */ 227 isolreceiver = darray_receiver_size_get(&srcvl->receivers); 228 res = darray_receiver_resize(&srcvl->receivers, isolreceiver + 1); 229 if(res != RES_OK) { 230 log_err(srcvl, receiver, "could not allocate the receiver.\n"); 231 goto error; 232 } 233 solreceiver = darray_receiver_data_get(&srcvl->receivers) + isolreceiver; 234 235 n = receiver->data.mapping.pairs.top - receiver->data.mapping.pairs.start; 236 FOR_EACH(i, 0, n) { 237 yaml_node_t* key; 238 yaml_node_t* val; 239 240 key = yaml_document_get_node(doc, receiver->data.mapping.pairs.start[i].key); 241 val = yaml_document_get_node(doc, receiver->data.mapping.pairs.start[i].value); 242 if(key->type != YAML_SCALAR_NODE) { 243 log_err(srcvl, key, "expect receiver parameters.\n"); 244 res = RES_BAD_ARG; 245 goto error; 246 } 247 #define SETUP_MASK(Flag, Name) { \ 248 if(mask & BIT(Flag)) { \ 249 log_err(srcvl, key, "the receiver "Name" is already defined.\n"); \ 250 res = RES_BAD_ARG; \ 251 goto error; \ 252 } \ 253 mask |= BIT(Flag); \ 254 } (void)0 255 if(!strcmp((char*)key->data.scalar.value, "name")) { 256 SETUP_MASK(NAME, "name"); 257 res = parse_string(srcvl, val, &solreceiver->name); 258 } else if(!strcmp((char*)key->data.scalar.value, "side")) { 259 SETUP_MASK(SIDE, "side"); 260 res = parse_side(srcvl, val, &solreceiver->side); 261 } else if(!strcmp((char*)key->data.scalar.value, "per_primitive")) { 262 SETUP_MASK(PER_PRIMITIVE, "per_primitive"); 263 res = parse_pp_output(srcvl, val, &solreceiver->per_primitive_output); 264 } else { 265 log_err(srcvl, key, "unknown receiver parameter `%s'.\n", 266 key->data.scalar.value); 267 res = RES_BAD_ARG; 268 } 269 if(res != RES_OK) goto error; 270 #undef SETUP_MASK 271 } 272 273 if(!(mask & BIT(NAME))) { 274 log_err(srcvl, receiver, "the receiver name is missing.\n"); 275 res = RES_BAD_ARG; 276 goto error; 277 } 278 279 exit: 280 return res; 281 error: 282 if(solreceiver) darray_receiver_pop_back(&srcvl->receivers); 283 goto exit; 284 } 285 286 static void 287 receivers_clear(struct srcvl* srcvl) 288 { 289 ASSERT(srcvl); 290 darray_receiver_clear(&srcvl->receivers); 291 } 292 293 static void 294 receivers_release(ref_T* ref) 295 { 296 struct srcvl* srcvl; 297 ASSERT(ref); 298 srcvl = CONTAINER_OF(ref, struct srcvl, ref); 299 if(srcvl->parser_is_init) yaml_parser_delete(&srcvl->parser); 300 str_release(&srcvl->stream_name); 301 darray_receiver_release(&srcvl->receivers); 302 MEM_RM(srcvl->allocator, srcvl); 303 } 304 305 /******************************************************************************* 306 * Local functions 307 ******************************************************************************/ 308 res_T 309 srcvl_create 310 (struct mem_allocator* allocater, struct srcvl** out_receivers) 311 { 312 struct srcvl* srcvl = NULL; 313 struct mem_allocator* mem_allocator; 314 res_T res = RES_OK; 315 ASSERT(out_receivers); 316 317 mem_allocator = allocater ? allocater : &mem_default_allocator; 318 srcvl = MEM_CALLOC(mem_allocator, 1, sizeof(struct srcvl)); 319 if(!srcvl) { 320 fprintf(stderr, "Could not allocate the loader of the srcvl.\n"); 321 res = RES_MEM_ERR; 322 goto error; 323 } 324 srcvl->allocator = mem_allocator; 325 ref_init(&srcvl->ref); 326 str_init(mem_allocator, &srcvl->stream_name); 327 darray_receiver_init(mem_allocator, &srcvl->receivers); 328 329 exit: 330 *out_receivers = srcvl; 331 return res; 332 error: 333 if(srcvl) { 334 srcvl_ref_put(srcvl); 335 srcvl = NULL; 336 } 337 goto exit; 338 } 339 340 void 341 srcvl_ref_get(struct srcvl* srcvl) 342 { 343 ASSERT(srcvl); 344 ref_get(&srcvl->ref); 345 } 346 347 void 348 srcvl_ref_put(struct srcvl* srcvl) 349 { 350 ASSERT(srcvl); 351 ref_put(&srcvl->ref, receivers_release); 352 } 353 354 res_T 355 srcvl_setup_stream 356 (struct srcvl* srcvl, 357 const char* stream_name, 358 FILE* stream) 359 { 360 res_T res = RES_OK; 361 ASSERT(srcvl && stream); 362 363 if(srcvl->parser_is_init) { 364 yaml_parser_delete(&srcvl->parser); 365 srcvl->parser_is_init = 0; 366 } 367 368 res = str_set(&srcvl->stream_name, stream_name ? stream_name:"<stream>"); 369 if(res != RES_OK) { 370 fprintf(stderr, "Could not register the filename of the receiver stream.\n"); 371 goto error; 372 } 373 if(!yaml_parser_initialize(&srcvl->parser)) { 374 fprintf(stderr, 375 "Could not initialise the YAML parser of the receiver stream.\n"); 376 res = RES_UNKNOWN_ERR; 377 goto error; 378 } 379 srcvl->parser_is_init = 1; 380 yaml_parser_set_input_file(&srcvl->parser, stream); 381 382 exit: 383 return res; 384 error: 385 str_clear(&srcvl->stream_name); 386 if(srcvl->parser_is_init) { 387 yaml_parser_delete(&srcvl->parser); 388 srcvl->parser_is_init = 0; 389 } 390 goto exit; 391 } 392 393 res_T 394 srcvl_load(struct srcvl* srcvl) 395 { 396 yaml_document_t doc; 397 yaml_node_t* root; 398 const char* stream_name; 399 intptr_t i, n; 400 int doc_is_init = 0; 401 res_T res = RES_OK; 402 ASSERT(srcvl); 403 404 stream_name = str_cget(&srcvl->stream_name); 405 receivers_clear(srcvl); /* Clean up previously loaded data */ 406 407 if(!srcvl->parser_is_init) { 408 res = RES_BAD_OP; 409 goto error; 410 } 411 412 if(!yaml_parser_load(&srcvl->parser, &doc)) { 413 fprintf(stderr, "%s:%lu:%lu: %s.\n", 414 stream_name, 415 (unsigned long)srcvl->parser.problem_mark.line+1, 416 (unsigned long)srcvl->parser.problem_mark.column+1, 417 srcvl->parser.problem); 418 yaml_parser_delete(&srcvl->parser); 419 srcvl->parser_is_init = 0; 420 res = RES_BAD_OP; 421 goto error; 422 } 423 doc_is_init = 1; 424 425 root = yaml_document_get_root_node(&doc); 426 if(!root) { 427 yaml_parser_delete(&srcvl->parser); 428 srcvl->parser_is_init = 0; 429 res = RES_BAD_OP; 430 goto error; 431 } 432 433 if(root->type != YAML_SEQUENCE_NODE) { 434 log_err(srcvl, root, "expect a list of srcvl.\n"); 435 res = RES_BAD_ARG; 436 goto error; 437 } 438 439 n = root->data.sequence.items.top - root->data.sequence.items.start; 440 FOR_EACH(i, 0, n) { 441 yaml_node_t* receiver; 442 443 receiver = yaml_document_get_node(&doc, root->data.sequence.items.start[i]); 444 res = parse_receiver(srcvl, &doc, receiver); 445 if(res != RES_OK) goto error; 446 } 447 exit: 448 if(doc_is_init) yaml_document_delete(&doc); 449 return res; 450 error: 451 receivers_clear(srcvl); 452 goto exit; 453 } 454 455 size_t 456 srcvl_count(const struct srcvl* srcvl) 457 { 458 ASSERT(srcvl); 459 return darray_receiver_size_get(&srcvl->receivers); 460 } 461 462 void 463 srcvl_get 464 (const struct srcvl* srcvl, 465 const size_t i, 466 struct srcvl_receiver* receiver) 467 { 468 const struct receiver* r; 469 ASSERT(srcvl && receiver && i < srcvl_count(srcvl)); 470 r = darray_receiver_cdata_get(&srcvl->receivers) + i; 471 receiver->name = str_cget(&r->name); 472 receiver->side = r->side; 473 receiver->per_primitive_output = r->per_primitive_output; 474 } 475