1#include "include/pw.h"
  2#include "src/types/string/string_internal.h"
  3
  4
  5[[nodiscard]] bool _pw_string_append_c32(PwValuePtr dest, char32_t c)
  6{
  7    pw_assert(pw_is_string(dest));
  8    if (!_pw_expand_string(dest, 1, calc_char_size(c))) {
  9        return false;
 10    }
 11    unsigned append_position;
 12    uint8_t* dest_ptr = _pw_string_start_inc_length(dest, 1, &append_position);
 13    uint8_t dest_char_size = dest->str_params.char_size;
 14    uint8_t* append_ptr = dest_ptr + append_position * dest_char_size;
 15
 16    _pw_put_char(append_ptr, c, dest_char_size);
 17    return true;
 18}
 19
 20[[nodiscard]] bool _pw_string_append_ascii(PwValuePtr dest, char* start_ptr, char* end_ptr)
 21{
 22    pw_assert(pw_is_string(dest));
 23
 24    if (!end_ptr) {
 25        end_ptr = start_ptr + strlen(start_ptr);
 26    }
 27    ptrdiff_t src_len = end_ptr - start_ptr;
 28    if (src_len <= 0) {
 29        return true;
 30    }
 31    if (src_len >= UINT_MAX) {
 32        pw_set_status(PwStatus(PweStringTooLong));
 33        return false;
 34    }
 35    if (!_pw_expand_string(dest, src_len, 1)) {
 36        return false;
 37    }
 38    unsigned append_position = _pw_string_inc_length(dest, src_len);
 39    StrPut fn_strput = _pw_strput_variants[dest->str_params.char_size][1];
 40    return fn_strput(dest, append_position, (uint8_t*) start_ptr, (uint8_t*) end_ptr);
 41}
 42
 43[[nodiscard]] bool _pw_string_append_utf8(PwValuePtr dest, char8_t* start_ptr, char8_t* end_ptr)
 44{
 45    pw_assert(pw_is_string(dest));
 46
 47    uint8_t src_char_size = 1;
 48    ptrdiff_t src_len;
 49    if (end_ptr) {
 50        unsigned n = end_ptr - start_ptr;
 51        src_len = utf8_strlen2_buf(start_ptr, &n, &src_char_size);
 52    } else {
 53        src_len = utf8_strlen3(start_ptr, &src_char_size, &end_ptr);
 54    }
 55    if (src_len <= 0) {
 56        return true;
 57    }
 58    if (src_len >= UINT_MAX) {
 59        pw_set_status(PwStatus(PweStringTooLong));
 60        return false;
 61    }
 62    if (!_pw_expand_string(dest, src_len, src_char_size)) {
 63        return false;
 64    }
 65    unsigned append_position = _pw_string_inc_length(dest, src_len);
 66    StrPut fn_strput = _pw_strput_variants[dest->str_params.char_size][0];
 67    return fn_strput(dest, append_position, (uint8_t*) start_ptr, (uint8_t*) end_ptr);
 68}
 69
 70[[nodiscard]] bool _pw_string_append_utf32(PwValuePtr dest, char32_t* start_ptr, char32_t* end_ptr)
 71{
 72    pw_assert(pw_is_string(dest));
 73
 74    uint8_t src_char_size = 1;
 75    if (!end_ptr) {
 76        end_ptr = start_ptr + utf32_strlen2(start_ptr, &src_char_size);
 77    }
 78    ptrdiff_t src_len = end_ptr - start_ptr;
 79    if (src_len <= 0) {
 80        return true;
 81    }
 82    if (src_len >= UINT_MAX / 4) {
 83        pw_set_status(PwStatus(PweStringTooLong));
 84        return false;
 85    }
 86    if (!_pw_expand_string(dest, src_len, src_char_size)) {
 87        return false;
 88    }
 89    unsigned append_position = _pw_string_inc_length(dest, src_len);
 90    StrPut fn_strput = _pw_strput_variants[dest->str_params.char_size][4];
 91    return fn_strput(dest, append_position, (uint8_t*) start_ptr, (uint8_t*) end_ptr);
 92}
 93
 94[[nodiscard]] bool _pw_string_append(PwValuePtr dest, PwValuePtr src)
 95{
 96    pw_assert(pw_is_string(dest));
 97    unsigned src_len = pw_strlen(src);
 98    unsigned src_char_size = src->str_params.char_size;
 99    if (!_pw_expand_string(dest, src_len, src_char_size)) {
100        return false;
101    }
102    unsigned append_position = _pw_string_inc_length(dest, src_len);
103    uint8_t* src_end_ptr;
104    uint8_t* src_start_ptr = _pw_string_start_end(src, &src_end_ptr);
105    StrPut fn_strput = _pw_strput_variants[dest->str_params.char_size][src_char_size];
106    return fn_strput(dest, append_position, (uint8_t*) src_start_ptr, (uint8_t*) src_end_ptr);
107}
108
109[[nodiscard]] bool pw_string_append_substring(PwValuePtr dest, PwValuePtr src, unsigned src_start_pos, unsigned src_end_pos)
110{
111    pw_assert(pw_is_string(dest));
112    unsigned src_len  = pw_strlen(src);
113    if (src_end_pos > src_len) {
114        src_end_pos = src_len;
115    }
116    if (src_start_pos >= src_end_pos) {
117        return true;
118    }
119    src_len = src_end_pos - src_start_pos;
120
121    // expand with char_size unchanged because it is unknown for substring of src
122
123    if (!_pw_expand_string(dest, src_len, 1)) {
124        return false;
125    }
126    uint8_t src_char_size = src->str_params.char_size;
127    uint8_t* src_start_ptr = _pw_string_start(src);
128    uint8_t* src_end_ptr = src_start_ptr + src_end_pos * src_char_size;
129    src_start_ptr += src_start_pos * src_char_size;
130
131    unsigned append_position = _pw_string_inc_length(dest, src_len);
132    StrPut fn_strput = _pw_strput_variants[dest->str_params.char_size][src_char_size];
133    return fn_strput(dest, append_position, src_start_ptr, src_end_ptr);
134}