@@ -1966,6 +1966,22 @@ gdv_int32 evaluate_return_char_length(gdv_int32 text_len, gdv_int32 actual_text_
19661966 return return_char_length;
19671967}
19681968
1969+ // Fill a buffer with repeated fill_text using O(log n) doubling strategy
1970+ FORCE_INLINE
1971+ void fill_buffer_with_pattern (gdv_binary dest, gdv_int32 total_fill_bytes,
1972+ const char * fill_text, gdv_int32 fill_text_len) {
1973+ gdv_int32 initial_copy = std::min (fill_text_len, total_fill_bytes);
1974+ memcpy (dest, fill_text, initial_copy);
1975+ gdv_int32 written = initial_copy;
1976+ while (written * 2 <= total_fill_bytes) {
1977+ memcpy (dest + written, dest, written);
1978+ written *= 2 ;
1979+ }
1980+ if (written < total_fill_bytes) {
1981+ memcpy (dest + written, dest, total_fill_bytes - written);
1982+ }
1983+ }
1984+
19691985FORCE_INLINE
19701986const char * lpad_utf8_int32_utf8 (gdv_int64 context, const char * text, gdv_int32 text_len,
19711987 gdv_int32 return_length, const char * fill_text,
@@ -2000,7 +2016,7 @@ const char* lpad_utf8_int32_utf8(gdv_int64 context, const char* text, gdv_int32
20002016 // FAST PATH: Single-byte fill (most common - space padding)
20012017 if (fill_text_len == 1 ) {
20022018 gdv_int32 out_len_bytes = chars_to_pad + text_len;
2003- char * ret =
2019+ gdv_binary ret =
20042020 reinterpret_cast <gdv_binary>(gdv_fn_context_arena_malloc (context, out_len_bytes));
20052021 if (ret == nullptr ) {
20062022 gdv_fn_context_set_error_msg (context,
@@ -2017,28 +2033,17 @@ const char* lpad_utf8_int32_utf8(gdv_int64 context, const char* text, gdv_int32
20172033 // GENERAL PATH: Multi-byte fill - use evaluate_return_char_length for buffer size
20182034 gdv_int32 return_char_length = evaluate_return_char_length (
20192035 text_len, actual_text_len, return_length, fill_text, fill_text_len);
2020- char * ret = reinterpret_cast <gdv_binary>(
2036+ gdv_binary ret = reinterpret_cast <gdv_binary>(
20212037 gdv_fn_context_arena_malloc (context, return_char_length));
20222038 if (ret == nullptr ) {
20232039 gdv_fn_context_set_error_msg (context, " Could not allocate memory for output string" );
20242040 *out_len = 0 ;
20252041 return " " ;
20262042 }
20272043
2028- // Fill using doubling strategy (O(log n) memcpy calls)
2044+ // Fill padding region using doubling strategy, then append text
20292045 gdv_int32 total_fill_bytes = return_char_length - text_len;
2030- // Copy only as much of fill_text as we need (may be less than fill_text_len)
2031- gdv_int32 initial_copy = std::min (fill_text_len, total_fill_bytes);
2032- memcpy (ret, fill_text, initial_copy);
2033- gdv_int32 written = initial_copy;
2034- while (written * 2 <= total_fill_bytes) {
2035- memcpy (ret + written, ret, written);
2036- written *= 2 ;
2037- }
2038- if (written < total_fill_bytes) {
2039- memcpy (ret + written, ret, total_fill_bytes - written);
2040- }
2041-
2046+ fill_buffer_with_pattern (ret, total_fill_bytes, fill_text, fill_text_len);
20422047 memcpy (ret + total_fill_bytes, text, text_len);
20432048 *out_len = return_char_length;
20442049 return ret;
@@ -2078,7 +2083,7 @@ const char* rpad_utf8_int32_utf8(gdv_int64 context, const char* text, gdv_int32
20782083 // FAST PATH: Single-byte fill (most common - space padding)
20792084 if (fill_text_len == 1 ) {
20802085 gdv_int32 out_len_bytes = chars_to_pad + text_len;
2081- char * ret =
2086+ gdv_binary ret =
20822087 reinterpret_cast <gdv_binary>(gdv_fn_context_arena_malloc (context, out_len_bytes));
20832088 if (ret == nullptr ) {
20842089 gdv_fn_context_set_error_msg (context,
@@ -2095,29 +2100,18 @@ const char* rpad_utf8_int32_utf8(gdv_int64 context, const char* text, gdv_int32
20952100 // GENERAL PATH: Multi-byte fill - use evaluate_return_char_length for buffer size
20962101 gdv_int32 return_char_length = evaluate_return_char_length (
20972102 text_len, actual_text_len, return_length, fill_text, fill_text_len);
2098- char * ret = reinterpret_cast <gdv_binary>(
2103+ gdv_binary ret = reinterpret_cast <gdv_binary>(
20992104 gdv_fn_context_arena_malloc (context, return_char_length));
21002105 if (ret == nullptr ) {
21012106 gdv_fn_context_set_error_msg (context, " Could not allocate memory for output string" );
21022107 *out_len = 0 ;
21032108 return " " ;
21042109 }
21052110
2106- // Copy text first, then fill using doubling strategy
2111+ // Copy text first, then fill padding region using doubling strategy
21072112 memcpy (ret, text, text_len);
21082113 gdv_int32 total_fill_bytes = return_char_length - text_len;
2109- // Copy only as much of fill_text as we need (may be less than fill_text_len)
2110- gdv_int32 initial_copy = std::min (fill_text_len, total_fill_bytes);
2111- memcpy (ret + text_len, fill_text, initial_copy);
2112- gdv_int32 written = initial_copy;
2113- while (written * 2 <= total_fill_bytes) {
2114- memcpy (ret + text_len + written, ret + text_len, written);
2115- written *= 2 ;
2116- }
2117- if (written < total_fill_bytes) {
2118- memcpy (ret + text_len + written, ret + text_len, total_fill_bytes - written);
2119- }
2120-
2114+ fill_buffer_with_pattern (ret + text_len, total_fill_bytes, fill_text, fill_text_len);
21212115 *out_len = return_char_length;
21222116 return ret;
21232117}
0 commit comments