1#include "include/pw.h"
 2#include "src/types/string/string_internal.h"
 3
 4[[ nodiscard]] bool pw_string_ltrim(PwValuePtr str)
 5{
 6    pw_assert_string(str);
 7
 8    uint8_t char_size = str->char_size;
 9    uint8_t* end_ptr;
10    uint8_t* start_ptr = _pw_string_start_end(str, &end_ptr);
11    StrSkipSpaces fn_skip_spaces = _pw_skip_spaces_variants[char_size];
12    uint8_t* nonspace_ptr = fn_skip_spaces(start_ptr, end_ptr);
13
14    if (nonspace_ptr == start_ptr) {
15        return true;
16    }
17    if ( nonspace_ptr == end_ptr) {
18        pw_destroy(str);
19        *str = PwString("");
20        return true;
21    }
22    ptrdiff_t n = end_ptr - nonspace_ptr;
23    unsigned new_length = n / char_size;
24    if (!_pw_string_need_copy_on_write(str)) {
25        memmove(start_ptr, nonspace_ptr, n);
26        _pw_string_set_length(str, new_length);
27        return true;
28    }
29    // make substring
30    pw_destroy(str);
31    if (!_pw_make_empty_string(str->type_id, new_length, char_size, str)) {
32        return false;
33    }
34    if (new_length) {
35        _pw_string_set_length(str, new_length);
36        StrAppend fn_append = _pw_str_append_variants[char_size][char_size];
37        if (!fn_append(str, 0, nonspace_ptr, end_ptr)) {
38            return false;
39        }
40        if (str->embedded) {
41            // clean remainder for fast comparison to work
42            unsigned i = char_size * new_length;
43            while (i < sizeof(str->str_1)) {
44                str->str_1[i++] = 0;
45            }
46        }
47    }
48    return true;
49}
50
51[[ nodiscard]] bool pw_string_rtrim(PwValuePtr str)
52{
53    pw_assert_string(str);
54
55    uint8_t char_size = str->char_size;
56    uint8_t* end_ptr;
57    uint8_t* start_ptr = _pw_string_start_end(str, &end_ptr);
58
59    if (start_ptr == end_ptr) {
60        return true;
61    }
62    while (start_ptr < end_ptr) {
63        uint8_t* prev_end_ptr = end_ptr;
64        char32_t c = _pw_get_char_reverse(&end_ptr, char_size);
65        if (!pw_isspace(c)) {
66            end_ptr = prev_end_ptr;
67            break;
68        }
69    }
70    if (start_ptr == end_ptr) {
71        pw_destroy(str);
72        *str = PwString("");
73        return true;
74    }
75    return pw_string_truncate(str, (end_ptr - start_ptr) / char_size);
76}
77
78[[ nodiscard]] bool pw_string_trim(PwValuePtr str)
79{
80    return pw_string_rtrim(str) && pw_string_ltrim(str);
81}