1 /* 2 * This file is part of libmodulemd 3 * Copyright (C) 2017-2020 Stephen Gallagher 4 * 5 * Fedora-License-Identifier: MIT 6 * SPDX-2.0-License-Identifier: MIT 7 * SPDX-3.0-License-Identifier: MIT 8 * 9 * This program is free software. 10 * For more information on the license, see COPYING. 11 * For more information on free software, see <https://www.gnu.org/philosophy/free-sw.en.html>. 12 */ 13 14 #pragma once 15 16 #include <glib.h> 17 #include <yaml.h> 18 19 #include "modulemd-errors.h" 20 #include "modulemd-service-level.h" 21 #include "modulemd-subdocument-info.h" 22 #include "private/modulemd-util.h" 23 24 G_BEGIN_DECLS 25 26 27 /** 28 * SECTION: modulemd-yaml 29 * @title: YAML Manipulation Tools 30 * @stability: private 31 * @short_description: Provides private YAML utilities for internal use. 32 */ 33 34 35 /** 36 * ModulemdYamlDocumentTypeEnum: 37 * @MODULEMD_YAML_DOC_UNKNOWN: Represents an unknown YAML document type. 38 * @MODULEMD_YAML_DOC_MODULESTREAM: Represents a `modulemd` (see 39 * #ModulemdModuleStream) YAML document type. 40 * @MODULEMD_YAML_DOC_DEFAULTS: Represents a `modulemd-defaults` (see 41 * #ModulemdDefaultsV1) YAML document type. 42 * @MODULEMD_YAML_DOC_TRANSLATIONS: Represents a `modulemd-translations` (see 43 * #ModulemdTranslation) YAML document type. 44 * @MODULEMD_YAML_DOC_PACKAGER: Represents a `modulemd-packager` document. 45 * V2 is a subset of #ModulemdModuleStreamV2 containing only the attributes that a 46 * package maintainer should modify. V3 (see #ModulemdPackagerV3) is a new YAML 47 * document type. Since: 2.9 48 * @MODULEMD_YAML_DOC_OBSOLETES: Represents a `modulemd-obsoletes` document (see 49 * #ModulemdObsoletes) YAML document type. Since: 2.10 50 * 51 * Since: 2.0 52 */ 53 typedef enum 54 { 55 MODULEMD_YAML_DOC_UNKNOWN = 0, 56 MODULEMD_YAML_DOC_MODULESTREAM, 57 MODULEMD_YAML_DOC_DEFAULTS, 58 MODULEMD_YAML_DOC_TRANSLATIONS, 59 MODULEMD_YAML_DOC_PACKAGER, 60 MODULEMD_YAML_DOC_OBSOLETES 61 } ModulemdYamlDocumentTypeEnum; 62 63 /** 64 * modulemd_yaml_string: 65 * @str: A pointer to a block of memory containing YAML. 66 * @len: The number of bytes currently in use in @str. 67 * 68 * #modulemd_yaml_string is an internal representation of an arbitrary length 69 * YAML string. 70 * 71 * Since: 2.0 72 */ 73 typedef struct _modulemd_yaml_string 74 { 75 char *str; 76 size_t len; 77 } modulemd_yaml_string; 78 79 /** 80 * write_yaml_string: 81 * @data: (inout): A void pointer to a #modulemd_yaml_string object. 82 * @buffer: (in): YAML text to append to @data. 83 * @size: (in): The number of bytes from @buffer to append to @data. 84 * 85 * Additionally memory for @data is automatically allocated if necessary. 86 * 87 * Since: 2.0 88 */ 89 int 90 write_yaml_string (void *data, unsigned char *buffer, size_t size); 91 92 /** 93 * modulemd_yaml_string_free: 94 * @yaml_string: (inout): A pointer to a #modulemd_yaml_string to be freed. 95 * 96 * Since: 2.0 97 */ 98 void 99 modulemd_yaml_string_free (modulemd_yaml_string *yaml_string); 100 101 G_DEFINE_AUTOPTR_CLEANUP_FUNC (FILE, fclose); 102 103 G_DEFINE_AUTOPTR_CLEANUP_FUNC (modulemd_yaml_string, 104 modulemd_yaml_string_free); 105 106 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (yaml_event_t, yaml_event_delete); 107 108 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (yaml_parser_t, yaml_parser_delete); 109 110 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (yaml_emitter_t, yaml_emitter_delete); 111 112 /** 113 * mmd_yaml_get_event_name: 114 * @type: (in): A libyaml event type. 115 * 116 * Returns: The string representation for @type. 117 * 118 * Since: 2.0 119 */ 120 const gchar * 121 mmd_yaml_get_event_name (yaml_event_type_t type); 122 123 /** 124 * MMD_INIT_YAML_PARSER: 125 * @_parser: (out): A variable name to use for the new parser object. 126 * 127 * This convenience macro allocates and initializes a new libyaml parser object 128 * named @_parser. 129 * 130 * Since: 2.0 131 */ 132 #define MMD_INIT_YAML_PARSER(_parser) \ 133 g_auto (yaml_parser_t) _parser; \ 134 yaml_parser_initialize (&_parser) 135 136 /** 137 * MMD_INIT_YAML_EMITTER: 138 * @_emitter: (out): A variable name to use for the new emitter object. 139 * 140 * This convenience macro allocates and initializes a new libyaml emitter 141 * object named @_emitter. 142 * 143 * Since: 2.0 144 */ 145 #define MMD_INIT_YAML_EMITTER(_emitter) \ 146 g_auto (yaml_emitter_t) _emitter; \ 147 yaml_emitter_initialize (&_emitter) 148 149 /** 150 * MMD_INIT_YAML_EVENT: 151 * @_event: (out): A variable name to use for the new event object. 152 * 153 * This convenience macro allocates and initializes a new libyaml event object 154 * named @_event. 155 * 156 * Since: 2.0 157 */ 158 #define MMD_INIT_YAML_EVENT(_event) \ 159 g_auto (yaml_event_t) _event; \ 160 memset (&(_event), 0, sizeof (yaml_event_t)) 161 162 /** 163 * MMD_INIT_YAML_STRING: 164 * @_emitter: (inout): A libyaml emitter object. 165 * @_string: (out): A variable name to use for the new yaml string object. 166 * 167 * This convenience macro allocates and initializes a new yaml string object 168 * named @_string and associates it as the output target for the libyaml 169 * emitter object @_emitter. 170 * 171 * Since: 2.0 172 */ 173 #define MMD_INIT_YAML_STRING(_emitter, _string) \ 174 g_autoptr (modulemd_yaml_string) _string = \ 175 g_malloc0_n (1, sizeof (modulemd_yaml_string)); \ 176 yaml_emitter_set_output (_emitter, write_yaml_string, (void *)_string) 177 178 /** 179 * MMD_REINIT_YAML_STRING: 180 * @_emitter: (inout): A libyaml emitter object to reinitialize. 181 * @_string: (inout): A variable name to reinitialize with a new yaml string 182 * object. 183 * 184 * This convenience macro deletes then initializes a new libyaml emitter named 185 * @_emitter, then deletes, reallocates, and initializes a new yaml string 186 * object named @_string and associates it as the output target for @_emitter. 187 * 188 * Since: 2.0 189 */ 190 #define MMD_REINIT_YAML_STRING(_emitter, _string) \ 191 yaml_emitter_delete (_emitter); \ 192 yaml_emitter_initialize (_emitter); \ 193 g_clear_pointer (&_string, modulemd_yaml_string_free); \ 194 _string = g_malloc0_n (1, sizeof (modulemd_yaml_string)); \ 195 yaml_emitter_set_output (_emitter, write_yaml_string, (void *)_string) 196 197 /** 198 * YAML_PARSER_PARSE_WITH_EXIT_FULL: 199 * @_parser: (inout): A libyaml parser object positioned at the beginning of an 200 * event. 201 * @_returnval: (in): The value to return in case of a parsing error. 202 * @_event: (out): Returns the libyaml event that was parsed. 203 * @_error: (out): A #GError that will return the reason for a parsing or 204 * validation error. 205 * 206 * DIRECT USE OF THIS MACRO SHOULD BE AVOIDED. This is the internal 207 * implementation for %YAML_PARSER_PARSE_WITH_EXIT_BOOL, 208 * %YAML_PARSER_PARSE_WITH_EXIT_INT, and %YAML_PARSER_PARSE_WITH_EXIT which 209 * should be used instead. 210 * 211 * Returns: Continues on if parsing of the event was successful. Returns 212 * @_returnval if a parse error occurred and sets @_error appropriately. 213 * 214 * Since: 2.0 215 */ 216 #define YAML_PARSER_PARSE_WITH_EXIT_FULL(_parser, _returnval, _event, _error) \ 217 do \ 218 { \ 219 if (!yaml_parser_parse (_parser, _event)) \ 220 { \ 221 g_debug ("Parser error"); \ 222 g_set_error_literal (_error, \ 223 MODULEMD_YAML_ERROR, \ 224 MMD_YAML_ERROR_UNPARSEABLE, \ 225 "Parser error"); \ 226 return _returnval; \ 227 } \ 228 if ((_event)->type == YAML_SCALAR_EVENT) \ 229 g_debug ("Parser event: %s: %s", \ 230 mmd_yaml_get_event_name ((_event)->type), \ 231 (const gchar *)event.data.scalar.value); \ 232 else \ 233 { \ 234 g_debug ("Parser event: %s", \ 235 mmd_yaml_get_event_name ((_event)->type)); \ 236 } \ 237 } \ 238 while (0) 239 240 /** 241 * YAML_PARSER_PARSE_WITH_EXIT_BOOL: 242 * @_parser: (inout): A libyaml parser object positioned at the beginning of an 243 * event. 244 * @_event: (out): Returns the libyaml event that was parsed. 245 * @_error: (out): A #GError that will return the reason for a parsing or 246 * validation error. 247 * 248 * Returns: Continues on if parsing of the event was successful. Returns 249 * FALSE if a parse error occurred and sets @_error appropriately. 250 * 251 * Since: 2.0 252 */ 253 #define YAML_PARSER_PARSE_WITH_EXIT_BOOL(_parser, _event, _error) \ 254 YAML_PARSER_PARSE_WITH_EXIT_FULL (_parser, FALSE, _event, _error) 255 256 /** 257 * YAML_PARSER_PARSE_WITH_EXIT_INT: 258 * @_parser: (inout): A libyaml parser object positioned at the beginning of an 259 * event. 260 * @_event: (out): Returns the libyaml event that was parsed. 261 * @_error: (out): A #GError that will return the reason for a parsing or 262 * validation error. 263 * 264 * Returns: Continues on if parsing of the event was successful. Returns 265 * 0 if a parse error occurred and sets @_error appropriately. 266 * 267 * Since: 2.0 268 */ 269 #define YAML_PARSER_PARSE_WITH_EXIT_INT(_parser, _event, _error) \ 270 YAML_PARSER_PARSE_WITH_EXIT_FULL (_parser, 0, _event, _error) 271 272 /** 273 * YAML_PARSER_PARSE_WITH_EXIT: 274 * @_parser: (inout): A libyaml parser object positioned at the beginning of an 275 * event. 276 * @_event: (out): Returns the libyaml event that was parsed. 277 * @_error: (out): A #GError that will return the reason for a parsing or 278 * validation error. 279 * 280 * Returns: Continues on if parsing of the event was successful. Returns 281 * NULL if a parse error occurred and sets @_error appropriately. 282 * 283 * Since: 2.0 284 */ 285 #define YAML_PARSER_PARSE_WITH_EXIT(_parser, _event, _error) \ 286 YAML_PARSER_PARSE_WITH_EXIT_FULL (_parser, NULL, _event, _error) 287 288 289 /** 290 * MMD_EMIT_WITH_EXIT_FULL: 291 * @_emitter: (inout): A libyaml emitter object positioned where @_event 292 * belongs in the YAML document. 293 * @_returnval: (in): The value to return in case of an output error. 294 * @_event: (in): The libyaml event to be emitted. 295 * @_error: (out): A #GError that will return the reason for an output error. 296 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 297 * @_error in case of failure. 298 * 299 * DIRECT USE OF THIS MACRO SHOULD BE AVOIDED. This is the internal 300 * implementation for %MMD_EMIT_WITH_EXIT and %MMD_EMIT_WITH_EXIT_PTR which 301 * should be used instead. 302 * 303 * Returns: Continues on if emitting of the event was successful. Returns 304 * @_returnval if an output error occurred and sets @_error appropriately. 305 * 306 * Since: 2.0 307 */ 308 #define MMD_EMIT_WITH_EXIT_FULL(_emitter, _returnval, _event, _error, ...) \ 309 do \ 310 { \ 311 int _ret; \ 312 g_debug ("Emitter event: %s", \ 313 mmd_yaml_get_event_name ((_event)->type)); \ 314 _ret = yaml_emitter_emit (_emitter, _event); \ 315 (_event)->type = 0; \ 316 if (!_ret) \ 317 { \ 318 g_debug (__VA_ARGS__); \ 319 g_set_error ( \ 320 _error, MODULEMD_YAML_ERROR, MMD_YAML_ERROR_EMIT, __VA_ARGS__); \ 321 return _returnval; \ 322 } \ 323 } \ 324 while (0) 325 326 /** 327 * MMD_EMIT_WITH_EXIT: 328 * @_emitter: (inout): A libyaml emitter object positioned where @_event 329 * belongs in the YAML document. 330 * @_event: (in): The libyaml event to be emitted. 331 * @_error: (out): A #GError that will return the reason for an output error. 332 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 333 * @_error in case of failure. 334 * 335 * Returns: Continues on if emitting of the event was successful. Returns 336 * FALSE if an output error occurred and sets @_error appropriately. 337 * 338 * Since: 2.0 339 */ 340 #define MMD_EMIT_WITH_EXIT(_emitter, _event, _error, ...) \ 341 MMD_EMIT_WITH_EXIT_FULL (_emitter, FALSE, _event, _error, __VA_ARGS__) 342 343 /** 344 * MMD_EMIT_WITH_EXIT_PTR: 345 * @_emitter: (inout): A libyaml emitter object positioned where @_event 346 * belongs in the YAML document. 347 * @_event: (in): The libyaml event to be emitted. 348 * @_error: (out): A #GError that will return the reason for an output error. 349 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 350 * @_error in case of failure. 351 * 352 * Returns: Continues on if emitting of the event was successful. Returns 353 * NULL if an output error occurred and sets @_error appropriately. 354 * 355 * Since: 2.0 356 */ 357 #define MMD_EMIT_WITH_EXIT_PTR(_emitter, _event, _error, ...) \ 358 MMD_EMIT_WITH_EXIT_FULL (_emitter, NULL, _event, _error, __VA_ARGS__) 359 360 /** 361 * MMD_YAML_ERROR_EVENT_EXIT_FULL: 362 * @_error: (out): A #GError that will return the reason for the error. 363 * @_errorcode: (in): The exact error code that should be set on @_error. 364 * @_event: (in): The libyaml event for which an error is to be reported. 365 * @_returnval: (in): The error value to return. 366 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 367 * @_error. 368 * 369 * DIRECT USE OF THIS MACRO SHOULD BE AVOIDED. This is the internal 370 * implementation for %MMD_YAML_ERROR_EVENT_EXIT, 371 * %MMD_YAML_ERROR_EVENT_EXIT_BOOL, and %MMD_YAML_ERROR_EVENT_EXIT_INT which 372 * should be used instead. 373 * 374 * Returns: Returns @_returnval and sets @_error appropriately. 375 * 376 * Since: 2.0 377 */ 378 #define MMD_YAML_ERROR_EVENT_EXIT_FULL( \ 379 _error, _errorcode, _event, _returnval, ...) \ 380 do \ 381 { \ 382 g_autofree gchar *formatted = g_strdup_printf (__VA_ARGS__); \ 383 g_autofree gchar *formatted2 = \ 384 g_strdup_printf ("%s [line %zu col %zu]", \ 385 formatted, \ 386 _event.start_mark.line + 1, \ 387 _event.start_mark.column + 1); \ 388 g_debug ("%s", formatted2); \ 389 g_set_error ( \ 390 _error, MODULEMD_YAML_ERROR, _errorcode, "%s", formatted2); \ 391 return _returnval; \ 392 } \ 393 while (0) 394 395 /** 396 * MMD_YAML_ERROR_EVENT_EXIT: 397 * @_error: (out): A #GError that will return the reason for the error. 398 * @_event: (in): The libyaml event for which an error is to be reported. 399 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 400 * @_error. 401 * 402 * Returns: Returns NULL and sets @_error appropriately. 403 * 404 * Since: 2.0 405 */ 406 #define MMD_YAML_ERROR_EVENT_EXIT(_error, _event, ...) \ 407 MMD_YAML_ERROR_EVENT_EXIT_FULL ( \ 408 _error, MMD_YAML_ERROR_PARSE, _event, NULL, __VA_ARGS__) 409 410 /** 411 * MMD_YAML_ERROR_EVENT_EXIT_BOOL: 412 * @_error: (out): A #GError that will return the reason for the error. 413 * @_event: (in): The libyaml event for which an error is to be reported. 414 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 415 * @_error. 416 * 417 * Returns: Returns FALSE and sets @_error appropriately. 418 * 419 * Since: 2.0 420 */ 421 #define MMD_YAML_ERROR_EVENT_EXIT_BOOL(_error, _event, ...) \ 422 MMD_YAML_ERROR_EVENT_EXIT_FULL ( \ 423 _error, MMD_YAML_ERROR_PARSE, _event, FALSE, __VA_ARGS__) 424 425 /** 426 * MMD_YAML_ERROR_EVENT_EXIT_INT: 427 * @_error: (out): A #GError that will return the reason for the error. 428 * @_event: (in): The libyaml event for which an error is to be reported. 429 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 430 * @_error. 431 * 432 * Returns: Returns 0 and sets @_error appropriately. 433 * 434 * Since: 2.0 435 */ 436 #define MMD_YAML_ERROR_EVENT_EXIT_INT(_error, _event, ...) \ 437 MMD_YAML_ERROR_EVENT_EXIT_FULL ( \ 438 _error, MMD_YAML_ERROR_PARSE, _event, 0, __VA_ARGS__) 439 440 /** 441 * MMD_SET_PARSED_YAML_STRING: 442 * @_parser: (inout): A libyaml parser object positioned at the beginning of an 443 * expected string event. 444 * @_error: (out): A #GError that will return the reason for a parsing or 445 * validation error. 446 * @_fn: (in): A setter method for a property of object @_obj to be called with 447 * the successfully parsed string. 448 * @_obj: (inout): The object that is to store the parsed string via its @_fn 449 * setter method. 450 * 451 * This convenience macro can be used when a YAML string (scalar) event is 452 * expected, and that string is to be stored in a property of libmodulemd 453 * object @_obj via setter method @_fn. 454 * 455 * Returns: Continues on if parsing of the event was successful. Returns 456 * NULL if a parse error occurred and sets @_error appropriately. 457 * 458 * Since: 2.0 459 */ 460 #define MMD_SET_PARSED_YAML_STRING(_parser, _error, _fn, _obj) \ 461 do \ 462 { \ 463 GError *_nested_error = NULL; \ 464 g_autofree gchar *_scalar = \ 465 modulemd_yaml_parse_string (_parser, &_nested_error); \ 466 if (!_scalar) \ 467 { \ 468 g_propagate_error (_error, _nested_error); \ 469 return NULL; \ 470 } \ 471 _fn (_obj, _scalar); \ 472 g_clear_pointer (&_scalar, g_free); \ 473 } \ 474 while (0) 475 476 /** 477 * mmd_emitter_start_stream: 478 * @emitter: (inout): A libyaml emitter object that will be positioned at the 479 * beginning of a new YAML output stream. 480 * @error: (out): A #GError that will return the reason for any error. 481 * 482 * Returns: TRUE if the YAML stream was started successfully. Returns FALSE if 483 * an error occurred and sets @error appropriately. 484 * 485 * Since: 2.0 486 */ 487 gboolean 488 mmd_emitter_start_stream (yaml_emitter_t *emitter, GError **error); 489 490 /** 491 * mmd_emitter_end_stream: 492 * @emitter: (inout): A libyaml emitter object that is positioned at the end of 493 * a YAML output stream to be closed. 494 * @error: (out): A #GError that will return the reason for any error. 495 * 496 * Returns: TRUE if the YAML stream was closed successfully. Returns FALSE if 497 * an error occurred and sets @error appropriately. 498 * 499 * Since: 2.0 500 */ 501 gboolean 502 mmd_emitter_end_stream (yaml_emitter_t *emitter, GError **error); 503 504 505 /** 506 * mmd_emitter_start_document: 507 * @emitter: (inout): A libyaml emitter object that is positioned at the start 508 * of where a new YAML document will be written. 509 * @error: (out): A #GError that will return the reason for any error. 510 * 511 * Emits a YAML document start header line. 512 * 513 * Returns: TRUE if the YAML document was started successfully. Returns FALSE 514 * if an error occurred and sets @error appropriately. 515 * 516 * Since: 2.0 517 */ 518 gboolean 519 mmd_emitter_start_document (yaml_emitter_t *emitter, GError **error); 520 521 /** 522 * mmd_emitter_end_document: 523 * @emitter: (inout): A libyaml emitter object that is positioned at the start 524 * of where a YAML document terminator will be written. 525 * @error: (out): A #GError that will return the reason for any error. 526 * 527 * Emits a YAML document termination line. 528 * 529 * Returns: TRUE if the YAML document was terminated successfully. Returns 530 * FALSE if an error occurred and sets @error appropriately. 531 * 532 * Since: 2.0 533 */ 534 gboolean 535 mmd_emitter_end_document (yaml_emitter_t *emitter, GError **error); 536 537 538 /** 539 * mmd_emitter_start_mapping: 540 * @emitter: (inout): A libyaml emitter object that is positioned at the start 541 * of where a new mapping will be written. 542 * @style: (in): The YAML mapping style for the output. 543 * @error: (out): A #GError that will return the reason for any error. 544 * 545 * Returns: TRUE if the YAML mapping was started successfully. Returns FALSE if 546 * an error occurred and sets @error appropriately. 547 * 548 * Since: 2.0 549 */ 550 gboolean 551 mmd_emitter_start_mapping (yaml_emitter_t *emitter, 552 yaml_mapping_style_t style, 553 GError **error); 554 555 /** 556 * mmd_emitter_end_mapping: 557 * @emitter: (inout): A libyaml emitter object that is positioned at the start 558 * of where a mapping ending will be written. 559 * @error: (out): A #GError that will return the reason for any error. 560 * 561 * Returns: TRUE if the YAML mapping was ended successfully. Returns FALSE if 562 * an error occurred and sets @error appropriately. 563 * 564 * Since: 2.0 565 */ 566 gboolean 567 mmd_emitter_end_mapping (yaml_emitter_t *emitter, GError **error); 568 569 570 /** 571 * mmd_emitter_start_sequence: 572 * @emitter: (inout): A libyaml emitter object that is positioned at the start 573 * of where a new sequence will be written. 574 * @style: (in): The YAML sequence style for the output. 575 * @error: (out): A #GError that will return the reason for any error. 576 * 577 * Returns: TRUE if the YAML sequence was started successfully. Returns FALSE 578 * if an error occurred and sets @error appropriately. 579 * 580 * Since: 2.0 581 */ 582 gboolean 583 mmd_emitter_start_sequence (yaml_emitter_t *emitter, 584 yaml_sequence_style_t style, 585 GError **error); 586 587 /** 588 * mmd_emitter_end_sequence: 589 * @emitter: (inout): A libyaml emitter object that is positioned at the start 590 * of where a sequence ending will be written. 591 * @error: (out): A #GError that will return the reason for any error. 592 * 593 * Returns: TRUE if the YAML sequence was ended successfully. Returns FALSE if 594 * an error occurred and sets @error appropriately. 595 * 596 * Since: 2.0 597 */ 598 gboolean 599 mmd_emitter_end_sequence (yaml_emitter_t *emitter, GError **error); 600 601 602 /** 603 * mmd_emitter_scalar: 604 * @emitter: (inout): A libyaml emitter object that is positioned at the start 605 * of where a scalar will be written. 606 * @scalar: (in): The scalar (string) to be written. 607 * @style: (in): The YAML scalar style for the output. 608 * @error: (out): A #GError that will return the reason for any error. 609 * 610 * Returns: TRUE if the YAML scalar was written successfully. Returns FALSE if 611 * an error occurred and sets @error appropriately. 612 * 613 * Since: 2.0 614 */ 615 gboolean 616 mmd_emitter_scalar (yaml_emitter_t *emitter, 617 const gchar *scalar, 618 yaml_scalar_style_t style, 619 GError **error); 620 621 622 /** 623 * mmd_emitter_strv: 624 * @emitter: (inout): A libyaml emitter object positioned at the start of where 625 * a string sequence will be written. 626 * @seq_style: (in): The YAML sequence style for the output. 627 * @list: (in): A list that will be emitted to the YAML emitter. 628 * @error: (out): A #GError that will return the reason for an emitting error. 629 * 630 * Returns: TRUE if the sequence emitted successfully. FALSE if an error was 631 * encountered and sets @error appropriately. 632 * 633 * Since: 2.0 634 */ 635 gboolean 636 mmd_emitter_strv (yaml_emitter_t *emitter, 637 yaml_sequence_style_t seq_style, 638 GStrv list, 639 GError **error); 640 641 642 /** 643 * modulemd_yaml_parse_date: 644 * @parser: (inout): A libyaml parser object positioned at the beginning of a 645 * date (YYYY-MM-DD) scalar entry. 646 * @error: (out): A #GError that will return the reason for a parsing or 647 * validation error. 648 * 649 * Returns: (transfer full): A newly-allocated #GDate representing the parsed 650 * value. NULL if a parse or validation error occurred and sets @error 651 * appropriately. 652 * 653 * Since: 2.0 654 */ 655 GDate * 656 modulemd_yaml_parse_date (yaml_parser_t *parser, GError **error); 657 658 659 /** 660 * modulemd_yaml_parse_string: 661 * @parser: (inout): A libyaml parser object positioned at the beginning of a 662 * string scalar entry. 663 * @error: (out): A #GError that will return the reason for a parsing or 664 * validation error. 665 * 666 * Returns: (transfer full): A newly-allocated `gchar *` representing the 667 * parsed value. NULL if a parse error occurred and sets @error appropriately. 668 * 669 * Since: 2.0 670 */ 671 gchar * 672 modulemd_yaml_parse_string (yaml_parser_t *parser, GError **error); 673 674 675 /** 676 * modulemd_yaml_parse_bool: 677 * @parser: (inout): A libyaml parser object positioned at the beginning of a 678 * boolean scalar entry. 679 * @error: (out): A #GError that will return the reason for a parsing or 680 * validation error. 681 * 682 * Returns: A boolean representing the parsed value. Returns FALSE if a parse 683 * error occurred and sets @error appropriately. 684 * 685 * Since: 2.2 686 */ 687 gboolean 688 modulemd_yaml_parse_bool (yaml_parser_t *parser, GError **error); 689 690 691 /** 692 * modulemd_yaml_parse_int64: 693 * @parser: (inout): A libyaml parser object positioned at the beginning of a 694 * int64 scalar entry. 695 * @error: (out): A #GError that will return the reason for a parsing or 696 * validation error. 697 * 698 * Returns: (transfer full): A 64-bit signed integer representing the parsed 699 * value. Returns 0 if a parse error occurred and sets @error appropriately. 700 * 701 * Since: 2.0 702 */ 703 gint64 704 modulemd_yaml_parse_int64 (yaml_parser_t *parser, GError **error); 705 706 707 /** 708 * modulemd_yaml_parse_uint64: 709 * @parser: (inout): A libyaml parser object positioned at the beginning of a 710 * uint64 scalar entry. 711 * @error: (out): A #GError that will return the reason for a parsing or 712 * validation error. 713 * 714 * Returns: (transfer full): A 64-bit unsigned integer representing the parsed 715 * value. Returns 0 if a parse error occurred and sets @error appropriately. 716 * 717 * Since: 2.0 718 */ 719 guint64 720 modulemd_yaml_parse_uint64 (yaml_parser_t *parser, GError **error); 721 722 723 /** 724 * modulemd_yaml_parse_string_set: 725 * @parser: (inout): A libyaml parser object positioned at the beginning of a 726 * sequence with string scalars. 727 * @error: (out): A #GError that will return the reason for a parsing or 728 * validation error. 729 * 730 * Returns: (transfer full): A newly-allocated #GHashTable * representing the 731 * parsed value. All parsed sequence entries are added as keys in the 732 * hashtable. NULL if a parse error occurred and sets @error appropriately. 733 * 734 * Since: 2.0 735 */ 736 GHashTable * 737 modulemd_yaml_parse_string_set (yaml_parser_t *parser, GError **error); 738 739 740 /** 741 * modulemd_yaml_parse_string_set_from_map: 742 * @parser: (inout): A libyaml parser object positioned at the beginning of a 743 * map containing a single key which is a sequence with string scalars. 744 * @key: (in): The key in a single-key mapping whose contents should be 745 * returned as a string set. 746 * @strict: (in): Whether the parser should return failure if it encounters an 747 * unknown mapping key or if it should ignore it. 748 * @error: (out): A #GError that will return the reason for a parsing or 749 * validation error. 750 * 751 * Function for retrieving a string set from a single-key map such as 752 * data.artifacts, data.api or data.filter from a module stream document. 753 * 754 * Returns: (transfer full): A newly-allocated #GHashTable * representing the 755 * parsed values. All parsed sequence entries are added as keys in the 756 * hashtable. NULL if a parse error occurred and sets @error appropriately. 757 * 758 * Since: 2.0 759 */ 760 GHashTable * 761 modulemd_yaml_parse_string_set_from_map (yaml_parser_t *parser, 762 const gchar *key, 763 gboolean strict, 764 GError **error); 765 766 767 /** 768 * modulemd_yaml_parse_string_string_map: 769 * @parser: (inout): A libyaml parser object positioned at the beginning of a 770 * map containing a scalar/scalar key/value pairs. 771 * @error: (out): A #GError that will return the reason for a parsing or 772 * validation error. 773 * 774 * Function for retrieving a hash table from a str/str map such as 775 * data.dependencies in ModuleStreamV1. 776 * 777 * Returns: (transfer full): A newly-allocated #GHashTable * representing the 778 * parsed values. NULL if a parse error occurred and sets @error appropriately. 779 * 780 * Since: 2.0 781 */ 782 GHashTable * 783 modulemd_yaml_parse_string_string_map (yaml_parser_t *parser, GError **error); 784 785 786 /** 787 * modulemd_yaml_parse_nested_set: 788 * @parser: (inout): A libyaml parser object positioned at the beginning of a 789 * map containing scalar keys with string set values. 790 * @error: (out): A #GError that will return the reason for a parsing or 791 * validation error. 792 * 793 * Function for retrieving a hash table from a str/string-set map such as 794 * data.dependencies in #ModulemdModuleStreamV2. 795 * 796 * Returns: (transfer full): A newly-allocated #GHashTable * representing the 797 * parsed values. NULL if a parse error occurred and sets @error appropriately. 798 * 799 * Since: 2.10 800 */ 801 GHashTable * 802 modulemd_yaml_parse_nested_set (yaml_parser_t *parser, GError **error); 803 804 /** 805 * modulemd_yaml_emit_nested_set: 806 * @emitter: (inout): A libyaml emitter object that is positioned where a nested 807 * set (a map containing scalar keys with string set values) should occur. 808 * @table: (in): The nested set to emit. 809 * @error: (out): A #GError that will return the reason for failing to emit. 810 * 811 * Returns: TRUE if the nested set emitted successfully. FALSE if an error was 812 * encountered and sets @error appropriately. 813 * 814 * Since: 2.10 815 */ 816 gboolean 817 modulemd_yaml_emit_nested_set (yaml_emitter_t *emitter, 818 GHashTable *table, 819 GError **error); 820 821 /** 822 * modulemd_yaml_parse_document_type: 823 * @parser: (inout): A libyaml parser object positioned at the beginning of a 824 * yaml subdocument immediately prior to a `YAML_DOCUMENT_START_EVENT`. 825 * 826 * Reads through a YAML subdocument to retrieve the document type, metadata 827 * version and the data section. 828 * 829 * Returns: (transfer full): A #ModulemdSubdocumentInfo with information on 830 * the parse results. 831 * 832 * Since: 2.0 833 */ 834 ModulemdSubdocumentInfo * 835 modulemd_yaml_parse_document_type (yaml_parser_t *parser); 836 837 838 /** 839 * modulemd_yaml_emit_document_headers: 840 * @emitter: (inout): A libyaml emitter object that is positioned where the 841 * `YAML_DOCUMENT_START_EVENT` should occur (so this must be after either a 842 * `YAML_STREAM_START_EVENT` or `YAML_DOCUMENT_END_EVENT`). 843 * @doctype: (in): The document type (see #ModulemdYamlDocumentTypeEnum) 844 * @mdversion: (in): The metadata version for this document 845 * @error: (out): A #GError that will return the reason for failing to emit. 846 * 847 * Creates the YAML header and returns @emitter positioned just before the 848 * `YAML_MAPPING_START` for the "data:" section. 849 * 850 * Returns: TRUE if the document emitted successfully. FALSE if an error was 851 * encountered and sets @error appropriately. 852 * 853 * Since: 2.0 854 */ 855 gboolean 856 modulemd_yaml_emit_document_headers (yaml_emitter_t *emitter, 857 ModulemdYamlDocumentTypeEnum doctype, 858 guint64 mdversion, 859 GError **error); 860 861 862 /** 863 * modulemd_yaml_emit_variant: 864 * @emitter: (inout): A libyaml emitter object that is positioned where the 865 * variant should occur. 866 * @variant: (in): The variant to emit. It must be either a boolean, string, 867 * array or dictionary. 868 * @error: (out): A #GError that will return the reason for failing to emit. 869 * 870 * Returns: TRUE if the variant emitted successfully. FALSE if an error was 871 * encountered and sets @error appropriately. 872 * 873 * Since: 2.0 874 */ 875 gboolean 876 modulemd_yaml_emit_variant (yaml_emitter_t *emitter, 877 GVariant *variant, 878 GError **error); 879 880 881 /** 882 * mmd_variant_from_scalar: 883 * @scalar: (in): A string or boolean value to read into a #GVariant 884 * 885 * Returns: (transfer full): A new, floating #GVariant representing a string 886 * or boolean value matching the scalar passed in. 887 * 888 * Since: 2.0 889 */ 890 GVariant * 891 mmd_variant_from_scalar (const gchar *scalar); 892 893 894 /** 895 * mmd_variant_from_mapping: 896 * @parser: (inout): A YAML parser positioned just after a `MAPPING_START` 897 * @error: (out): A #GError that will return the reason for failing to parse. 898 * 899 * Returns: (transfer full): A new, floating #GVariant representing a hash 900 * table with string keys and #GVariant values. 901 * 902 * Since: 2.0 903 */ 904 GVariant * 905 mmd_variant_from_mapping (yaml_parser_t *parser, GError **error); 906 907 908 /** 909 * mmd_variant_from_sequence: 910 * @parser: (inout): A YAML parser positioned just after a `SEQUENCE_START` 911 * @error: (out): A #GError that will return the reason for failing to parse. 912 * 913 * Returns: (transfer full): A new, floating #GVariant representing a list of 914 * #GVariant values. 915 * 916 * Since: 2.0 917 */ 918 GVariant * 919 mmd_variant_from_sequence (yaml_parser_t *parser, GError **error); 920 921 922 /** 923 * mmd_parse_xmd: 924 * @parser: (inout): A YAML parser positioned just after an 'xmd' mapping key. 925 * @error: (out): A #GError that will return the reason for failing to parse. 926 * 927 * Returns: (transfer full): A new, floating #GVariant representing the parsed 928 * XMD (eXtensible MetaData). 929 * 930 * Since: 2.10 931 */ 932 GVariant * 933 mmd_parse_xmd (yaml_parser_t *parser, GError **error); 934 935 936 /** 937 * skip_unknown_yaml: 938 * @parser: (inout): A YAML parser positioned just after an unexpected map key. 939 * @error: (out): A #GError that will return the reason for failing to parse. 940 * 941 * This function is used to skip a section of YAML that contains unknown keys. 942 * The intent here is that it will allow libmodulemd to be forward-compatible 943 * with new, backwards-compatible changes in the metadata format. This function 944 * will advance @parser to just before the next key in the map. 945 * 946 * Returns: TRUE if the parser was able to skip the unknown values safely. 947 * FALSE and sets @error appropriately if the document was malformed YAML. 948 */ 949 gboolean 950 skip_unknown_yaml (yaml_parser_t *parser, GError **error); 951 952 953 /** 954 * SKIP_UNKNOWN: 955 * @_parser: (inout): A YAML parser positioned just after an unexpected map key. 956 * @_returnval: (in): The error value to return. 957 * @...: (in): Additional argument(s) to pass to g_set_error() when setting 958 * `error`. 959 * 960 * This convenience macro is a wrapper around skip_unknown_yaml() used to skip 961 * a section of YAML that contains unknown keys. 962 * 963 * NOTE: Local variables `strict` and `error` are expected to be present in the 964 * code from which this macro is used. 965 * 966 * Returns: If `strict` is TRUE or skip_unknown_yaml() fails, @_returnval is 967 * returned and `error` is set appropriately. 968 * 969 * Since: 2.0 970 */ 971 #define SKIP_UNKNOWN(_parser, _returnval, ...) \ 972 do \ 973 { \ 974 g_debug (__VA_ARGS__); \ 975 if (strict) \ 976 { \ 977 MMD_YAML_ERROR_EVENT_EXIT_FULL (error, \ 978 MMD_YAML_ERROR_UNKNOWN_ATTR, \ 979 event, \ 980 _returnval, \ 981 __VA_ARGS__); \ 982 } \ 983 \ 984 if (!skip_unknown_yaml (_parser, error)) \ 985 return _returnval; \ 986 break; \ 987 } \ 988 while (0) 989 990 991 /* A set of macros for simple emitting of common elements */ 992 /** 993 * NON_EMPTY_TABLE: 994 * @table: A #GHashTable. 995 * 996 * Returns: FALSE if @table is empty, otherwise TRUE. 997 * 998 * Since: 2.0 999 */ 1000 #define NON_EMPTY_TABLE(table) (g_hash_table_size (table) != 0) 1001 1002 /** 1003 * NON_EMPTY_ARRAY: 1004 * @array: A #GPtrArray. 1005 * 1006 * Returns: FALSE if @array is empty, otherwise TRUE. 1007 * 1008 * Since: 2.0 1009 */ 1010 #define NON_EMPTY_ARRAY(array) (array->len != 0) 1011 1012 /** 1013 * EMIT_SCALAR_FULL: 1014 * @emitter: (inout): A libyaml emitter object positioned where a scalar 1015 * belongs in the YAML document. 1016 * @error: (out): A #GError that will return the reason for an output error. 1017 * @value: (in): The scalar (string) to be written. 1018 * @style: (in): The YAML scalar style for the output. 1019 * 1020 * Emits scalar @value using style @style. 1021 * 1022 * Returns: Continues on if the YAML scalar was written successfully. Returns 1023 * FALSE if an error occurred and sets @error appropriately. 1024 * 1025 * Since: 2.1 1026 */ 1027 #define EMIT_SCALAR_FULL(emitter, error, value, style) \ 1028 do \ 1029 { \ 1030 if (!mmd_emitter_scalar (emitter, value, style, error)) \ 1031 return FALSE; \ 1032 } \ 1033 while (0) 1034 1035 /** 1036 * EMIT_SCALAR: 1037 * @emitter: (inout): A libyaml emitter object positioned where a scalar 1038 * belongs in the YAML document. 1039 * @error: (out): A #GError that will return the reason for an output error. 1040 * @value: (in): The scalar (string) to be written. 1041 * 1042 * Emits scalar @value using style `YAML_PLAIN_SCALAR_STYLE`. 1043 * 1044 * Returns: Continues on if the YAML scalar was written successfully. Returns 1045 * FALSE if an error occurred and sets @error appropriately. 1046 * 1047 * Since: 2.0 1048 */ 1049 #define EMIT_SCALAR(emitter, error, value) \ 1050 EMIT_SCALAR_FULL (emitter, error, value, YAML_PLAIN_SCALAR_STYLE) 1051 1052 /** 1053 * EMIT_KEY_VALUE_FULL: 1054 * @emitter: (inout): A libyaml emitter object positioned where a scalar 1055 * belongs in the YAML document. 1056 * @error: (out): A #GError that will return the reason for an output error. 1057 * @key: (in): The key (string) to be written. 1058 * @value: (in): The scalar (string) to be written. 1059 * @style: (in): The YAML scalar style for the output. 1060 * 1061 * Emits key/value pair (@key: @value) using style @style. 1062 * 1063 * NOTE: This macro outputs both a key and a value for that key, thus it must 1064 * only be used from within a YAML mapping. 1065 * 1066 * Returns: Continues on if the YAML key/value pair was written successfully. 1067 * Returns FALSE if an error occurred and sets @error appropriately. 1068 * 1069 * Since: 2.1 1070 */ 1071 #define EMIT_KEY_VALUE_FULL(emitter, error, key, value, style) \ 1072 do \ 1073 { \ 1074 if (value == NULL) \ 1075 { \ 1076 g_set_error (error, \ 1077 MODULEMD_YAML_ERROR, \ 1078 MMD_YAML_ERROR_EMIT, \ 1079 "Value for key %s was NULL on emit", \ 1080 key); \ 1081 return FALSE; \ 1082 } \ 1083 EMIT_SCALAR (emitter, error, key); \ 1084 EMIT_SCALAR_FULL (emitter, error, value, style); \ 1085 } \ 1086 while (0) 1087 1088 /** 1089 * EMIT_KEY_VALUE: 1090 * @emitter: (inout): A libyaml emitter object positioned where a scalar 1091 * belongs in the YAML document. 1092 * @error: (out): A #GError that will return the reason for an output error. 1093 * @key: (in): The key (string) to be written. 1094 * @value: (in): The scalar (string) to be written. 1095 * 1096 * Emits key/value pair (@key: @value) using style `YAML_PLAIN_SCALAR_STYLE`. 1097 * 1098 * NOTE: This macro outputs both a key and a value for that key, thus it must 1099 * only be used from within a YAML mapping. 1100 * 1101 * Returns: Continues on if the YAML key/value pair was written successfully. 1102 * Returns FALSE if an error occurred and sets @error appropriately. 1103 * 1104 * Since: 2.0 1105 */ 1106 #define EMIT_KEY_VALUE(emitter, error, key, value) \ 1107 EMIT_KEY_VALUE_FULL (emitter, error, key, value, YAML_PLAIN_SCALAR_STYLE) 1108 1109 1110 /** 1111 * EMIT_KEY_VALUE_IF_SET: 1112 * @emitter: (inout): A libyaml emitter object positioned where a scalar 1113 * belongs in the YAML document. 1114 * @error: (out): A #GError that will return the reason for an output error. 1115 * @key: (in): The key (string) to be written. 1116 * @value: (in): The scalar (string) to be written. 1117 * 1118 * Emits key/value pair (@key: @value) only if @value is not NULL. 1119 * 1120 * NOTE: This macro outputs both a key and a value for that key, thus it must 1121 * only be used from within a YAML mapping. 1122 * 1123 * Returns: Continues on if @value is NULL or the YAML key/value pair was 1124 * written successfully. Returns FALSE if an error occurred and sets @error 1125 * appropriately. 1126 * 1127 * Since: 2.0 1128 */ 1129 #define EMIT_KEY_VALUE_IF_SET(emitter, error, key, value) \ 1130 do \ 1131 { \ 1132 if (value != NULL) \ 1133 { \ 1134 EMIT_KEY_VALUE (emitter, error, key, value); \ 1135 } \ 1136 } \ 1137 while (0) 1138 1139 /** 1140 * EMIT_MAPPING_START_WITH_STYLE: 1141 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1142 * of where a new mapping will be written. 1143 * @error: (out): A #GError that will return the reason for any error. 1144 * @style: (in): The YAML mapping style for the output. 1145 * 1146 * Returns: Continues on if the YAML mapping was started successfully. Returns 1147 * FALSE if an error occurred and sets @error appropriately. 1148 * 1149 * Since: 2.0 1150 */ 1151 #define EMIT_MAPPING_START_WITH_STYLE(emitter, error, style) \ 1152 do \ 1153 { \ 1154 if (!mmd_emitter_start_mapping (emitter, style, error)) \ 1155 return FALSE; \ 1156 } \ 1157 while (0) 1158 1159 /** 1160 * EMIT_MAPPING_START: 1161 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1162 * of where a new mapping will be written. 1163 * @error: (out): A #GError that will return the reason for any error. 1164 * 1165 * Returns: Continues on if the YAML mapping was started successfully using 1166 * style `YAML_BLOCK_MAPPING_STYLE`. Returns FALSE if an error occurred and 1167 * sets @error appropriately. 1168 * 1169 * Since: 2.0 1170 */ 1171 #define EMIT_MAPPING_START(emitter, error) \ 1172 EMIT_MAPPING_START_WITH_STYLE (emitter, error, YAML_BLOCK_MAPPING_STYLE) 1173 1174 /** 1175 * EMIT_MAPPING_END: 1176 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1177 * of where a mapping ending will be written. 1178 * @error: (out): A #GError that will return the reason for any error. 1179 * 1180 * Returns: Continues on if the YAML mapping was ended successfully. Returns 1181 * FALSE if an error occurred and sets @error appropriately. 1182 * 1183 * Since: 2.0 1184 */ 1185 #define EMIT_MAPPING_END(emitter, error) \ 1186 do \ 1187 { \ 1188 if (!mmd_emitter_end_mapping (emitter, error)) \ 1189 return FALSE; \ 1190 } \ 1191 while (0) 1192 1193 /** 1194 * EMIT_SEQUENCE_START_WITH_STYLE: 1195 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1196 * of where a new sequence will be written. 1197 * @error: (out): A #GError that will return the reason for any error. 1198 * @style: (in): The YAML sequence style for the output. 1199 * 1200 * Returns: Continues on if the YAML sequence was started successfully. Returns 1201 * FALSE if an error occurred and sets @error appropriately. 1202 * 1203 * Since: 2.0 1204 */ 1205 #define EMIT_SEQUENCE_START_WITH_STYLE(emitter, error, style) \ 1206 do \ 1207 { \ 1208 if (!mmd_emitter_start_sequence (emitter, style, error)) \ 1209 return FALSE; \ 1210 } \ 1211 while (0) 1212 1213 /** 1214 * EMIT_SEQUENCE_START: 1215 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1216 * of where a new sequence will be written. 1217 * @error: (out): A #GError that will return the reason for any error. 1218 * 1219 * Returns: Continues on if the YAML sequence was started successfully using 1220 * style `YAML_BLOCK_SEQUENCE_STYLE`. Returns FALSE if an error occurred and 1221 * sets @error appropriately. 1222 * 1223 * Since: 2.0 1224 */ 1225 #define EMIT_SEQUENCE_START(emitter, error) \ 1226 EMIT_SEQUENCE_START_WITH_STYLE (emitter, error, YAML_BLOCK_SEQUENCE_STYLE) 1227 1228 /** 1229 * EMIT_SEQUENCE_END: 1230 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1231 * of where a sequence ending will be written. 1232 * @error: (out): A #GError that will return the reason for any error. 1233 * 1234 * Returns: Continues on if the YAML sequence was ended successfully. Returns 1235 * FALSE if an error occurred and sets @error appropriately. 1236 * 1237 * Since: 2.0 1238 */ 1239 #define EMIT_SEQUENCE_END(emitter, error) \ 1240 do \ 1241 { \ 1242 if (!mmd_emitter_end_sequence (emitter, error)) \ 1243 return FALSE; \ 1244 } \ 1245 while (0) 1246 1247 /** 1248 * EMIT_HASHTABLE_VALUES_IF_NON_EMPTY: 1249 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1250 * of where a new mapping will be written. 1251 * @error: (out): A #GError that will return the reason for any error. 1252 * @key: (in): The name to be used as the identifier for the output mapping. 1253 * @table: (in): The #GHashTable that is to be output. 1254 * @emitfn: (in): A function used to emit each of the hash table values. 1255 * 1256 * Does nothing if the hash table @table is empty. Otherwise, calls @emitfn 1257 * to emit each of the values from @table identified as @key. 1258 * 1259 * NOTE: This macro outputs both a key and a sub-mapping value for that key, 1260 * thus it must only be used from within a YAML mapping. 1261 * 1262 * Returns: Continues on if the YAML mapping was output successfully. Returns 1263 * FALSE if an error occurred and sets @error appropriately. 1264 * 1265 * Since: 2.0 1266 */ 1267 #define EMIT_HASHTABLE_VALUES_IF_NON_EMPTY( \ 1268 emitter, error, key, table, emitfn) \ 1269 do \ 1270 { \ 1271 if (NON_EMPTY_TABLE (table)) \ 1272 { \ 1273 EMIT_SCALAR (emitter, error, key); \ 1274 EMIT_MAPPING_START (emitter, error); \ 1275 gsize i; \ 1276 g_autoptr (GPtrArray) keys = \ 1277 modulemd_ordered_str_keys (table, modulemd_strcmp_sort); \ 1278 for (i = 0; i < keys->len; i++) \ 1279 { \ 1280 if (!emitfn ( \ 1281 g_hash_table_lookup (table, g_ptr_array_index (keys, i)), \ 1282 emitter, \ 1283 error)) \ 1284 return FALSE; \ 1285 } \ 1286 EMIT_MAPPING_END (emitter, error); \ 1287 } \ 1288 } \ 1289 while (0) 1290 1291 /** 1292 * EMIT_HASHTABLE_KEY_VALUES_IF_NON_EMPTY: 1293 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1294 * of where a new mapping will be written. 1295 * @error: (out): A #GError that will return the reason for any error. 1296 * @key: (in): The name to be used as the identifier for the output mapping. 1297 * @table: (in): The #GHashTable that is to be output. Both the keys and values 1298 * must be strings. 1299 * 1300 * Does nothing if the hash table @table is empty. Otherwise, outputs a YAML 1301 * mapping with the key/value pairs from @table identified as @key. 1302 * 1303 * NOTE: This macro outputs both a key and a sub-mapping value for that key, 1304 * thus it must only be used from within a YAML mapping. 1305 * 1306 * Returns: Continues on if the YAML mapping was output successfully. Returns 1307 * FALSE if an error occurred and sets @error appropriately. 1308 * 1309 * Since: 2.0 1310 */ 1311 #define EMIT_HASHTABLE_KEY_VALUES_IF_NON_EMPTY(emitter, error, key, table) \ 1312 do \ 1313 { \ 1314 if (NON_EMPTY_TABLE (table)) \ 1315 { \ 1316 EMIT_SCALAR (emitter, error, key); \ 1317 EMIT_MAPPING_START (emitter, error); \ 1318 gsize i; \ 1319 g_autoptr (GPtrArray) keys = \ 1320 modulemd_ordered_str_keys (table, modulemd_strcmp_sort); \ 1321 for (i = 0; i < keys->len; i++) \ 1322 { \ 1323 EMIT_SCALAR (emitter, error, g_ptr_array_index (keys, i)); \ 1324 EMIT_SCALAR ( \ 1325 emitter, \ 1326 error, \ 1327 g_hash_table_lookup (table, g_ptr_array_index (keys, i))); \ 1328 } \ 1329 EMIT_MAPPING_END (emitter, error); \ 1330 } \ 1331 } \ 1332 while (0) 1333 1334 /** 1335 * EMIT_STRING_SET: 1336 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1337 * of where a new sequence will be written. 1338 * @error: (out): A #GError that will return the reason for any error. 1339 * @key: (in): The name to be used as the identifier for the output sequence. 1340 * @table: (in): The #GHashTable that is to be output. The keys are expected to 1341 * be a set() of strings. 1342 * 1343 * Raises an error if the hash table @table is empty. Otherwise, outputs a YAML 1344 * sequence using style `YAML_BLOCK_SEQUENCE_STYLE` with the keys from @table 1345 * identified as @key. 1346 * 1347 * NOTE: This macro outputs both a key and an array value for that key, thus it 1348 * must only be used from within a YAML mapping. 1349 * 1350 * Returns: Continues on if the YAML sequence was output successfully. Returns 1351 * FALSE if an error occurred and sets @error appropriately. 1352 * 1353 * Since: 2.0 1354 */ 1355 #define EMIT_STRING_SET(emitter, error, key, table) \ 1356 do \ 1357 { \ 1358 if (!NON_EMPTY_TABLE (table)) \ 1359 { \ 1360 g_set_error (error, \ 1361 MODULEMD_YAML_ERROR, \ 1362 MMD_YAML_ERROR_EMIT, \ 1363 "String set for key %s was empty on emit", \ 1364 key); \ 1365 return FALSE; \ 1366 } \ 1367 EMIT_STRING_SET_FULL ( \ 1368 emitter, error, key, table, YAML_BLOCK_SEQUENCE_STYLE); \ 1369 } \ 1370 while (0) 1371 1372 /** 1373 * EMIT_STRING_SET_IF_NON_EMPTY: 1374 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1375 * of where a new sequence will be written. 1376 * @error: (out): A #GError that will return the reason for any error. 1377 * @key: (in): The name to be used as the identifier for the output sequence. 1378 * @table: (in): The #GHashTable that is to be output. The keys are expected to 1379 * be a set() of strings. 1380 * 1381 * Does nothing if the hash table @table is empty. Otherwise, outputs a YAML 1382 * sequence using style `YAML_BLOCK_SEQUENCE_STYLE` with the keys from @table 1383 * identified as @key. 1384 * 1385 * NOTE: This macro outputs both a key and an array value for that key, thus it 1386 * must only be used from within a YAML mapping. 1387 * 1388 * Returns: Continues on if the YAML sequence was output successfully. Returns 1389 * FALSE if an error occurred and sets @error appropriately. 1390 * 1391 * Since: 2.0 1392 */ 1393 #define EMIT_STRING_SET_IF_NON_EMPTY(emitter, error, key, table) \ 1394 do \ 1395 { \ 1396 if (NON_EMPTY_TABLE (table)) \ 1397 { \ 1398 EMIT_STRING_SET (emitter, error, key, table); \ 1399 } \ 1400 } \ 1401 while (0) 1402 1403 /** 1404 * EMIT_STRING_SET_FULL: 1405 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1406 * of where a new sequence will be written. 1407 * @error: (out): A #GError that will return the reason for any error. 1408 * @key: (in): The name to be used as the identifier for the output sequence. 1409 * @table: (in): The #GHashTable that is to be output. The keys are expected to 1410 * be a set() of strings. 1411 * @sequence_style: (in): The YAML sequence style for the output. 1412 * 1413 * Outputs a YAML sequence with the keys from @table identified as @key. 1414 * 1415 * NOTE: This macro outputs both a key and an array value for that key, thus it 1416 * must only be used from within a YAML mapping. 1417 * 1418 * Returns: Continues on if the YAML sequence was output successfully. Returns 1419 * FALSE if an error occurred and sets @error appropriately. 1420 * 1421 * Since: 2.1 1422 */ 1423 #define EMIT_STRING_SET_FULL(emitter, error, key, table, sequence_style) \ 1424 do \ 1425 { \ 1426 EMIT_SCALAR (emitter, error, key); \ 1427 EMIT_SEQUENCE_START_WITH_STYLE (emitter, error, sequence_style); \ 1428 gsize i; \ 1429 g_autoptr (GPtrArray) keys = \ 1430 modulemd_ordered_str_keys (table, modulemd_strcmp_sort); \ 1431 for (i = 0; i < keys->len; i++) \ 1432 { \ 1433 EMIT_SCALAR (emitter, error, g_ptr_array_index (keys, i)); \ 1434 } \ 1435 EMIT_SEQUENCE_END (emitter, error); \ 1436 } \ 1437 while (0) 1438 1439 /** 1440 * EMIT_ARRAY_VALUES: 1441 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1442 * of where a new sequence will be written. 1443 * @error: (out): A #GError that will return the reason for any error. 1444 * @key: (in): The name to be used as the identifier for the output sequence. 1445 * @array: (in): The #GPtrArray that is to be output. 1446 * @emitfn: (in): A function used to emit each of the array values. 1447 * 1448 * Raises an error if the array @array is empty. Otherwise, calls @emitfn 1449 * to emit each of the values from @array identified as @key. 1450 * 1451 * NOTE: This macro outputs both a key and an array value for that key, thus it 1452 * must only be used from within a YAML mapping. 1453 * 1454 * Returns: Continues on if the YAML sequence was output successfully. Returns 1455 * FALSE if an error occurred and sets @error appropriately. 1456 * 1457 * Since: 2.0 1458 */ 1459 #define EMIT_ARRAY_VALUES(emitter, error, key, array, emitfn) \ 1460 do \ 1461 { \ 1462 if (!NON_EMPTY_ARRAY (array)) \ 1463 { \ 1464 g_set_error (error, \ 1465 MODULEMD_YAML_ERROR, \ 1466 MMD_YAML_ERROR_EMIT, \ 1467 "Array for key %s was empty on emit", \ 1468 key); \ 1469 return FALSE; \ 1470 } \ 1471 EMIT_SCALAR (emitter, error, key); \ 1472 EMIT_SEQUENCE_START (emitter, error); \ 1473 gsize i; \ 1474 for (i = 0; i < array->len; i++) \ 1475 { \ 1476 if (!emitfn (g_ptr_array_index (array, i), emitter, error)) \ 1477 return FALSE; \ 1478 } \ 1479 EMIT_SEQUENCE_END (emitter, error); \ 1480 } \ 1481 while (0) 1482 1483 /** 1484 * EMIT_ARRAY_VALUES_IF_NON_EMPTY: 1485 * @emitter: (inout): A libyaml emitter object that is positioned at the start 1486 * of where a new sequence will be written. 1487 * @error: (out): A #GError that will return the reason for any error. 1488 * @key: (in): The name to be used as the identifier for the output sequence. 1489 * @array: (in): The #GPtrArray that is to be output. 1490 * @emitfn: (in): A function used to emit each of the array values. 1491 * 1492 * Does nothing if the array @array is empty. Otherwise, calls @emitfn to emit 1493 * each of the values from @array identified as @key. 1494 * 1495 * NOTE: This macro outputs both a key and an array value for that key, thus it 1496 * must only be used from within a YAML mapping. 1497 * 1498 * Returns: Continues on if the YAML sequence was output successfully. Returns 1499 * FALSE if an error occurred and sets @error appropriately. 1500 * 1501 * Since: 2.0 1502 */ 1503 #define EMIT_ARRAY_VALUES_IF_NON_EMPTY(emitter, error, key, array, emitfn) \ 1504 do \ 1505 { \ 1506 if (NON_EMPTY_ARRAY (array)) \ 1507 { \ 1508 EMIT_ARRAY_VALUES (emitter, error, key, array, emitfn); \ 1509 } \ 1510 } \ 1511 while (0) 1512 1513 G_END_DECLS 1514