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}