UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 /** 29 * @file map.h 30 * @brief Interface for map implementations. 31 * @author Mike Becker 32 * @author Olaf Wintermann 33 * @copyright 2-Clause BSD License 34 */ 35 36 #ifndef UCX_MAP_H 37 #define UCX_MAP_H 38 39 #include "common.h" 40 #include "collection.h" 41 #include "string.h" 42 #include "hash_key.h" 43 44 #ifndef UCX_LIST_H 45 // forward-declare CxList 46 typedef struct cx_list_s CxList; 47 #endif 48 49 #ifdef __cplusplus 50 extern "C" { 51 #endif 52 53 /** Type for the UCX map. */ 54 typedef struct cx_map_s CxMap; 55 56 /** Type for a map entry. */ 57 typedef struct cx_map_entry_s CxMapEntry; 58 59 /** Type for a map iterator. */ 60 typedef struct cx_map_iterator_s CxMapIterator; 61 62 /** Type for map class definitions. */ 63 typedef struct cx_map_class_s cx_map_class; 64 65 /** Structure for the UCX map. */ 66 struct cx_map_s { 67 /** 68 * Base attributes. 69 */ 70 CX_COLLECTION_BASE; 71 /** The map class definition. */ 72 cx_map_class *cl; 73 }; 74 75 /** 76 * A map entry. 77 */ 78 struct cx_map_entry_s { 79 /** 80 * A pointer to the key. 81 */ 82 const CxHashKey *key; 83 /** 84 * A pointer to the value. 85 */ 86 void *value; 87 }; 88 89 /** 90 * The type of iterator for a map. 91 */ 92 enum cx_map_iterator_type { 93 /** 94 * Iterates over key/value pairs. 95 */ 96 CX_MAP_ITERATOR_PAIRS, 97 /** 98 * Iterates over keys only. 99 */ 100 CX_MAP_ITERATOR_KEYS, 101 /** 102 * Iterates over values only. 103 */ 104 CX_MAP_ITERATOR_VALUES 105 }; 106 107 /** 108 * Internal iterator struct - use CxMapIterator. 109 */ 110 struct cx_map_iterator_s { 111 /** 112 * Inherited common data for all iterators. 113 */ 114 CX_ITERATOR_BASE; 115 116 /** 117 * Handle for the source map. 118 */ 119 CxMap *map; 120 121 /** 122 * Handle for the current element. 123 * 124 * @attention Depends on the map implementation, do not assume a type (better: do not use!). 125 */ 126 void *elem; 127 128 /** 129 * Reserved memory for a map entry. 130 * 131 * If a map implementation uses an incompatible layout, the iterator needs something 132 * to point to during iteration which @em is compatible. 133 */ 134 CxMapEntry entry; 135 136 /** 137 * Field for storing the current slot number. 138 * 139 * (Used internally) 140 */ 141 size_t slot; 142 143 /** 144 * Counts the elements successfully. 145 * It usually does not denote a stable index within the map as it would be for arrays. 146 */ 147 size_t index; 148 149 /** 150 * The size of a value stored in this map. 151 */ 152 size_t elem_size; 153 154 /** 155 * May contain the total number of elements, if known. 156 * Set to @c SIZE_MAX when the total number is unknown during iteration. 157 * 158 * @remark The UCX implementations of #CxMap always know the number of elements they store. 159 */ 160 size_t elem_count; 161 162 /** 163 * The type of this iterator. 164 */ 165 enum cx_map_iterator_type type; 166 }; 167 168 /** 169 * The class definition for arbitrary maps. 170 */ 171 struct cx_map_class_s { 172 /** 173 * Deallocates the entire memory. 174 */ 175 void (*deallocate)(struct cx_map_s *map); 176 177 /** 178 * Removes all elements. 179 */ 180 void (*clear)(struct cx_map_s *map); 181 182 /** 183 * Add or overwrite an element. 184 * If the @p value is @c NULL, the implementation 185 * shall only allocate memory instead of adding an existing value to the map. 186 * Returns a pointer to the allocated memory or @c NULL if allocation fails. 187 */ 188 void *(*put)(CxMap *map, CxHashKey key, void *value); 189 190 /** 191 * Returns an element. 192 */ 193 void *(*get)(const CxMap *map, CxHashKey key); 194 195 /** 196 * Removes an element. 197 * 198 * Implementations SHALL check if @p targetbuf is set and copy the elements 199 * to the buffer without invoking any destructor. 200 * When @p targetbuf is not set, the destructors SHALL be invoked. 201 * 202 * The function SHALL return zero when the @p key was found and 203 * non-zero, otherwise. 204 */ 205 int (*remove)(CxMap *map, CxHashKey key, void *targetbuf); 206 207 /** 208 * Creates an iterator for this map. 209 */ 210 CxMapIterator (*iterator)(const CxMap *map, enum cx_map_iterator_type type); 211 }; 212 213 /** 214 * A shared instance of an empty map. 215 * 216 * Writing to that map is not allowed. 217 * 218 * You can use this as a placeholder for initializing CxMap pointers 219 * for which you do not want to reserve memory right from the beginning. 220 */ 221 CX_EXPORT extern CxMap *const cxEmptyMap; 222 223 /** 224 * Deallocates the memory of the specified map. 225 * 226 * Also calls the content destructor functions for each element, if specified. 227 * 228 * @param map the map to be freed 229 */ 230 CX_EXPORT void cxMapFree(CxMap *map); 231 232 233 /** 234 * Clears a map by removing all elements. 235 * 236 * Also calls the content destructor functions for each element, if specified. 237 * 238 * @param map the map to be cleared 239 */ 240 cx_attr_nonnull 241 CX_EXPORT void cxMapClear(CxMap *map); 242 243 /** 244 * Returns the number of elements in this map. 245 * 246 * @param map the map 247 * @return the number of stored elements 248 */ 249 cx_attr_nonnull 250 CX_EXPORT size_t cxMapSize(const CxMap *map); 251 252 /** 253 * Creates a value iterator for a map. 254 * 255 * When the map is storing pointers, those pointers are returned. 256 * Otherwise, the iterator iterates over pointers to the memory within the map where the 257 * respective elements are stored. 258 * 259 * @note An iterator iterates over all elements successively. Therefore, the order 260 * highly depends on the map implementation and may change arbitrarily when the contents change. 261 * 262 * @param map the map to create the iterator for (can be @c NULL) 263 * @return an iterator for the currently stored values 264 */ 265 cx_attr_nodiscard 266 CX_EXPORT CxMapIterator cxMapIteratorValues(const CxMap *map); 267 268 /** 269 * Creates a key iterator for a map. 270 * 271 * The elements of the iterator are keys of type CxHashKey, and the pointer returned 272 * during iterator shall be treated as @c const @c CxHashKey* . 273 * 274 * @note An iterator iterates over all elements successively. Therefore, the order 275 * highly depends on the map implementation and may change arbitrarily when the contents change. 276 * 277 * @param map the map to create the iterator for (can be @c NULL) 278 * @return an iterator for the currently stored keys 279 */ 280 cx_attr_nodiscard 281 CX_EXPORT CxMapIterator cxMapIteratorKeys(const CxMap *map); 282 283 /** 284 * Creates an iterator for a map. 285 * 286 * The elements of the iterator are key/value pairs of type CxMapEntry, and the pointer returned 287 * during iterator shall be treated as @c const @c CxMapEntry* . 288 * 289 * @note An iterator iterates over all elements successively. Therefore, the order 290 * highly depends on the map implementation and may change arbitrarily when the contents change. 291 * 292 * @param map the map to create the iterator for (can be @c NULL) 293 * @return an iterator for the currently stored entries 294 * @see cxMapIteratorKeys() 295 * @see cxMapIteratorValues() 296 */ 297 cx_attr_nodiscard 298 CX_EXPORT CxMapIterator cxMapIterator(const CxMap *map); 299 300 /** 301 * Puts a key/value-pair into the map. 302 * 303 * A possible existing value will be overwritten. 304 * If destructor functions are specified, they are called for 305 * the overwritten element. 306 * 307 * If this map is storing pointers, the @p value pointer is written 308 * to the map. Otherwise, the memory is copied from @p value with 309 * memcpy(). 310 * 311 * The @p key is always copied. 312 * 313 * @param map the map 314 * @param key the key 315 * @param value the value 316 * @retval zero success 317 * @retval non-zero value on memory allocation failure 318 * @see cxMapPut() 319 */ 320 cx_attr_nonnull 321 CX_EXPORT int cx_map_put(CxMap *map, CxHashKey key, void *value); 322 323 /** 324 * Puts a key/value-pair into the map. 325 * 326 * A possible existing value will be overwritten. 327 * If destructor functions are specified, they are called for 328 * the overwritten element. 329 * 330 * If this map is storing pointers, the @p value pointer is written 331 * to the map. Otherwise, the memory is copied from @p value with 332 * memcpy(). 333 * 334 * The @p key is always copied. 335 * 336 * @param map (@c CxMap*) the map 337 * @param key (any supported key type) the key 338 * @param value (@c void*) the value 339 * @retval zero success 340 * @retval non-zero value on memory allocation failure 341 * @see CX_HASH_KEY() 342 */ 343 #define cxMapPut(map, key, value) cx_map_put(map, CX_HASH_KEY(key), value) 344 345 /** 346 * Allocates memory for a value in the map associated with the specified key. 347 * 348 * A possible existing value will be overwritten. 349 * If destructor functions are specified, they are called for 350 * the overwritten element. 351 * 352 * If the map is storing pointers, this function returns a @c void** pointer, 353 * meaning a pointer to that pointer. 354 * 355 * The @p key is always copied. 356 * 357 * @param map the map 358 * @param key the key 359 * @return the pointer to the allocated memory or @c NULL if allocation fails 360 * @retval zero success 361 * @retval non-zero value on memory allocation failure 362 * @see cxMapEmplace() 363 */ 364 cx_attr_nonnull 365 CX_EXPORT void *cx_map_emplace(CxMap *map, CxHashKey key); 366 367 /** 368 * Allocates memory for a value in the map associated with the specified key. 369 * 370 * A possible existing value will be overwritten. 371 * If destructor functions are specified, they are called for 372 * the overwritten element. 373 * 374 * If the map is storing pointers, this function returns a @c void** pointer, 375 * meaning a pointer to that pointer. 376 * 377 * The @p key is always copied. 378 * 379 * @param map (@c CxMap*) the map 380 * @param key (any supported key type) the key 381 * @return the pointer to the allocated memory or @c NULL if allocation fails 382 * @retval zero success 383 * @retval non-zero value on memory allocation failure 384 * @see CX_HASH_KEY() 385 */ 386 #define cxMapEmplace(map, key) cx_map_emplace(map, CX_HASH_KEY(key)) 387 388 /** 389 * Retrieves a value by using a key. 390 * 391 * If this map is storing pointers, the stored pointer is returned. 392 * Otherwise, a pointer to the element within the map's memory 393 * is returned (which is valid as long as the element stays in the map). 394 * 395 * @param map the map 396 * @param key the key 397 * @return the value 398 * @see cxMapGet() 399 */ 400 cx_attr_nonnull cx_attr_nodiscard 401 CX_EXPORT void *cx_map_get(const CxMap *map, CxHashKey key); 402 403 /** 404 * Retrieves a value by using a key. 405 * 406 * If this map is storing pointers, the stored pointer is returned. 407 * Otherwise, a pointer to the element within the map's memory 408 * is returned (which is valid as long as the element stays in the map). 409 * 410 * @param map (@c CxMap*) the map 411 * @param key (any supported key type) the key 412 * @return (@c void*) the value or @c NULL when no value with that @p key exists 413 * @see CX_HASH_KEY() 414 */ 415 #define cxMapGet(map, key) cx_map_get(map, CX_HASH_KEY(key)) 416 417 /** 418 * Checks if a map contains a specific key. 419 * 420 * @param map (@c CxMap*) the map 421 * @param key (any supported key type) the key 422 * @retval true if the key exists in the map 423 * @retval false if the key does not exist in the map 424 * @see CX_HASH_KEY() 425 */ 426 #define cxMapContains(map, key) (cxMapGet(map, key) != NULL) 427 428 /** 429 * Removes a key/value-pair from the map by using the key. 430 * 431 * Invokes the destructor functions, if any, on the removed element if and only if the 432 * @p targetbuf is @c NULL. 433 * 434 * @param map the map 435 * @param key the key 436 * @param targetbuf the optional buffer where the removed element shall be copied to 437 * @retval zero success 438 * @retval non-zero the key was not found 439 * 440 * @see cxMapRemove() 441 * @see cxMapRemoveAndGet() 442 */ 443 cx_attr_nonnull_arg(1) 444 CX_EXPORT int cx_map_remove(CxMap *map, CxHashKey key, void *targetbuf); 445 446 /** 447 * Removes a key/value-pair from the map by using the key. 448 * 449 * Always invokes the destructor functions, if any, on the removed element. 450 * 451 * @param map (@c CxMap*) the map 452 * @param key (any supported key type) the key 453 * @retval zero success 454 * @retval non-zero the key was not found 455 * 456 * @see cxMapRemoveAndGet() 457 * @see CX_HASH_KEY() 458 */ 459 #define cxMapRemove(map, key) cx_map_remove(map, CX_HASH_KEY(key), NULL) 460 461 /** 462 * Removes a key/value-pair from the map by using the key. 463 * 464 * This function will copy the contents of the removed element 465 * to the target buffer, which must be guaranteed to be large enough 466 * to hold the element (the map's element size). 467 * The destructor functions, if any, will @em not be called. 468 * 469 * If this map is storing pointers, the element is the pointer itself 470 * and not the object it points to. 471 * 472 * @param map (@c CxMap*) the map 473 * @param key (any supported key type) the key 474 * @param targetbuf (@c void*) the buffer where the element shall be copied to 475 * @retval zero success 476 * @retval non-zero the key was not found 477 * 478 * @see cxMapRemove() 479 * @see CX_HASH_KEY() 480 */ 481 #define cxMapRemoveAndGet(map, key, targetbuf) cx_map_remove(map, CX_HASH_KEY(key), targetbuf) 482 483 484 /** 485 * Performs a deep clone of one map into another. 486 * 487 * If the destination map already contains entries, the cloned entries 488 * are added to that map, possibly overwriting existing elements when 489 * the keys already exist. 490 * 491 * When elements in the destination map need to be replaced, any destructor 492 * function is called on the replaced elements before replacing them. 493 * 494 * @attention If the cloned elements need to be destroyed by a destructor 495 * function, you must make sure that the destination map also uses this 496 * destructor function. 497 * 498 * @param dst the destination map 499 * @param src the source map 500 * @param clone_func the clone function for the values 501 * @param clone_allocator the allocator that is passed to the clone function 502 * @param data optional additional data that is passed to the clone function 503 * @retval zero when all elements were successfully cloned 504 * @retval non-zero when an allocation error occurred 505 */ 506 cx_attr_nonnull_arg(1, 2, 3) 507 CX_EXPORT int cxMapClone(CxMap *dst, const CxMap *src, 508 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); 509 510 511 /** 512 * Clones entries of a map if their key is not present in another map. 513 * 514 * @param dst the destination map 515 * @param minuend the map to subtract the entries from 516 * @param subtrahend the map containing the elements to be subtracted 517 * @param clone_func the clone function for the values 518 * @param clone_allocator the allocator that is passed to the clone function 519 * @param data optional additional data that is passed to the clone function 520 * @retval zero when the elements were successfully cloned 521 * @retval non-zero when an allocation error occurred 522 */ 523 cx_attr_nonnull_arg(1, 2, 3, 4) 524 CX_EXPORT int cxMapDifference(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend, 525 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); 526 527 /** 528 * Clones entries of a map if their key is not present in a list. 529 * 530 * Note that the list must contain keys of type @c CxKey 531 * (or pointers to such keys) and must use @c cx_hash_key_cmp 532 * as the compare function. 533 * Generic key types cannot be processed in this case. 534 * 535 * @param dst the destination map 536 * @param src the source map 537 * @param keys the list of @c CxKey items 538 * @param clone_func the clone function for the values 539 * @param clone_allocator the allocator that is passed to the clone function 540 * @param data optional additional data that is passed to the clone function 541 * @retval zero when the elements were successfully cloned 542 * @retval non-zero when an allocation error occurred 543 */ 544 cx_attr_nonnull_arg(1, 2, 3, 4) 545 CX_EXPORT int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys, 546 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); 547 548 549 /** 550 * Clones entries of a map only if their key is present in another map. 551 * 552 * @param dst the destination map 553 * @param src the map to clone the entries from 554 * @param other the map to check for existence of the keys 555 * @param clone_func the clone function for the values 556 * @param clone_allocator the allocator that is passed to the clone function 557 * @param data optional additional data that is passed to the clone function 558 * @retval zero when the elements were successfully cloned 559 * @retval non-zero when an allocation error occurred 560 */ 561 cx_attr_nonnull_arg(1, 2, 3, 4) 562 CX_EXPORT int cxMapIntersection(CxMap *dst, const CxMap *src, const CxMap *other, 563 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); 564 565 /** 566 * Clones entries of a map only if their key is present in a list. 567 * 568 * Note that the list must contain keys of type @c CxKey 569 * (or pointers to such keys) and must use @c cx_hash_key_cmp 570 * as the compare function. 571 * Generic key types cannot be processed in this case. 572 * 573 * @param dst the destination map 574 * @param src the source map 575 * @param keys the list of @c CxKey items 576 * @param clone_func the clone function for the values 577 * @param clone_allocator the allocator that is passed to the clone function 578 * @param data optional additional data that is passed to the clone function 579 * @retval zero when the elements were successfully cloned 580 * @retval non-zero when an allocation error occurred 581 */ 582 cx_attr_nonnull_arg(1, 2, 3, 4) 583 CX_EXPORT int cxMapListIntersection(CxMap *dst, const CxMap *src, const CxList *keys, 584 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); 585 586 /** 587 * Clones entries into a map if their key does not exist yet. 588 * 589 * If you want to calculate the union of two maps into a fresh new map, 590 * you can proceed as follows: 591 * 1. Clone the first map into a fresh, empty map. 592 * 2. Use this function to clone the second map into the result from step 1. 593 * 594 * @param dst the destination map 595 * @param src the map to clone the entries from 596 * @param clone_func the clone function for the values 597 * @param clone_allocator the allocator that is passed to the clone function 598 * @param data optional additional data that is passed to the clone function 599 * @retval zero when the elements were successfully cloned 600 * @retval non-zero when an allocation error occurred 601 */ 602 cx_attr_nonnull_arg(1, 2, 3) 603 CX_EXPORT int cxMapUnion(CxMap *dst, const CxMap *src, 604 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data); 605 606 /** 607 * Performs a shallow clone of one map into another. 608 * 609 * This function uses the default allocator, if needed, and performs 610 * shallow clones with @c memcpy(). 611 * 612 * If the destination map already contains entries, the cloned entries 613 * are added to that map, possibly overwriting existing elements when 614 * the keys already exist. 615 * 616 * When elements in the destination map need to be replaced, any destructor 617 * function is called on the replaced elements before replacing them. 618 * 619 * @attention If the cloned elements need to be destroyed by a destructor 620 * function, you must make sure that the destination map also uses this 621 * destructor function. 622 * 623 * @param dst the destination map 624 * @param src the source map 625 * @retval zero when all elements were successfully cloned 626 * @retval non-zero when an allocation error occurred 627 * @see cxMapClone() 628 */ 629 cx_attr_nonnull 630 CX_EXPORT int cxMapCloneSimple(CxMap *dst, const CxMap *src); 631 632 /** 633 * Clones entries of a map if their key is not present in another map. 634 * 635 * This function uses the default allocator, if needed, and performs 636 * shallow clones with @c memcpy(). 637 * 638 * @param dst the destination map 639 * @param minuend the map to subtract the entries from 640 * @param subtrahend the map containing the elements to be subtracted 641 * @retval zero when the elements were successfully cloned 642 * @retval non-zero when an allocation error occurred 643 */ 644 cx_attr_nonnull 645 CX_EXPORT int cxMapDifferenceSimple(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend); 646 647 /** 648 * Clones entries of a map if their key is not present in a list. 649 * 650 * This function uses the default allocator, if needed, and performs 651 * shallow clones with @c memcpy(). 652 * 653 * Note that the list must contain keys of type @c CxKey 654 * (or pointers to such keys) and must use @c cx_hash_key_cmp 655 * as the compare function. 656 * Generic key types cannot be processed in this case. 657 * 658 * @param dst the destination map 659 * @param src the source map 660 * @param keys the list of @c CxKey items 661 * @retval zero when the elements were successfully cloned 662 * @retval non-zero when an allocation error occurred 663 * @see cxMapListDifference() 664 */ 665 cx_attr_nonnull 666 CX_EXPORT int cxMapListDifferenceSimple(CxMap *dst, const CxMap *src, const CxList *keys); 667 668 669 /** 670 * Clones entries of a map only if their key is present in another map. 671 * 672 * This function uses the default allocator, if needed, and performs 673 * shallow clones with @c memcpy(). 674 * 675 * @param dst the destination map 676 * @param src the map to clone the entries from 677 * @param other the map to check for existence of the keys 678 * @retval zero when the elements were successfully cloned 679 * @retval non-zero when an allocation error occurred 680 */ 681 cx_attr_nonnull 682 CX_EXPORT int cxMapIntersectionSimple(CxMap *dst, const CxMap *src, const CxMap *other); 683 684 /** 685 * Clones entries of a map only if their key is present in a list. 686 * 687 * This function uses the default allocator, if needed, and performs 688 * shallow clones with @c memcpy(). 689 * 690 * Note that the list must contain keys of type @c CxKey 691 * (or pointers to such keys) and must use @c cx_hash_key_cmp 692 * as the compare function. 693 * Generic key types cannot be processed in this case. 694 * 695 * @param dst the destination map 696 * @param src the source map 697 * @param keys the list of @c CxKey items 698 * @retval zero when the elements were successfully cloned 699 * @retval non-zero when an allocation error occurred 700 */ 701 cx_attr_nonnull 702 CX_EXPORT int cxMapListIntersectionSimple(CxMap *dst, const CxMap *src, const CxList *keys); 703 704 /** 705 * Clones entries into a map if their key does not exist yet. 706 * 707 * This function uses the default allocator, if needed, and performs 708 * shallow clones with @c memcpy(). 709 * 710 * If you want to calculate the union of two maps into a fresh new map, 711 * you can proceed as follows: 712 * 1. Clone the first map into a fresh, empty map. 713 * 2. Use this function to clone the second map into the result from step 1. 714 * 715 * @param dst the destination map 716 * @param src the map to clone the entries from 717 * @retval zero when the elements were successfully cloned 718 * @retval non-zero when an allocation error occurred 719 */ 720 cx_attr_nonnull 721 CX_EXPORT int cxMapUnionSimple(CxMap *dst, const CxMap *src); 722 723 #ifdef __cplusplus 724 } // extern "C" 725 #endif 726 727 #endif // UCX_MAP_H 728