1#include "include/pw.h"
  2#include "src/types/string/string_internal.h"
  3
  4
  5[[nodiscard]] bool pw_string_insert_chars(PwValuePtr str, unsigned position, char32_t chr, unsigned n)
  6{
  7    if (n == 0) {
  8        return true;
  9    }
 10    pw_assert(position <= pw_strlen(str));
 11
 12    if (!_pw_expand_string(str, n, calc_char_size(chr))) {
 13        return false;
 14    }
 15    unsigned prev_len;
 16    uint8_t* dest_ptr = _pw_string_start_inc_length(str, n, &prev_len);
 17    uint8_t char_size = str->str_params.char_size;
 18    uint8_t* ins_ptr = dest_ptr + position * char_size;
 19
 20    if (position < prev_len) {
 21        memmove(ins_ptr + n * char_size, ins_ptr, (prev_len - position) * char_size);
 22    }
 23    while (n--) {
 24        ins_ptr += _pw_put_char(ins_ptr, chr, char_size);
 25    }
 26    return true;
 27}
 28
 29[[nodiscard]] bool _pw_string_insert_ascii(PwValuePtr dest, unsigned position, char* start_ptr, char* end_ptr)
 30{
 31    pw_assert(pw_is_string(dest));
 32
 33    if (!end_ptr) {
 34        end_ptr = start_ptr + strlen(start_ptr);
 35    }
 36    ptrdiff_t src_len = end_ptr - start_ptr;
 37    if (src_len <= 0) {
 38        return true;
 39    }
 40    if (src_len >= UINT_MAX) {
 41        pw_set_status(PwStatus(PweStringTooLong));
 42        return false;
 43    }
 44    if (!_pw_expand_string(dest, src_len, 1)) {
 45        return false;
 46    }
 47    unsigned prev_len;
 48    uint8_t* dest_ptr = _pw_string_start_inc_length(dest, src_len, &prev_len);
 49    uint8_t dest_char_size = dest->str_params.char_size;
 50    uint8_t* ins_ptr = dest_ptr + position * dest_char_size;
 51    if (position < prev_len) {
 52        memmove(ins_ptr + src_len * dest_char_size, ins_ptr, (prev_len - position) * dest_char_size);
 53    }
 54    StrPut fn_strput = _pw_strput_variants[dest_char_size][1];
 55    return fn_strput(dest, position, (uint8_t*) start_ptr, (uint8_t*) end_ptr);
 56}
 57
 58[[nodiscard]] bool _pw_string_insert_utf8(PwValuePtr dest, unsigned position, char8_t* start_ptr, char8_t* end_ptr)
 59{
 60    pw_assert(pw_is_string(dest));
 61
 62    uint8_t src_char_size = 1;
 63    ptrdiff_t src_len;
 64    if (end_ptr) {
 65        unsigned n = end_ptr - start_ptr;
 66        src_len = utf8_strlen2_buf(start_ptr, &n, &src_char_size);
 67    } else {
 68        src_len = utf8_strlen3(start_ptr, &src_char_size, &end_ptr);
 69    }
 70    if (src_len <= 0) {
 71        return true;
 72    }
 73    if (src_len >= UINT_MAX) {
 74        pw_set_status(PwStatus(PweStringTooLong));
 75        return false;
 76    }
 77    if (!_pw_expand_string(dest, src_len, src_char_size)) {
 78        return false;
 79    }
 80    unsigned prev_len;
 81    uint8_t* dest_ptr = _pw_string_start_inc_length(dest, src_len, &prev_len);
 82    uint8_t dest_char_size = dest->str_params.char_size;
 83    uint8_t* ins_ptr = dest_ptr + position * dest_char_size;
 84    if (position < prev_len) {
 85        memmove(ins_ptr + src_len * dest_char_size, ins_ptr, (prev_len - position) * dest_char_size);
 86    }
 87    StrPut fn_strput = _pw_strput_variants[dest_char_size][0];
 88    return fn_strput(dest, position, (uint8_t*) start_ptr, (uint8_t*) end_ptr);
 89}
 90
 91[[nodiscard]] bool _pw_string_insert_utf32(PwValuePtr dest, unsigned position, char32_t* start_ptr, char32_t* end_ptr)
 92{
 93    pw_assert(pw_is_string(dest));
 94
 95    uint8_t src_char_size = 1;
 96    if (!end_ptr) {
 97        end_ptr = start_ptr + utf32_strlen2(start_ptr, &src_char_size);
 98    }
 99    ptrdiff_t src_len = end_ptr - start_ptr;
100    if (src_len <= 0) {
101        return true;
102    }
103    if (src_len >= UINT_MAX / 4) {
104        pw_set_status(PwStatus(PweStringTooLong));
105        return false;
106    }
107    if (!_pw_expand_string(dest, src_len, src_char_size)) {
108        return false;
109    }
110    unsigned prev_len;
111    uint8_t* dest_ptr = _pw_string_start_inc_length(dest, src_len, &prev_len);
112    uint8_t dest_char_size = dest->str_params.char_size;
113    uint8_t* ins_ptr = dest_ptr + position * dest_char_size;
114    if (position < prev_len) {
115        memmove(ins_ptr + src_len * dest_char_size, ins_ptr, (prev_len - position) * dest_char_size);
116    }
117    StrPut fn_strput = _pw_strput_variants[dest_char_size][4];
118    return fn_strput(dest, position, (uint8_t*) start_ptr, (uint8_t*) end_ptr);
119}
120
121[[nodiscard]] bool _pw_string_insert(PwValuePtr dest, unsigned position, PwValuePtr src)
122{
123    pw_assert(pw_is_string(dest));
124    unsigned src_len = pw_strlen(src);
125    uint8_t src_char_size = src->str_params.char_size;
126    if (!_pw_expand_string(dest, src_len, src_char_size)) {
127        return false;
128    }
129    uint8_t* src_end_ptr;
130    uint8_t* src_start_ptr = _pw_string_start_end(src, &src_end_ptr);
131    unsigned prev_len;
132    uint8_t* dest_ptr = _pw_string_start_inc_length(dest, src_len, &prev_len);
133    uint8_t dest_char_size = dest->str_params.char_size;
134    uint8_t* ins_ptr = dest_ptr + position * dest_char_size;
135    if (position < prev_len) {
136        memmove(ins_ptr + src_len * dest_char_size, ins_ptr, (prev_len - position) * dest_char_size);
137    }
138    StrPut fn_strput = _pw_strput_variants[dest_char_size][src_char_size];
139    return fn_strput(dest, position, src_start_ptr, src_end_ptr);
140}
141
142[[nodiscard]] bool pw_string_insert_substring(PwValuePtr dest, unsigned position,
143                                              PwValuePtr src, unsigned src_start_pos, unsigned src_end_pos)
144{
145    pw_assert(pw_is_string(dest));
146    unsigned src_len  = pw_strlen(src);
147    if (src_end_pos > src_len) {
148        src_end_pos = src_len;
149    }
150    if (src_start_pos >= src_end_pos) {
151        return true;
152    }
153    src_len = src_end_pos - src_start_pos;
154
155    // expand with char_size unchanged because it is unknown for substring of src
156
157    if (!_pw_expand_string(dest, src_len, 1)) {
158        return false;
159    }
160    uint8_t src_char_size = src->str_params.char_size;
161    uint8_t* src_start_ptr = _pw_string_start(src);
162    uint8_t* src_end_ptr = src_start_ptr + src_end_pos * src_char_size;
163    src_start_ptr += src_start_pos * src_char_size;
164
165    unsigned prev_len;
166    uint8_t* dest_ptr = _pw_string_start_inc_length(dest, src_len, &prev_len);
167    uint8_t dest_char_size = dest->str_params.char_size;
168    uint8_t* ins_ptr = dest_ptr + position * dest_char_size;
169    if (position < prev_len) {
170        memmove(ins_ptr + src_len * dest_char_size, ins_ptr, (prev_len - position) * dest_char_size);
171    }
172    StrPut fn_strput = _pw_strput_variants[dest_char_size][src_char_size];
173    return fn_strput(dest, position, src_start_ptr, src_end_ptr);
174}