ucx/cx/string.h

branch
dav-2
changeset 894
e86049631677
parent 891
4d58cbcc9efa
equal deleted inserted replaced
893:38800d479cd4 894:e86049631677
38 38
39 #include "common.h" 39 #include "common.h"
40 #include "allocator.h" 40 #include "allocator.h"
41 41
42 #include <string.h> 42 #include <string.h>
43
44 /** Convenience macro for creating a null string */
45 #define CX_NULLSTR cx_mutstr(NULL)
43 46
44 /** Expands a UCX string as printf arguments. */ 47 /** Expands a UCX string as printf arguments. */
45 #define CX_SFMT(s) (int) (s).length, (s).ptr 48 #define CX_SFMT(s) (int) (s).length, (s).ptr
46 49
47 /** Format specifier for a UCX string */ 50 /** Format specifier for a UCX string */
154 * @param cstring the string to wrap (must be zero-terminated) 157 * @param cstring the string to wrap (must be zero-terminated)
155 * @return the wrapped string 158 * @return the wrapped string
156 * 159 *
157 * @see cx_mutstrn() 160 * @see cx_mutstrn()
158 */ 161 */
159 cx_attr_nodiscard cx_attr_cstr_arg(1) 162 CX_NODISCARD CX_CSTR_ARG(1)
160 CX_INLINE cxmutstr cx_mutstr(char *cstring) { 163 CX_INLINE cxmutstr cx_mutstr(char *cstring) {
161 cxmutstr str; 164 cxmutstr str;
162 str.ptr = cstring; 165 str.ptr = cstring;
163 str.length = cstring == NULL ? 0 : strlen(cstring); 166 str.length = cstring == NULL ? 0 : strlen(cstring);
164 return str; 167 return str;
178 * @param length the length of the string 181 * @param length the length of the string
179 * @return the wrapped string 182 * @return the wrapped string
180 * 183 *
181 * @see cx_mutstr() 184 * @see cx_mutstr()
182 */ 185 */
183 cx_attr_nodiscard cx_attr_access_rw(1, 2) 186 CX_NODISCARD CX_ACCESS_RW(1, 2)
184 CX_INLINE cxmutstr cx_mutstrn(char *cstring, size_t length) { 187 CX_INLINE cxmutstr cx_mutstrn(char *cstring, size_t length) {
185 cxmutstr str; 188 cxmutstr str;
186 str.ptr = cstring; 189 str.ptr = cstring;
187 str.length = length; 190 str.length = length;
188 return str; 191 return str;
203 * @param cstring the string to wrap (must be zero-terminated) 206 * @param cstring the string to wrap (must be zero-terminated)
204 * @return the wrapped string 207 * @return the wrapped string
205 * 208 *
206 * @see cx_strn() 209 * @see cx_strn()
207 */ 210 */
208 cx_attr_nodiscard cx_attr_cstr_arg(1) 211 CX_NODISCARD CX_CSTR_ARG(1)
209 CX_INLINE cxstring cx_str(const char *cstring) { 212 CX_INLINE cxstring cx_str(const char *cstring) {
210 cxstring str; 213 cxstring str;
211 str.ptr = cstring; 214 str.ptr = cstring;
212 str.length = cstring == NULL ? 0 : strlen(cstring); 215 str.length = cstring == NULL ? 0 : strlen(cstring);
213 return str; 216 return str;
228 * @param length the length of the string 231 * @param length the length of the string
229 * @return the wrapped string 232 * @return the wrapped string
230 * 233 *
231 * @see cx_str() 234 * @see cx_str()
232 */ 235 */
233 cx_attr_nodiscard cx_attr_access_r(1, 2) 236 CX_NODISCARD CX_ACCESS_R(1, 2)
234 CX_INLINE cxstring cx_strn(const char *cstring, size_t length) { 237 CX_INLINE cxstring cx_strn(const char *cstring, size_t length) {
235 cxstring str; 238 cxstring str;
236 str.ptr = cstring; 239 str.ptr = cstring;
237 str.length = length; 240 str.length = length;
238 return str; 241 return str;
239 } 242 }
240 243
241 #ifdef __cplusplus 244 #ifdef __cplusplus
242 cx_attr_nodiscard 245 CX_NODISCARD
243 CX_CPPDECL cxstring cx_strcast(cxmutstr str) { 246 CX_CPPDECL cxmutstr cx_strcast_m(cxmutstr str) {
247 return str;
248 }
249 CX_NODISCARD
250 CX_CPPDECL cxstring cx_strcast_m(cxstring str) {
251 return str;
252 }
253 CX_NODISCARD
254 CX_CPPDECL cxmutstr cx_strcast_m(char *str) {
255 return cx_mutstr(str);
256 }
257 CX_NODISCARD
258 CX_CPPDECL cxmutstr cx_strcast_m(unsigned char *str) {
259 return cx_mutstr(reinterpret_cast<char*>(str));
260 }
261 CX_NODISCARD
262 CX_CPPDECL cxstring cx_strcast_m(const char *str) {
263 return cx_str(str);
264 }
265 CX_NODISCARD
266 CX_CPPDECL cxstring cx_strcast_m(const unsigned char *str) {
267 return cx_str(reinterpret_cast<const char*>(str));
268 }
269 CX_NODISCARD
270 CX_CPPDECL cxstring cx_strcast_(cxmutstr str) {
244 return cx_strn(str.ptr, str.length); 271 return cx_strn(str.ptr, str.length);
245 } 272 }
246 cx_attr_nodiscard 273 CX_NODISCARD
247 CX_CPPDECL cxstring cx_strcast(cxstring str) { 274 CX_CPPDECL cxstring cx_strcast_(cxstring str) {
248 return str; 275 return str;
249 } 276 }
250 cx_attr_nodiscard 277 #define cx_strcast(s) cx_strcast_(cx_strcast_m(s))
251 CX_CPPDECL cxstring cx_strcast(const char *str) {
252 return cx_str(str);
253 }
254 cx_attr_nodiscard
255 CX_CPPDECL cxstring cx_strcast(const unsigned char *str) {
256 return cx_str(reinterpret_cast<const char*>(str));
257 }
258 extern "C" {
259 #else 278 #else
260 /** 279 /**
261 * Internal function, do not use. 280 * Internal function, do not use.
262 * @param str 281 * @param str
263 * @return 282 * @return
283 * @see cx_strcast_m()
264 * @see cx_strcast() 284 * @see cx_strcast()
265 */ 285 */
266 cx_attr_nodiscard 286 CX_NODISCARD
267 CX_INLINE cxstring cx_strcast_m(cxmutstr str) { 287 CX_INLINE cxmutstr cx_strcast_cxms(cxmutstr str) {
268 return (cxstring) {str.ptr, str.length}; 288 return str;
269 } 289 }
270 /** 290 /**
271 * Internal function, do not use. 291 * Internal function, do not use.
272 * @param str 292 * @param str
273 * @return 293 * @return
294 * @see cx_strcast_m()
274 * @see cx_strcast() 295 * @see cx_strcast()
275 */ 296 */
276 cx_attr_nodiscard 297 CX_NODISCARD
277 CX_INLINE cxstring cx_strcast_c(cxstring str) { 298 CX_INLINE cxstring cx_strcast_cxs(cxstring str) {
278 return str; 299 return str;
279 } 300 }
280 301
281 /** 302 /**
282 * Internal function, do not use. 303 * Internal function, do not use.
283 * @param str 304 * @param str
284 * @return 305 * @return
306 * @see cx_strcast_m()
285 * @see cx_strcast() 307 * @see cx_strcast()
286 */ 308 */
287 cx_attr_nodiscard 309 CX_NODISCARD
288 CX_INLINE cxstring cx_strcast_u(const unsigned char *str) { 310 CX_INLINE cxmutstr cx_strcast_uc(unsigned char *str) {
289 return cx_str((const char*)str); 311 return cx_mutstr((char*)str);
290 } 312 }
291 313
292 /** 314 /**
293 * Internal function, do not use. 315 * Internal function, do not use.
294 * @param str 316 * @param str
295 * @return 317 * @return
318 * @see cx_strcast_m()
296 * @see cx_strcast() 319 * @see cx_strcast()
297 */ 320 */
298 cx_attr_nodiscard 321 CX_NODISCARD
299 CX_INLINE cxstring cx_strcast_z(const char *str) { 322 CX_INLINE cxmutstr cx_strcast_c(char *str) {
323 return cx_mutstr(str);
324 }
325
326 /**
327 * Internal function, do not use.
328 * @param str
329 * @return
330 * @see cx_strcast_m()
331 * @see cx_strcast()
332 */
333 CX_NODISCARD
334 CX_INLINE cxstring cx_strcast_ucc(const unsigned char *str) {
335 return cx_str((const char*)str);
336 }
337
338 /**
339 * Internal function, do not use.
340 * @param str
341 * @return
342 * @see cx_strcast_m()
343 * @see cx_strcast()
344 */
345 CX_NODISCARD
346 CX_INLINE cxstring cx_strcast_cc(const char *str) {
300 return cx_str(str); 347 return cx_str(str);
301 } 348 }
302 349
303 /** 350 /**
304 * Wraps any string into an UCX string. 351 * Wraps any string into an UCX string.
305 * 352 *
306 * @param str (any supported string type) the string to cast 353 * @param str (any supported string type) the string to cast
307 * @return (@c cxstring) the string wrapped as UCX string 354 * @return (@c cxstring) or (@c cxmutstr) the string wrapped as UCX string
308 */ 355 */
309 #define cx_strcast(str) _Generic((str), \ 356 #define cx_strcast_m(str) _Generic((str), \
310 cxmutstr: cx_strcast_m, \ 357 cxstring: cx_strcast_cxs, \
311 cxstring: cx_strcast_c, \ 358 cxmutstr: cx_strcast_cxms, \
312 const unsigned char*: cx_strcast_u, \ 359 const unsigned char*: cx_strcast_ucc, \
313 unsigned char *: cx_strcast_u, \ 360 unsigned char *: cx_strcast_uc, \
314 const char*: cx_strcast_z, \ 361 const char*: cx_strcast_cc, \
315 char *: cx_strcast_z) (str) 362 char *: cx_strcast_c) (str)
363
364 /**
365 * Internal function, do not use.
366 * @param str
367 * @return
368 */
369 CX_INLINE cxstring cx_strcast_1(cxmutstr str) {
370 return (cxstring){str.ptr, str.length};
371 }
372
373 /**
374 * Internal function, do not use.
375 * @param str
376 * @return
377 */
378 CX_INLINE cxstring cx_strcast_2(cxstring str) {
379 return str;
380 }
381
382 /** internal conversion macro */
383 #define cx_strcast_(str) _Generic((str), \
384 cxmutstr: cx_strcast_1, \
385 cxstring: cx_strcast_2)(str)
386
387 /**
388 * Converts any string to a cxstring.
389 *
390 * @param str (any supported string type) the string to cast
391 * @return he string converted to a (@c cxstring)
392 */
393 #define cx_strcast(str) cx_strcast_(cx_strcast_m(str))
316 #endif 394 #endif
395
396 /**
397 * Casts away constness and converts a cxstring to a cxmutstr.
398 * For internal use only!
399 * @param str
400 * @return
401 */
402 CX_INLINE cxmutstr cx_mutstrcast(cxstring str) {
403 cxmutstr s;
404 s.ptr = (char*)str.ptr;
405 s.length = str.length;
406 return s;
407 }
317 408
318 /** 409 /**
319 * Passes the pointer in this string to the cxDefaultAllocator's @c free() function. 410 * Passes the pointer in this string to the cxDefaultAllocator's @c free() function.
320 * 411 *
321 * The pointer in the struct is set to @c NULL, and the length is set to zero, 412 * The pointer in the struct is set to @c NULL, and the length is set to zero,
325 * you ever have a <code>const char*</code> you are really supposed to free. 416 * you ever have a <code>const char*</code> you are really supposed to free.
326 * If you encounter such a situation, you should double-check your code. 417 * If you encounter such a situation, you should double-check your code.
327 * 418 *
328 * @param str the string to free 419 * @param str the string to free
329 */ 420 */
330 CX_EXPORT void cx_strfree(cxmutstr *str); 421 CX_EXTERN
422 void cx_strfree(cxmutstr *str);
331 423
332 /** 424 /**
333 * Passes the pointer in this string to the allocator's free function. 425 * Passes the pointer in this string to the allocator's free function.
334 * 426 *
335 * The pointer in the struct is set to @c NULL, and the length is set to zero, 427 * The pointer in the struct is set to @c NULL, and the length is set to zero,
340 * If you encounter such a situation, you should double-check your code. 432 * If you encounter such a situation, you should double-check your code.
341 * 433 *
342 * @param alloc the allocator 434 * @param alloc the allocator
343 * @param str the string to free 435 * @param str the string to free
344 */ 436 */
345 cx_attr_nonnull_arg(1) 437 CX_EXTERN CX_NONNULL_ARG(1)
346 CX_EXPORT void cx_strfree_a(const CxAllocator *alloc, cxmutstr *str); 438 void cx_strfree_a(const CxAllocator *alloc, cxmutstr *str);
347 439
348 /** 440 /**
349 * Copies a string. 441 * Copies a string.
350 * 442 *
351 * The memory in the @p dest structure is either allocated or re-allocated to fit the entire 443 * Internal function - do not use.
352 * source string, including a zero-terminator.
353 *
354 * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is.
355 * 444 *
356 * @param alloc the allocator 445 * @param alloc the allocator
357 * @param dest a pointer to the structure where to copy the contents to 446 * @param dest a pointer to the structure where to copy the contents to
358 * @param src the source string 447 * @param src the source string
359 * 448 *
360 * @retval zero success 449 * @retval zero success
361 * @retval non-zero if re-allocation failed 450 * @retval non-zero if re-allocation failed
362 */ 451 * @see cx_strcpy_a()
363 cx_attr_nonnull_arg(1) 452 */
364 CX_EXPORT int cx_strcpy_a(const CxAllocator *alloc, cxmutstr *dest, cxstring src); 453 CX_EXTERN CX_NONNULL_ARG(1)
365 454 int cx_strcpy_a_(const CxAllocator *alloc, cxmutstr *dest, cxstring src);
366 455
367 /** 456 /**
368 * Copies a string. 457 * Copies a string.
369 * 458 *
370 * The memory in the @p dest structure is either allocated or re-allocated to fit the entire 459 * The memory in the @p dest structure is either allocated or re-allocated to fit the entire
371 * source string, including a zero-terminator. 460 * source string, including a zero-terminator.
372 * 461 *
373 * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is. 462 * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is.
374 * 463 *
464 * @param alloc (@c CxAllocator*) the allocator
375 * @param dest (@c cxmutstr*) a pointer to the structure where to copy the contents to 465 * @param dest (@c cxmutstr*) a pointer to the structure where to copy the contents to
376 * @param src (@c cxstring) the source string 466 * @param src the source string
377 * 467 * @retval zero success
468 * @retval non-zero if re-allocation failed
469 */
470 #define cx_strcpy_a(alloc, dest, src) cx_strcpy_a_(alloc, dest, cx_strcast(src))
471
472 /**
473 * Copies a string.
474 *
475 * The memory in the @p dest structure is either allocated or re-allocated to fit the entire
476 * source string, including a zero-terminator.
477 *
478 * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is.
479 *
480 * @param dest (@c cxmutstr*) a pointer to the structure where to copy the contents to
481 * @param src the source string
378 * @retval zero success 482 * @retval zero success
379 * @retval non-zero if re-allocation failed 483 * @retval non-zero if re-allocation failed
380 */ 484 */
381 #define cx_strcpy(dest, src) cx_strcpy_a(cxDefaultAllocator, dest, src) 485 #define cx_strcpy(dest, src) cx_strcpy_a(cxDefaultAllocator, dest, src)
382 486
390 * 494 *
391 * @param count the total number of specified strings 495 * @param count the total number of specified strings
392 * @param ... all strings 496 * @param ... all strings
393 * @return the accumulated length of all strings 497 * @return the accumulated length of all strings
394 */ 498 */
395 cx_attr_nodiscard 499 CX_EXTERN CX_NODISCARD
396 CX_EXPORT size_t cx_strlen(size_t count, ...); 500 size_t cx_strlen(size_t count, ...);
397 501
398 /** 502 /**
399 * Concatenates strings. 503 * Concatenates strings.
400 * 504 *
401 * The resulting string will be allocated by the specified allocator. 505 * The resulting string will be allocated by the specified allocator.
402 * So developers @em must pass the return value to cx_strfree_a() eventually. 506 * So developers @em must pass the return value to cx_strfree_a() eventually.
403 * 507 *
404 * If @p str already contains a string, the memory will be reallocated and 508 * If @p str already contains a string, the memory will be reallocated and
405 * the other strings are appended. Otherwise, new memory is allocated. 509 * the other strings are appended. Otherwise, new memory is allocated.
406 *
407 * If memory allocation fails, the pointer in the returned string will
408 * be @c NULL. Depending on the allocator, @c errno might be set.
409 * 510 *
410 * @note It is guaranteed that there is only one allocation for the 511 * @note It is guaranteed that there is only one allocation for the
411 * resulting string. 512 * resulting string.
412 * It is also guaranteed that the returned string is zero-terminated. 513 * It is also guaranteed that the returned string is zero-terminated.
514 * If allocation fails, the @c ptr in the returned string will be @c NULL.
413 * 515 *
414 * @param alloc the allocator to use 516 * @param alloc the allocator to use
415 * @param str the string the other strings shall be concatenated to 517 * @param str the string the other strings shall be concatenated to
416 * @param count the number of the other following strings to concatenate 518 * @param count the number of the other following strings to concatenate
417 * @param ... all other UCX strings 519 * @param ... all other UCX strings
418 * @return the concatenated string 520 * @return the concatenated string
419 */ 521 */
420 cx_attr_nodiscard cx_attr_nonnull 522 CX_EXTERN CX_NONNULL
421 CX_EXPORT cxmutstr cx_strcat_ma(const CxAllocator *alloc, 523 cxmutstr cx_strcat_a(const CxAllocator *alloc,
422 cxmutstr str, size_t count, ...); 524 cxmutstr str, size_t count, ...);
423 525
424 /** 526 /**
425 * Concatenates strings and returns a new string. 527 * Concatenates strings and returns a new string.
426 * 528 *
427 * The resulting string will be allocated by the specified allocator. 529 * The resulting string will be allocated by the cxDefaultAllocator.
428 * So developers @em must pass the return value to cx_strfree_a() eventually. 530 * So developers @em must pass the return value to cx_strfree() eventually.
429 *
430 * If memory allocation fails, the pointer in the returned string will
431 * be @c NULL. Depending on the allocator, @c errno might be set.
432 * 531 *
433 * @note It is guaranteed that there is only one allocation for the 532 * @note It is guaranteed that there is only one allocation for the
434 * resulting string. 533 * resulting string.
435 * It is also guaranteed that the returned string is zero-terminated. 534 * It is also guaranteed that the returned string is zero-terminated.
436 * 535 * If allocation fails, the @c ptr in the returned string will be @c NULL.
437 * @param alloc (@c CxAllocator*) the allocator to use 536 *
438 * @param count (@c size_t) the number of the other following strings to concatenate 537 * @param str (@c cxmutstr*) the string the other strings shall be concatenated to
439 * @param ... all other UCX strings
440 * @return (@c cxmutstr) the concatenated string
441 */
442 #define cx_strcat_a(alloc, count, ...) \
443 cx_strcat_ma(alloc, cx_mutstrn(NULL, 0), count, __VA_ARGS__)
444
445 /**
446 * Concatenates strings and returns a new string.
447 *
448 * The resulting string will be allocated by the cxDefaultAllocator.
449 * So developers @em must pass the return value to cx_strfree() eventually.
450 *
451 * If memory allocation fails, the pointer in the returned string will
452 * be @c NULL and @c errno might be set.
453 *
454 * @note It is guaranteed that there is only one allocation for the
455 * resulting string.
456 * It is also guaranteed that the returned string is zero-terminated.
457 *
458 * @param count (@c size_t) the number of the other following strings to concatenate 538 * @param count (@c size_t) the number of the other following strings to concatenate
459 * @param ... all other UCX strings 539 * @param ... all other UCX strings
460 * @return (@c cxmutstr) the concatenated string 540 * @return the concatenated string
461 */ 541 */
462 #define cx_strcat(count, ...) \ 542 #define cx_strcat(str, count, ...) \
463 cx_strcat_ma(cxDefaultAllocator, cx_mutstrn(NULL, 0), count, __VA_ARGS__) 543 cx_strcat_a(cxDefaultAllocator, str, count, __VA_ARGS__)
464 544
465 /** 545 /**
466 * Concatenates strings. 546 * Returns a substring.
467 * 547 *
468 * The resulting string will be allocated by the cxDefaultAllocator. 548 * Internal function - do not use.
469 * So developers @em must pass the return value to cx_strfree() eventually.
470 *
471 * If @p str already contains a string, the memory will be reallocated and
472 * the other strings are appended. Otherwise, new memory is allocated.
473 *
474 * If memory allocation fails, the pointer in the returned string will
475 * be @c NULL and @c errno might be set.
476 *
477 * @note It is guaranteed that there is only one allocation for the
478 * resulting string.
479 * It is also guaranteed that the returned string is zero-terminated.
480 *
481 * @param str (@c cxmutstr) the string the other strings shall be concatenated to
482 * @param count (@c size_t) the number of the other following strings to concatenate
483 * @param ... all other strings
484 * @return (@c cxmutstr) the concatenated string
485 */
486 #define cx_strcat_m(str, count, ...) \
487 cx_strcat_ma(cxDefaultAllocator, str, count, __VA_ARGS__)
488
489 /**
490 * Returns a substring starting at the specified location.
491 *
492 * @attention the new string references the same memory area as the
493 * input string and is usually @em not zero-terminated.
494 * Use cx_strdup() to get a copy.
495 *
496 * @param string input string
497 * @param start start location of the substring
498 * @return a substring of @p string starting at @p start
499 *
500 * @see cx_strsubsl()
501 * @see cx_strsubs_m()
502 * @see cx_strsubsl_m()
503 */
504 cx_attr_nodiscard
505 CX_EXPORT cxstring cx_strsubs(cxstring string, size_t start);
506
507 /**
508 * Returns a substring starting at the specified location.
509 *
510 * The returned string will be limited to @p length bytes or the number
511 * of bytes available in @p string, whichever is smaller.
512 *
513 * @attention the new string references the same memory area as the
514 * input string and is usually @em not zero-terminated.
515 * Use cx_strdup() to get a copy.
516 * 549 *
517 * @param string input string 550 * @param string input string
518 * @param start start location of the substring 551 * @param start start location of the substring
519 * @param length the maximum length of the returned string 552 * @param length the maximum length of the returned string
520 * @return a substring of @p string starting at @p start 553 * @return a substring of @p string starting at @p start
521 * 554 * @see cx_strsubsl()
522 * @see cx_strsubs() 555 */
523 * @see cx_strsubs_m() 556 CX_EXTERN CX_NODISCARD
524 * @see cx_strsubsl_m() 557 cxstring cx_strsubsl_(cxstring string, size_t start, size_t length);
525 */ 558
526 cx_attr_nodiscard 559 /**
527 CX_EXPORT cxstring cx_strsubsl(cxstring string, size_t start, size_t length); 560 * Returns a substring.
528 561 *
529 /** 562 * Internal function - do not use.
530 * Returns a substring starting at the specified location.
531 *
532 * @attention the new string references the same memory area as the
533 * input string and is usually @em not zero-terminated.
534 * Use cx_strdup() to get a copy.
535 * 563 *
536 * @param string input string 564 * @param string input string
537 * @param start start location of the substring 565 * @param start start location of the substring
538 * @return a substring of @p string starting at @p start 566 * @return a substring of @p string starting at @p start
539 *
540 * @see cx_strsubsl_m()
541 * @see cx_strsubs() 567 * @see cx_strsubs()
568 */
569 CX_EXTERN CX_NODISCARD
570 cxstring cx_strsubs_(cxstring string, size_t start);
571
572 /**
573 * Internal conversion function - do not use.
574 * @param string
575 * @param start
576 * @return
577 */
578 CX_INLINE
579 cxmutstr cx_strsubs_m_(cxmutstr string, size_t start) {
580 return cx_mutstrcast(cx_strsubs_(cx_strcast(string), start));
581 }
582
583 /**
584 * Internal conversion function - do not use.
585 * @param string
586 * @param start
587 * @param length
588 * @return
589 */
590 CX_INLINE
591 cxmutstr cx_strsubsl_m_(cxmutstr string, size_t start, size_t length) {
592 return cx_mutstrcast(cx_strsubsl_(cx_strcast(string), start, length));
593 }
594
595 #ifdef __cplusplus
596 CX_CPPDECL cxstring cx_strsubs_cpp_(cxstring string, size_t start) {
597 return cx_strsubs_(string, start);
598 }
599 CX_CPPDECL cxstring cx_strsubsl_cpp_(cxstring string, size_t start, size_t length) {
600 return cx_strsubsl_(string, start, length);
601 }
602 CX_CPPDECL cxmutstr cx_strsubs_cpp_(cxmutstr string, size_t start) {
603 return cx_strsubs_m_(string, start);
604 }
605 CX_CPPDECL cxmutstr cx_strsubsl_cpp_(cxmutstr string, size_t start, size_t length) {
606 return cx_strsubsl_m_(string, start, length);
607 }
608 #define cx_strsubs(string, start) cx_strsubs_cpp_(cx_strcast_m(string), start)
609 #define cx_strsubsl(string, start, length) cx_strsubsl_cpp_(cx_strcast_m(string), start, length)
610 #else
611 /**
612 * Returns a substring starting at the specified location.
613 *
614 * @attention the new string references the same memory area as the
615 * input string and is @em not zero-terminated.
616 * Use cx_strdup() to get a copy.
617 *
618 * @param string input string
619 * @param start (@c size_t) start location of the substring
620 * @return (@c cxstring or @c cxmutstr) a substring of @p string starting at @p start
621 *
542 * @see cx_strsubsl() 622 * @see cx_strsubsl()
543 */ 623 */
544 cx_attr_nodiscard 624 #define cx_strsubs(string, start) _Generic(cx_strcast_m(string), \
545 CX_EXPORT cxmutstr cx_strsubs_m(cxmutstr string, size_t start); 625 cxstring: cx_strsubs_, \
626 cxmutstr: cx_strsubs_m_)(cx_strcast_m(string), start)
546 627
547 /** 628 /**
548 * Returns a substring starting at the specified location. 629 * Returns a substring starting at the specified location.
549 * 630 *
550 * The returned string will be limited to @p length bytes or the number 631 * The returned string will be limited to @p length bytes or the number
557 * @param string input string 638 * @param string input string
558 * @param start start location of the substring 639 * @param start start location of the substring
559 * @param length the maximum length of the returned string 640 * @param length the maximum length of the returned string
560 * @return a substring of @p string starting at @p start 641 * @return a substring of @p string starting at @p start
561 * 642 *
562 * @see cx_strsubs_m()
563 * @see cx_strsubs() 643 * @see cx_strsubs()
564 * @see cx_strsubsl() 644 */
565 */ 645 #define cx_strsubsl(string, start, length) _Generic(cx_strcast_m(string), \
566 cx_attr_nodiscard 646 cxstring: cx_strsubsl_, \
567 CX_EXPORT cxmutstr cx_strsubsl_m(cxmutstr string, size_t start, size_t length); 647 cxmutstr: cx_strsubsl_m_)(cx_strcast_m(string), start, length)
648 #endif
649
650 /**
651 * Returns the character at the specified index offset.
652 *
653 * Internal function - do not use.
654 *
655 * @param str the string
656 * @param index the index offset
657 * @return the character at the index
658 * @see cx_strat()
659 */
660 CX_INLINE
661 char cx_strat_(cxstring str, off_t index) {
662 size_t i;
663 if (index >= 0) {
664 i = index;
665 } else {
666 i = (size_t) (str.length + index);
667 }
668 if (i >= str.length) {
669 return '\0';
670 }
671 return str.ptr[i];
672 }
673
674 /**
675 * Returns the character at the specified index offset.
676 *
677 * When the @p index is negative, the character is counted from the end of the
678 * string where -1 denotes the last character in the string.
679 *
680 * When the @p index is out of bounds, the function returns zero.
681 *
682 * @param str the string
683 * @param index the index offset
684 * @return the character at the index
685 * @see cx_strat()
686 */
687 #define cx_strat(str, index) cx_strat_(cx_strcast(str), index)
688
689 /**
690 * Searches for a character in a string.
691 * Internal function - do not use.
692 * @param string
693 * @param chr
694 * @return
695 * @see cx_strchr()
696 */
697 CX_EXTERN CX_NODISCARD
698 cxstring cx_strchr_(cxstring string, int chr);
699
700 /**
701 * Searches for a character in a string.
702 * Internal function - do not use.
703 * @param string
704 * @param chr
705 * @return
706 * @see cx_strrchr()
707 */
708 CX_EXTERN CX_NODISCARD
709 cxstring cx_strrchr_(cxstring string, int chr);
710
711 #ifdef __cplusplus
712 CX_CPPDECL cxstring cx_strchr_cpp_(cxstring string, int chr) {
713 return cx_strchr_(string, chr);
714 }
715 CX_CPPDECL cxmutstr cx_strchr_cpp_(cxmutstr string, int chr) {
716 return cx_mutstrcast(cx_strchr_(cx_strcast(string), chr));
717 }
718 #define cx_strchr(s, chr) cx_strchr_cpp_(cx_strcast_m(s), chr)
719 CX_CPPDECL cxstring cx_strrchr_cpp_(cxstring string, int chr) {
720 return cx_strrchr_(string, chr);
721 }
722 CX_CPPDECL cxmutstr cx_strrchr_cpp_(cxmutstr string, int chr) {
723 return cx_mutstrcast(cx_strrchr_(cx_strcast(string), chr));
724 }
725 #define cx_strrchr(s, chr) cx_strrchr_cpp_(cx_strcast_m(s), chr)
726 #else
727 /**
728 * Internal conversion function - do not use.
729 * @param string
730 * @param chr
731 * @return
732 */
733 CX_INLINE cxmutstr cx_strchr_m_(cxmutstr string, int chr) {
734 return cx_mutstrcast(cx_strchr_(cx_strcast(string), chr));
735 }
736 /**
737 * Internal conversion function - do not use.
738 * @param string
739 * @param chr
740 * @return
741 */
742 CX_INLINE cxmutstr cx_strrchr_m_(cxmutstr string, int chr) {
743 return cx_mutstrcast(cx_strrchr_(cx_strcast(string), chr));
744 }
568 745
569 /** 746 /**
570 * Returns a substring starting at the location of the first occurrence of the 747 * Returns a substring starting at the location of the first occurrence of the
571 * specified character. 748 * specified character.
572 * 749 *
573 * If the string does not contain the character, an empty string is returned. 750 * If the string does not contain the character, an empty string is returned.
574 * 751 *
575 * @param string the string where to locate the character 752 * @param string the string where to locate the character
576 * @param chr the character to locate 753 * @param chr (@c int) the character to locate
577 * @return a substring starting at the first location of @p chr 754 * @return (@c cxstring or @c cxmutstr) a substring starting at the first
578 * 755 * location of @p chr
579 * @see cx_strchr_m() 756 */
580 */ 757 #define cx_strchr(string, chr) _Generic(cx_strcast_m(string), \
581 cx_attr_nodiscard 758 cxstring: cx_strchr_, \
582 CX_EXPORT cxstring cx_strchr(cxstring string, int chr); 759 cxmutstr: cx_strchr_m_)(cx_strcast_m(string), chr)
583
584 /**
585 * Returns a substring starting at the location of the first occurrence of the
586 * specified character.
587 *
588 * If the string does not contain the character, an empty string is returned.
589 *
590 * @param string the string where to locate the character
591 * @param chr the character to locate
592 * @return a substring starting at the first location of @p chr
593 *
594 * @see cx_strchr()
595 */
596 cx_attr_nodiscard
597 CX_EXPORT cxmutstr cx_strchr_m(cxmutstr string, int chr);
598 760
599 /** 761 /**
600 * Returns a substring starting at the location of the last occurrence of the 762 * Returns a substring starting at the location of the last occurrence of the
601 * specified character. 763 * specified character.
602 * 764 *
603 * If the string does not contain the character, an empty string is returned. 765 * If the string does not contain the character, an empty string is returned.
604 * 766 *
605 * @param string the string where to locate the character 767 * @param string the string where to locate the character
606 * @param chr the character to locate 768 * @param chr (@c int) the character to locate
607 * @return a substring starting at the last location of @p chr 769 * @return (@c cxstring or @c cxmutstr) a substring starting at the last
608 * 770 * location of @p chr
609 * @see cx_strrchr_m() 771 */
610 */ 772 #define cx_strrchr(string, chr) _Generic(cx_strcast_m(string), \
611 cx_attr_nodiscard 773 cxstring: cx_strrchr_, \
612 CX_EXPORT cxstring cx_strrchr(cxstring string, int chr); 774 cxmutstr: cx_strrchr_m_)(cx_strcast_m(string), chr)
613 775 #endif
614 /** 776
615 * Returns a substring starting at the location of the last occurrence of the 777 /**
616 * specified character. 778 * Searches for a specific substring.
617 * 779 *
618 * If the string does not contain the character, an empty string is returned. 780 * Internal function - do not use.
619 * 781 *
620 * @param string the string where to locate the character 782 * @param haystack the string to be scanned
621 * @param chr the character to locate 783 * @param needle string containing the sequence of characters to match
622 * @return a substring starting at the last location of @p chr 784 * @return a substring starting at the first occurrence of @p needle,
623 * 785 * or an empty string, if the sequence is not contained
624 * @see cx_strrchr() 786 * @see cx_strstr()
625 */ 787 */
626 cx_attr_nodiscard 788 CX_EXTERN CX_NODISCARD
627 CX_EXPORT cxmutstr cx_strrchr_m(cxmutstr string, int chr); 789 cxstring cx_strstr_(cxstring haystack, cxstring needle);
790
791 #ifdef __cplusplus
792 CX_CPPDECL cxstring cx_strstr_cpp_(cxstring haystack, cxstring needle) {
793 return cx_strstr_(haystack, needle);
794 }
795 CX_CPPDECL cxmutstr cx_strstr_cpp_(cxmutstr haystack, cxstring needle) {
796 return cx_mutstrcast(cx_strstr_(cx_strcast(haystack), needle));
797 }
798 #define cx_strstr(h,n) cx_strstr_cpp_(cx_strcast_m(h), cx_strcast(n))
799 #else
800 /**
801 * Internal conversion - do not use.
802 * @param haystack
803 * @param needle
804 * @return
805 */
806 CX_INLINE cxmutstr cx_strstr_m_(cxmutstr haystack, cxstring needle) {
807 return cx_mutstrcast(cx_strstr_(cx_strcast(haystack), needle));
808 }
628 809
629 /** 810 /**
630 * Returns a substring starting at the location of the first occurrence of the 811 * Returns a substring starting at the location of the first occurrence of the
631 * specified string. 812 * specified string.
632 * 813 *
634 * 815 *
635 * If @p needle is an empty string, the complete @p haystack is 816 * If @p needle is an empty string, the complete @p haystack is
636 * returned. 817 * returned.
637 * 818 *
638 * @param haystack the string to be scanned 819 * @param haystack the string to be scanned
639 * @param needle string containing the sequence of characters to match 820 * @param needle string containing the sequence of characters to match
640 * @return a substring starting at the first occurrence of 821 * @return (@c cxstring or @c cxmutstr) a substring starting at the first
641 * @p needle, or an empty string, if the sequence is not 822 * occurrence of @p needle, or an empty string, if the sequence is not contained
642 * contained 823 */
643 * @see cx_strstr_m() 824 #define cx_strstr(haystack, needle) _Generic(cx_strcast_m(haystack), \
644 */ 825 cxstring: cx_strstr_,\
645 cx_attr_nodiscard 826 cxmutstr: cx_strstr_m_)(cx_strcast_m(haystack), cx_strcast(needle))
646 CX_EXPORT cxstring cx_strstr(cxstring haystack, cxstring needle); 827 #endif
647
648 /**
649 * Returns a substring starting at the location of the first occurrence of the
650 * specified string.
651 *
652 * If @p haystack does not contain @p needle, an empty string is returned.
653 *
654 * If @p needle is an empty string, the complete @p haystack is
655 * returned.
656 *
657 * @param haystack the string to be scanned
658 * @param needle string containing the sequence of characters to match
659 * @return a substring starting at the first occurrence of
660 * @p needle, or an empty string, if the sequence is not
661 * contained
662 * @see cx_strstr()
663 */
664 cx_attr_nodiscard
665 CX_EXPORT cxmutstr cx_strstr_m(cxmutstr haystack, cxstring needle);
666 828
667 /** 829 /**
668 * Splits a given string using a delimiter string. 830 * Splits a given string using a delimiter string.
669 * 831 *
670 * @note The resulting array contains strings that point to the source 832 * Internal function - do not use.
671 * @p string. Use cx_strdup() to get copies.
672 * 833 *
673 * @param string the string to split 834 * @param string the string to split
674 * @param delim the delimiter 835 * @param delim the delimiter
675 * @param limit the maximum number of split items 836 * @param limit the maximum number of split items
676 * @param output a preallocated array of at least @p limit length 837 * @param output the output array
677 * @return the actual number of split items 838 * @return the actual number of split items
678 */ 839 * @see cx_strsplit()
679 cx_attr_nodiscard cx_attr_nonnull cx_attr_access_w(4, 3) 840 */
680 CX_EXPORT size_t cx_strsplit(cxstring string, cxstring delim, 841 CX_EXTERN CX_NODISCARD CX_NONNULL CX_ACCESS_W(4, 3)
842 size_t cx_strsplit_(cxstring string, cxstring delim,
681 size_t limit, cxstring *output); 843 size_t limit, cxstring *output);
682 844
683 /** 845 /**
684 * Splits a given string using a delimiter string. 846 * Splits a given string using a delimiter string.
685 * 847 *
686 * The array pointed to by @p output will be allocated by @p allocator. 848 * Internal function - do not use.
687 *
688 * @note The resulting array contains strings that point to the source
689 * @p string. Use cx_strdup() to get copies.
690 *
691 * @attention If allocation fails, the @c NULL pointer will be written to
692 * @p output and the number returned will be zero.
693 * 849 *
694 * @param allocator the allocator to use for allocating the resulting array 850 * @param allocator the allocator to use for allocating the resulting array
695 * @param string the string to split 851 * @param string the string to split
696 * @param delim the delimiter 852 * @param delim the delimiter
697 * @param limit the maximum number of split items 853 * @param limit the maximum number of split items
698 * @param output a pointer where the address of the allocated array shall be 854 * @param output the output array
699 * written to
700 * @return the actual number of split items 855 * @return the actual number of split items
701 */ 856 * @see cx_strsplit_a()
702 cx_attr_nodiscard cx_attr_nonnull cx_attr_access_w(5) 857 */
703 CX_EXPORT size_t cx_strsplit_a(const CxAllocator *allocator, 858 CX_EXTERN CX_NODISCARD CX_NONNULL CX_ACCESS_W(5)
859 size_t cx_strsplit_a_(const CxAllocator *allocator,
704 cxstring string, cxstring delim, 860 cxstring string, cxstring delim,
705 size_t limit, cxstring **output); 861 size_t limit, cxstring **output);
706 862
707 863
708 /** 864 /**
709 * Splits a given string using a delimiter string. 865 * Splits a given string using a delimiter string.
710 * 866 *
711 * @note The resulting array contains strings that point to the source 867 * Internal function - do not use.
712 * @p string. Use cx_strdup() to get copies.
713 * 868 *
714 * @param string the string to split 869 * @param string the string to split
715 * @param delim the delimiter 870 * @param delim the delimiter
716 * @param limit the maximum number of split items 871 * @param limit the maximum number of split items
717 * @param output a preallocated array of at least @p limit length 872 * @param output the output array
718 * @return the actual number of split items 873 * @return the actual number of split items
719 */ 874 * @see cx_strsplit_m()
720 cx_attr_nodiscard cx_attr_nonnull cx_attr_access_w(4, 3) 875 */
721 CX_EXPORT size_t cx_strsplit_m(cxmutstr string, cxstring delim, 876 CX_EXTERN CX_NODISCARD CX_NONNULL CX_ACCESS_W(4, 3)
877 size_t cx_strsplit_m_(cxmutstr string, cxstring delim,
722 size_t limit, cxmutstr *output); 878 size_t limit, cxmutstr *output);
723 879
724 /** 880 /**
725 * Splits a given string using a delimiter string. 881 * Splits a given string using a delimiter string.
726 * 882 *
727 * The array pointed to by @p output will be allocated by @p allocator. 883 * Internal function - do not use.
728 *
729 * @note The resulting array contains strings that point to the source
730 * @p string. Use cx_strdup() to get copies.
731 *
732 * @attention If allocation fails, the @c NULL pointer will be written to
733 * @p output and the number returned will be zero.
734 * 884 *
735 * @param allocator the allocator to use for allocating the resulting array 885 * @param allocator the allocator to use for allocating the resulting array
736 * @param string the string to split 886 * @param string the string to split
737 * @param delim the delimiter 887 * @param delim the delimiter
738 * @param limit the maximum number of split items 888 * @param limit the maximum number of split items
739 * @param output a pointer where the address of the allocated array shall be 889 * @param output the output array
740 * written to
741 * @return the actual number of split items 890 * @return the actual number of split items
742 */ 891 * @see cx_strsplit_ma()
743 cx_attr_nodiscard cx_attr_nonnull cx_attr_access_w(5) 892 */
744 CX_EXPORT size_t cx_strsplit_ma(const CxAllocator *allocator, 893 CX_EXTERN CX_NODISCARD CX_NONNULL CX_ACCESS_W(5)
894 size_t cx_strsplit_ma_(const CxAllocator *allocator,
745 cxmutstr string, cxstring delim, size_t limit, 895 cxmutstr string, cxstring delim, size_t limit,
746 cxmutstr **output); 896 cxmutstr **output);
897
898 #ifdef __cplusplus
899 CX_CPPDECL size_t cx_strsplit_cpp_(cxstring string, cxstring delim,
900 size_t limit, cxstring *output) {
901 return cx_strsplit_(string, delim, limit, output);
902 }
903 CX_CPPDECL size_t cx_strsplit_cpp_(cxmutstr string, cxstring delim,
904 size_t limit, cxmutstr *output) {
905 return cx_strsplit_m_(string, delim, limit, output);
906 }
907 CX_CPPDECL size_t cx_strsplit_a_cpp_(const CxAllocator *allocator,
908 cxstring string, cxstring delim, size_t limit, cxstring **output) {
909 return cx_strsplit_a_(allocator, string, delim, limit, output);
910 }
911 CX_CPPDECL size_t cx_strsplit_a_cpp_(const CxAllocator *allocator,
912 cxmutstr string, cxstring delim, size_t limit, cxmutstr **output) {
913 return cx_strsplit_ma_(allocator, string, delim, limit, output);
914 }
915 #define cx_strsplit(string, delim, limit, output) \
916 cx_strsplit_cpp_(cx_strcast_m(string), cx_strcast(delim), limit, output)
917 #define cx_strsplit_a(allocator, string, delim, limit, output) \
918 cx_strsplit_a_cpp_(allocator, cx_strcast_m(string), cx_strcast(delim), limit, output)
919 #else
920 /**
921 * Splits a given string using a delimiter string.
922 *
923 * @note The resulting array contains strings that point to the source
924 * @p string. Use cx_strdup() to get copies.
925 *
926 * @param string the string to split
927 * @param delim the delimiter
928 * @param limit (@c size_t) the maximum number of split items
929 * @param output (@c cxstring* or @c cxmutstr*) a preallocated array of at
930 * least @p limit length
931 * @return the actual number of split items
932 */
933 #define cx_strsplit(string, delim, limit, output) \
934 _Generic(cx_strcast_m(string), \
935 cxstring: cx_strsplit_, \
936 cxmutstr: cx_strsplit_m_)\
937 (cx_strcast_m(string), cx_strcast(delim), limit, output)
938
939 /**
940 * Splits a given string using a delimiter string.
941 *
942 * The array pointed to by @p output will be allocated by @p allocator.
943 *
944 * @note The resulting array contains strings that point to the source
945 * @p string. Use cx_strdup() to get copies.
946 *
947 * @attention If allocation fails, the @c NULL pointer will be written to
948 * @p output and the number returned will be zero.
949 *
950 * @param allocator (@c CxAllocator*) the allocator to use for allocating the resulting array
951 * @param string the string to split
952 * @param delim the delimiter
953 * @param limit (@c size_t) the maximum number of split items
954 * @param output (@c cxstring** or @c cxmutstr**) a pointer where the address
955 * of the allocated array shall be written to
956 * @return the actual number of split items
957 */
958 #define cx_strsplit_a(allocator, string, delim, limit, output) \
959 _Generic(cx_strcast_m(string), \
960 cxstring: cx_strsplit_a_, \
961 cxmutstr: cx_strsplit_ma_)\
962 (allocator, cx_strcast_m(string), cx_strcast(delim), limit, output)
963 #endif
747 964
748 /** 965 /**
749 * Compares two strings. 966 * Compares two strings.
750 * 967 *
751 * @param s1 the first string 968 * @param s1 the first string
752 * @param s2 the second string 969 * @param s2 the second string
753 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 970 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger
754 * than @p s2, zero if both strings equal 971 * than @p s2, zero if both strings equal
755 */ 972 */
756 cx_attr_nodiscard 973 CX_EXTERN CX_NODISCARD
757 CX_EXPORT int cx_strcmp_(cxstring s1, cxstring s2); 974 int cx_strcmp_(cxstring s1, cxstring s2);
758 975
759 /** 976 /**
760 * Compares two strings. 977 * Compares two strings.
761 * 978 *
762 * @param s1 the first string 979 * @param s1 the first string
772 * @param s1 the first string 989 * @param s1 the first string
773 * @param s2 the second string 990 * @param s2 the second string
774 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 991 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger
775 * than @p s2, zero if both strings equal ignoring case 992 * than @p s2, zero if both strings equal ignoring case
776 */ 993 */
777 cx_attr_nodiscard 994 CX_EXTERN CX_NODISCARD
778 CX_EXPORT int cx_strcasecmp_(cxstring s1, cxstring s2); 995 int cx_strcasecmp_(cxstring s1, cxstring s2);
779 996
780 /** 997 /**
781 * Compares two strings ignoring case. 998 * Compares two strings ignoring case.
782 * 999 *
783 * @param s1 the first string 1000 * @param s1 the first string
798 * @param s1 the first string 1015 * @param s1 the first string
799 * @param s2 the second string 1016 * @param s2 the second string
800 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 1017 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger
801 * than @p s2, zero if both strings equal 1018 * than @p s2, zero if both strings equal
802 */ 1019 */
803 cx_attr_nodiscard cx_attr_nonnull 1020 CX_EXTERN CX_NODISCARD CX_NONNULL
804 CX_EXPORT int cx_strcmp_p(const void *s1, const void *s2); 1021 int cx_strcmp_p(const void *s1, const void *s2);
805 1022
806 /** 1023 /**
807 * Compares two strings ignoring case. 1024 * Compares two strings ignoring case.
808 * 1025 *
809 * This function has a compatible signature for the use as a cx_compare_func. 1026 * This function has a compatible signature for the use as a cx_compare_func.
811 * @param s1 the first string 1028 * @param s1 the first string
812 * @param s2 the second string 1029 * @param s2 the second string
813 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger 1030 * @return negative if @p s1 is smaller than @p s2, positive if @p s1 is larger
814 * than @p s2, zero if both strings equal ignoring case 1031 * than @p s2, zero if both strings equal ignoring case
815 */ 1032 */
816 cx_attr_nodiscard cx_attr_nonnull 1033 CX_EXTERN CX_NODISCARD CX_NONNULL
817 CX_EXPORT int cx_strcasecmp_p(const void *s1, const void *s2); 1034 int cx_strcasecmp_p(const void *s1, const void *s2);
818
819 1035
820 /** 1036 /**
821 * Creates a duplicate of the specified string. 1037 * Creates a duplicate of the specified string.
822 * 1038 *
823 * The new string will contain a copy allocated by @p allocator. 1039 * The new string will contain a copy allocated by @p allocator.
827 * @param allocator the allocator to use 1043 * @param allocator the allocator to use
828 * @param string the string to duplicate 1044 * @param string the string to duplicate
829 * @return a duplicate of the string 1045 * @return a duplicate of the string
830 * @see cx_strdup() 1046 * @see cx_strdup()
831 */ 1047 */
832 cx_attr_nodiscard cx_attr_nonnull 1048 CX_EXTERN CX_NODISCARD CX_NONNULL
833 CX_EXPORT cxmutstr cx_strdup_a_(const CxAllocator *allocator, cxstring string); 1049 cxmutstr cx_strdup_a_(const CxAllocator *allocator, cxstring string);
834 1050
835 /** 1051 /**
836 * Creates a duplicate of the specified string. 1052 * Creates a duplicate of the specified string.
837 * 1053 *
838 * The new string will contain a copy allocated by @p allocator. 1054 * The new string will contain a copy allocated by @p allocator.
861 * @see cx_strfree() 1077 * @see cx_strfree()
862 */ 1078 */
863 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string) 1079 #define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string)
864 1080
865 /** 1081 /**
1082 * Trims a string.
1083 * Internal function - do not use.
1084 * @param string
1085 * @return
1086 */
1087 CX_EXTERN CX_NODISCARD
1088 cxstring cx_strtrim_(cxstring string);
1089
1090 #ifdef __cplusplus
1091 CX_CPPDECL cxstring cx_strtrim_cpp_(cxstring string) {
1092 return cx_strtrim_(string);
1093 }
1094 CX_CPPDECL cxmutstr cx_strtrim_cpp_(cxmutstr string) {
1095 return cx_mutstrcast(cx_strtrim_(cx_strcast(string)));
1096 }
1097 #define cx_strtrim(string) cx_strtrim_cpp_(cx_strcast_m(string))
1098 #else
1099 /**
1100 * Internal conversion function.
1101 * @param string
1102 * @return
1103 */
1104 CX_INLINE cxmutstr cx_strtrim_m_(cxmutstr string) {
1105 return cx_mutstrcast(cx_strtrim_(cx_strcast(string)));
1106 }
1107
1108 /**
866 * Omits leading and trailing spaces. 1109 * Omits leading and trailing spaces.
867 * 1110 *
868 * @note the returned string references the same memory, thus you 1111 * @note the returned string references the same memory, thus you
869 * must @em not free the returned memory. 1112 * must @em not free the returned memory.
870 * 1113 *
871 * @param string the string that shall be trimmed 1114 * @param string the string that shall be trimmed
872 * @return the trimmed string 1115 * @return (@c cxstring or @c cxmutstr) the trimmed string
873 */ 1116 */
874 cx_attr_nodiscard 1117 #define cx_strtrim(string) _Generic(cx_strcast_m(string), \
875 CX_EXPORT cxstring cx_strtrim(cxstring string); 1118 cxstring: cx_strtrim_, \
876 1119 cxmutstr: cx_strtrim_m_)(cx_strcast_m(string))
877 /** 1120 #endif
878 * Omits leading and trailing spaces.
879 *
880 * @note the returned string references the same memory, thus you
881 * must @em not free the returned memory.
882 *
883 * @param string the string that shall be trimmed
884 * @return the trimmed string
885 */
886 cx_attr_nodiscard
887 CX_EXPORT cxmutstr cx_strtrim_m(cxmutstr string);
888 1121
889 /** 1122 /**
890 * Checks if a string has a specific prefix. 1123 * Checks if a string has a specific prefix.
891 * 1124 *
892 * @param string the string to check 1125 * @param string the string to check
893 * @param prefix the prefix the string should have 1126 * @param prefix the prefix the string should have
894 * @return @c true, if and only if the string has the specified prefix, 1127 * @return @c true, if and only if the string has the specified prefix,
895 * @c false otherwise 1128 * @c false otherwise
896 */ 1129 */
897 cx_attr_nodiscard 1130 CX_EXTERN CX_NODISCARD
898 CX_EXPORT bool cx_strprefix_(cxstring string, cxstring prefix); 1131 bool cx_strprefix_(cxstring string, cxstring prefix);
899 1132
900 /** 1133 /**
901 * Checks if a string has a specific prefix. 1134 * Checks if a string has a specific prefix.
902 * 1135 *
903 * @param string the string to check 1136 * @param string the string to check
913 * @param string the string to check 1146 * @param string the string to check
914 * @param suffix the suffix the string should have 1147 * @param suffix the suffix the string should have
915 * @return @c true, if and only if the string has the specified suffix, 1148 * @return @c true, if and only if the string has the specified suffix,
916 * @c false otherwise 1149 * @c false otherwise
917 */ 1150 */
918 cx_attr_nodiscard 1151 CX_EXTERN CX_NODISCARD
919 CX_EXPORT bool cx_strsuffix_(cxstring string, cxstring suffix); 1152 bool cx_strsuffix_(cxstring string, cxstring suffix);
920 1153
921 /** 1154 /**
922 * Checks if a string has a specific suffix. 1155 * Checks if a string has a specific suffix.
923 * 1156 *
924 * @param string the string to check 1157 * @param string the string to check
934 * @param string the string to check 1167 * @param string the string to check
935 * @param prefix the prefix the string should have 1168 * @param prefix the prefix the string should have
936 * @return @c true, if and only if the string has the specified prefix, 1169 * @return @c true, if and only if the string has the specified prefix,
937 * @c false otherwise 1170 * @c false otherwise
938 */ 1171 */
939 cx_attr_nodiscard 1172 CX_EXTERN CX_NODISCARD
940 CX_EXPORT bool cx_strcaseprefix_(cxstring string, cxstring prefix); 1173 bool cx_strcaseprefix_(cxstring string, cxstring prefix);
941 1174
942 /** 1175 /**
943 * Checks if a string has a specific prefix, ignoring the case. 1176 * Checks if a string has a specific prefix, ignoring the case.
944 * 1177 *
945 * @param string the string to check 1178 * @param string the string to check
955 * @param string the string to check 1188 * @param string the string to check
956 * @param suffix the suffix the string should have 1189 * @param suffix the suffix the string should have
957 * @return @c true, if and only if the string has the specified suffix, 1190 * @return @c true, if and only if the string has the specified suffix,
958 * @c false otherwise 1191 * @c false otherwise
959 */ 1192 */
960 cx_attr_nodiscard 1193 CX_EXTERN CX_NODISCARD
961 CX_EXPORT bool cx_strcasesuffix_(cxstring string, cxstring suffix); 1194 bool cx_strcasesuffix_(cxstring string, cxstring suffix);
962 1195
963 /** 1196 /**
964 * Checks, if a string has a specific suffix, ignoring the case. 1197 * Checks, if a string has a specific suffix, ignoring the case.
965 * 1198 *
966 * @param string the string to check 1199 * @param string the string to check
971 #define cx_strcasesuffix(string, suffix) cx_strcasesuffix_(cx_strcast(string), cx_strcast(suffix)) 1204 #define cx_strcasesuffix(string, suffix) cx_strcasesuffix_(cx_strcast(string), cx_strcast(suffix))
972 1205
973 /** 1206 /**
974 * Replaces a string with another string. 1207 * Replaces a string with another string.
975 * 1208 *
1209 * Internal function - do not use.
1210 *
1211 * @param allocator
1212 * @param str
1213 * @param search
1214 * @param replacement
1215 * @param replmax
1216 * @return
1217 * @see cx_strreplace_a()
1218 * @see cx_strreplace()
1219 * @see cx_strreplacen_a()
1220 * @see cx_strreplacen()
1221 */
1222 CX_EXTERN CX_NODISCARD CX_NONNULL
1223 cxmutstr cx_strreplace_(const CxAllocator *allocator,
1224 cxstring str, cxstring search, cxstring replacement, size_t replmax);
1225
1226 /**
1227 * Replaces a string with another string.
1228 *
976 * The function replaces at most @p replmax occurrences. 1229 * The function replaces at most @p replmax occurrences.
977 * 1230 *
978 * The returned string will be allocated by @p allocator and is guaranteed 1231 * The returned string will be allocated by @p allocator and is guaranteed
979 * to be zero-terminated. 1232 * to be zero-terminated.
980 * 1233 *
981 * If allocation fails, or the input string is empty, 1234 * If allocation fails, or the input string is empty,
982 * the returned string will be empty. 1235 * the returned string will be empty.
983 * 1236 *
984 * @param allocator the allocator to use 1237 * @param allocator (@c CxAllocator*) the allocator to use
985 * @param str the string where replacements should be applied 1238 * @param str the string where replacements should be applied
986 * @param search the string to search for 1239 * @param search the string to search for
987 * @param replacement the replacement string 1240 * @param replacement the replacement string
988 * @param replmax maximum number of replacements 1241 * @param replmax (@c size_t) maximum number of replacements
989 * @return the resulting string after applying the replacements 1242 * @return (@c cxmutstr) the resulting string after applying the replacements
990 */ 1243 */
991 cx_attr_nodiscard cx_attr_nonnull 1244 #define cx_strreplacen_a(allocator, str, search, replacement, replmax) \
992 CX_EXPORT cxmutstr cx_strreplacen_a(const CxAllocator *allocator, 1245 cx_strreplace_(allocator, cx_strcast(str), cx_strcast(search), cx_strcast(replacement), replmax)
993 cxstring str, cxstring search, cxstring replacement, size_t replmax);
994 1246
995 /** 1247 /**
996 * Replaces a string with another string. 1248 * Replaces a string with another string.
997 * 1249 *
998 * The function replaces at most @p replmax occurrences. 1250 * The function replaces at most @p replmax occurrences.
1001 * to be zero-terminated. 1253 * to be zero-terminated.
1002 * 1254 *
1003 * If allocation fails, or the input string is empty, 1255 * If allocation fails, or the input string is empty,
1004 * the returned string will be empty. 1256 * the returned string will be empty.
1005 * 1257 *
1006 * @param str (@c cxstring) the string where replacements should be applied 1258 * @param str the string where replacements should be applied
1007 * @param search (@c cxstring) the string to search for 1259 * @param search the string to search for
1008 * @param replacement (@c cxstring) the replacement string 1260 * @param replacement the replacement string
1009 * @param replmax (@c size_t) maximum number of replacements 1261 * @param replmax (@c size_t) maximum number of replacements
1010 * @return (@c cxmutstr) the resulting string after applying the replacements 1262 * @return (@c cxmutstr) the resulting string after applying the replacements
1011 */ 1263 */
1012 #define cx_strreplacen(str, search, replacement, replmax) \ 1264 #define cx_strreplacen(str, search, replacement, replmax) \
1013 cx_strreplacen_a(cxDefaultAllocator, str, search, replacement, replmax) 1265 cx_strreplacen_a(cxDefaultAllocator, str, search, replacement, replmax)
1020 * 1272 *
1021 * If allocation fails, or the input string is empty, 1273 * If allocation fails, or the input string is empty,
1022 * the returned string will be empty. 1274 * the returned string will be empty.
1023 * 1275 *
1024 * @param allocator (@c CxAllocator*) the allocator to use 1276 * @param allocator (@c CxAllocator*) the allocator to use
1025 * @param str (@c cxstring) the string where replacements should be applied 1277 * @param str the string where replacements should be applied
1026 * @param search (@c cxstring) the string to search for 1278 * @param search the string to search for
1027 * @param replacement (@c cxstring) the replacement string 1279 * @param replacement the replacement string
1028 * @return (@c cxmutstr) the resulting string after applying the replacements 1280 * @return (@c cxmutstr) the resulting string after applying the replacements
1029 */ 1281 */
1030 #define cx_strreplace_a(allocator, str, search, replacement) \ 1282 #define cx_strreplace_a(allocator, str, search, replacement) \
1031 cx_strreplacen_a(allocator, str, search, replacement, SIZE_MAX) 1283 cx_strreplacen_a(allocator, str, search, replacement, SIZE_MAX)
1032 1284
1037 * to be zero-terminated. 1289 * to be zero-terminated.
1038 * 1290 *
1039 * If allocation fails, or the input string is empty, 1291 * If allocation fails, or the input string is empty,
1040 * the returned string will be empty. 1292 * the returned string will be empty.
1041 * 1293 *
1042 * @param str (@c cxstring) the string where replacements should be applied 1294 * @param str the string where replacements should be applied
1043 * @param search (@c cxstring) the string to search for 1295 * @param search the string to search for
1044 * @param replacement (@c cxstring) the replacement string 1296 * @param replacement the replacement string
1045 * @return (@c cxmutstr) the resulting string after applying the replacements 1297 * @return (@c cxmutstr) the resulting string after applying the replacements
1046 */ 1298 */
1047 #define cx_strreplace(str, search, replacement) \ 1299 #define cx_strreplace(str, search, replacement) \
1048 cx_strreplacen_a(cxDefaultAllocator, str, search, replacement, SIZE_MAX) 1300 cx_strreplacen_a(cxDefaultAllocator, str, search, replacement, SIZE_MAX)
1049 1301
1053 * @param str the string to tokenize 1305 * @param str the string to tokenize
1054 * @param delim the delimiter (must not be empty) 1306 * @param delim the delimiter (must not be empty)
1055 * @param limit the maximum number of tokens that shall be returned 1307 * @param limit the maximum number of tokens that shall be returned
1056 * @return a new string tokenization context 1308 * @return a new string tokenization context
1057 */ 1309 */
1058 cx_attr_nodiscard 1310 CX_EXTERN CX_NODISCARD
1059 CX_EXPORT CxStrtokCtx cx_strtok_(cxstring str, cxstring delim, size_t limit); 1311 CxStrtokCtx cx_strtok_(cxstring str, cxstring delim, size_t limit);
1060 1312
1061 /** 1313 /**
1062 * Creates a string tokenization context. 1314 * Creates a string tokenization context.
1063 * 1315 *
1064 * @param str the string to tokenize 1316 * @param str the string to tokenize
1077 * @param ctx the tokenization context 1329 * @param ctx the tokenization context
1078 * @param token a pointer to memory where the next token shall be stored 1330 * @param token a pointer to memory where the next token shall be stored
1079 * @return true if successful, false if the limit or the end of the string 1331 * @return true if successful, false if the limit or the end of the string
1080 * has been reached 1332 * has been reached
1081 */ 1333 */
1082 cx_attr_nonnull cx_attr_nodiscard cx_attr_access_w(2) 1334 CX_EXTERN CX_NONNULL CX_NODISCARD CX_ACCESS_W(2)
1083 CX_EXPORT bool cx_strtok_next(CxStrtokCtx *ctx, cxstring *token); 1335 bool cx_strtok_next_(CxStrtokCtx *ctx, cxstring *token);
1084 1336
1085 /** 1337 #ifdef __cplusplus
1086 * Returns the next token of a mutable string. 1338 CX_CPPDECL cx_strtok_next(CxStrtokCtx *ctx, cxstring *token) {
1339 return cx_strtok_next_(ctx, token);
1340 }
1341 CX_CPPDECL cx_strtok_next(CxStrtokCtx *ctx, cxmutstr *token) {
1342 // Note: this is actually UB - fixed with start_lifetime_as() in C++23
1343 // but it works on all supported platforms
1344 return cx_strtok_next_(ctx, reinterpret_cast<cxstring*>(token));
1345 }
1346 #else // ! __cplusplus
1347 /**
1348 * Returns the next token.
1087 * 1349 *
1088 * The token will point to the source string. 1350 * The token will point to the source string.
1089 * 1351 *
1090 * @attention 1352 * @param ctx (@c CxStrtokCtx*) the tokenization context
1091 * If the context was not initialized over a mutable string, modifying 1353 * @param token a pointer to either a @c cxstring or @c cxmutstr
1092 * the data of the returned token is undefined behavior. 1354 * where the next token shall be stored
1093 *
1094 * @param ctx the tokenization context
1095 * @param token a pointer to memory where the next token shall be stored
1096 * @return true if successful, false if the limit or the end of the string 1355 * @return true if successful, false if the limit or the end of the string
1097 * has been reached 1356 * has been reached
1098 */ 1357 */
1099 cx_attr_nonnull cx_attr_nodiscard cx_attr_access_w(2) 1358 #define cx_strtok_next(ctx, token) _Generic((token), \
1100 CX_EXPORT bool cx_strtok_next_m(CxStrtokCtx *ctx, cxmutstr *token); 1359 cxstring*: cx_strtok_next_, \
1360 cxmutstr*: cx_strtok_next_)(ctx, (cxstring*)token)
1361 #endif
1101 1362
1102 /** 1363 /**
1103 * Defines an array of more delimiters for the specified tokenization context. 1364 * Defines an array of more delimiters for the specified tokenization context.
1104 * 1365 *
1105 * @param ctx the tokenization context 1366 * @param ctx the tokenization context
1106 * @param delim array of more delimiters 1367 * @param delim array of more delimiters
1107 * @param count number of elements in the array 1368 * @param count number of elements in the array
1108 */ 1369 */
1109 cx_attr_nonnull cx_attr_access_r(2, 3) 1370 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
1110 CX_EXPORT void cx_strtok_delim(CxStrtokCtx *ctx, const cxstring *delim, size_t count); 1371 void cx_strtok_delim(CxStrtokCtx *ctx, const cxstring *delim, size_t count);
1111 1372
1112 /* ------------------------------------------------------------------------- * 1373 /* ------------------------------------------------------------------------- *
1113 * string to number conversion functions * 1374 * string to number conversion functions *
1114 * ------------------------------------------------------------------------- */ 1375 * ------------------------------------------------------------------------- */
1115 1376
1125 * @param base 2, 8, 10, or 16 1386 * @param base 2, 8, 10, or 16
1126 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1387 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1127 * @retval zero success 1388 * @retval zero success
1128 * @retval non-zero conversion was not possible 1389 * @retval non-zero conversion was not possible
1129 */ 1390 */
1130 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1391 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1131 CX_EXPORT int cx_strtos_lc_(cxstring str, short *output, int base, const char *groupsep); 1392 int cx_strtos_lc_(cxstring str, short *output, int base, const char *groupsep);
1132 1393
1133 /** 1394 /**
1134 * Converts a string to a number. 1395 * Converts a string to a number.
1135 * 1396 *
1136 * The function returns non-zero when conversion is not possible. 1397 * The function returns non-zero when conversion is not possible.
1142 * @param base 2, 8, 10, or 16 1403 * @param base 2, 8, 10, or 16
1143 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1404 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1144 * @retval zero success 1405 * @retval zero success
1145 * @retval non-zero conversion was not possible 1406 * @retval non-zero conversion was not possible
1146 */ 1407 */
1147 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1408 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1148 CX_EXPORT int cx_strtoi_lc_(cxstring str, int *output, int base, const char *groupsep); 1409 int cx_strtoi_lc_(cxstring str, int *output, int base, const char *groupsep);
1149 1410
1150 /** 1411 /**
1151 * Converts a string to a number. 1412 * Converts a string to a number.
1152 * 1413 *
1153 * The function returns non-zero when conversion is not possible. 1414 * The function returns non-zero when conversion is not possible.
1159 * @param base 2, 8, 10, or 16 1420 * @param base 2, 8, 10, or 16
1160 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1421 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1161 * @retval zero success 1422 * @retval zero success
1162 * @retval non-zero conversion was not possible 1423 * @retval non-zero conversion was not possible
1163 */ 1424 */
1164 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1425 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1165 CX_EXPORT int cx_strtol_lc_(cxstring str, long *output, int base, const char *groupsep); 1426 int cx_strtol_lc_(cxstring str, long *output, int base, const char *groupsep);
1166 1427
1167 /** 1428 /**
1168 * Converts a string to a number. 1429 * Converts a string to a number.
1169 * 1430 *
1170 * The function returns non-zero when conversion is not possible. 1431 * The function returns non-zero when conversion is not possible.
1176 * @param base 2, 8, 10, or 16 1437 * @param base 2, 8, 10, or 16
1177 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1438 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1178 * @retval zero success 1439 * @retval zero success
1179 * @retval non-zero conversion was not possible 1440 * @retval non-zero conversion was not possible
1180 */ 1441 */
1181 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1442 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1182 CX_EXPORT int cx_strtoll_lc_(cxstring str, long long *output, int base, const char *groupsep); 1443 int cx_strtoll_lc_(cxstring str, long long *output, int base, const char *groupsep);
1183 1444
1184 /** 1445 /**
1185 * Converts a string to a number. 1446 * Converts a string to a number.
1186 * 1447 *
1187 * The function returns non-zero when conversion is not possible. 1448 * The function returns non-zero when conversion is not possible.
1193 * @param base 2, 8, 10, or 16 1454 * @param base 2, 8, 10, or 16
1194 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1455 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1195 * @retval zero success 1456 * @retval zero success
1196 * @retval non-zero conversion was not possible 1457 * @retval non-zero conversion was not possible
1197 */ 1458 */
1198 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1459 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1199 CX_EXPORT int cx_strtoi8_lc_(cxstring str, int8_t *output, int base, const char *groupsep); 1460 int cx_strtoi8_lc_(cxstring str, int8_t *output, int base, const char *groupsep);
1200 1461
1201 /** 1462 /**
1202 * Converts a string to a number. 1463 * Converts a string to a number.
1203 * 1464 *
1204 * The function returns non-zero when conversion is not possible. 1465 * The function returns non-zero when conversion is not possible.
1210 * @param base 2, 8, 10, or 16 1471 * @param base 2, 8, 10, or 16
1211 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1472 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1212 * @retval zero success 1473 * @retval zero success
1213 * @retval non-zero conversion was not possible 1474 * @retval non-zero conversion was not possible
1214 */ 1475 */
1215 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1476 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1216 CX_EXPORT int cx_strtoi16_lc_(cxstring str, int16_t *output, int base, const char *groupsep); 1477 int cx_strtoi16_lc_(cxstring str, int16_t *output, int base, const char *groupsep);
1217 1478
1218 /** 1479 /**
1219 * Converts a string to a number. 1480 * Converts a string to a number.
1220 * 1481 *
1221 * The function returns non-zero when conversion is not possible. 1482 * The function returns non-zero when conversion is not possible.
1227 * @param base 2, 8, 10, or 16 1488 * @param base 2, 8, 10, or 16
1228 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1489 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1229 * @retval zero success 1490 * @retval zero success
1230 * @retval non-zero conversion was not possible 1491 * @retval non-zero conversion was not possible
1231 */ 1492 */
1232 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1493 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1233 CX_EXPORT int cx_strtoi32_lc_(cxstring str, int32_t *output, int base, const char *groupsep); 1494 int cx_strtoi32_lc_(cxstring str, int32_t *output, int base, const char *groupsep);
1234 1495
1235 /** 1496 /**
1236 * Converts a string to a number. 1497 * Converts a string to a number.
1237 * 1498 *
1238 * The function returns non-zero when conversion is not possible. 1499 * The function returns non-zero when conversion is not possible.
1244 * @param base 2, 8, 10, or 16 1505 * @param base 2, 8, 10, or 16
1245 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1506 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1246 * @retval zero success 1507 * @retval zero success
1247 * @retval non-zero conversion was not possible 1508 * @retval non-zero conversion was not possible
1248 */ 1509 */
1249 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1510 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1250 CX_EXPORT int cx_strtoi64_lc_(cxstring str, int64_t *output, int base, const char *groupsep); 1511 int cx_strtoi64_lc_(cxstring str, int64_t *output, int base, const char *groupsep);
1251 1512
1252 /** 1513 /**
1253 * Converts a string to a number. 1514 * Converts a string to a number.
1254 * 1515 *
1255 * The function returns non-zero when conversion is not possible. 1516 * The function returns non-zero when conversion is not possible.
1261 * @param base 2, 8, 10, or 16 1522 * @param base 2, 8, 10, or 16
1262 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1523 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1263 * @retval zero success 1524 * @retval zero success
1264 * @retval non-zero conversion was not possible 1525 * @retval non-zero conversion was not possible
1265 */ 1526 */
1266 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1527 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1267 CX_EXPORT int cx_strtous_lc_(cxstring str, unsigned short *output, int base, const char *groupsep); 1528 int cx_strtous_lc_(cxstring str, unsigned short *output, int base, const char *groupsep);
1268 1529
1269 /** 1530 /**
1270 * Converts a string to a number. 1531 * Converts a string to a number.
1271 * 1532 *
1272 * The function returns non-zero when conversion is not possible. 1533 * The function returns non-zero when conversion is not possible.
1278 * @param base 2, 8, 10, or 16 1539 * @param base 2, 8, 10, or 16
1279 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1540 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1280 * @retval zero success 1541 * @retval zero success
1281 * @retval non-zero conversion was not possible 1542 * @retval non-zero conversion was not possible
1282 */ 1543 */
1283 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1544 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1284 CX_EXPORT int cx_strtou_lc_(cxstring str, unsigned int *output, int base, const char *groupsep); 1545 int cx_strtou_lc_(cxstring str, unsigned int *output, int base, const char *groupsep);
1285 1546
1286 /** 1547 /**
1287 * Converts a string to a number. 1548 * Converts a string to a number.
1288 * 1549 *
1289 * The function returns non-zero when conversion is not possible. 1550 * The function returns non-zero when conversion is not possible.
1295 * @param base 2, 8, 10, or 16 1556 * @param base 2, 8, 10, or 16
1296 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1557 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1297 * @retval zero success 1558 * @retval zero success
1298 * @retval non-zero conversion was not possible 1559 * @retval non-zero conversion was not possible
1299 */ 1560 */
1300 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1561 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1301 CX_EXPORT int cx_strtoul_lc_(cxstring str, unsigned long *output, int base, const char *groupsep); 1562 int cx_strtoul_lc_(cxstring str, unsigned long *output, int base, const char *groupsep);
1302 1563
1303 /** 1564 /**
1304 * Converts a string to a number. 1565 * Converts a string to a number.
1305 * 1566 *
1306 * The function returns non-zero when conversion is not possible. 1567 * The function returns non-zero when conversion is not possible.
1312 * @param base 2, 8, 10, or 16 1573 * @param base 2, 8, 10, or 16
1313 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1574 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1314 * @retval zero success 1575 * @retval zero success
1315 * @retval non-zero conversion was not possible 1576 * @retval non-zero conversion was not possible
1316 */ 1577 */
1317 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1578 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1318 CX_EXPORT int cx_strtoull_lc_(cxstring str, unsigned long long *output, int base, const char *groupsep); 1579 int cx_strtoull_lc_(cxstring str, unsigned long long *output, int base, const char *groupsep);
1319 1580
1320 /** 1581 /**
1321 * Converts a string to a number. 1582 * Converts a string to a number.
1322 * 1583 *
1323 * The function returns non-zero when conversion is not possible. 1584 * The function returns non-zero when conversion is not possible.
1329 * @param base 2, 8, 10, or 16 1590 * @param base 2, 8, 10, or 16
1330 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1591 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1331 * @retval zero success 1592 * @retval zero success
1332 * @retval non-zero conversion was not possible 1593 * @retval non-zero conversion was not possible
1333 */ 1594 */
1334 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1595 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1335 CX_EXPORT int cx_strtou8_lc_(cxstring str, uint8_t *output, int base, const char *groupsep); 1596 int cx_strtou8_lc_(cxstring str, uint8_t *output, int base, const char *groupsep);
1336 1597
1337 /** 1598 /**
1338 * Converts a string to a number. 1599 * Converts a string to a number.
1339 * 1600 *
1340 * The function returns non-zero when conversion is not possible. 1601 * The function returns non-zero when conversion is not possible.
1346 * @param base 2, 8, 10, or 16 1607 * @param base 2, 8, 10, or 16
1347 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1608 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1348 * @retval zero success 1609 * @retval zero success
1349 * @retval non-zero conversion was not possible 1610 * @retval non-zero conversion was not possible
1350 */ 1611 */
1351 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1612 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1352 CX_EXPORT int cx_strtou16_lc_(cxstring str, uint16_t *output, int base, const char *groupsep); 1613 int cx_strtou16_lc_(cxstring str, uint16_t *output, int base, const char *groupsep);
1353 1614
1354 /** 1615 /**
1355 * Converts a string to a number. 1616 * Converts a string to a number.
1356 * 1617 *
1357 * The function returns non-zero when conversion is not possible. 1618 * The function returns non-zero when conversion is not possible.
1363 * @param base 2, 8, 10, or 16 1624 * @param base 2, 8, 10, or 16
1364 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1625 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1365 * @retval zero success 1626 * @retval zero success
1366 * @retval non-zero conversion was not possible 1627 * @retval non-zero conversion was not possible
1367 */ 1628 */
1368 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1629 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1369 CX_EXPORT int cx_strtou32_lc_(cxstring str, uint32_t *output, int base, const char *groupsep); 1630 int cx_strtou32_lc_(cxstring str, uint32_t *output, int base, const char *groupsep);
1370 1631
1371 /** 1632 /**
1372 * Converts a string to a number. 1633 * Converts a string to a number.
1373 * 1634 *
1374 * The function returns non-zero when conversion is not possible. 1635 * The function returns non-zero when conversion is not possible.
1380 * @param base 2, 8, 10, or 16 1641 * @param base 2, 8, 10, or 16
1381 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1642 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1382 * @retval zero success 1643 * @retval zero success
1383 * @retval non-zero conversion was not possible 1644 * @retval non-zero conversion was not possible
1384 */ 1645 */
1385 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1646 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1386 CX_EXPORT int cx_strtou64_lc_(cxstring str, uint64_t *output, int base, const char *groupsep); 1647 int cx_strtou64_lc_(cxstring str, uint64_t *output, int base, const char *groupsep);
1387 1648
1388 /** 1649 /**
1389 * Converts a string to a number. 1650 * Converts a string to a number.
1390 * 1651 *
1391 * The function returns non-zero when conversion is not possible. 1652 * The function returns non-zero when conversion is not possible.
1397 * @param base 2, 8, 10, or 16 1658 * @param base 2, 8, 10, or 16
1398 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1659 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1399 * @retval zero success 1660 * @retval zero success
1400 * @retval non-zero conversion was not possible 1661 * @retval non-zero conversion was not possible
1401 */ 1662 */
1402 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1663 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1403 CX_EXPORT int cx_strtoz_lc_(cxstring str, size_t *output, int base, const char *groupsep); 1664 int cx_strtoz_lc_(cxstring str, size_t *output, int base, const char *groupsep);
1404 1665
1405 /** 1666 /**
1406 * Converts a string to a single precision floating-point number. 1667 * Converts a string to a single precision floating-point number.
1407 * 1668 *
1408 * The function returns non-zero when conversion is not possible. 1669 * The function returns non-zero when conversion is not possible.
1414 * @param decsep the decimal separator 1675 * @param decsep the decimal separator
1415 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1676 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1416 * @retval zero success 1677 * @retval zero success
1417 * @retval non-zero conversion was not possible 1678 * @retval non-zero conversion was not possible
1418 */ 1679 */
1419 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1680 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1420 CX_EXPORT int cx_strtof_lc_(cxstring str, float *output, char decsep, const char *groupsep); 1681 int cx_strtof_lc_(cxstring str, float *output, char decsep, const char *groupsep);
1421 1682
1422 /** 1683 /**
1423 * Converts a string to a double precision floating-point number. 1684 * Converts a string to a double precision floating-point number.
1424 * 1685 *
1425 * The function returns non-zero when conversion is not possible. 1686 * The function returns non-zero when conversion is not possible.
1431 * @param decsep the decimal separator 1692 * @param decsep the decimal separator
1432 * @param groupsep each character in this string is treated as a group separator and ignored during conversion 1693 * @param groupsep each character in this string is treated as a group separator and ignored during conversion
1433 * @retval zero success 1694 * @retval zero success
1434 * @retval non-zero conversion was not possible 1695 * @retval non-zero conversion was not possible
1435 */ 1696 */
1436 cx_attr_access_w(2) cx_attr_nonnull_arg(2) 1697 CX_EXTERN CX_ACCESS_W(2) CX_NONNULL_ARG(2)
1437 CX_EXPORT int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep); 1698 int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep);
1438 1699
1439 /** 1700 /**
1440 * Converts a string to a number. 1701 * Converts a string to a number.
1441 * 1702 *
1442 * The function returns non-zero when conversion is not possible. 1703 * The function returns non-zero when conversion is not possible.
2078 * @retval zero success 2339 * @retval zero success
2079 * @retval non-zero conversion was not possible 2340 * @retval non-zero conversion was not possible
2080 */ 2341 */
2081 #define cx_strtod(str, output) cx_strtod_lc_(cx_strcast(str), output, '.', ",") 2342 #define cx_strtod(str, output) cx_strtod_lc_(cx_strcast(str), output, '.', ",")
2082 2343
2083 #ifdef __cplusplus
2084 } // extern "C"
2085 #endif
2086
2087 #endif //UCX_STRING_H 2344 #endif //UCX_STRING_H

mercurial