| 2110 | } |
| 2111 | |
| 2112 | FORCE_INLINE |
| 2113 | const char* rpad_utf8_int32_utf8(gdv_int64 context, const char* text, gdv_int32 text_len, |
| 2114 | gdv_int32 return_length, const char* fill_text, |
| 2115 | gdv_int32 fill_text_len, gdv_int32* out_len) { |
| 2116 | // if the text length or the defined return length (number of characters to return) |
| 2117 | // is <=0, then return an empty string. |
| 2118 | return_length = std::min(max_str_length, return_length); |
| 2119 | return_length = std::max(min_str_length, return_length); |
| 2120 | if (text_len == 0 || return_length <= 0) { |
| 2121 | *out_len = 0; |
| 2122 | return ""; |
| 2123 | } |
| 2124 | |
| 2125 | // count the number of utf8 characters on text, ignoring invalid bytes |
| 2126 | int actual_text_len = utf8_length_ignore_invalid(text, text_len); |
| 2127 | |
| 2128 | if (return_length == actual_text_len || |
| 2129 | (return_length > actual_text_len && fill_text_len == 0)) { |
| 2130 | // case where the return length is same as the text's length, or if it need to |
| 2131 | // fill into text but "fill_text" is empty, then return text directly. |
| 2132 | *out_len = text_len; |
| 2133 | return text; |
| 2134 | } |
| 2135 | if (return_length < actual_text_len) { |
| 2136 | // case where it truncates the result on return length. |
| 2137 | *out_len = utf8_byte_pos(context, text, text_len, return_length); |
| 2138 | return text; |
| 2139 | } |
| 2140 | |
| 2141 | gdv_int32 chars_to_pad = return_length - actual_text_len; |
| 2142 | |
| 2143 | // FAST PATH: Single-byte fill (most common - space padding) |
| 2144 | if (fill_text_len == 1) { |
| 2145 | gdv_int32 out_len_bytes = chars_to_pad + text_len; |
| 2146 | gdv_binary ret = |
| 2147 | reinterpret_cast<gdv_binary>(gdv_fn_context_arena_malloc(context, out_len_bytes)); |
| 2148 | if (ret == nullptr) { |
| 2149 | gdv_fn_context_set_error_msg(context, |
| 2150 | "Could not allocate memory for output string"); |
| 2151 | *out_len = 0; |
| 2152 | return ""; |
| 2153 | } |
| 2154 | memcpy(ret, text, text_len); |
| 2155 | memset(ret + text_len, fill_text[0], chars_to_pad); |
| 2156 | *out_len = out_len_bytes; |
| 2157 | return ret; |
| 2158 | } |
| 2159 | |
| 2160 | // GENERAL PATH: Multi-byte fill - use evaluate_return_char_length for buffer size |
| 2161 | gdv_int32 return_char_length = evaluate_return_char_length( |
| 2162 | text_len, actual_text_len, return_length, fill_text, fill_text_len); |
| 2163 | gdv_binary ret = reinterpret_cast<gdv_binary>( |
| 2164 | gdv_fn_context_arena_malloc(context, return_char_length)); |
| 2165 | if (ret == nullptr) { |
| 2166 | gdv_fn_context_set_error_msg(context, "Could not allocate memory for output string"); |
| 2167 | *out_len = 0; |
| 2168 | return ""; |
| 2169 | } |