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 string.h 30 * @brief Strings that know their length. 31 * @author Mike Becker 32 * @author Olaf Wintermann 33 * @copyright 2-Clause BSD License 34 */ 35 36 #ifndef UCX_STRING_H 37 #define UCX_STRING_H 38 39 #include "common.h" 40 #include "allocator.h" 41 42 /** 43 * The maximum length of the "needle" in cx_strstr() that can use SBO. 44 */ 45 extern const unsigned cx_strstr_sbo_size; 46 47 /** 48 * The UCX string structure. 49 */ 50 struct cx_mutstr_s { 51 /** 52 * A pointer to the string. 53 * @note The string is not necessarily @c NULL terminated. 54 * Always use the length. 55 */ 56 char *ptr; 57 /** The length of the string */ 58 size_t length; 59 }; 60 61 /** 62 * A mutable string. 63 */ 64 typedef struct cx_mutstr_s cxmutstr; 65 66 /** 67 * The UCX string structure for immutable (constant) strings. 68 */ 69 struct cx_string_s { 70 /** 71 * A pointer to the immutable string. 72 * @note The string is not necessarily @c NULL terminated. 73 * Always use the length. 74 */ 75 const char *ptr; 76 /** The length of the string */ 77 size_t length; 78 }; 79 80 /** 81 * An immutable string. 82 */ 83 typedef struct cx_string_s cxstring; 84 85 /** 86 * Context for string tokenizing. 87 */ 88 struct cx_strtok_ctx_s { 89 /** 90 * The string to tokenize. 91 */ 92 cxstring str; 93 /** 94 * The primary delimiter. 95 */ 96 cxstring delim; 97 /** 98 * Optional array of more delimiters. 99 */ 100 const cxstring *delim_more; 101 /** 102 * Length of the array containing more delimiters. 103 */ 104 size_t delim_more_count; 105 /** 106 * Position of the currently active token in the source string. 107 */ 108 size_t pos; 109 /** 110 * Position of next delimiter in the source string. 111 * 112 * If the tokenizer has not yet returned a token, the content of this field 113 * is undefined. If the tokenizer reached the end of the string, this field 114 * contains the length of the source string. 115 */ 116 size_t delim_pos; 117 /** 118 * The position of the next token in the source string. 119 */ 120 size_t next_pos; 121 /** 122 * The number of already found tokens. 123 */ 124 size_t found; 125 /** 126 * The maximum number of tokens that shall be returned. 127 */ 128 size_t limit; 129 }; 130 131 /** 132 * A string tokenizing context. 133 */ 134 typedef struct cx_strtok_ctx_s CxStrtokCtx; 135 136 #ifdef __cplusplus 137 extern "C" { 138 139 /** 140 * A literal initializer for an UCX string structure. 141 * 142 * @param literal the string literal 143 */ 144 #define CX_STR(literal) cxstring{literal, sizeof(literal) - 1} 145 146 #else // __cplusplus 147 148 /** 149 * A literal initializer for an UCX string structure. 150 * 151 * The argument MUST be a string (const char*) @em literal. 152 * 153 * @param literal the string literal 154 */ 155 #define CX_STR(literal) (cxstring){literal, sizeof(literal) - 1} 156 157 #endif 158 159 160 /** 161 * Wraps a mutable string that must be zero-terminated. 162 * 163 * The length is implicitly inferred by using a call to @c strlen(). 164 * 165 * @note the wrapped string will share the specified pointer to the string. 166 * If you do want a copy, use cx_strdup() on the return value of this function. 167 * 168 * If you need to wrap a constant string, use cx_str(). 169 * 170 * @param cstring the string to wrap, must be zero-terminated 171 * @return the wrapped string 172 * 173 * @see cx_mutstrn() 174 */ 175 cx_attr_nonnull 176 cx_attr_nodiscard 177 cx_attr_cstr_arg(1) 178 cxmutstr cx_mutstr(char *cstring); 179 180 /** 181 * Wraps a string that does not need to be zero-terminated. 182 * 183 * The argument may be @c NULL if the length is zero. 184 * 185 * @note the wrapped string will share the specified pointer to the string. 186 * If you do want a copy, use cx_strdup() on the return value of this function. 187 * 188 * If you need to wrap a constant string, use cx_strn(). 189 * 190 * @param cstring the string to wrap (or @c NULL, only if the length is zero) 191 * @param length the length of the string 192 * @return the wrapped string 193 * 194 * @see cx_mutstr() 195 */ 196 cx_attr_nodiscard 197 cx_attr_access_rw(1, 2) 198 cxmutstr cx_mutstrn( 199 char *cstring, 200 size_t length 201 ); 202 203 /** 204 * Wraps a string that must be zero-terminated. 205 * 206 * The length is implicitly inferred by using a call to @c strlen(). 207 * 208 * @note the wrapped string will share the specified pointer to the string. 209 * If you do want a copy, use cx_strdup() on the return value of this function. 210 * 211 * If you need to wrap a non-constant string, use cx_mutstr(). 212 * 213 * @param cstring the string to wrap, must be zero-terminated 214 * @return the wrapped string 215 * 216 * @see cx_strn() 217 */ 218 cx_attr_nonnull 219 cx_attr_nodiscard 220 cx_attr_cstr_arg(1) 221 cxstring cx_str(const char *cstring); 222 223 224 /** 225 * Wraps a string that does not need to be zero-terminated. 226 * 227 * The argument may be @c NULL if the length is zero. 228 * 229 * @note the wrapped string will share the specified pointer to the string. 230 * If you do want a copy, use cx_strdup() on the return value of this function. 231 * 232 * If you need to wrap a non-constant string, use cx_mutstrn(). 233 * 234 * @param cstring the string to wrap (or @c NULL, only if the length is zero) 235 * @param length the length of the string 236 * @return the wrapped string 237 * 238 * @see cx_str() 239 */ 240 cx_attr_nodiscard 241 cx_attr_access_r(1, 2) 242 cxstring cx_strn( 243 const char *cstring, 244 size_t length 245 ); 246 247 #ifdef __cplusplus 248 } // extern "C" 249 cx_attr_nodiscard 250 static inline cxstring cx_strcast(cxmutstr str) { 251 return cx_strn(str.ptr, str.length); 252 } 253 cx_attr_nodiscard 254 static inline cxstring cx_strcast(cxstring str) { 255 return str; 256 } 257 extern "C" { 258 #else 259 /** 260 * Internal function, do not use. 261 * @param str 262 * @return 263 * @see cx_strcast() 264 */ 265 cx_attr_nodiscard 266 static inline cxstring cx_strcast_m(cxmutstr str) { 267 return (cxstring) {str.ptr, str.length}; 268 } 269 /** 270 * Internal function, do not use. 271 * @param str 272 * @return 273 * @see cx_strcast() 274 */ 275 cx_attr_nodiscard 276 static inline cxstring cx_strcast_c(cxstring str) { 277 return str; 278 } 279 280 /** 281 * Casts a mutable string to an immutable string. 282 * 283 * Does nothing for already immutable strings. 284 * 285 * @note This is not seriously a cast. Instead, you get a copy 286 * of the struct with the desired pointer type. Both structs still 287 * point to the same location, though! 288 * 289 * @param str (@c cxstring or @c cxmutstr) the string to cast 290 * @return (@c cxstring) an immutable copy of the string pointer 291 */ 292 #define cx_strcast(str) _Generic((str), \ 293 cxmutstr: cx_strcast_m, \ 294 cxstring: cx_strcast_c) \ 295 (str) 296 #endif 297 298 /** 299 * Passes the pointer in this string to @c free(). 300 * 301 * The pointer in the struct is set to @c NULL and the length is set to zero. 302 * 303 * @note There is no implementation for cxstring, because it is unlikely that 304 * you ever have a <code>const char*</code> you are really supposed to free. 305 * If you encounter such situation, you should double-check your code. 306 * 307 * @param str the string to free 308 */ 309 void cx_strfree(cxmutstr *str); 310 311 /** 312 * Passes the pointer in this string to the allocators free function. 313 * 314 * The pointer in the struct is set to @c NULL and the length is set to zero. 315 * 316 * @note There is no implementation for cxstring, because it is unlikely that 317 * you ever have a <code>const char*</code> you are really supposed to free. 318 * If you encounter such situation, you should double-check your code. 319 * 320 * @param alloc the allocator 321 * @param str the string to free 322 */ 323 cx_attr_nonnull_arg(1) 324 void cx_strfree_a( 325 const CxAllocator *alloc, 326 cxmutstr *str 327 ); 328 329 /** 330 * Returns the accumulated length of all specified strings. 331 * 332 * If this sum overflows, errno is set to EOVERFLOW. 333 * 334 * @attention if the count argument is larger than the number of the 335 * specified strings, the behavior is undefined. 336 * 337 * @param count the total number of specified strings 338 * @param ... all strings 339 * @return the accumulated length of all strings 340 */ 341 cx_attr_nodiscard 342 size_t cx_strlen( 343 size_t count, 344 ... 345 ); 346 347 /** 348 * Concatenates strings. 349 * 350 * The resulting string will be allocated by the specified allocator. 351 * So developers @em must pass the return value to cx_strfree_a() eventually. 352 * 353 * If @p str already contains a string, the memory will be reallocated and 354 * the other strings are appended. Otherwise, new memory is allocated. 355 * 356 * If memory allocation fails, the pointer in the returned string will 357 * be @c NULL. Depending on the allocator, @c errno might be set. 358 * 359 * @note It is guaranteed that there is only one allocation for the 360 * resulting string. 361 * It is also guaranteed that the returned string is zero-terminated. 362 * 363 * @param alloc the allocator to use 364 * @param str the string the other strings shall be concatenated to 365 * @param count the number of the other following strings to concatenate 366 * @param ... all other UCX strings 367 * @return the concatenated string 368 */ 369 cx_attr_nodiscard 370 cx_attr_nonnull 371 cxmutstr cx_strcat_ma( 372 const CxAllocator *alloc, 373 cxmutstr str, 374 size_t count, 375 ... 376 ); 377 378 /** 379 * Concatenates strings and returns a new string. 380 * 381 * The resulting string will be allocated by the specified allocator. 382 * So developers @em must pass the return value to cx_strfree_a() eventually. 383 * 384 * If memory allocation fails, the pointer in the returned string will 385 * be @c NULL. Depending on the allocator, @c errno might be set. 386 * 387 * @note It is guaranteed that there is only one allocation for the 388 * resulting string. 389 * It is also guaranteed that the returned string is zero-terminated. 390 * 391 * @param alloc (@c CxAllocator*) the allocator to use 392 * @param count (@c size_t) the number of the other following strings to concatenate 393 * @param ... all other UCX strings 394 * @return (@c cxmutstr) the concatenated string 395 */ 396 #define cx_strcat_a(alloc, count, ...) \ 397 cx_strcat_ma(alloc, cx_mutstrn(NULL, 0), count, __VA_ARGS__) 398 399 /** 400 * Concatenates strings and returns a new string. 401 * 402 * The resulting string will be allocated by standard @c malloc(). 403 * So developers @em must pass the return value to cx_strfree() eventually. 404 * 405 * If memory allocation fails, the pointer in the returned string will 406 * be @c NULL and @c errno might be set. 407 * 408 * @note It is guaranteed that there is only one allocation for the 409 * resulting string. 410 * It is also guaranteed that the returned string is zero-terminated. 411 * 412 * @param count (@c size_t) the number of the other following strings to concatenate 413 * @param ... all other UCX strings 414 * @return (@c cxmutstr) the concatenated string 415 */ 416 #define cx_strcat(count, ...) \ 417 cx_strcat_ma(cxDefaultAllocator, cx_mutstrn(NULL, 0), count, __VA_ARGS__) 418 419 /** 420 * Concatenates strings. 421 * 422 * The resulting string will be allocated by standard @c malloc(). 423 * So developers @em must pass the return value to cx_strfree() eventually. 424 * 425 * If @p str already contains a string, the memory will be reallocated and 426 * the other strings are appended. Otherwise, new memory is allocated. 427 * 428 * If memory allocation fails, the pointer in the returned string will 429 * be @c NULL and @c errno might be set. 430 * 431 * @note It is guaranteed that there is only one allocation for the 432 * resulting string. 433 * It is also guaranteed that the returned string is zero-terminated. 434 * 435 * @param str (@c cxmutstr) the string the other strings shall be concatenated to 436 * @param count (@c size_t) the number of the other following strings to concatenate 437 * @param ... all other strings 438 * @return (@c cxmutstr) the concatenated string 439 */ 440 #define cx_strcat_m(str, count, ...) \ 441 cx_strcat_ma(cxDefaultAllocator, str, count, __VA_ARGS__) 442 443 /** 444 * Returns a substring starting at the specified location. 445 * 446 * @attention the new string references the same memory area as the 447 * input string and is usually @em not zero-terminated. 448 * Use cx_strdup() to get a copy. 449 * 450 * @param string input string 451 * @param start start location of the substring 452 * @return a substring of @p string starting at @p start 453 * 454 * @see cx_strsubsl() 455 * @see cx_strsubs_m() 456 * @see cx_strsubsl_m() 457 */ 458 cx_attr_nodiscard 459 cxstring cx_strsubs( 460 cxstring string, 461 size_t start 462 ); 463 464 /** 465 * Returns a substring starting at the specified location. 466 * 467 * The returned string will be limited to @p length bytes or the number 468 * of bytes available in @p string, whichever is smaller. 469 * 470 * @attention the new string references the same memory area as the 471 * input string and is usually @em not zero-terminated. 472 * Use cx_strdup() to get a copy. 473 * 474 * @param string input string 475 * @param start start location of the substring 476 * @param length the maximum length of the returned string 477 * @return a substring of @p string starting at @p start 478 * 479 * @see cx_strsubs() 480 * @see cx_strsubs_m() 481 * @see cx_strsubsl_m() 482 */ 483 cx_attr_nodiscard 484 cxstring cx_strsubsl( 485 cxstring string, 486 size_t start, 487 size_t length 488 ); 489 490 /** 491 * Returns a substring starting at the specified location. 492 * 493 * @attention the new string references the same memory area as the 494 * input string and is usually @em not zero-terminated. 495 * Use cx_strdup() to get a copy. 496 * 497 * @param string input string 498 * @param start start location of the substring 499 * @return a substring of @p string starting at @p start 500 * 501 * @see cx_strsubsl_m() 502 * @see cx_strsubs() 503 * @see cx_strsubsl() 504 */ 505 cx_attr_nodiscard 506 cxmutstr cx_strsubs_m( 507 cxmutstr string, 508 size_t start 509 ); 510 511 /** 512 * Returns a substring starting at the specified location. 513 * 514 * The returned string will be limited to @p length bytes or the number 515 * of bytes available in @p string, whichever is smaller. 516 * 517 * @attention the new string references the same memory area as the 518 * input string and is usually @em not zero-terminated. 519 * Use cx_strdup() to get a copy. 520 * 521 * @param string input string 522 * @param start start location of the substring 523 * @param length the maximum length of the returned string 524 * @return a substring of @p string starting at @p start 525 * 526 * @see cx_strsubs_m() 527 * @see cx_strsubs() 528 * @see cx_strsubsl() 529 */ 530 cx_attr_nodiscard 531 cxmutstr cx_strsubsl_m( 532 cxmutstr string, 533 size_t start, 534 size_t length 535 ); 536 537 /** 538 * Returns a substring starting at the location of the first occurrence of the 539 * specified character. 540 * 541 * If the string does not contain the character, an empty string is returned. 542 * 543 * @param string the string where to locate the character 544 * @param chr the character to locate 545 * @return a substring starting at the first location of @p chr 546 * 547 * @see cx_strchr_m() 548 */ 549 cx_attr_nodiscard 550 cxstring cx_strchr( 551 cxstring string, 552 int chr 553 ); 554 555 /** 556 * Returns a substring starting at the location of the first occurrence of the 557 * specified character. 558 * 559 * If the string does not contain the character, an empty string is returned. 560 * 561 * @param string the string where to locate the character 562 * @param chr the character to locate 563 * @return a substring starting at the first location of @p chr 564 * 565 * @see cx_strchr() 566 */ 567 cx_attr_nodiscard 568 cxmutstr cx_strchr_m( 569 cxmutstr string, 570 int chr 571 ); 572 573 /** 574 * Returns a substring starting at the location of the last occurrence of the 575 * specified character. 576 * 577 * If the string does not contain the character, an empty string is returned. 578 * 579 * @param string the string where to locate the character 580 * @param chr the character to locate 581 * @return a substring starting at the last location of @p chr 582 * 583 * @see cx_strrchr_m() 584 */ 585 cx_attr_nodiscard 586 cxstring cx_strrchr( 587 cxstring string, 588 int chr 589 ); 590 591 /** 592 * Returns a substring starting at the location of the last occurrence of the 593 * specified character. 594 * 595 * If the string does not contain the character, an empty string is returned. 596 * 597 * @param string the string where to locate the character 598 * @param chr the character to locate 599 * @return a substring starting at the last location of @p chr 600 * 601 * @see cx_strrchr() 602 */ 603 cx_attr_nodiscard 604 cxmutstr cx_strrchr_m( 605 cxmutstr string, 606 int chr 607 ); 608 609 /** 610 * Returns a substring starting at the location of the first occurrence of the 611 * specified string. 612 * 613 * If @p haystack does not contain @p needle, an empty string is returned. 614 * 615 * If @p needle is an empty string, the complete @p haystack is 616 * returned. 617 * 618 * @param haystack the string to be scanned 619 * @param needle string containing the sequence of characters to match 620 * @return a substring starting at the first occurrence of 621 * @p needle, or an empty string, if the sequence is not 622 * contained 623 * @see cx_strstr_m() 624 */ 625 cx_attr_nodiscard 626 cxstring cx_strstr( 627 cxstring haystack, 628 cxstring needle 629 ); 630 631 /** 632 * Returns a substring starting at the location of the first occurrence of the 633 * specified string. 634 * 635 * If @p haystack does not contain @p needle, an empty string is returned. 636 * 637 * If @p needle is an empty string, the complete @p haystack is 638 * returned. 639 * 640 * @param haystack the string to be scanned 641 * @param needle string containing the sequence of characters to match 642 * @return a substring starting at the first occurrence of 643 * @p needle, or an empty string, if the sequence is not 644 * contained 645 * @see cx_strstr() 646 */ 647 cx_attr_nodiscard 648 cxmutstr cx_strstr_m( 649 cxmutstr haystack, 650 cxstring needle 651 ); 652 653 /** 654 * Splits a given string using a delimiter string. 655 * 656 * @note The resulting array contains strings that point to the source 657 * @p string. Use cx_strdup() to get copies. 658 * 659 * @param string the string to split 660 * @param delim the delimiter 661 * @param limit the maximum number of split items 662 * @param output a pre-allocated array of at least @p limit length 663 * @return the actual number of split items 664 */ 665 cx_attr_nodiscard 666 cx_attr_nonnull 667 cx_attr_access_w(4, 3) 668 size_t cx_strsplit( 669 cxstring string, 670 cxstring delim, 671 size_t limit, 672 cxstring *output 673 ); 674 675 /** 676 * Splits a given string using a delimiter string. 677 * 678 * The array pointed to by @p output will be allocated by @p allocator. 679 * 680 * @note The resulting array contains strings that point to the source 681 * @p string. Use cx_strdup() to get copies. 682 * 683 * @attention If allocation fails, the @c NULL pointer will be written to 684 * @p output and the number returned will be zero. 685 * 686 * @param allocator the allocator to use for allocating the resulting array 687 * @param string the string to split 688 * @param delim the delimiter 689 * @param limit the maximum number of split items 690 * @param output a pointer where the address of the allocated array shall be 691 * written to 692 * @return the actual number of split items 693 */ 694 cx_attr_nodiscard 695 cx_attr_nonnull 696 cx_attr_access_w(5) 697 size_t cx_strsplit_a( 698 const CxAllocator *allocator, 699 cxstring string, 700 cxstring delim, 701 size_t limit, 702 cxstring **output 703 ); 704 705 706 /** 707 * Splits a given string using a delimiter string. 708 * 709 * @note The resulting array contains strings that point to the source 710 * @p string. Use cx_strdup() to get copies. 711 * 712 * @param string the string to split 713 * @param delim the delimiter 714 * @param limit the maximum number of split items 715 * @param output a pre-allocated array of at least @p limit length 716 * @return the actual number of split items 717 */ 718 cx_attr_nodiscard 719 cx_attr_nonnull 720 cx_attr_access_w(4, 3) 721 size_t cx_strsplit_m( 722 cxmutstr string, 723 cxstring delim, 724 size_t limit, 725 cxmutstr *output 726 ); 727 728 /** 729 * Splits a given string using a delimiter string. 730 * 731 * The array pointed to by @p output will be allocated by @p allocator. 732 * 733 * @note The resulting array contains strings that point to the source 734 * @p string. Use cx_strdup() to get copies. 735 * 736 * @attention If allocation fails, the @c NULL pointer will be written to 737 * @p output and the number returned will be zero. 738 * 739 * @param allocator the allocator to use for allocating the resulting array 740 * @param string the string to split 741 * @param delim the delimiter 742 * @param limit the maximum number of split items 743 * @param output a pointer where the address of the allocated array shall be 744 * written to 745 * @return the actual number of split items 746 */ 747 cx_attr_nodiscard 748 cx_attr_nonnull 749 cx_attr_access_w(5) 750 size_t cx_strsplit_ma( 751 const CxAllocator *allocator, 752 cxmutstr string, 753 cxstring delim, 754 size_t limit, 755 cxmutstr **output 756 ); 757 758 /** 759 * Compares two strings. 760 * 761 * @param s1 the first string 762 * @param s2 the second string 763 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 764 * than @p s2, zero if both strings equal 765 */ 766 cx_attr_nodiscard 767 int cx_strcmp( 768 cxstring s1, 769 cxstring s2 770 ); 771 772 /** 773 * Compares two strings ignoring case. 774 * 775 * @param s1 the first string 776 * @param s2 the second string 777 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 778 * than @p s2, zero if both strings equal ignoring case 779 */ 780 cx_attr_nodiscard 781 int cx_strcasecmp( 782 cxstring s1, 783 cxstring s2 784 ); 785 786 /** 787 * Compares two strings. 788 * 789 * This function has a compatible signature for the use as a cx_compare_func. 790 * 791 * @param s1 the first string 792 * @param s2 the second string 793 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 794 * than @p s2, zero if both strings equal 795 */ 796 cx_attr_nodiscard 797 cx_attr_nonnull 798 int cx_strcmp_p( 799 const void *s1, 800 const void *s2 801 ); 802 803 /** 804 * Compares two strings ignoring case. 805 * 806 * This function has a compatible signature for the use as a cx_compare_func. 807 * 808 * @param s1 the first string 809 * @param s2 the second string 810 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 811 * than @p s2, zero if both strings equal ignoring case 812 */ 813 cx_attr_nodiscard 814 cx_attr_nonnull 815 int cx_strcasecmp_p( 816 const void *s1, 817 const void *s2 818 ); 819 820 821 /** 822 * Creates a duplicate of the specified string. 823 * 824 * The new string will contain a copy allocated by @p allocator. 825 * 826 * @note The returned string is guaranteed to be zero-terminated. 827 * 828 * @param allocator the allocator to use 829 * @param string the string to duplicate 830 * @return a duplicate of the string 831 * @see cx_strdup() 832 */ 833 cx_attr_nodiscard 834 cx_attr_nonnull 835 cxmutstr cx_strdup_a( 836 const CxAllocator *allocator, 837 cxstring string 838 ); 839 840 /** 841 * Creates a duplicate of the specified string. 842 * 843 * The new string will contain a copy allocated by standard 844 * @c malloc(). So developers @em must pass the return value to cx_strfree(). 845 * 846 * @note The returned string is guaranteed to be zero-terminated. 847 * 848 * @param string (@c cxstring) the string to duplicate 849 * @return (@c cxmutstr) a duplicate of the string 850 * @see cx_strdup_a() 851 */ 852 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string) 853 854 855 /** 856 * Creates a duplicate of the specified string. 857 * 858 * The new string will contain a copy allocated by @p allocator. 859 * 860 * @note The returned string is guaranteed to be zero-terminated. 861 * 862 * @param allocator (@c CxAllocator*) the allocator to use 863 * @param string (@c cxmutstr) the string to duplicate 864 * @return (@c cxmutstr) a duplicate of the string 865 * @see cx_strdup_m() 866 */ 867 #define cx_strdup_ma(allocator, string) cx_strdup_a(allocator, cx_strcast(string)) 868 869 /** 870 * Creates a duplicate of the specified string. 871 * 872 * The new string will contain a copy allocated by standard 873 * @c malloc(). So developers @em must pass the return value to cx_strfree(). 874 * 875 * @note The returned string is guaranteed to be zero-terminated. 876 * 877 * @param string (@c cxmutstr) the string to duplicate 878 * @return (@c cxmutstr) a duplicate of the string 879 * @see cx_strdup_ma() 880 */ 881 #define cx_strdup_m(string) cx_strdup_a(cxDefaultAllocator, cx_strcast(string)) 882 883 /** 884 * Omits leading and trailing spaces. 885 * 886 * @note the returned string references the same memory, thus you 887 * must @em not free the returned memory. 888 * 889 * @param string the string that shall be trimmed 890 * @return the trimmed string 891 */ 892 cx_attr_nodiscard 893 cxstring cx_strtrim(cxstring string); 894 895 /** 896 * Omits leading and trailing spaces. 897 * 898 * @note the returned string references the same memory, thus you 899 * must @em not free the returned memory. 900 * 901 * @param string the string that shall be trimmed 902 * @return the trimmed string 903 */ 904 cx_attr_nodiscard 905 cxmutstr cx_strtrim_m(cxmutstr string); 906 907 /** 908 * Checks, if a string has a specific prefix. 909 * 910 * @param string the string to check 911 * @param prefix the prefix the string should have 912 * @return @c true, if and only if the string has the specified prefix, 913 * @c false otherwise 914 */ 915 cx_attr_nodiscard 916 bool cx_strprefix( 917 cxstring string, 918 cxstring prefix 919 ); 920 921 /** 922 * Checks, if a string has a specific suffix. 923 * 924 * @param string the string to check 925 * @param suffix the suffix the string should have 926 * @return @c true, if and only if the string has the specified suffix, 927 * @c false otherwise 928 */ 929 cx_attr_nodiscard 930 bool cx_strsuffix( 931 cxstring string, 932 cxstring suffix 933 ); 934 935 /** 936 * Checks, if a string has a specific prefix, ignoring the case. 937 * 938 * @param string the string to check 939 * @param prefix the prefix the string should have 940 * @return @c true, if and only if the string has the specified prefix, 941 * @c false otherwise 942 */ 943 cx_attr_nodiscard 944 bool cx_strcaseprefix( 945 cxstring string, 946 cxstring prefix 947 ); 948 949 /** 950 * Checks, if a string has a specific suffix, ignoring the case. 951 * 952 * @param string the string to check 953 * @param suffix the suffix the string should have 954 * @return @c true, if and only if the string has the specified suffix, 955 * @c false otherwise 956 */ 957 cx_attr_nodiscard 958 bool cx_strcasesuffix( 959 cxstring string, 960 cxstring suffix 961 ); 962 963 /** 964 * Converts the string to lower case. 965 * 966 * The change is made in-place. If you want a copy, use cx_strdup(), first. 967 * 968 * @param string the string to modify 969 * @see cx_strdup() 970 */ 971 void cx_strlower(cxmutstr string); 972 973 /** 974 * Converts the string to upper case. 975 * 976 * The change is made in-place. If you want a copy, use cx_strdup(), first. 977 * 978 * @param string the string to modify 979 * @see cx_strdup() 980 */ 981 void cx_strupper(cxmutstr string); 982 983 /** 984 * Replaces a pattern in a string with another string. 985 * 986 * The pattern is taken literally and is no regular expression. 987 * Replaces at most @p replmax occurrences. 988 * 989 * The returned string will be allocated by @p allocator and is guaranteed 990 * to be zero-terminated. 991 * 992 * If allocation fails, or the input string is empty, 993 * the returned string will be empty. 994 * 995 * @param allocator the allocator to use 996 * @param str the string where replacements should be applied 997 * @param pattern the pattern to search for 998 * @param replacement the replacement string 999 * @param replmax maximum number of replacements 1000 * @return the resulting string after applying the replacements 1001 */ 1002 cx_attr_nodiscard 1003 cx_attr_nonnull 1004 cxmutstr cx_strreplacen_a( 1005 const CxAllocator *allocator, 1006 cxstring str, 1007 cxstring pattern, 1008 cxstring replacement, 1009 size_t replmax 1010 ); 1011 1012 /** 1013 * Replaces a pattern in a string with another string. 1014 * 1015 * The pattern is taken literally and is no regular expression. 1016 * Replaces at most @p replmax occurrences. 1017 * 1018 * The returned string will be allocated by @c malloc() and is guaranteed 1019 * to be zero-terminated. 1020 * 1021 * If allocation fails, or the input string is empty, 1022 * the returned string will be empty. 1023 * 1024 * @param str (@c cxstring) the string where replacements should be applied 1025 * @param pattern (@c cxstring) the pattern to search for 1026 * @param replacement (@c cxstring) the replacement string 1027 * @param replmax (@c size_t) maximum number of replacements 1028 * @return (@c cxmutstr) the resulting string after applying the replacements 1029 */ 1030 #define cx_strreplacen(str, pattern, replacement, replmax) \ 1031 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, replmax) 1032 1033 /** 1034 * Replaces a pattern in a string with another string. 1035 * 1036 * The pattern is taken literally and is no regular expression. 1037 * 1038 * The returned string will be allocated by @p allocator and is guaranteed 1039 * to be zero-terminated. 1040 * 1041 * If allocation fails, or the input string is empty, 1042 * the returned string will be empty. 1043 * 1044 * @param allocator (@c CxAllocator*) the allocator to use 1045 * @param str (@c cxstring) the string where replacements should be applied 1046 * @param pattern (@c cxstring) the pattern to search for 1047 * @param replacement (@c cxstring) the replacement string 1048 * @return (@c cxmutstr) the resulting string after applying the replacements 1049 */ 1050 #define cx_strreplace_a(allocator, str, pattern, replacement) \ 1051 cx_strreplacen_a(allocator, str, pattern, replacement, SIZE_MAX) 1052 1053 /** 1054 * Replaces a pattern in a string with another string. 1055 * 1056 * The pattern is taken literally and is no regular expression. 1057 * Replaces at most @p replmax occurrences. 1058 * 1059 * The returned string will be allocated by @c malloc() and is guaranteed 1060 * to be zero-terminated. 1061 * 1062 * If allocation fails, or the input string is empty, 1063 * the returned string will be empty. 1064 * 1065 * @param str (@c cxstring) the string where replacements should be applied 1066 * @param pattern (@c cxstring) the pattern to search for 1067 * @param replacement (@c cxstring) the replacement string 1068 * @return (@c cxmutstr) the resulting string after applying the replacements 1069 */ 1070 #define cx_strreplace(str, pattern, replacement) \ 1071 cx_strreplacen_a(cxDefaultAllocator, str, pattern, replacement, SIZE_MAX) 1072 1073 /** 1074 * Creates a string tokenization context. 1075 * 1076 * @param str the string to tokenize 1077 * @param delim the delimiter (must not be empty) 1078 * @param limit the maximum number of tokens that shall be returned 1079 * @return a new string tokenization context 1080 */ 1081 cx_attr_nodiscard 1082 CxStrtokCtx cx_strtok( 1083 cxstring str, 1084 cxstring delim, 1085 size_t limit 1086 ); 1087 1088 /** 1089 * Creates a string tokenization context for a mutable string. 1090 * 1091 * @param str the string to tokenize 1092 * @param delim the delimiter (must not be empty) 1093 * @param limit the maximum number of tokens that shall be returned 1094 * @return a new string tokenization context 1095 */ 1096 cx_attr_nodiscard 1097 CxStrtokCtx cx_strtok_m( 1098 cxmutstr str, 1099 cxstring delim, 1100 size_t limit 1101 ); 1102 1103 /** 1104 * Returns the next token. 1105 * 1106 * The token will point to the source string. 1107 * 1108 * @param ctx the tokenization context 1109 * @param token a pointer to memory where the next token shall be stored 1110 * @return true if successful, false if the limit or the end of the string 1111 * has been reached 1112 */ 1113 cx_attr_nonnull 1114 cx_attr_nodiscard 1115 cx_attr_access_w(2) 1116 bool cx_strtok_next( 1117 CxStrtokCtx *ctx, 1118 cxstring *token 1119 ); 1120 1121 /** 1122 * Returns the next token of a mutable string. 1123 * 1124 * The token will point to the source string. 1125 * If the context was not initialized over a mutable string, modifying 1126 * the data of the returned token is undefined behavior. 1127 * 1128 * @param ctx the tokenization context 1129 * @param token a pointer to memory where the next token shall be stored 1130 * @return true if successful, false if the limit or the end of the string 1131 * has been reached 1132 */ 1133 cx_attr_nonnull 1134 cx_attr_nodiscard 1135 cx_attr_access_w(2) 1136 bool cx_strtok_next_m( 1137 CxStrtokCtx *ctx, 1138 cxmutstr *token 1139 ); 1140 1141 /** 1142 * Defines an array of more delimiters for the specified tokenization context. 1143 * 1144 * @param ctx the tokenization context 1145 * @param delim array of more delimiters 1146 * @param count number of elements in the array 1147 */ 1148 cx_attr_nonnull 1149 cx_attr_access_r(2, 3) 1150 void cx_strtok_delim( 1151 CxStrtokCtx *ctx, 1152 const cxstring *delim, 1153 size_t count 1154 ); 1155 1156 /* ------------------------------------------------------------------------- * 1157 * string to number conversion functions * 1158 * ------------------------------------------------------------------------- */ 1159 1160 /** 1161 * @copydoc cx_strtouz_lc() 1162 */ 1163 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1164 int cx_strtos_lc(cxstring str, short *output, int base, const char *groupsep); 1165 /** 1166 * @copydoc cx_strtouz_lc() 1167 */ 1168 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1169 int cx_strtoi_lc(cxstring str, int *output, int base, const char *groupsep); 1170 /** 1171 * @copydoc cx_strtouz_lc() 1172 */ 1173 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1174 int cx_strtol_lc(cxstring str, long *output, int base, const char *groupsep); 1175 /** 1176 * @copydoc cx_strtouz_lc() 1177 */ 1178 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1179 int cx_strtoll_lc(cxstring str, long long *output, int base, const char *groupsep); 1180 /** 1181 * @copydoc cx_strtouz_lc() 1182 */ 1183 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1184 int cx_strtoi8_lc(cxstring str, int8_t *output, int base, const char *groupsep); 1185 /** 1186 * @copydoc cx_strtouz_lc() 1187 */ 1188 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1189 int cx_strtoi16_lc(cxstring str, int16_t *output, int base, const char *groupsep); 1190 /** 1191 * @copydoc cx_strtouz_lc() 1192 */ 1193 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1194 int cx_strtoi32_lc(cxstring str, int32_t *output, int base, const char *groupsep); 1195 /** 1196 * @copydoc cx_strtouz_lc() 1197 */ 1198 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1199 int cx_strtoi64_lc(cxstring str, int64_t *output, int base, const char *groupsep); 1200 /** 1201 * @copydoc cx_strtouz_lc() 1202 */ 1203 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1204 int cx_strtoz_lc(cxstring str, ssize_t *output, int base, const char *groupsep); 1205 /** 1206 * @copydoc cx_strtouz_lc() 1207 */ 1208 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1209 int cx_strtous_lc(cxstring str, unsigned short *output, int base, const char *groupsep); 1210 /** 1211 * @copydoc cx_strtouz_lc() 1212 */ 1213 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1214 int cx_strtou_lc(cxstring str, unsigned int *output, int base, const char *groupsep); 1215 /** 1216 * @copydoc cx_strtouz_lc() 1217 */ 1218 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1219 int cx_strtoul_lc(cxstring str, unsigned long *output, int base, const char *groupsep); 1220 /** 1221 * @copydoc cx_strtouz_lc() 1222 */ 1223 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1224 int cx_strtoull_lc(cxstring str, unsigned long long *output, int base, const char *groupsep); 1225 /** 1226 * @copydoc cx_strtouz_lc() 1227 */ 1228 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1229 int cx_strtou8_lc(cxstring str, uint8_t *output, int base, const char *groupsep); 1230 /** 1231 * @copydoc cx_strtouz_lc() 1232 */ 1233 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1234 int cx_strtou16_lc(cxstring str, uint16_t *output, int base, const char *groupsep); 1235 /** 1236 * @copydoc cx_strtouz_lc() 1237 */ 1238 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1239 int cx_strtou32_lc(cxstring str, uint32_t *output, int base, const char *groupsep); 1240 /** 1241 * @copydoc cx_strtouz_lc() 1242 */ 1243 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1244 int cx_strtou64_lc(cxstring str, uint64_t *output, int base, const char *groupsep); 1245 1246 /** 1247 * Converts a string to a number. 1248 * 1249 * The function returns non-zero when conversion is not possible. 1250 * In that case the function sets errno to EINVAL when the reason is an invalid character or an unsupported base. 1251 * It sets errno to ERANGE when the target datatype is too small. 1252 * 1253 * @param str the string to convert 1254 * @param output a pointer to the integer variable where the result shall be stored 1255 * @param base 2, 8, 10, or 16 1256 * @param groupsep each character in this string is treated as group separator and ignored during conversion 1257 * @retval zero success 1258 * @retval non-zero conversion was not possible 1259 */ 1260 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1261 int cx_strtouz_lc(cxstring str, size_t *output, int base, const char *groupsep); 1262 1263 /** 1264 * Converts a string to a single precision floating point number. 1265 * 1266 * The function returns non-zero when conversion is not possible. 1267 * In that case the function sets errno to EINVAL when the reason is an invalid character. 1268 * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. 1269 * 1270 * The decimal separator is assumed to be a dot character. 1271 * The comma character is treated as group separator and ignored during parsing. 1272 * If you want to choose a different format, use cx_strtof_lc(). 1273 * 1274 * @param str the string to convert 1275 * @param output a pointer to the float variable where the result shall be stored 1276 * @param decsep the decimal separator 1277 * @param groupsep each character in this string is treated as group separator and ignored during conversion 1278 * @retval zero success 1279 * @retval non-zero conversion was not possible 1280 */ 1281 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1282 int cx_strtof_lc(cxstring str, float *output, char decsep, const char *groupsep); 1283 1284 /** 1285 * Converts a string to a double precision floating point number. 1286 * 1287 * The function returns non-zero when conversion is not possible. 1288 * In that case the function sets errno to EINVAL when the reason is an invalid character. 1289 * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. 1290 * 1291 * The decimal separator is assumed to be a dot character. 1292 * The comma character is treated as group separator and ignored during parsing. 1293 * If you want to choose a different format, use cx_strtof_lc(). 1294 * 1295 * @param str the string to convert 1296 * @param output a pointer to the float variable where the result shall be stored 1297 * @param decsep the decimal separator 1298 * @param groupsep each character in this string is treated as group separator and ignored during conversion 1299 * @retval zero success 1300 * @retval non-zero conversion was not possible 1301 */ 1302 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1303 int cx_strtod_lc(cxstring str, double *output, char decsep, const char *groupsep); 1304 1305 #ifndef CX_STR_IMPLEMENTATION 1306 /** 1307 * @copydoc cx_strtouz_lc() 1308 */ 1309 #define cx_strtos_lc(str, output, base, groupsep) cx_strtos_lc(cx_strcast(str), output, base, groupsep) 1310 /** 1311 * @copydoc cx_strtouz_lc() 1312 */ 1313 #define cx_strtoi_lc(str, output, base, groupsep) cx_strtoi_lc(cx_strcast(str), output, base, groupsep) 1314 /** 1315 * @copydoc cx_strtouz_lc() 1316 */ 1317 #define cx_strtol_lc(str, output, base, groupsep) cx_strtol_lc(cx_strcast(str), output, base, groupsep) 1318 /** 1319 * @copydoc cx_strtouz_lc() 1320 */ 1321 #define cx_strtoll_lc(str, output, base, groupsep) cx_strtoll_lc(cx_strcast(str), output, base, groupsep) 1322 /** 1323 * @copydoc cx_strtouz_lc() 1324 */ 1325 #define cx_strtoi8_lc(str, output, base, groupsep) cx_strtoi8_lc(cx_strcast(str), output, base, groupsep) 1326 /** 1327 * @copydoc cx_strtouz_lc() 1328 */ 1329 #define cx_strtoi16_lc(str, output, base, groupsep) cx_strtoi16_lc(cx_strcast(str), output, base, groupsep) 1330 /** 1331 * @copydoc cx_strtouz_lc() 1332 */ 1333 #define cx_strtoi32_lc(str, output, base, groupsep) cx_strtoi32_lc(cx_strcast(str), output, base, groupsep) 1334 /** 1335 * @copydoc cx_strtouz_lc() 1336 */ 1337 #define cx_strtoi64_lc(str, output, base, groupsep) cx_strtoi64_lc(cx_strcast(str), output, base, groupsep) 1338 /** 1339 * @copydoc cx_strtouz_lc() 1340 */ 1341 #define cx_strtoz_lc(str, output, base, groupsep) cx_strtoz_lc(cx_strcast(str), output, base, groupsep) 1342 /** 1343 * @copydoc cx_strtouz_lc() 1344 */ 1345 #define cx_strtous_lc(str, output, base, groupsep) cx_strtous_lc(cx_strcast(str), output, base, groupsep) 1346 /** 1347 * @copydoc cx_strtouz_lc() 1348 */ 1349 #define cx_strtou_lc(str, output, base, groupsep) cx_strtou_lc(cx_strcast(str), output, base, groupsep) 1350 /** 1351 * @copydoc cx_strtouz_lc() 1352 */ 1353 #define cx_strtoul_lc(str, output, base, groupsep) cx_strtoul_lc(cx_strcast(str), output, base, groupsep) 1354 /** 1355 * @copydoc cx_strtouz_lc() 1356 */ 1357 #define cx_strtoull_lc(str, output, base, groupsep) cx_strtoull_lc(cx_strcast(str), output, base, groupsep) 1358 /** 1359 * @copydoc cx_strtouz_lc() 1360 */ 1361 #define cx_strtou8_lc(str, output, base, groupsep) cx_strtou8_lc(cx_strcast(str), output, base, groupsep) 1362 /** 1363 * @copydoc cx_strtouz_lc() 1364 */ 1365 #define cx_strtou16_lc(str, output, base, groupsep) cx_strtou16_lc(cx_strcast(str), output, base, groupsep) 1366 /** 1367 * @copydoc cx_strtouz_lc() 1368 */ 1369 #define cx_strtou32_lc(str, output, base, groupsep) cx_strtou32_lc(cx_strcast(str), output, base, groupsep) 1370 /** 1371 * @copydoc cx_strtouz_lc() 1372 */ 1373 #define cx_strtou64_lc(str, output, base, groupsep) cx_strtou64_lc(cx_strcast(str), output, base, groupsep) 1374 /** 1375 * Converts a string to a number. 1376 * 1377 * The function returns non-zero when conversion is not possible. 1378 * In that case the function sets errno to EINVAL when the reason is an invalid character or an unsupported base. 1379 * It sets errno to ERANGE when the target datatype is too small. 1380 * 1381 * @param str the string to convert 1382 * @param output a pointer to the integer variable where the result shall be stored 1383 * @param base 2, 8, 10, or 16 1384 * @param groupsep each character in this string is treated as group separator and ignored during conversion 1385 * @retval zero success 1386 * @retval non-zero conversion was not possible 1387 */ 1388 #define cx_strtouz_lc(str, output, base, groupsep) cx_strtouz_lc(cx_strcast(str), output, base, groupsep) 1389 1390 /** 1391 * @copydoc cx_strtouz() 1392 */ 1393 #define cx_strtos(str, output, base) cx_strtos_lc(str, output, base, ",") 1394 /** 1395 * @copydoc cx_strtouz() 1396 */ 1397 #define cx_strtoi(str, output, base) cx_strtoi_lc(str, output, base, ",") 1398 /** 1399 * @copydoc cx_strtouz() 1400 */ 1401 #define cx_strtol(str, output, base) cx_strtol_lc(str, output, base, ",") 1402 /** 1403 * @copydoc cx_strtouz() 1404 */ 1405 #define cx_strtoll(str, output, base) cx_strtoll_lc(str, output, base, ",") 1406 /** 1407 * @copydoc cx_strtouz() 1408 */ 1409 #define cx_strtoi8(str, output, base) cx_strtoi8_lc(str, output, base, ",") 1410 /** 1411 * @copydoc cx_strtouz() 1412 */ 1413 #define cx_strtoi16(str, output, base) cx_strtoi16_lc(str, output, base, ",") 1414 /** 1415 * @copydoc cx_strtouz() 1416 */ 1417 #define cx_strtoi32(str, output, base) cx_strtoi32_lc(str, output, base, ",") 1418 /** 1419 * @copydoc cx_strtouz() 1420 */ 1421 #define cx_strtoi64(str, output, base) cx_strtoi64_lc(str, output, base, ",") 1422 /** 1423 * @copydoc cx_strtouz() 1424 */ 1425 #define cx_strtoz(str, output, base) cx_strtoz_lc(str, output, base, ",") 1426 /** 1427 * @copydoc cx_strtouz() 1428 */ 1429 #define cx_strtous(str, output, base) cx_strtous_lc(str, output, base, ",") 1430 /** 1431 * @copydoc cx_strtouz() 1432 */ 1433 #define cx_strtou(str, output, base) cx_strtou_lc(str, output, base, ",") 1434 /** 1435 * @copydoc cx_strtouz() 1436 */ 1437 #define cx_strtoul(str, output, base) cx_strtoul_lc(str, output, base, ",") 1438 /** 1439 * @copydoc cx_strtouz() 1440 */ 1441 #define cx_strtoull(str, output, base) cx_strtoull_lc(str, output, base, ",") 1442 /** 1443 * @copydoc cx_strtouz() 1444 */ 1445 #define cx_strtou8(str, output, base) cx_strtou8_lc(str, output, base, ",") 1446 /** 1447 * @copydoc cx_strtouz() 1448 */ 1449 #define cx_strtou16(str, output, base) cx_strtou16_lc(str, output, base, ",") 1450 /** 1451 * @copydoc cx_strtouz() 1452 */ 1453 #define cx_strtou32(str, output, base) cx_strtou32_lc(str, output, base, ",") 1454 /** 1455 * @copydoc cx_strtouz() 1456 */ 1457 #define cx_strtou64(str, output, base) cx_strtou64_lc(str, output, base, ",") 1458 /** 1459 * Converts a string to a number. 1460 * 1461 * The function returns non-zero when conversion is not possible. 1462 * In that case the function sets errno to EINVAL when the reason is an invalid character or an unsupported base. 1463 * It sets errno to ERANGE when the target datatype is too small. 1464 * 1465 * The comma character is treated as group separator and ignored during parsing. 1466 * If you want to choose the set of group separators, use the @c _lc variant of this function (e.g. cx_strtouz_lc()). 1467 * 1468 * @param str the string to convert 1469 * @param output a pointer to the integer variable where the result shall be stored 1470 * @param base 2, 8, 10, or 16 1471 * @retval zero success 1472 * @retval non-zero conversion was not possible 1473 */ 1474 #define cx_strtouz(str, output, base) cx_strtouz_lc(str, output, base, ",") 1475 1476 /** 1477 * Converts a string to a single precision floating point number. 1478 * 1479 * The function returns non-zero when conversion is not possible. 1480 * In that case the function sets errno to EINVAL when the reason is an invalid character. 1481 * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. 1482 * 1483 * The decimal separator is assumed to be a dot character. 1484 * The comma character is treated as group separator and ignored during parsing. 1485 * If you want to choose a different format, use cx_strtof_lc(). 1486 * 1487 * @param str the string to convert 1488 * @param output a pointer to the float variable where the result shall be stored 1489 * @param decsep the decimal separator 1490 * @param groupsep each character in this string is treated as group separator and ignored during conversion 1491 * @retval zero success 1492 * @retval non-zero conversion was not possible 1493 */ 1494 #define cx_strtof_lc(str, output, decsep, groupsep) cx_strtof_lc(cx_strcast(str), output, decsep, groupsep) 1495 /** 1496 * Converts a string to a double precision floating point number. 1497 * 1498 * The function returns non-zero when conversion is not possible. 1499 * In that case the function sets errno to EINVAL when the reason is an invalid character. 1500 * 1501 * The decimal separator is assumed to be a dot character. 1502 * The comma character is treated as group separator and ignored during parsing. 1503 * If you want to choose a different format, use cx_strtof_lc(). 1504 * 1505 * @param str the string to convert 1506 * @param output a pointer to the double variable where the result shall be stored 1507 * @param decsep the decimal separator 1508 * @param groupsep each character in this string is treated as group separator and ignored during conversion 1509 * @retval zero success 1510 * @retval non-zero conversion was not possible 1511 */ 1512 #define cx_strtod_lc(str, output, decsep, groupsep) cx_strtod_lc(cx_strcast(str), output, decsep, groupsep) 1513 1514 /** 1515 * Converts a string to a single precision floating point number. 1516 * 1517 * The function returns non-zero when conversion is not possible. 1518 * In that case the function sets errno to EINVAL when the reason is an invalid character. 1519 * It sets errno to ERANGE when the necessary representation would exceed the limits defined in libc's float.h. 1520 * 1521 * The decimal separator is assumed to be a dot character. 1522 * The comma character is treated as group separator and ignored during parsing. 1523 * If you want to choose a different format, use cx_strtof_lc(). 1524 * 1525 * @param str the string to convert 1526 * @param output a pointer to the float variable where the result shall be stored 1527 * @retval zero success 1528 * @retval non-zero conversion was not possible 1529 */ 1530 #define cx_strtof(str, output) cx_strtof_lc(str, output, '.', ",") 1531 /** 1532 * Converts a string to a double precision floating point number. 1533 * 1534 * The function returns non-zero when conversion is not possible. 1535 * In that case the function sets errno to EINVAL when the reason is an invalid character. 1536 * 1537 * The decimal separator is assumed to be a dot character. 1538 * The comma character is treated as group separator and ignored during parsing. 1539 * If you want to choose a different format, use cx_strtof_lc(). 1540 * 1541 * @param str the string to convert 1542 * @param output a pointer to the double variable where the result shall be stored 1543 * @retval zero success 1544 * @retval non-zero conversion was not possible 1545 */ 1546 #define cx_strtod(str, output) cx_strtod_lc(str, output, '.', ",") 1547 1548 #endif 1549 1550 #ifdef __cplusplus 1551 } // extern "C" 1552 #endif 1553 1554 #endif //UCX_STRING_H 1555