From: yu.dongliang <18588496441@163.com> Date: Tue, 3 Mar 2026 08:48:08 +0000 (+0800) Subject: css: add a simple css parser X-Git-Url: http://baseworks.info/?a=commitdiff_plain;ds=sidebyside;p=abc.git css: add a simple css parser --- diff --git a/examples/css.html b/examples/css.html new file mode 100644 index 0000000..7e1dda0 --- /dev/null +++ b/examples/css.html @@ -0,0 +1,18 @@ + + + + + + + +

Hello World!

+

这个段落采用CSS样式化。

+ + + diff --git a/html/Makefile b/html/Makefile index b04c19b..e404606 100644 --- a/html/Makefile +++ b/html/Makefile @@ -1,9 +1,11 @@ CFILES += main.c CFILES += abc_obj.c CFILES += abc_html.c -CFILES += abc_html_util.c +CFILES += abc_css.c +CFILES += abc_io_util.c CFILES += abc_io_file.c CFILES += abc_io_http.c +CFILES += abc_io_str.c CFILES += ../js/util/scf_string.c CFILES += ../js/util/scf_graph.c diff --git a/html/abc_css.c b/html/abc_css.c new file mode 100644 index 0000000..4ddf3b1 --- /dev/null +++ b/html/abc_css.c @@ -0,0 +1,300 @@ +#include"abc_html.h" +int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags); +html_label_t* __html_find_label(const char* name); + +static int __css_parse_value(abc_obj_t* css, abc_obj_t* attr) +{ + scf_string_t* value = scf_string_alloc(); + if (!value) + return -ENOMEM; + + abc_char_t* c = NULL; + abc_char_t* c2 = NULL; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) { + scf_loge("\n"); + scf_string_free(value); + return -1; + } + + css->text_pos += c->len; + + if (';' == c->c) + break; + else + scf_string_cat_cstr_len(value, c->utf8, c->len); + + free(c); + c = NULL; + } + + int tmp = c->c; + + free(c); + c = NULL; + + if (attr->value) + scf_string_free(attr->value); + + attr->value = value; + return tmp; +} + +static int __css_parse_attr2(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* attrs, int n_attrs) +{ + scf_string_t* key = scf_string_alloc(); + if (!key) + return -ENOMEM; + + abc_char_t* c = NULL; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) { + scf_loge("\n"); + scf_string_free(key); + return -1; + } + + css->text_pos += c->len; + + if ('}' == c->c) { + free(c); + scf_string_free(key); + return '}'; + } + + if (':' == c->c) + break; + + if ('_' == c->c + || '-' == c->c + || ('a' <= c->c && 'z' >= c->c)) { + scf_string_cat_cstr_len(key, c->utf8, c->len); + + } else if (' ' == c->c || '\t' == c->c || '\r' == c->c) { + + } else { + scf_loge("invalid char '%c:%#x' in CSS attribute, file: %s, line: %d\n", + c->c, c->c, css->file->data, css->text_line); + assert(0); + free(c); + scf_string_free(key); + return -1; + } + + free(c); + c = NULL; + } + + int tmp = c->c; + + free(c); + c = NULL; + + scf_list_t* l; + abc_obj_t* attr; + + int i; + int j; + if (attrs && n_attrs > 0) { + for (i = 0; i < n_attrs; i++) { + + for (j = 0; attrs[i].names[j]; j++) { + if (!strcmp(attrs[i].names[j], key->data)) + goto found; + } + } + } + + scf_loge("invalid HTML attribute '%s' in file: %s, line: %d\n", key->data, css->file->data, css->text_pos); + scf_string_free(key); + return -1; + +found: + for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) { + attr = scf_list_data(l, abc_obj_t, list); + + for (j = 0; attr->keys[j]; j++) { + if (!strcmp(attr->keys[j], key->data)) + break; + } + } + + if (l == scf_list_sentinel(&obj->attrs)) { + int ret = __html_add_attr(obj, attrs[i].type, attrs[i].names, attrs[i].value, attrs[i].flags); + if (ret < 0) + return ret; + + l = scf_list_tail(&obj->attrs); + attr = scf_list_data(l, abc_obj_t, list); + } + + scf_string_free(key); + key = NULL; + + attr->line = css->text_line; + attr->pos = css->text_pos; + + return __css_parse_value(css, attr); +} + +static int __css_parse_attr(abc_obj_t* css, abc_obj_t* obj, const html_attr_t* attrs, int n_attrs) +{ + int ret = 0; + + while (1) { + ret = __css_parse_attr2(css, obj, attrs, n_attrs); + if (ret < 0) + return ret; + + if ('}' == ret) + break; + } + + return ret; +} + +static int __css_parse_obj(abc_obj_t* css, abc_char_t* c) +{ + html_label_t* label; + abc_obj_t* obj; + + scf_string_t* key = scf_string_cstr_len(c->utf8, c->len); + + css->text_pos += c->len; + free(c); + c = NULL; + + if (!key) + return -ENOMEM; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) { + scf_loge("\n"); + scf_string_free(key); + return -1; + } + + css->text_pos += c->len; + + if (' ' == c->c || '{' == c->c) + break; + + if ('\n' == c->c) { + css->text_line++; + css->text_pos = 0; + break; + } + + scf_string_cat_cstr_len(key, c->utf8, c->len); + free(c); + c = NULL; + } + + int tmp = c->c; + int ret; + + free(c); + c = NULL; + + label = __html_find_label(key->data); + if (!label) { + scf_loge("invalid HTML label '%s' in file: %s, line: %d\n", + key->data, css->file->data, css->text_line); + scf_string_free(key); + return -1; + } + + scf_string_free(key); + key = NULL; + + obj = abc_obj_alloc(css->file, css->text_line, css->text_pos, label->type); + if (!obj) + return -ENOMEM; + + obj->flags = label->flags; + obj->keys = label->names; + + obj->parent = css; + + switch (tmp) { + case '{': + ret = __css_parse_attr(css, obj, label->attrs, label->n_attrs); + if (ret < 0) { + abc_obj_free(obj); + return ret; + } + break; + default: + ret = 0; + break; + }; + + scf_list_add_tail(&css->childs, &obj->list); + return 0; +} + +int abc_css_parse(abc_obj_t* css) +{ + abc_char_t* c; + abc_io_t* io = abc_io_array[ABC_PROTO_STR]; + + css->io.proto = io->proto; + css->io.priv = NULL; + css->io.open = io->open; + css->io.close = io->close; + css->io.popc = io->popc; + css->io.post = io->post; + + css->text_line = 1; + css->text_pos = 0; + + int ret = io->open(&css->io, css->text->data); + if (ret < 0) + return ret; + + while (1) { + c = __io_pop_char(&css->io); + if (!c) + return -1; + + if (EOF == c->c) { + free(c); + return 0; + } + + if ('\n' == c->c || '\r' == c->c) { + css->text_line++; + css->text_pos = 0; + + free(c); + continue; + } + + if (' ' == c->c || '\t' == c->c) { + css->text_pos++; + free(c); + continue; + } + + if (('a' <= c->c && 'z' >= c->c) + || (0x4e00 <= c->c && 0x9fa5 >= c->c)) { + + int ret = __css_parse_obj(css, c); + if (ret < 0) { + scf_loge("css->text_line: %d, css->text_pos: %d\n", css->text_line, css->text_pos); + return ret; + } + } else { + scf_loge("%c:%#x, css->text_line: %d, css->text_pos: %d\n", c->c, c->c, css->text_line, css->text_pos); + free(c); + return -1; + } + } + + return -1; +} diff --git a/html/abc_html.c b/html/abc_html.c index a9b0fe0..664da6b 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -1,33 +1,5 @@ #include"abc_html.h" -typedef struct { - char** names; - char* value; - int type; - int flags; -} html_attr_t; - -typedef struct { - char** names; - int type; - - int n_attrs; - html_attr_t* attrs; - - uint32_t flags; -} html_label_t; - -#define abc_number_of(__array) (sizeof(__array) / sizeof(__array[0])) - -extern abc_io_t abc_io_file; -extern abc_io_t abc_io_http; - -static abc_io_t* abc_io_array[ABC_PROTO_NB] = -{ - [ABC_PROTO_FILE] = &abc_io_file, - [ABC_PROTO_HTTP] = &abc_io_http, -}; - // HTML attrs static char* src_keys[] = {"src", "源", NULL}; static char* href_keys[] = {"href", "地址", NULL}; @@ -37,7 +9,9 @@ static char* height_keys[] = {"height", "高度", NULL}; static char* font_keys[] = {"font", "字体", NULL}; static char* font_size_keys[] = {"font-size", "字号", NULL}; -static char* font_color_keys[] = {"font-color", "字体颜色", NULL}; +static char* font_color_keys[] = {"font-color", "字体颜色", "color", "颜色", NULL}; + +static char* text_align_keys[] = {"text-align", "对齐", NULL}; static char* type_keys[] = {"type", "类型", NULL}; static char* name_keys[] = {"name", "名字", NULL}; @@ -99,6 +73,7 @@ static char* play_keys[] = {"play", "播放", NULL}; static char* progress_keys[] = {"progress", "进度条", NULL}; static char* script_keys[] = {"script", "脚本", NULL}; +static char* style_keys[] = {"style", "样式", NULL}; static html_attr_t html_attrs[] = { @@ -158,8 +133,10 @@ static html_attr_t h6_attrs[] = static html_attr_t p_attrs[] = { - {font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0}, - {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0}, + {font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0}, + {font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0}, + {font_color_keys, "black", ABC_HTML_ATTR_FONT_COLOR, ABC_HTML_FLAG_SHOW}, + {text_align_keys, "left", ABC_HTML_ATTR_TEXT_ALIGN, ABC_HTML_FLAG_SHOW}, }; static html_attr_t a_attrs[] = @@ -273,12 +250,13 @@ static html_label_t html_labels[] = {progress_keys, ABC_HTML_PROGRESS, 0, NULL, ABC_HTML_FLAG_OPEN}, {script_keys, ABC_HTML_SCRIPT, abc_number_of(script_attrs), script_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, + + {style_keys, ABC_HTML_STYLE, 0, NULL, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SHOW}, }; static int __html_parse_obj(abc_html_t* html, abc_char_t* c); - -static html_label_t* __html_find_label(const char* name) +html_label_t* __html_find_label(const char* name) { html_label_t* label; @@ -298,7 +276,7 @@ static html_label_t* __html_find_label(const char* name) return NULL; } -static int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags) +int __html_add_attr(abc_obj_t* obj, int type, char** names, const char* value, int flags) { abc_obj_t* attr = abc_obj_alloc(NULL, 0, 0, type); if (!attr) @@ -443,7 +421,7 @@ int abc_html_post(abc_html_t** pp, abc_html_t* form, abc_obj_t* submit) html->io.popc = io->popc; html->io.post = io->post; - ret = io->post(html, url->data + n, content); + ret = io->post(&html->io, url->data + n, content); if (ret < 0) { scf_string_free(url); scf_string_free(content); @@ -495,7 +473,7 @@ int abc_html_open(abc_html_t** pp, const char* path) html->io.popc = io->popc; html->io.post = io->post; - int ret = io->open(html, path + n); + int ret = io->open(&html->io, path + n); if (ret < 0) { free(html); return ret; @@ -518,10 +496,10 @@ void abc_html_close(abc_html_t* html) abc_char_t* c; if (html) { - while ( html->tmp_list) { - c = html->tmp_list; + while ( html->io.tmp_list) { + c = html->io.tmp_list; - html->tmp_list = c->next; + html->io.tmp_list = c->next; free(c); } @@ -529,7 +507,7 @@ void abc_html_close(abc_html_t* html) abc_obj_free(html->root); if (html->io.close) - html->io.close(html); + html->io.close(&html->io); if (html->file) scf_string_free(html->file); @@ -550,7 +528,7 @@ static int __html_parse_end(abc_html_t* html, abc_obj_t* obj) abc_char_t* c = NULL; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(end); @@ -595,7 +573,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) int flag = 0; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(text); @@ -610,14 +588,14 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) if (ABC_HTML_SCRIPT != obj->type) break; - abc_char_t* c2 = __html_pop_char(html); + abc_char_t* c2 = __io_pop_char(&html->io); if (!c2) { scf_loge("\n"); scf_string_free(text); return -1; } - __html_push_char(html, c2); + __io_push_char(&html->io, c2); if ('/' == c2->c) break; @@ -643,7 +621,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) text = NULL; if (ABC_HTML_FLAG_OPEN == (obj->flags & 0x1)) { // single labels - __html_push_char(html, c); + __io_push_char(&html->io, c); c = NULL; return 0; }; @@ -652,7 +630,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) free(c); c = NULL; - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); free(c); @@ -735,7 +713,7 @@ static int __html_parse_value(abc_html_t* html, abc_obj_t* attr) int flag = 0; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(value); @@ -749,9 +727,9 @@ static int __html_parse_value(abc_html_t* html, abc_obj_t* attr) break; if ('/' == c->c) { - c2 = __html_pop_char(html); + c2 = __io_pop_char(&html->io); - __html_push_char(html, c2); + __io_push_char(&html->io, c2); if ('>' == c2->c) break; } @@ -791,7 +769,7 @@ static int __html_parse_attr2(abc_html_t* html, abc_obj_t* obj, const html_attr_ abc_char_t* c = NULL; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(key); @@ -1015,7 +993,7 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) return ret; } #if 1 - assert(!html->tmp_list_js); + assert(!html->io.tmp_list_js); void* so = dlopen(obj->js_so->data, RTLD_LAZY); void (*f)() = dlsym(so, "__js_main"); @@ -1025,13 +1003,13 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) so = NULL; #endif abc_char_t* c; - while ( html->tmp_list_js) { - c = html->tmp_list_js; + while ( html->io.tmp_list_js) { + c = html->io.tmp_list_js; - html->tmp_list_js = c->next; + html->io.tmp_list_js = c->next; - c->next = html->tmp_list; - html->tmp_list = c; + c->next = html->io.tmp_list; + html->io.tmp_list = c; } } @@ -1053,7 +1031,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) return -ENOMEM; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); scf_string_free(key); @@ -1135,7 +1113,7 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) } if ('/' == ret) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) { scf_loge("\n"); return -1; @@ -1160,6 +1138,15 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) return -1; break; + case ABC_HTML_STYLE: + if (obj->text) { + scf_logi("\033[33mcss: %s\033[0m\n", obj->text->data); + + if (abc_css_parse(obj) < 0) + return -1; + } + break; + case ABC_HTML_VIDEO: html->has_video = 1; @@ -1180,7 +1167,7 @@ int abc_html_parse(abc_html_t* html) abc_char_t* c; while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if (!c) return -1; @@ -1204,12 +1191,12 @@ int abc_html_parse(abc_html_t* html) free(c); - c = __html_pop_char(html); + c = __io_pop_char(&html->io); if ('!' == c->c) { // free(c); while (1) { - c = __html_pop_char(html); + c = __io_pop_char(&html->io); int tmp = c->c; free(c); diff --git a/html/abc_html.h b/html/abc_html.h index 66e9a55..81f7891 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -1,50 +1,35 @@ #ifndef ABC_HTML_H #define ABC_HTML_H +#include"abc_io.h" #include"abc_obj.h" #include"scf_parse.h" -typedef struct abc_char_s abc_char_t; typedef struct abc_html_s abc_html_t; -typedef struct abc_io_s abc_io_t; -enum abc_protos -{ - ABC_PROTO_FILE, - ABC_PROTO_HTTP, - - ABC_PROTO_NB -}; - -#define ABC_UTF8_MAX 6 -struct abc_char_s -{ - abc_char_t* next; - int c; +typedef struct { + char** names; + char* value; + int type; + int flags; +} html_attr_t; - int len; - uint8_t utf8[ABC_UTF8_MAX]; -}; +typedef struct { + char** names; + int type; -struct abc_io_s -{ - char* proto; - void* priv; + int n_attrs; + html_attr_t* attrs; - int (*open )(abc_html_t* html, const char* path); - void (*close)(abc_html_t* html); + uint32_t flags; +} html_label_t; - int (*popc )(abc_html_t* html); - int (*post )(abc_html_t* html, const char* path, scf_string_t* content); -}; +#define abc_number_of(__array) (sizeof(__array) / sizeof(__array[0])) struct abc_html_s { scf_list_t list; - abc_char_t* tmp_list; - abc_char_t* tmp_list_js; - abc_obj_t* root; abc_obj_t* current; @@ -56,7 +41,6 @@ struct abc_html_s scf_parse_t* js; - uint8_t download :1; uint8_t has_video:1; }; @@ -65,8 +49,6 @@ int abc_html_post (abc_html_t** pp, abc_html_t* form, abc_obj_t* submit); void abc_html_close(abc_html_t* html); int abc_html_parse(abc_html_t* html); - -abc_char_t* __html_pop_char (abc_html_t* html); -void __html_push_char(abc_html_t* html, abc_char_t* c); +int abc_css_parse (abc_obj_t* css); #endif diff --git a/html/abc_io.h b/html/abc_io.h new file mode 100644 index 0000000..c5ca2db --- /dev/null +++ b/html/abc_io.h @@ -0,0 +1,51 @@ +#ifndef ABC_IO_H +#define ABC_IO_H + +#include"scf_string.h" +#include"scf_list.h" + +typedef struct abc_char_s abc_char_t; +typedef struct abc_io_s abc_io_t; + +enum abc_protos +{ + ABC_PROTO_FILE, + ABC_PROTO_HTTP, + ABC_PROTO_STR, + + ABC_PROTO_NB +}; + +extern abc_io_t* abc_io_array[ABC_PROTO_NB]; + +#define ABC_UTF8_MAX 6 +struct abc_char_s +{ + abc_char_t* next; + int c; + + int len; + uint8_t utf8[ABC_UTF8_MAX]; +}; + +struct abc_io_s +{ + char* proto; + + void* priv; + uint8_t download:1; + + abc_char_t* tmp_list; + abc_char_t* tmp_list_js; + + int (*open )(abc_io_t* io, const char* path); + void (*close)(abc_io_t* io); + + int (*popc )(abc_io_t* io); + int (*post )(abc_io_t* io, const char* path, scf_string_t* content); +}; + +abc_char_t* __io_pop_char (abc_io_t* io); +void __io_push_char(abc_io_t* io, abc_char_t* c); + +#endif diff --git a/html/abc_io_file.c b/html/abc_io_file.c index 16afbbd..8bf2fed 100644 --- a/html/abc_io_file.c +++ b/html/abc_io_file.c @@ -1,12 +1,12 @@ -#include"abc_html.h" +#include"abc_io.h" -static int __file_open(abc_html_t* html, const char* path) +static int __file_open(abc_io_t* io, const char* path) { - if (!html || !path) + if (!io || !path) return -EINVAL; - html->io.priv = fopen(path, "r"); - if (!html->io.priv) { + io->priv = fopen(path, "r"); + if (!io->priv) { char cwd[4096]; getcwd(cwd, 4095); @@ -14,25 +14,20 @@ static int __file_open(abc_html_t* html, const char* path) return -1; } - html->download = 1; + io->download = 1; return 0; } -static void __file_close(abc_html_t* html) +static void __file_close(abc_io_t* io) { - if (html && html->io.priv) { - - fclose(html->io.priv); - } + if (io && io->priv) + fclose(io->priv); } -static int __file_popc(abc_html_t* html) +static int __file_popc(abc_io_t* io) { - if (html && html->io.priv) { - - return fgetc(html->io.priv); - } - + if (io && io->priv) + return fgetc(io->priv); return EOF; } diff --git a/html/abc_io_http.c b/html/abc_io_http.c index 1d6b246..559fea1 100644 --- a/html/abc_io_http.c +++ b/html/abc_io_http.c @@ -1,4 +1,4 @@ -#include"abc_html.h" +#include"abc_io.h" typedef struct { scf_string_t* host; @@ -89,11 +89,11 @@ static void http_chunk_size(abc_http_t* http) } } -static int http_filter_chunk(abc_html_t* html) +static int http_filter_chunk(abc_io_t* io) { - abc_http_t* http = html->io.priv; + abc_http_t* http = io->priv; - if (html->download) + if (io->download) return 0; while (http->cpos < http->rbuf->len) { @@ -108,7 +108,7 @@ static int http_filter_chunk(abc_html_t* html) http->cpos += 2; if (0 == http->content_length) { - html->download = 1; + io->download = 1; return 0; } @@ -134,8 +134,8 @@ static int http_filter_chunk(abc_html_t* html) static void* http_thread(void* arg) { - abc_html_t* html = arg; - abc_http_t* http = html->io.priv; + abc_io_t* io = arg; + abc_http_t* http = io->priv; while (!http->exit) { struct epoll_event ev; @@ -193,14 +193,14 @@ static void* http_thread(void* arg) if (http->rpos > 0) { if (!http->chunk_flag) { if (http->content_length == http->rbuf->len - http->rpos) { - html->download = 1; + io->download = 1; scf_logi("http response: %s\n", http->rbuf->data); } } else { - http_filter_chunk(html); + http_filter_chunk(io); - if (html->download) + if (io->download) scf_logi("http response: %s\n", http->rbuf->data); } } @@ -212,7 +212,7 @@ static void* http_thread(void* arg) if (ev.events & EPOLLOUT) { pthread_mutex_lock(&http->mutex); if (0 == http->wpos) { - html->download = 0; + io->download = 0; http->rbuf->len = 0; http->rpos = 0; } @@ -379,9 +379,9 @@ static int __http_open2(abc_http_t** pp, const char* path) return 0; } -static int __http_open(abc_html_t* html, const char* path) +static int __http_open(abc_io_t* io, const char* path) { - if (!html || !path) + if (!io || !path) return -EINVAL; abc_http_t* http = NULL; @@ -413,11 +413,11 @@ static int __http_open(abc_html_t* html, const char* path) ABC_HTTP_FILL("Accept: */*\r\n"); ABC_HTTP_FILL("\r\n"); - html->io.priv = http; + io->priv = http; - if (pthread_create(&http->tid, NULL, http_thread, html)) { + if (pthread_create(&http->tid, NULL, http_thread, io)) { abc_http_close(http); - html->io.priv = NULL; + io->priv = NULL; return -1; } @@ -425,9 +425,9 @@ static int __http_open(abc_html_t* html, const char* path) return 0; } -static int __http_post(abc_html_t* html, const char* path, scf_string_t* content) +static int __http_post(abc_io_t* io, const char* path, scf_string_t* content) { - if (!html || !path || !content) + if (!io || !path || !content) return -EINVAL; abc_http_t* http = NULL; @@ -459,11 +459,11 @@ static int __http_post(abc_html_t* html, const char* path, scf_string_t* content ABC_HTTP_FILL(content->data); - html->io.priv = http; + io->priv = http; - if (pthread_create(&http->tid, NULL, http_thread, html)) { + if (pthread_create(&http->tid, NULL, http_thread, io)) { abc_http_close(http); - html->io.priv = NULL; + io->priv = NULL; return -1; } @@ -471,18 +471,18 @@ static int __http_post(abc_html_t* html, const char* path, scf_string_t* content return 0; } -static void __http_close(abc_html_t* html) +static void __http_close(abc_io_t* io) { - if (html) - abc_http_close(html->io.priv); + if (io) + abc_http_close(io->priv); } -static int __http_popc(abc_html_t* html) +static int __http_popc(abc_io_t* io) { abc_http_t* http; - if (html) { - http = html->io.priv; + if (io) { + http = io->priv; if (http) { int c; diff --git a/html/abc_io_str.c b/html/abc_io_str.c new file mode 100644 index 0000000..ba31fcf --- /dev/null +++ b/html/abc_io_str.c @@ -0,0 +1,65 @@ +#include"abc_io.h" + +typedef struct { + scf_string_t* text; + int text_i; +} abc_str_t; + +static int __str_open(abc_io_t* io, const char* path) +{ + if (!io || !path) + return -EINVAL; + + abc_str_t* s = calloc(1, sizeof(abc_str_t)); + if (!s) + return -ENOMEM; + + s->text = scf_string_cstr(path); + if (!s->text) { + free(s); + return -ENOMEM; + } + + io->priv = s; + io->download = 1; + return 0; +} + +static void __str_close(abc_io_t* io) +{ + abc_str_t* s; + + if (io && io->priv) { + s = io->priv; + + if (s->text) + scf_string_free(s->text); + + free(s); + io->priv = NULL; + } +} + +static int __str_popc(abc_io_t* io) +{ + abc_str_t* s; + + if (io && io->priv) { + s = io->priv; + + if (s->text_i < s->text->len) + return s->text->data[s->text_i++]; + } + + return EOF; +} + +abc_io_t abc_io_str = +{ + .proto = "str://", + + .open = __str_open, + .close = __str_close, + + .popc = __str_popc, +}; diff --git a/html/abc_io_util.c b/html/abc_io_util.c new file mode 100644 index 0000000..dd1fa0b --- /dev/null +++ b/html/abc_io_util.c @@ -0,0 +1,97 @@ +#include"abc_io.h" + +extern abc_io_t abc_io_file; +extern abc_io_t abc_io_http; +extern abc_io_t abc_io_str; + +abc_io_t* abc_io_array[ABC_PROTO_NB] = +{ + [ABC_PROTO_FILE] = &abc_io_file, + [ABC_PROTO_HTTP] = &abc_io_http, + [ABC_PROTO_STR] = &abc_io_str, +}; + +abc_char_t* __io_pop_char(abc_io_t* io) +{ + assert(io); + + abc_char_t* c; + + if (io->tmp_list) { + c = io->tmp_list; + io->tmp_list = c->next; + return c; + } + + c = malloc(sizeof(abc_char_t)); + if (!c) + return NULL; + + int ret = io->popc(io); + if (EOF == ret) { + c->c = ret; + return c; + } + + if (ret < 0x80) { + c->c = ret; + c->len = 1; + c->utf8[0] = ret; + return c; + } + + if (0x6 == (ret >> 5)) { + c->c = ret & 0x1f; + c->len = 2; + + } else if (0xe == (ret >> 4)) { + c->c = ret & 0xf; + c->len = 3; + + } else if (0x1e == (ret >> 3)) { + c->c = ret & 0x7; + c->len = 4; + + } else if (0x3e == (ret >> 2)) { + c->c = ret & 0x3; + c->len = 5; + + } else if (0x7e == (ret >> 1)) { + c->c = ret & 0x1; + c->len = 6; + } else { + scf_loge("utf8 first byte wrong %#x\n", ret); + free(c); + return NULL; + } + + c->utf8[0] = ret; + + int i; + for (i = 1; i < c->len; i++) { + + ret = io->popc(io); + + if (0x2 == (ret >> 6)) { + c->c <<= 6; + c->c |= ret & 0x3f; + + c->utf8[i] = ret; + } else { + scf_loge("utf8 byte[%d] wrong %#x\n", i + 1, ret); + free(c); + return NULL; + } + } + + return c; +} + +void __io_push_char(abc_io_t* io, abc_char_t* c) +{ + assert(io); + assert(c); + + c->next = io->tmp_list; + io->tmp_list = c; +} diff --git a/html/abc_obj.h b/html/abc_obj.h index f87c59a..c1a74f3 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -4,6 +4,7 @@ #include"scf_string.h" #include"scf_list.h" #include"abc_ffmpeg.h" +#include"abc_io.h" typedef struct abc_obj_s abc_obj_t; @@ -56,6 +57,8 @@ enum abc_objs ABC_HTML_SCRIPT, + ABC_HTML_STYLE, + ABC_HTML_NB, // total HTML objects ABC_HTML_ATTR_ID, @@ -75,6 +78,8 @@ enum abc_objs ABC_HTML_ATTR_FONT_SIZE, ABC_HTML_ATTR_FONT_COLOR, + ABC_HTML_ATTR_TEXT_ALIGN, + ABC_HTML_ATTR_WIDTH, ABC_HTML_ATTR_HEIGHT, @@ -124,6 +129,10 @@ struct abc_obj_s scf_string_t* value; scf_string_t* text; + int text_line; + int text_pos; + abc_io_t io; + scf_string_t* file; // file name int line; // line int pos; // position diff --git a/html/main.c b/html/main.c index ff8a438..4a8eb4b 100644 --- a/html/main.c +++ b/html/main.c @@ -14,7 +14,7 @@ int main(int argc, char* argv[]) return -1; } - while (!html->download) + while (!html->io.download) usleep(50 * 1000); if (abc_html_parse(html) < 0) { diff --git a/js/abc_libjs.c b/js/abc_libjs.c index 5532441..f8a1312 100644 --- a/js/abc_libjs.c +++ b/js/abc_libjs.c @@ -126,9 +126,9 @@ int abc_html_write(abc_html_t* html, const char* s) while (*pp) pp = &(*pp)->next; - *pp = html->tmp_list_js; + *pp = html->io.tmp_list_js; - html->tmp_list_js = h; + html->io.tmp_list_js = h; return 0; error: diff --git a/js/abc_libjs.so b/js/abc_libjs.so index 376eaa0..b5d7e51 100755 Binary files a/js/abc_libjs.so and b/js/abc_libjs.so differ diff --git a/ui/Makefile b/ui/Makefile index f9c56cc..8624094 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -43,10 +43,11 @@ CFILES += abc_render_video.c CFILES += abc_render_audio.c CFILES += ../html/abc_html.c -CFILES += ../html/abc_html_util.c CFILES += ../html/abc_obj.c +CFILES += ../html/abc_io_util.c CFILES += ../html/abc_io_file.c CFILES += ../html/abc_io_http.c +CFILES += ../html/abc_io_str.c CFILES += ../ffmpeg/abc_ffmpeg_img.c CFILES += ../ffmpeg/abc_ffmpeg_input.c diff --git a/ui/main.c b/ui/main.c index 6556e51..41801d7 100644 --- a/ui/main.c +++ b/ui/main.c @@ -58,7 +58,7 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) GdkWindow* window; GdkCursor* cursor; - if (!ctx->current->download) + if (!ctx->current->io.download) return 0; if (!ctx->current->root) @@ -375,7 +375,7 @@ static gboolean timer_handler(gpointer user_data) abc_obj_t* obj; if (ctx->current) { - if (!ctx->current->download) + if (!ctx->current->io.download) return TRUE; if (!ctx->current->root) { @@ -494,7 +494,7 @@ int main(int argc, char *argv[]) return ret; } - while (!html->download) + while (!html->io.download) usleep(50 * 1000); ret = abc_html_parse(html);