test(txt) initial unit tests and general code cleanup/fixes (#2623)
* test(txt): Add test for identifying empty text when trying to get next line * test(txt): Rename next line empty string handling test * test(txt): Add tests for _lv_txt_is_cmd * test(txt): Add initial tests for _lv_txt_ins * fix(txt): Check for NULL before using strlen Passing NULL to strlen is not defined, so we should avoid it * txt: Update docs Remove docs from source file and add comment about pointers to NULL terminated arrays where necessary * txt: Misc update in encoded_size * test(txt): first tests for _lv_txt_cut * tests: Remove -Wmissing-prototype flag from compilation This will allow us to have cleaner test cases files. * test(txt): Remove test (funtion) prototypes as they're no longer necessary * Update src/misc/lv_txt.h Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> * Update src/misc/lv_txt.h Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> * Revert "tests: Remove -Wmissing-prototype flag from compilation" This reverts commit 8b3217de8d9210eb2e6da5e94c0735beb2735be7. * test(txt): Use pragma to disable missing-prototype warning * test: use extended set of compile options for test cases * Revert "test(txt): Use pragma to disable missing-prototype warning" This reverts commit 64909e30ed124ca1e8ca390ca0639479c3e34f44. * test(txt): Add assert to test_txt_cut_len_longer_than_string test * test(txt): Add test for _lv_txt_encoded_next on valid ascii input * test(txt): Add tests for _lv_txt_encoded_next with 2 byte long inputs * test(txt): Add tests for _lv_txt_encoded_next with 3 byte long inputs * test(txt): Add tests for _lv_txt_encoded_next with 4 byte long inputs * cleanup(txt): Add helper macros to identify ASCII and UTF8 codes * cleanup(txt): Add missing LV_ prefix to helper macros Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com> Co-authored-by: embeddedt <42941056+embeddedt@users.noreply.github.com>
This commit is contained in:
@@ -78,21 +78,16 @@
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#define LV_IS_ASCII(value) ((value & 0x80U) == 0x00U)
|
||||
#define LV_IS_2BYTES_UTF8_CODE(value) ((value & 0xE0U) == 0xC0U)
|
||||
#define LV_IS_3BYTES_UTF8_CODE(value) ((value & 0xF0U) == 0xE0U)
|
||||
#define LV_IS_4BYTES_UTF8_CODE(value) ((value & 0xF8U) == 0xF0U)
|
||||
#define LV_IS_INVALID_UTF8_CODE(value) ((value & 0xC0U) != 0x80U)
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Get size of a text
|
||||
* @param size_res pointer to a 'point_t' variable to store the result
|
||||
* @param text pointer to a text
|
||||
* @param font pointer to font of the text
|
||||
* @param letter_space letter space of the text
|
||||
* @param txt.line_space line space of the text
|
||||
* @param flags settings for the text from ::lv_text_flag_t
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid
|
||||
* line breaks
|
||||
*/
|
||||
void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, lv_coord_t letter_space,
|
||||
lv_coord_t line_space, lv_coord_t max_width, lv_text_flag_t flag)
|
||||
{
|
||||
@@ -280,18 +275,6 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next line of text. Check line length and break chars too.
|
||||
*
|
||||
* A line of txt includes the \n character.
|
||||
*
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks
|
||||
* @param flags settings for the text from 'txt_flag_type' enum
|
||||
* @return the index of the first char of the new line (in byte index not letter index. With UTF-8 they are different)
|
||||
*/
|
||||
uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font,
|
||||
lv_coord_t letter_space, lv_coord_t max_width, lv_text_flag_t flag)
|
||||
{
|
||||
@@ -343,16 +326,6 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font,
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the length of a text with a given font
|
||||
* @param txt a '\0' terminate string
|
||||
* @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in
|
||||
* UTF-8)
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param flags settings for the text from 'txt_flag_t' enum
|
||||
* @return length of a char_num long text
|
||||
*/
|
||||
lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t * font, lv_coord_t letter_space,
|
||||
lv_text_flag_t flag)
|
||||
{
|
||||
@@ -392,14 +365,6 @@ lv_coord_t lv_txt_get_width(const char * txt, uint32_t length, const lv_font_t *
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check next character in a string and decide if the character is part of the command or not
|
||||
* @param state pointer to a txt_cmd_state_t variable which stores the current state of command
|
||||
* processing (Inited to TXT_CMD_STATE_WAIT )
|
||||
* @param c the current character
|
||||
* @return true: the character is part of a command and should not be written,
|
||||
* false: the character should be written
|
||||
*/
|
||||
bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c)
|
||||
{
|
||||
bool ret = false;
|
||||
@@ -431,15 +396,10 @@ bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a string into an other
|
||||
* @param txt_buf the original text (must be big enough for the result text)
|
||||
* @param pos position to insert. Expressed in character index and not byte index (Different in
|
||||
* UTF-8) 0: before the original text, 1: after the first char etc.
|
||||
* @param ins_txt text to insert
|
||||
*/
|
||||
void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
|
||||
{
|
||||
if(txt_buf == NULL || ins_txt == NULL) return;
|
||||
|
||||
size_t old_len = strlen(txt_buf);
|
||||
size_t ins_len = strlen(ins_txt);
|
||||
if(ins_len == 0) return;
|
||||
@@ -457,15 +417,9 @@ void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt)
|
||||
lv_memcpy_small(txt_buf + pos, ins_txt, ins_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a part of a string
|
||||
* @param txt string to modify
|
||||
* @param pos position where to start the deleting (0: before the first char, 1: after the first
|
||||
* char etc.)
|
||||
* @param len number of characters to delete
|
||||
*/
|
||||
void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len)
|
||||
{
|
||||
if(txt == NULL) return;
|
||||
|
||||
size_t old_len = strlen(txt);
|
||||
|
||||
@@ -479,11 +433,6 @@ void _lv_txt_cut(char * txt, uint32_t pos, uint32_t len)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a new formatted text. Memory will be allocated to store the text.
|
||||
* @param fmt `printf`-like format
|
||||
* @return pointer to the allocated text string.
|
||||
*/
|
||||
LV_FORMAT_ATTRIBUTE(1, 0) char * _lv_txt_set_text_vfmt(const char * fmt, va_list ap)
|
||||
{
|
||||
/*Allocate space for the new text by using trick from C99 standard section 7.19.6.12*/
|
||||
@@ -541,19 +490,19 @@ void _lv_txt_encoded_letter_next_2(const char * txt, uint32_t * letter, uint32_t
|
||||
/**
|
||||
* Give the size of an UTF-8 coded character
|
||||
* @param str pointer to a character in a string
|
||||
* @return length of the UTF-8 character (1,2,3 or 4). O on invalid code
|
||||
* @return length of the UTF-8 character (1,2,3 or 4), 0 on invalid code.
|
||||
*/
|
||||
static uint8_t lv_txt_utf8_size(const char * str)
|
||||
{
|
||||
if((str[0] & 0x80) == 0)
|
||||
if(LV_IS_ASCII(str[0]))
|
||||
return 1;
|
||||
else if((str[0] & 0xE0) == 0xC0)
|
||||
else if(LV_IS_2BYTES_UTF8_CODE(str[0]))
|
||||
return 2;
|
||||
else if((str[0] & 0xF0) == 0xE0)
|
||||
else if(LV_IS_3BYTES_UTF8_CODE(str[0]))
|
||||
return 3;
|
||||
else if((str[0] & 0xF8) == 0xF0)
|
||||
else if(LV_IS_4BYTES_UTF8_CODE(str[0]))
|
||||
return 4;
|
||||
return 0; /*If the char was invalid tell it's 1 byte long*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,47 +588,47 @@ static uint32_t lv_txt_utf8_next(const char * txt, uint32_t * i)
|
||||
if(i == NULL) i = &i_tmp;
|
||||
|
||||
/*Normal ASCII*/
|
||||
if((txt[*i] & 0x80) == 0) {
|
||||
if(LV_IS_ASCII(txt[*i])) {
|
||||
result = txt[*i];
|
||||
(*i)++;
|
||||
}
|
||||
/*Real UTF-8 decode*/
|
||||
else {
|
||||
/*2 bytes UTF-8 code*/
|
||||
if((txt[*i] & 0xE0) == 0xC0) {
|
||||
if(LV_IS_2BYTES_UTF8_CODE(txt[*i])) {
|
||||
result = (uint32_t)(txt[*i] & 0x1F) << 6;
|
||||
(*i)++;
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0;
|
||||
result += (txt[*i] & 0x3F);
|
||||
(*i)++;
|
||||
}
|
||||
/*3 bytes UTF-8 code*/
|
||||
else if((txt[*i] & 0xF0) == 0xE0) {
|
||||
else if(LV_IS_3BYTES_UTF8_CODE(txt[*i])) {
|
||||
result = (uint32_t)(txt[*i] & 0x0F) << 12;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0;
|
||||
result += (uint32_t)(txt[*i] & 0x3F) << 6;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0;
|
||||
result += (txt[*i] & 0x3F);
|
||||
(*i)++;
|
||||
}
|
||||
/*4 bytes UTF-8 code*/
|
||||
else if((txt[*i] & 0xF8) == 0xF0) {
|
||||
else if(LV_IS_4BYTES_UTF8_CODE(txt[*i])) {
|
||||
result = (uint32_t)(txt[*i] & 0x07) << 18;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0;
|
||||
result += (uint32_t)(txt[*i] & 0x3F) << 12;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0;
|
||||
result += (uint32_t)(txt[*i] & 0x3F) << 6;
|
||||
(*i)++;
|
||||
|
||||
if((txt[*i] & 0xC0) != 0x80) return 0; /*Invalid UTF-8 code*/
|
||||
if(LV_IS_INVALID_UTF8_CODE(txt[*i])) return 0;
|
||||
result += txt[*i] & 0x3F;
|
||||
(*i)++;
|
||||
}
|
||||
@@ -736,7 +685,8 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id)
|
||||
uint32_t byte_cnt = 0;
|
||||
for(i = 0; i < utf8_id && txt[byte_cnt] != '\0'; i++) {
|
||||
uint8_t c_size = _lv_txt_encoded_size(&txt[byte_cnt]);
|
||||
byte_cnt += c_size > 0 ? c_size : 1;
|
||||
/* If the char was invalid tell it's 1 byte long*/
|
||||
byte_cnt += c_size ? c_size : 1;
|
||||
}
|
||||
|
||||
return byte_cnt;
|
||||
|
||||
@@ -122,15 +122,15 @@ bool _lv_txt_is_cmd(lv_text_cmd_state_t * state, uint32_t c);
|
||||
|
||||
/**
|
||||
* Insert a string into an other
|
||||
* @param txt_buf the original text (must be big enough for the result text)
|
||||
* @param txt_buf the original text (must be big enough for the result text and NULL terminated)
|
||||
* @param pos position to insert (0: before the original text, 1: after the first char etc.)
|
||||
* @param ins_txt text to insert
|
||||
* @param ins_txt text to insert, must be '\0' terminated
|
||||
*/
|
||||
void _lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt);
|
||||
|
||||
/**
|
||||
* Delete a part of a string
|
||||
* @param txt string to modify
|
||||
* @param txt string to modify, must be '\0' terminated and should point to a heap or stack frame, not read-only memory.
|
||||
* @param pos position where to start the deleting (0: before the first char, 1: after the first
|
||||
* char etc.)
|
||||
* @param len number of characters to delete
|
||||
|
||||
Reference in New Issue
Block a user