@@ -288,6 +288,24 @@ _mstr_adjust_index(mstr_view s, mlib_upsized_integer pos, bool clamp_to_length)
288
288
return pos .bits .as_unsigned ;
289
289
}
290
290
291
+ /**
292
+ * @brief Obtain the code unit at the given zero-based index, with negative index wrapping.
293
+ *
294
+ * This function asserts that the index is in-bounds for the given string.
295
+ *
296
+ * @param s The string to be inspected.
297
+ * @param pos The index to access. Zero is the first code unit, and -1 is the last.
298
+ * @return char The code unit at position `pos`.
299
+ */
300
+ static inline char
301
+ mstr_at (mstr_view s , mlib_upsized_integer pos_ )
302
+ {
303
+ size_t pos = _mstr_adjust_index (s , pos_ , false);
304
+ return s .data [pos ];
305
+ }
306
+
307
+ #define mstr_at (S , Pos ) (mstr_at)(mstr_view_from(S), mlib_upsize_integer(Pos))
308
+
291
309
/**
292
310
* @brief Create a new `mstr_view` that views a substring within another string
293
311
*
@@ -441,6 +459,63 @@ mstr_find_first_of(mstr_view hay, mstr_view const needles, mlib_upsized_integer
441
459
#define _mstr_find_first_of_argc_3 (Hay , Needle , Pos ) _mstr_find_first_of_argc_4(Hay, Needle, Pos, SIZE_MAX)
442
460
#define _mstr_find_first_of_argc_4 (Hay , Needle , Pos , Len ) mstr_find_first_of(Hay, Needle, mlib_upsize_integer(Pos), Len)
443
461
462
+ /**
463
+ * @brief Trim leading latin (ASCII) whitespace from the given string
464
+ *
465
+ * @param s The string to be inspected
466
+ * @return mstr_view A substring view of `s` that excludes any leading whitespace
467
+ */
468
+ static inline mstr_view
469
+ mstr_trim_left (mstr_view s )
470
+ {
471
+ while (s .len ) {
472
+ char c = mstr_at (s , 0 );
473
+ if (c == ' ' || c == '\n' || c == '\r' || c == '\t' ) {
474
+ s = mstr_substr (s , 1 );
475
+ } else {
476
+ break ;
477
+ }
478
+ }
479
+ return s ;
480
+ }
481
+ #define mstr_trim_left (S ) (mstr_trim_left)(mstr_view_from(S))
482
+
483
+ /**
484
+ * @brief Trim trailing latin (ASCII) whitespace from the given string
485
+ *
486
+ * @param s The string to be insepcted
487
+ * @return mstr_view A substring view of `s` that excludes any trailing whitespace.
488
+ */
489
+ static inline mstr_view
490
+ mstr_trim_right (mstr_view s )
491
+ {
492
+ while (s .len ) {
493
+ char c = mstr_at (s , -1 );
494
+ if (c == ' ' || c == '\n' || c == '\r' || c == '\t' ) {
495
+ s = mstr_slice (s , 0 , -1 );
496
+ } else {
497
+ break ;
498
+ }
499
+ }
500
+ return s ;
501
+ }
502
+ #define mstr_trim_right (S ) (mstr_trim_right)(mstr_view_from(S))
503
+
504
+ /**
505
+ * @brief Trim leading and trailing latin (ASCII) whitespace from the string
506
+ *
507
+ * @param s The string to be inspected
508
+ * @return mstr_view A substring of `s` that excludes leading and trailing whitespace.
509
+ */
510
+ static inline mstr_view
511
+ mstr_trim (mstr_view s )
512
+ {
513
+ s = mstr_trim_left (s );
514
+ s = mstr_trim_right (s );
515
+ return s ;
516
+ }
517
+ #define mstr_trim (S ) (mstr_trim)(mstr_view_from(S))
518
+
444
519
/**
445
520
* @brief Split a single string view into two strings at the given position
446
521
*
0 commit comments