mirror of
https://github.com/lexborisov/Modest
synced 2024-11-29 17:03:17 +03:00
276 lines
11 KiB
C
276 lines
11 KiB
C
|
/*
|
||
|
Copyright (C) 2016 Alexander Borisov
|
||
|
|
||
|
This library is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU Lesser General Public
|
||
|
License as published by the Free Software Foundation; either
|
||
|
version 2.1 of the License, or (at your option) any later version.
|
||
|
|
||
|
This library is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
Lesser General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Lesser General Public
|
||
|
License along with this library; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
||
|
Author: lex.borisov@gmail.com (Alexander Borisov)
|
||
|
*/
|
||
|
|
||
|
#include "mycss/selectors/serialization.h"
|
||
|
#include "mycss/selectors/myosi_resource.h"
|
||
|
|
||
|
void mycss_selectors_serialization_chain(mycss_selectors_t* selectors, mycss_selectors_entry_t* selector,
|
||
|
mycss_callback_serialization_f callback, void* context)
|
||
|
{
|
||
|
while(selector) {
|
||
|
if(selector->combinator == MyCSS_SELECTORS_COMBINATOR_DESCENDANT)
|
||
|
callback(" ", 1, context);
|
||
|
else if(selector->combinator == MyCSS_SELECTORS_COMBINATOR_UNDEF) {
|
||
|
/* fprintf(fh, "") */
|
||
|
}
|
||
|
else {
|
||
|
callback(" ", 1, context);
|
||
|
|
||
|
const char *comb_name = mycss_selectors_resource_combinator_names_map[ selector->combinator ];
|
||
|
callback(comb_name, strlen(comb_name), context);
|
||
|
|
||
|
callback(" ", 1, context);
|
||
|
}
|
||
|
|
||
|
mycss_selectors_serialization_selector(selectors, selector, callback, context);
|
||
|
|
||
|
selector = selector->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool mycss_selectors_serialization_list(mycss_selectors_t* selectors, mycss_selectors_list_t* selectors_list,
|
||
|
mycss_callback_serialization_f callback, void* context)
|
||
|
{
|
||
|
while(selectors_list) {
|
||
|
for(size_t i = 0; i < selectors_list->entries_list_length; i++)
|
||
|
{
|
||
|
mycss_selectors_entries_list_t *entries = &selectors_list->entries_list[i];
|
||
|
mycss_selectors_serialization_chain(selectors, entries->entry, callback, context);
|
||
|
|
||
|
if((i + 1) != selectors_list->entries_list_length)
|
||
|
callback(", ", 2, context);
|
||
|
}
|
||
|
|
||
|
if(selectors_list->declaration_entry) {
|
||
|
callback(" {", 2, context);
|
||
|
mycss_declaration_serialization_entries(selectors->ref_entry, selectors_list->declaration_entry, callback, context);
|
||
|
callback("}", 1, context);
|
||
|
}
|
||
|
|
||
|
if(selectors_list->flags == MyCSS_SELECTORS_FLAGS_SELECTOR_BAD) {
|
||
|
callback("^BAD_SELECTOR_LIST", 18, context);
|
||
|
}
|
||
|
|
||
|
if(selectors_list->next)
|
||
|
callback("\n", 1, context);
|
||
|
|
||
|
selectors_list = selectors_list->next;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool mycss_selectors_serialization_selector(mycss_selectors_t* selectors, mycss_selectors_entry_t* selector,
|
||
|
mycss_callback_serialization_f callback, void* context)
|
||
|
{
|
||
|
switch(selector->type) {
|
||
|
case MyCSS_SELECTORS_TYPE_ELEMENT: {
|
||
|
if(selector->ns_entry)
|
||
|
mycss_namespace_serialization_entry(selectors->ref_entry->ns, selector->ns_entry, callback, context, true);
|
||
|
|
||
|
if(selector->key)
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case MyCSS_SELECTORS_TYPE_ATTRIBUTE: {
|
||
|
callback("[", 1, context);
|
||
|
|
||
|
if(selector->ns_entry)
|
||
|
mycss_namespace_serialization_entry(selectors->ref_entry->ns, selector->ns_entry, callback, context, true);
|
||
|
|
||
|
if(selector->key)
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
|
||
|
if(selector->value == NULL) {
|
||
|
callback("]", 1, context);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* match value: =, |=, ~=... */
|
||
|
callback(" ", 1, context);
|
||
|
|
||
|
const char *match_name = mycss_selectors_resource_matcher_names_map[ mycss_selector_value_attribute(selector->value)->match ];
|
||
|
callback(match_name, strlen(match_name), context);
|
||
|
|
||
|
callback(" ", 1, context);
|
||
|
|
||
|
/* value */
|
||
|
if(mycss_selector_value_attribute(selector->value)->value) {
|
||
|
myhtml_string_t *str_value = mycss_selector_value_attribute(selector->value)->value;
|
||
|
callback(str_value->data, str_value->length, context);
|
||
|
}
|
||
|
|
||
|
/* modificator */
|
||
|
if(mycss_selector_value_attribute(selector->value)->mod & MyCSS_SELECTORS_MOD_I) {
|
||
|
callback(" i", 2, context);
|
||
|
}
|
||
|
|
||
|
callback("]", 1, context);
|
||
|
break;
|
||
|
}
|
||
|
case MyCSS_SELECTORS_TYPE_ID: {
|
||
|
if(selector->key) {
|
||
|
callback("#", 1, context);
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case MyCSS_SELECTORS_TYPE_CLASS: {
|
||
|
if(selector->key) {
|
||
|
callback(".", 1, context);
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case MyCSS_SELECTORS_TYPE_PSEUDO_CLASS_FUNCTION: {
|
||
|
if(selector->key) {
|
||
|
callback(":", 1, context);
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
}
|
||
|
|
||
|
callback("(", 1, context);
|
||
|
|
||
|
switch (selector->sub_type) {
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_HAS:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NOT:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_MATCHES:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT:
|
||
|
if(selector->value)
|
||
|
mycss_selectors_serialization_list(selectors, selector->value, callback, context);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_CHILD:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_COLUMN:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE:
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE:
|
||
|
if(selector->value) {
|
||
|
mycss_an_plus_b_serialization(selector->value, callback, context);
|
||
|
|
||
|
if(mycss_selector_value_an_plus_b(selector->value)->of) {
|
||
|
callback(" of ", 4, context);
|
||
|
mycss_selectors_serialization_list(selectors, mycss_selector_value_an_plus_b(selector->value)->of, callback, context);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP: {
|
||
|
mycss_selectors_function_drop_type_t drop_val = mycss_selector_value_drop(selector->value);
|
||
|
|
||
|
if(drop_val & MyCSS_SELECTORS_FUNCTION_DROP_TYPE_ACTIVE) {
|
||
|
callback("active", 6, context);
|
||
|
|
||
|
if(drop_val != MyCSS_SELECTORS_FUNCTION_DROP_TYPE_ACTIVE)
|
||
|
callback(" || ", 4, context);
|
||
|
}
|
||
|
|
||
|
if(drop_val & MyCSS_SELECTORS_FUNCTION_DROP_TYPE_VALID) {
|
||
|
callback("valid", 5, context);
|
||
|
|
||
|
if(drop_val & MyCSS_SELECTORS_FUNCTION_DROP_TYPE_INVALID)
|
||
|
callback(" || ", 4, context);
|
||
|
}
|
||
|
|
||
|
if(drop_val & MyCSS_SELECTORS_FUNCTION_DROP_TYPE_INVALID)
|
||
|
callback("invalid", 7, context);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR:
|
||
|
{
|
||
|
if(selector->value) {
|
||
|
myhtml_string_t *str_fname = mycss_selector_value_string(selector->value);
|
||
|
callback(str_fname->data, str_fname->length, context);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LANG: {
|
||
|
if(selector->value) {
|
||
|
mycss_selectors_value_lang_t *lang = mycss_selector_value_lang(selector->value);
|
||
|
|
||
|
while(lang) {
|
||
|
callback(lang->str.data, lang->str.length, context);
|
||
|
|
||
|
if(lang->next)
|
||
|
callback(", ", 2, context);
|
||
|
|
||
|
lang = lang->next;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
callback(")", 1, context);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MyCSS_SELECTORS_TYPE_PSEUDO_CLASS: {
|
||
|
callback(":", 1, context);
|
||
|
|
||
|
if(selector->key)
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MyCSS_SELECTORS_TYPE_PSEUDO_ELEMENT: {
|
||
|
callback("::", 2, context);
|
||
|
|
||
|
if(selector->key)
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default: {
|
||
|
if(selector->key)
|
||
|
callback(selector->key->data, selector->key->length, context);
|
||
|
|
||
|
callback("^U", 2, context);
|
||
|
break;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
if(selector->sub_type == MyCSS_SELECTORS_SUB_TYPE_UNKNOWN)
|
||
|
callback("^UST", 4, context);
|
||
|
|
||
|
if(selector->flags & MyCSS_SELECTORS_FLAGS_SELECTOR_BAD)
|
||
|
callback("^B", 2, context);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|