Add bxs_substr() and bxs_prepend_spaces() to 'bxstring' module

This commit is contained in:
Thomas Jensen 2023-10-10 21:29:40 +02:00
parent 770838b273
commit 775cabfbf6
No known key found for this signature in database
GPG Key ID: A4ACEE270D0FB7DB
5 changed files with 186 additions and 1 deletions

View File

@ -254,6 +254,31 @@ bxstr_t *bxs_trimdup(bxstr_t *pString, size_t start_idx, size_t end_idx)
bxstr_t *bxs_substr(bxstr_t *pString, size_t start_idx, size_t end_idx)
{
if (pString == NULL) {
return NULL;
}
if (start_idx > pString->num_chars_visible) {
start_idx = pString->num_chars_visible;
}
if (end_idx > pString->num_chars_visible) {
end_idx = pString->num_chars_visible;
}
if (end_idx < start_idx) {
bx_fprintf(stderr, "%s: internal error: end_idx before start_idx in bxs_substr()\n", PROJECT);
return NULL;
}
ucs4_t save = pString->memory[pString->first_char[end_idx]];
set_char_at(pString->memory, pString->first_char[end_idx], char_nul);
bxstr_t *result = bxs_from_unicode(pString->memory + pString->first_char[start_idx]);
set_char_at(pString->memory, pString->first_char[end_idx], save);
return result;
}
bxstr_t *bxs_strcat(bxstr_t *pString, uint32_t *pToAppend)
{
if (pToAppend == NULL) {
@ -444,6 +469,54 @@ bxstr_t *bxs_rtrim(bxstr_t *pString)
bxstr_t *bxs_prepend_spaces(bxstr_t *pString, size_t n)
{
bxstr_t *result = NULL;
if (n == 0) {
result = bxs_strdup(pString);
}
else if (pString == NULL) {
uint32_t *s = u32_nspaces(n);
result = bxs_from_unicode(s);
BFREE(s);
}
else {
result = (bxstr_t *) calloc(1, sizeof(bxstr_t));
result->memory = (uint32_t *) malloc((pString->num_chars + n + 1) * sizeof(uint32_t));
uint32_t *s = u32_nspaces(n);
u32_cpy(result->memory, s, n);
BFREE(s);
u32_cpy(result->memory + n, pString->memory, pString->num_chars);
set_char_at(result->memory, pString->num_chars + n, char_nul);
result->ascii = (char *) malloc((pString->num_columns + n + 1) * sizeof(char));
memset(result->ascii, ' ', n);
strcpy(result->ascii + n, pString->ascii);
result->indent = pString->indent + n;
result->num_columns = pString->num_columns + n;
result->num_chars = pString->num_chars + n;
result->num_chars_visible = pString->num_chars_visible + n;
result->num_chars_invisible = pString->num_chars_invisible;
result->trailing = pString->trailing;
result->first_char = (size_t *) malloc((pString->num_chars_visible + n + 1) * sizeof(size_t));
result->visible_char = (size_t *) malloc((pString->num_chars_visible + n + 1) * sizeof(size_t));
for (size_t i=0; i < n; i++) {
result->first_char[i] = i;
result->visible_char[i] = i;
}
for (size_t i=0; i <= pString->num_chars_visible; i++) {
result->first_char[i + n] = pString->first_char[i] + n;
result->visible_char[i + n] = pString->visible_char[i] + n;
}
}
return result;
}
void bxs_append_spaces(bxstr_t *pString, size_t n)
{
if (pString == NULL || n == 0) {

View File

@ -104,13 +104,25 @@ bxstr_t *bxs_strdup(bxstr_t *pString);
* Take a substring from the given string, trim leading and trailing space from it, and duplicate the result in a new
* string. If invisible characters are included in the string, they are also duplicated.
* @param pString the source string
* @param start_idx the index of the first visible character of the substring
* @param start_idx the index of the first visible character of the substring, used as index into `first_char` and
* `visible_char`
* @param end_idx the index of the first visible character following the substring
* @return the trimmed and duplicated substring, for which new memory was allocated
*/
bxstr_t *bxs_trimdup(bxstr_t *pString, size_t start_idx, size_t end_idx);
/**
* Take a substring from the given string.
* @param pString the source string
* @param start_idx the index of the first visible character of the substring, used as index into `first_char` and
* `visible_char`
* @param end_idx the index of the first visible character following the substring
* @return the substring, in new memory
*/
bxstr_t *bxs_substr(bxstr_t *pString, size_t start_idx, size_t end_idx);
/**
* Combine `pString + pToAppend` into a new string. Memory for the input strings is NOT modified or freed.
* @param pString the string to append to
@ -206,6 +218,15 @@ uint32_t *bxs_ltrim(bxstr_t *pString, size_t max);
bxstr_t *bxs_rtrim(bxstr_t *pString);
/**
* Prepend `n` spaces to the start of the given string. New memory is allocated for the result.
* @param pString the original string (will not be modified, can be NULL, in which case spaces only in result)
* @param n the number of spaces to prepend
* @returns spaces plus original string, in new memory. Will be NULL only of `pString` == NULL and `n` == 0.
*/
bxstr_t *bxs_prepend_spaces(bxstr_t *pString, size_t n);
/**
* Append `n` spaces to the end of the given string. The given string is *modified* accordingly.
* @param pString the string to modify

View File

@ -487,6 +487,26 @@ void test_bxs_cut_front_zero(void **state)
void test_bxs_first_char_ptr_errors(void **state)
{
UNUSED(state);
uint32_t *actual = bxs_first_char_ptr(NULL, 0);
assert_null(actual);
uint32_t *ustr32 = u32_strconv_from_arg("ab\x1b[38;5;203mc\x1b[0m\x1b[38;5;198md\x1b[0me", "ASCII");
assert_non_null(ustr32);
bxstr_t *input = bxs_from_unicode(ustr32);
actual = bxs_first_char_ptr(input, 1000);
assert_non_null(actual);
assert_true(u32_is_blank(actual));
bxs_free(input);
BFREE(ustr32);
}
void test_bxs_last_char_ptr(void **state)
{
UNUSED(state);
@ -507,6 +527,16 @@ void test_bxs_last_char_ptr(void **state)
void test_bxs_unindent_ptr_null(void **state)
{
UNUSED(state);
uint32_t *actual = bxs_unindent_ptr(NULL);
assert_null(actual);
}
void test_bxs_trimdup_null(void **state)
{
UNUSED(state);
@ -662,6 +692,39 @@ void test_bxs_trimdup_ansi_same(void **state)
void test_bxs_substr_errors(void **state)
{
UNUSED(state);
uint32_t *ustr32 = u32_strconv_from_arg("ab\x1b[38;5;203mc\x1b[0m\x1b[38;5;198md\x1b[0me", "ASCII");
assert_non_null(ustr32);
bxstr_t *input = bxs_from_unicode(ustr32);
bxstr_t *actual = bxs_substr(NULL, 0, 0);
assert_null(actual);
actual = bxs_substr(input, 1000, input->num_chars);
assert_non_null(actual);
assert_true(bxs_is_empty(actual));
bxs_free(actual);
actual = bxs_substr(input, input->num_chars - 1, 1000);
assert_non_null(actual);
assert_string_equal("e", actual->ascii);
assert_int_equal(1, actual->num_chars);
bxs_free(actual);
actual = bxs_substr(input, 3, 0); /* start_idx > end_idx */
assert_null(actual);
assert_int_equal(1, collect_err_size);
assert_string_equal("boxes: internal error: end_idx before start_idx in bxs_substr()\n", collect_err[0]);
BFREE(ustr32);
bxs_free(input);
}
void test_bxs_strcat_empty(void **state)
{
UNUSED(state);
@ -1086,6 +1149,22 @@ void test_bxs_rtrim_empty(void **state)
void test_bxs_prepend_spaces_null(void **state)
{
UNUSED(state);
bxstr_t *actual = bxs_prepend_spaces(NULL, 2);
assert_non_null(actual);
assert_string_equal(" ", actual->ascii);
assert_int_equal(2, (int) actual->num_chars);
assert_int_equal(2, (int) actual->num_chars_visible);
assert_int_equal(0, (int) actual->num_chars_invisible);
bxs_free(actual);
}
void test_bxs_append_spaces(void **state)
{
UNUSED(state);

View File

@ -45,8 +45,12 @@ void test_bxs_strdup(void **state);
void test_bxs_cut_front(void **state);
void test_bxs_cut_front_zero(void **state);
void test_bxs_first_char_ptr_errors(void **state);
void test_bxs_last_char_ptr(void **state);
void test_bxs_unindent_ptr_null(void **state);
void test_bxs_trimdup_null(void **state);
void test_bxs_trimdup_invalid_startidx(void **state);
void test_bxs_trimdup_invalid_endidx(void **state);
@ -56,6 +60,8 @@ void test_bxs_trimdup_vanish(void **state);
void test_bxs_trimdup_ansi(void **state);
void test_bxs_trimdup_ansi_same(void **state);
void test_bxs_substr_errors(void **state);
void test_bxs_strcat(void **state);
void test_bxs_strcat_empty(void **state);
void test_bxs_strcat_empty2(void **state);
@ -77,6 +83,8 @@ void test_bxs_ltrim_max(void **state);
void test_bxs_rtrim(void **state);
void test_bxs_rtrim_empty(void **state);
void test_bxs_prepend_spaces_null(void **state);
void test_bxs_append_spaces(void **state);
void test_bxs_to_output(void **state);

View File

@ -140,7 +140,9 @@ int main(void)
cmocka_unit_test_setup(test_bxs_strdup, beforeTest),
cmocka_unit_test_setup(test_bxs_cut_front, beforeTest),
cmocka_unit_test_setup(test_bxs_cut_front_zero, beforeTest),
cmocka_unit_test_setup(test_bxs_first_char_ptr_errors, beforeTest),
cmocka_unit_test_setup(test_bxs_last_char_ptr, beforeTest),
cmocka_unit_test_setup(test_bxs_unindent_ptr_null, beforeTest),
cmocka_unit_test_setup(test_bxs_trimdup_null, beforeTest),
cmocka_unit_test_setup(test_bxs_trimdup_invalid_startidx, beforeTest),
cmocka_unit_test_setup(test_bxs_trimdup_invalid_endidx, beforeTest),
@ -149,6 +151,7 @@ int main(void)
cmocka_unit_test_setup(test_bxs_trimdup_vanish, beforeTest),
cmocka_unit_test_setup(test_bxs_trimdup_ansi, beforeTest),
cmocka_unit_test_setup(test_bxs_trimdup_ansi_same, beforeTest),
cmocka_unit_test_setup(test_bxs_substr_errors, beforeTest),
cmocka_unit_test_setup(test_bxs_strcat, beforeTest),
cmocka_unit_test_setup(test_bxs_strcat_empty, beforeTest),
cmocka_unit_test_setup(test_bxs_strcat_empty2, beforeTest),
@ -165,6 +168,7 @@ int main(void)
cmocka_unit_test_setup(test_bxs_ltrim_max, beforeTest),
cmocka_unit_test_setup(test_bxs_rtrim, beforeTest),
cmocka_unit_test_setup(test_bxs_rtrim_empty, beforeTest),
cmocka_unit_test_setup(test_bxs_prepend_spaces_null, beforeTest),
cmocka_unit_test_setup(test_bxs_append_spaces, beforeTest),
cmocka_unit_test_setup(test_bxs_to_output, beforeTest),
cmocka_unit_test_setup(test_bxs_is_empty_null, beforeTest),