| 2053 | } |
| 2054 | |
| 2055 | FORCE_INLINE |
| 2056 | const char* rpad_utf8_int32_utf8(gdv_int64 context, const char* text, gdv_int32 text_len, |
| 2057 | gdv_int32 return_length, const char* fill_text, |
| 2058 | gdv_int32 fill_text_len, gdv_int32* out_len) { |
| 2059 | // if the text length or the defined return length (number of characters to return) |
| 2060 | // is <=0, then return an empty string. |
| 2061 | return_length = std::min(max_str_length, return_length); |
| 2062 | return_length = std::max(min_str_length, return_length); |
| 2063 | if (text_len == 0 || return_length <= 0) { |
| 2064 | *out_len = 0; |
| 2065 | return ""; |
| 2066 | } |
| 2067 | |
| 2068 | // count the number of utf8 characters on text, ignoring invalid bytes |
| 2069 | int actual_text_len = utf8_length_ignore_invalid(text, text_len); |
| 2070 | |
| 2071 | if (return_length == actual_text_len || |
| 2072 | (return_length > actual_text_len && fill_text_len == 0)) { |
| 2073 | // case where the return length is same as the text's length, or if it need to |
| 2074 | // fill into text but "fill_text" is empty, then return text directly. |
| 2075 | *out_len = text_len; |
| 2076 | return text; |
| 2077 | } |
| 2078 | if (return_length < actual_text_len) { |
| 2079 | // case where it truncates the result on return length. |
| 2080 | *out_len = utf8_byte_pos(context, text, text_len, return_length); |
| 2081 | return text; |
| 2082 | } |
| 2083 | |
| 2084 | gdv_int32 chars_to_pad = return_length - actual_text_len; |
| 2085 | |
| 2086 | // FAST PATH: Single-byte fill (most common - space padding) |
| 2087 | if (fill_text_len == 1) { |
| 2088 | gdv_int32 out_len_bytes = chars_to_pad + text_len; |
| 2089 | gdv_binary ret = |
| 2090 | reinterpret_cast<gdv_binary>(gdv_fn_context_arena_malloc(context, out_len_bytes)); |
| 2091 | if (ret == nullptr) { |
| 2092 | gdv_fn_context_set_error_msg(context, |
| 2093 | "Could not allocate memory for output string"); |
| 2094 | *out_len = 0; |
| 2095 | return ""; |
| 2096 | } |
| 2097 | memcpy(ret, text, text_len); |
| 2098 | memset(ret + text_len, fill_text[0], chars_to_pad); |
| 2099 | *out_len = out_len_bytes; |
| 2100 | return ret; |
| 2101 | } |
| 2102 | |
| 2103 | // GENERAL PATH: Multi-byte fill - use evaluate_return_char_length for buffer size |
| 2104 | gdv_int32 return_char_length = evaluate_return_char_length( |
| 2105 | text_len, actual_text_len, return_length, fill_text, fill_text_len); |
| 2106 | gdv_binary ret = reinterpret_cast<gdv_binary>( |
| 2107 | gdv_fn_context_arena_malloc(context, return_char_length)); |
| 2108 | if (ret == nullptr) { |
| 2109 | gdv_fn_context_set_error_msg(context, "Could not allocate memory for output string"); |
| 2110 | *out_len = 0; |
| 2111 | return ""; |
| 2112 | } |