mirror of
https://github.com/ascii-boxes/boxes.git
synced 2024-12-04 22:11:07 +01:00
Add bxs_substr() and bxs_prepend_spaces() to 'bxstring' module
This commit is contained in:
parent
770838b273
commit
775cabfbf6
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user