| 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, |
| 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 |
| 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 |
| 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. |
| 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 |