String::String(rune code) { rune r[2] = { code, 0 }; s_len = s_cap = 0; s_data = nullptr; grow(utf8_encoded_len(r) + 1); utf8_encode(r, s_data, s_cap); s_len = utf8_len(s_data); }
String::String(const rune *r) { if (r == nullptr) { s_len = 0; s_cap = kSmallestString; s_data = new char[s_cap]; *s_data = 0; } else { s_len = s_cap = 0; s_data = nullptr; grow(utf8_encoded_len(r) + 1); utf8_encode(r, s_data, s_cap); s_len = utf8_len(s_data); } }
static uint32 parse_numeric_entity(const struct array entity) { size_t i = 0; if (i < entity.size && '#' == entity.data[i]) { unsigned base; uint32 v; i++; switch (entity.data[i]) { case 'x': case 'X': base = 16; i++; break; default: base = 10; } v = 0; while (i < entity.size) { unsigned d; d = hex2int_inline(entity.data[i++]); if (d >= base) goto error; v = v * base + d; if (v >= 0x10ffffU) goto error; } if (0 == utf8_encoded_len(v)) goto error; return v; } error: return -1; }
static int html_parse(struct html_output *output, const struct array array) { size_t i, line_num; const char *msg; uint32 c; unsigned c_len; struct array tag, text; struct html_node *nodes, *root; line_num = 1; root = html_node_alloc(); nodes = root; tag = zero_array; text = array_init(array.data, 0); for (i = 0; i < array.size; i += c_len) { const char *next_ptr; c = utf8_decode(&array.data[i], i - array.size); if ((uint32)-1 == c) { msg = "Invalid UTF-8 encoding"; goto error; } c_len = utf8_encoded_len(c); next_ptr = &array.data[i + c_len]; switch (c) { case '<': if (tag.data) { tag.size += c_len; } else { if (text.data && text.size > 0) { struct html_node *node; node = html_node_alloc(); node->type = HTML_NODE_TEXT; node->array = text; node->next = NULL; nodes->next = node; nodes = node; text = zero_array; } tag.data = deconstify_gchar(next_ptr); tag.size = 0; } break; case '>': if (!tag.data) { g_warning("'>' but no open tag"); if (text.data) text.size += c_len; } else if ( HTML_TAG_COMMENT == parse_tag(tag) && 0 != memcmp(&tag.data[tag.size - 2], "--", 2) ) { tag.size += c_len; } else { struct html_node *node; node = html_node_alloc(); node->type = HTML_NODE_TAG; node->array = tag; node->next = NULL; nodes->next = node; nodes = node; tag = zero_array; text = array_init(next_ptr, 0); } break; case '\n': line_num++; /* FALL THROUGH */ default: if (tag.data) { tag.size += c_len; } else if (text.data) { text.size += c_len; } } } { struct render_context ctx; ctx = zero_render_context; ctx.output = output; ctx.root = root; html_render(&ctx); } html_free(root); return 0; error: g_warning("line %zu: error: %s", line_num, msg); html_free(root); return -1; }