ufold

Прелама сваки UTF-8 улазни ред да стане у задату дужину
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување e92bad6391aa2ca8648976a8307ae7b6cc4a2601
родитељ 3a7da39339cdc139b724e6eba90001a623dc76e4
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Mon, 19 Jul 2021 20:12:09 +0200

Added logic for -s (spaces option)

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
Mdo-test | 16++++++++--------
Mufold.c | 227+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
измењених датотека: 2, додавања: 189(+), брисања: 54(-)

diff --git a/do-test b/do-test @@ -1,26 +1,26 @@ #!/bin/sh echo -ne "Test 1 - normal:\t" -fold test1.txt > f.out -ufold test1.txt > uf.out +fold -w 20 test1.txt > f.out +ufold -w 20 test1.txt > uf.out diff f.out uf.out 2>/dev/null >/dev/null && echo "PASS" || echo "FAIL" rm -f f.out uf.out echo -ne "Test 1 - spaces:\t" -fold -s test1.txt > f.out -ufold -s test1.txt > uf.out +fold -w 20 -s test1.txt > f.out +ufold -w 20 -s test1.txt > uf.out diff f.out uf.out 2>/dev/null >/dev/null && echo "PASS" || echo "FAIL" rm -f f.out uf.out echo -ne "Test 2 - normal:\t" -fold test2.txt > f.out -ufold test2.txt > uf.out +fold -w 20 test2.txt > f.out +ufold -w 20 test2.txt > uf.out diff f.out uf.out 2>/dev/null >/dev/null && echo "PASS" || echo "FAIL" rm -f f.out uf.out echo -ne "Test 2 - spaces:\t" -fold -s test2.txt > f.out -ufold -s test2.txt > uf.out +fold -w 20 -s test2.txt > f.out +ufold -w 20 -s test2.txt > uf.out diff f.out uf.out 2>/dev/null >/dev/null && echo "PASS" || echo "FAIL" rm -f f.out uf.out diff --git a/ufold.c b/ufold.c @@ -55,6 +55,183 @@ starts_with(const char* s, const char* with) return *with == 0; } +void +fold_line_spaces(const u8* line, const int width) +{ + if (!line) + return; + + /* + * Idea: + * 1. store characters in token until line is exhausted + * 2. when ' ' or end of line is encountered: + * 2,1, if token length > width, see if current column is 0: + * 2.1.1. if it isn't, output newline and go to 2.1.2. + * 2.1.2. (if it is) output chunks of length "width" until the + * end of token, then reset token + * 2.2. if token length <= width, see if token length + current + * column exceed width + * 2.2.1. if they do, output newline and go to 2.2.2. + * 2.2.2. (if they don't) output token + * 3. go to 1. unless line is exhausted + */ + const u8* pline = line; + u32 uch = 0; + u32 token[MAXINPUTBUF]; + u32* ptoken = NULL; + u8 u8ch[7]; + size_t u8ch_len = 0; + size_t delta = 0; + size_t len = 0; + size_t col = 0; + + *token = 0; + ptoken = token; + /* 1. */ + while (1) + { + u8_char_to_u32(&uch, pline, &len); + if (!len) + return; + *ptoken++ = uch; + pline += len; + + /* 2. */ + if (uch == (u32)L' ' || !uch) + { + + if (ptoken - token > width) + { + /* 2.1. */ + if (col > 0) + { + /* 2.1.1. */ + printf("\n"); + col = 0; + } + + /* 2.1.2. */ + *ptoken = 0; + ptoken = token; + while (*ptoken) + { + u8ch_len = u32_char_to_u8(u8ch, + *ptoken); + if (!u8ch_len) + return; + u8ch[u8ch_len] = 0; + + if (*ptoken == (u32)L'\t') + delta = 8 - (col % 8); + else + delta = 1; + + if (col + delta > width) + { + printf("\n"); + col = 0; + if (*ptoken == (u32)'\t') + delta = 8; + else + delta = 1; + } + printf("%s", u8ch); + col += delta; + ptoken += u8ch_len; + } + *token = 0; + ptoken = token; + } + else + { + /* 2.2. */ + if (ptoken - token + col > width) + { + /* 2.2.1. */ + printf("\n"); + col = 0; + } + + /* 2.2.2. */ + *ptoken = 0; + ptoken = token; + while (*ptoken) + { + u8ch_len = u32_char_to_u8(u8ch, + *ptoken); + if (!u8ch_len) + return; + u8ch[u8ch_len] = 0; + + if (*ptoken == (u32)L'\t') + delta = 8 - (col % 8); + else + delta = 1; + + printf("%s", u8ch); + col += delta; + ptoken++; + } + *token = 0; + ptoken = token; + } + } + + /* 3. */ + if (!uch) + break; + } +} + +void +fold_line_normal(const u8* line, const int width) +{ + if (!line) + return; + + const u8* pline = line; + const u8* pline_inner = NULL; + u32 uch; + u8 u8_char[7]; + u8* pu8_char = NULL; + size_t uch_len; + size_t delta = 0; + size_t col = 0; + + while (*pline) + { + /* convert only to get byte length */ + u8_char_to_u32(&uch, pline, &uch_len); + if (!uch_len) + return; + + pline_inner = pline; + pu8_char = u8_char; + while (*pline_inner && pline_inner < pline + uch_len) + *pu8_char++ = *pline_inner++; + *pu8_char = 0; + + if (uch == (u32)L'\t') + delta = 8 - (col % 8); + else + delta = 1; + + if (col + delta > width) + { + printf("\n"); + col = 0; + if (uch == (u32)L'\t') + delta = 8; + else + delta = 1; + } + + printf("%s", u8_char); + col += delta; + pline += uch_len; + } +} + int main(int argc, char** argv) { @@ -130,16 +307,6 @@ main(int argc, char** argv) return error(errno, "Cannot open file"); char line[MAXINPUTBUF]; - u32 token[MAXBUF]; - u32 uch; - u8 u8_char[8]; - u8* pu8_char = NULL; - u8* pline = NULL; - u8* pline_inner = NULL; - u32* ptoken = NULL; - long col = 0; - long delta = 0; - size_t len = 0; while (!feof(input)) { if (!fgets(line, MAXINPUTBUF, input)) @@ -152,44 +319,12 @@ main(int argc, char** argv) char* eol = strchr(line, '\n'); if (eol) *eol = 0; - pline = (u8*)line; - while (*pline) - { - if (spaces) - { - /* TODO: -s logic */ - } - else - { - u8_char_to_u32(&uch, pline, &len); - pline_inner = pline; - pu8_char = u8_char; - while (*pline_inner && pline_inner < - pline + len) - *pu8_char++ = *pline_inner++; - *pu8_char = 0; - if (uch == (u32)L'\t') - delta = 8 - (col % 8); - else - delta = 1; - if (col + delta > width) - { - printf("\n"); - col = 0; - if (uch == (u32)L'\t') - delta = 8; - else - delta = 1; - } - printf("%s", u8_char); - col += delta; - pline += len; - } - } + if (spaces) + fold_line_spaces((const u8*)line, width); + else + fold_line_normal((const u8*)line, width); printf("\n"); - col = 0; } - //printf("\n"); fclose(input); return 0;