Created
January 11, 2022 23:11
-
-
Save peterdelevoryas/aa4c4cf3fd812a817ffaa66a58a68cf6 to your computer and use it in GitHub Desktop.
Unit test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#define ESCAPE "\x1B" | |
#define ESC_BAT ESCAPE"B" | |
#define ESC_MCU_BL_VER ESCAPE"U" | |
#define ESC_MCU_RUN_VER ESCAPE"R" | |
#define ESC_ALT ESCAPE"[5;7m" | |
#define ESC_RST ESCAPE"[m" | |
#define ESC_NOR ESCAPE"[0m" | |
#define LINE_DELIMITER '\x1F' | |
#ifdef CONFIG_FBY3 | |
#define FRAME_BUFF_SIZE 5120 | |
#else | |
#define FRAME_BUFF_SIZE 4096 | |
#endif | |
#define FRAME_PAGE_BUF_SIZE 256 | |
#define MAX_UART_SEL_NAME_SIZE 16 | |
struct frame { | |
char title[32]; | |
size_t max_size; | |
size_t max_page; | |
char *buf; | |
uint16_t idx_head, idx_tail; | |
uint8_t line_per_page; | |
uint8_t line_width; | |
uint16_t lines, pages; | |
uint8_t esc_sts; | |
uint8_t overwrite; | |
time_t mtime; | |
int (*init)(struct frame *self, size_t size); | |
int (*append)(struct frame *self, char *string, int indent); | |
int (*insert)(struct frame *self, char *string, int indent); | |
int (*getPage)(struct frame *self, int page, char *page_buf, size_t page_buf_size); | |
int (*isFull)(struct frame *self); | |
int (*isEscSeq)(struct frame *self, char chr); | |
int (*parse)(struct frame *self, char *buf, size_t buf_size, char *input, int indent); | |
}; | |
// return 0 on seccuess | |
static int frame_init (struct frame *self, size_t size) { | |
// Reset status | |
self->idx_head = self->idx_tail = 0; | |
self->lines = 0; | |
self->esc_sts = 0; | |
self->pages = 1; | |
if (self->buf != NULL && self->max_size == size) { | |
// reinit | |
return 0; | |
} | |
if (self->buf != NULL && self->max_size != size){ | |
free(self->buf); | |
} | |
// Initialize Configuration | |
self->title[0] = '\0'; | |
self->buf = malloc(size); | |
self->max_size = size; | |
self->max_page = size; | |
self->line_per_page = 7; | |
self->line_width = 16; | |
self->overwrite = 0; | |
if (self->buf) | |
return 0; | |
else | |
return -1; | |
} | |
static const char *find_esc(const char *buf, int blen, const char *esc, size_t elen) { | |
const char *ptr; | |
// to find the last CSI-codes | |
if (!(ptr = memrchr(buf, esc[0], blen))) | |
return NULL; | |
if ((blen - (ptr - buf) >= elen) && !memcmp(ptr, esc, elen)) | |
return ptr; | |
return NULL; | |
} | |
void print_string(const char *s) | |
{ | |
int is_escape = 0; | |
for (int i = 0; s[i]; i++) { | |
char c = s[i]; | |
switch (c) { | |
case 'a'...'l': | |
case 'n'...'z': | |
if (is_escape) { | |
printf(" "); | |
} | |
printf("%c", c); | |
is_escape = 0; | |
break; | |
case '[': | |
case ';': | |
case '0'...'9': | |
case 'm': | |
if (!is_escape) { | |
printf(" "); | |
} | |
printf("%c", c); | |
is_escape = 1; | |
break; | |
default: | |
printf(" \\x%02x", (unsigned char)c); | |
is_escape = 1; | |
break; | |
} | |
} | |
} | |
// return 0 on seccuess | |
static int frame_append (struct frame *self, char *string, int indent) | |
{ | |
const size_t buf_size = 64; | |
char buf[buf_size]; | |
char *ptr; | |
int ret; | |
ret = self->parse(self, buf, buf_size, string, indent); | |
if (ret < 0) | |
return ret; | |
strcpy(buf, string); | |
print_string(buf); | |
printf("\n"); | |
for (ptr = buf; *ptr != '\0'; ptr++) { | |
if (self->isFull(self)) { | |
if (self->overwrite) { | |
if (self->buf[self->idx_head] == LINE_DELIMITER) | |
self->lines--; | |
self->idx_head = (self->idx_head + 1) % self->max_size; | |
} else | |
return -1; | |
} | |
if (*ptr == LINE_DELIMITER) { | |
self->lines++; | |
// workaround when Blink CSI-codes spread 2 pages, | |
// add ESC_RST to the end of previous page, | |
// add ESC_ALT to the start of next page | |
if (!(self->lines % self->line_per_page)) { | |
const char *esc = find_esc(buf, ptr - buf, ESC_ALT, strlen(ESC_ALT)); | |
if (esc != NULL) { | |
esc += strlen(ESC_ALT); | |
if (!find_esc(esc, ptr - esc, ESC_RST, strlen(ESC_RST))) { | |
char tmp[16], *ptmp; | |
snprintf(tmp, sizeof(tmp), ESC_RST"%c"ESC_ALT, LINE_DELIMITER); | |
for (ptmp = tmp; *ptmp; ptmp++) { | |
if (self->isFull(self)) { | |
if (!self->overwrite) { | |
return -1; | |
} | |
if (self->buf[self->idx_head] == LINE_DELIMITER) | |
self->lines--; | |
self->idx_head = (self->idx_head + 1) % self->max_size; | |
} | |
self->buf[self->idx_tail] = *ptmp; | |
self->idx_tail = (self->idx_tail + 1) % self->max_size; | |
} | |
continue; | |
} | |
} | |
} | |
} | |
self->buf[self->idx_tail] = *ptr; | |
self->idx_tail = (self->idx_tail + 1) % self->max_size; | |
} | |
self->pages = (self->lines / self->line_per_page) + | |
((self->lines % self->line_per_page)?1:0); | |
if (self->pages > self->max_page) | |
self->pages = self->max_page; | |
return 0; | |
} | |
int do_nothing(void) { | |
return 0; | |
} | |
void unit_test(const char *input) { | |
struct frame f; | |
memset(&f, 0, sizeof(f)); | |
f.isFull = (void*)do_nothing; | |
f.parse = (void*)do_nothing; | |
frame_init(&f, 32); | |
f.lines = f.line_per_page - 1; | |
char s[256]; | |
int n = sprintf(s, "%s", input); | |
while ((n + 1) % f.line_per_page) { | |
s[n++] = 'a'; | |
} | |
s[n++] = LINE_DELIMITER; | |
s[n] = '\0'; | |
printf("input: "); | |
frame_append(&f, s, 0); | |
printf("output: "); | |
print_string(f.buf); | |
printf("\n"); | |
} | |
int main(void) | |
{ | |
printf("ESC_ALT="); | |
print_string(ESC_ALT); | |
printf("\n"); | |
printf("ESC_RST="); | |
print_string(ESC_RST); | |
printf("\n"); | |
printf("Workaround will be applied:\n"); | |
unit_test("abc" ESC_ALT "def"); | |
unit_test("abc" ESC_RST "def" ESC_ALT); | |
printf("Workaround won't be applied:\n"); | |
unit_test("abc" ESC_ALT "def" ESC_RST); | |
unit_test("abcdef"); | |
unit_test("abc" ESC_RST); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
gcc test.c && ./a.out
: