diff --git a/include/modest/finder/pseudo_class.h b/include/modest/finder/pseudo_class.h index f9425ed..2c192ab 100644 --- a/include/modest/finder/pseudo_class.h +++ b/include/modest/finder/pseudo_class.h @@ -43,6 +43,7 @@ bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_child(modest bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_column(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); bool modest_finder_selector_sub_type_pseudo_class_function_nth_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); +bool modest_finder_selector_sub_type_pseudo_class_function_contains(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); /* classes */ bool modest_finder_selector_sub_type_pseudo_class_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); diff --git a/include/modest/finder/resource.h b/include/modest/finder/resource.h index 0d312ba..206f641 100644 --- a/include/modest/finder/resource.h +++ b/include/modest/finder/resource.h @@ -41,6 +41,7 @@ static const modest_finder_selector_type_f modest_finder_static_selector_sub_typ { modest_finder_selector_sub_type_pseudo_class_function_undef, /* UNDEF */ modest_finder_selector_sub_type_pseudo_class_function_undef, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNKNOWN */ + modest_finder_selector_sub_type_pseudo_class_function_contains, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CONTAINS */ modest_finder_selector_sub_type_pseudo_class_function_current, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT */ modest_finder_selector_sub_type_pseudo_class_function_dir, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR */ modest_finder_selector_sub_type_pseudo_class_function_drop, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP */ @@ -54,7 +55,6 @@ static const modest_finder_selector_type_f modest_finder_static_selector_sub_typ modest_finder_selector_sub_type_pseudo_class_function_nth_last_column, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN */ modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE */ modest_finder_selector_sub_type_pseudo_class_function_nth_of_type /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE */ - }; /* see enum mycss_selectors_sub_type (mycss_selectors_sub_type_t) on mycss/selectors/myosi.h */ diff --git a/include/mycss/selectors/function.h b/include/mycss/selectors/function.h index 7b2d4d3..0a769b0 100644 --- a/include/mycss/selectors/function.h +++ b/include/mycss/selectors/function.h @@ -65,6 +65,7 @@ void mycss_selectors_function_begin_nth_last_child(mycss_entry_t* entry, mycss_s void mycss_selectors_function_begin_nth_last_of_type(mycss_entry_t* entry, mycss_selectors_entry_t* selector); void mycss_selectors_function_begin_has(mycss_entry_t* entry, mycss_selectors_entry_t* selector); void mycss_selectors_function_begin_nth_column(mycss_entry_t* entry, mycss_selectors_entry_t* selector); +void mycss_selectors_function_begin_contains(mycss_entry_t* entry, mycss_selectors_entry_t* selector); void mycss_selectors_begin_unknown(mycss_entry_t* entry, mycss_selectors_entry_t* selector); diff --git a/include/mycss/selectors/function_parser.h b/include/mycss/selectors/function_parser.h index 2a7e690..0fac6e2 100644 --- a/include/mycss/selectors/function_parser.h +++ b/include/mycss/selectors/function_parser.h @@ -38,6 +38,8 @@ bool mycss_selectors_unknown_parser(mycss_entry_t* entry, mycss_token_t* token, bool mycss_selectors_function_parser_not_or_matches_or_current_parser(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_selectors_function_parser_has(mycss_entry_t* entry, mycss_token_t* token, bool last_response); +bool mycss_selectors_function_parser_contains(mycss_entry_t* entry, mycss_token_t* token, bool last_response); + bool mycss_selectors_function_parser_nth_with_selectors(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_selectors_function_parser_nth_with_selectors_need_of(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_selectors_function_parser_nth_with_selectors_need_of_after(mycss_entry_t* entry, mycss_token_t* token, bool last_response); diff --git a/include/mycss/selectors/function_resource.h b/include/mycss/selectors/function_resource.h index 67c48ac..08aff1d 100644 --- a/include/mycss/selectors/function_resource.h +++ b/include/mycss/selectors/function_resource.h @@ -24,7 +24,7 @@ #define MyCSS_SELECTORS_FUNCTION_NAME_STATIC_SIZE 57 -static const mycss_selectots_function_begin_entry_t mycss_selectors_function_begin_map_index[] = +static const mycss_selectots_function_begin_entry_t mycss_selectors_function_begin_map_index[] = { {NULL, 0, NULL, 0, 0}, {"dir", 3, mycss_selectors_function_begin_dir, 0, 1}, @@ -78,7 +78,7 @@ static const mycss_selectots_function_begin_entry_t mycss_selectors_function_beg {"nth-child", 9, mycss_selectors_function_begin_nth_child, 0, 49}, {NULL, 0, NULL, 0, 0}, {NULL, 0, NULL, 0, 0}, - {NULL, 0, NULL, 0, 0}, + {"contains", 8, mycss_selectors_function_begin_contains, 0, 52}, {NULL, 0, NULL, 0, 0}, {NULL, 0, NULL, 0, 0}, {NULL, 0, NULL, 0, 0}, diff --git a/include/mycss/selectors/myosi.h b/include/mycss/selectors/myosi.h index 525bf00..a74b6fe 100644 --- a/include/mycss/selectors/myosi.h +++ b/include/mycss/selectors/myosi.h @@ -99,20 +99,21 @@ typedef mycss_selectors_sub_type_t; enum mycss_selectors_sub_type_pseudo_class_function { MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNDEF = 0x00, MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNKNOWN = 0x01, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT = 0x02, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR = 0x03, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP = 0x04, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_HAS = 0x05, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LANG = 0x06, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_MATCHES = 0x07, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NOT = 0x08, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_CHILD = 0x09, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_COLUMN = 0x0a, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD = 0x0b, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN = 0x0c, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE = 0x0d, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE = 0x0e, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY = 0x0f + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CONTAINS = 0x02, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT = 0x03, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR = 0x04, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP = 0x05, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_HAS = 0x06, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LANG = 0x07, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_MATCHES = 0x08, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NOT = 0x09, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_CHILD = 0x0a, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_COLUMN = 0x0b, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD = 0x0c, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN = 0x0d, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE = 0x0e, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE = 0x0f, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY = 0x10 } typedef mycss_selectors_sub_type_pseudo_class_function_t; diff --git a/include/mycss/selectors/value.h b/include/mycss/selectors/value.h index f7db204..2298145 100644 --- a/include/mycss/selectors/value.h +++ b/include/mycss/selectors/value.h @@ -83,6 +83,7 @@ void * mycss_selectors_value_pseudo_class_function_nth_last_child_create(mycss_e void * mycss_selectors_value_pseudo_class_function_nth_last_column_create(mycss_entry_t* entry, bool set_clean); void * mycss_selectors_value_pseudo_class_function_nth_last_of_type_create(mycss_entry_t* entry, bool set_clean); void * mycss_selectors_value_pseudo_class_function_nth_of_type_create(mycss_entry_t* entry, bool set_clean); +void * mycss_selectors_value_pseudo_class_function_contains_create(mycss_entry_t* entry, bool set_clean); /* pseudo class function destroy */ void * mycss_selectors_value_pseudo_class_function_undef_destroy(mycss_entry_t* entry, void* value, bool self_destroy); @@ -99,6 +100,7 @@ void * mycss_selectors_value_pseudo_class_function_nth_last_child_destroy(mycss_ void * mycss_selectors_value_pseudo_class_function_nth_last_column_destroy(mycss_entry_t* entry, void* value, bool self_destroy); void * mycss_selectors_value_pseudo_class_function_nth_last_of_type_destroy(mycss_entry_t* entry, void* value, bool self_destroy); void * mycss_selectors_value_pseudo_class_function_nth_of_type_destroy(mycss_entry_t* entry, void* value, bool self_destroy); +void * mycss_selectors_value_pseudo_class_function_contains_destroy(mycss_entry_t* entry, void* value, bool self_destroy); #ifdef __cplusplus } /* extern "C" */ diff --git a/include/mycss/selectors/value_resource.h b/include/mycss/selectors/value_resource.h index 7bbc06d..32d0061 100644 --- a/include/mycss/selectors/value_resource.h +++ b/include/mycss/selectors/value_resource.h @@ -39,6 +39,7 @@ static const mycss_selectors_value_destroy_f mycss_selectors_value_destroy_map[M static const mycss_selectors_value_function_destroy_f mycss_selectors_value_function_destroy_map[MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY] = { mycss_selectors_value_pseudo_class_function_undef_destroy, mycss_selectors_value_pseudo_class_function_undef_destroy, + mycss_selectors_value_pseudo_class_function_contains_destroy, mycss_selectors_value_pseudo_class_function_current_destroy, mycss_selectors_value_pseudo_class_function_dir_destroy, mycss_selectors_value_pseudo_class_function_drop_destroy, diff --git a/source/modest/finder/finder.c b/source/modest/finder/finder.c index bf52435..32f77fa 100644 --- a/source/modest/finder/finder.c +++ b/source/modest/finder/finder.c @@ -161,7 +161,7 @@ mystatus_t modest_finder_by_selectors_list(modest_finder_t* finder, myhtml_tree_ if(status) return MODEST_STATUS_ERROR_MEMORY_ALLOCATION; } - + for(size_t i = 0; i < selector_list->entries_list_length; i++) { mycss_selectors_specificity_t spec = selector_list->entries_list[i].specificity; @@ -179,6 +179,7 @@ myhtml_tree_node_t * modest_finder_node_combinator_begin(modest_finder_t* finder if(selector == NULL) return NULL; + myhtml_tree_node_t *node = base_node; while(node) { @@ -191,7 +192,7 @@ myhtml_tree_node_t * modest_finder_node_combinator_begin(modest_finder_t* finder } else { myhtml_tree_node_t *find_node = modest_finder_static_selector_combinator_map[selector->next->combinator](finder, node, selector_list, selector->next, spec, callback_found, ctx); - + if(find_node == NULL) { while(node != base_node && node->next == NULL) node = node->parent; @@ -217,7 +218,7 @@ myhtml_tree_node_t * modest_finder_node_combinator_begin(modest_finder_t* finder node = node->next; } } - + return NULL; } diff --git a/source/modest/finder/pseudo_class.c b/source/modest/finder/pseudo_class.c index f26ac69..07181c2 100644 --- a/source/modest/finder/pseudo_class.c +++ b/source/modest/finder/pseudo_class.c @@ -77,6 +77,72 @@ bool modest_finder_selector_sub_type_pseudo_class_function_has(modest_finder_t* return false; } +bool modest_finder_selector_sub_type_pseudo_class_function_contains(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec) +{ + if(base_node == NULL) + return false; + + myhtml_tree_node_t *text_node = myhtml_node_child(base_node); + if(text_node == NULL) + return false; + + const char* text = myhtml_node_text(text_node, NULL); + if(text == NULL) + return false; + + mycss_selectors_list_t *list = (mycss_selectors_list_t*)selector->value; + for(size_t i = 0; i < list->entries_list_length; i++) { + char *data = NULL; + data = mycore_malloc(0); + if(data == NULL) { + return false; + } + + mycss_selectors_entry_t *sel_entry = list->entries_list[i].entry; + if(sel_entry->key->data){ + const char *str = sel_entry->key->data; + int length = strlen(str) + 1; + + char *new_data = mycore_realloc(data, length); + if(new_data == NULL) { + mycore_free(data); + return false; + } + + snprintf(new_data, length, "%s", str); + data = new_data; + } + + mycss_selectors_entry_t *next = sel_entry->next; + while(next) { + if(next->key->data) { + int prev = strlen(data); + const char *whitespace = (prev > 0) ? " " : ""; + const char *str = next->key->data; + int length = strlen(whitespace) + strlen(str) + 1; + + char *new_data = mycore_realloc(data, prev + length); + if(new_data == NULL) { + mycore_free(data); + return false; + } + + snprintf(&new_data[prev], length, "%s%s", whitespace, str); + data = new_data; + } + next = next->next; + } + + if(strstr(text, data) != NULL) { + mycore_free(data); + return true; + } + mycore_free(data); + } + + return false; +} + bool modest_finder_selector_sub_type_pseudo_class_function_lang(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec) { return false; diff --git a/source/modest/finder/pseudo_class.h b/source/modest/finder/pseudo_class.h index c9c1c07..4f28a26 100644 --- a/source/modest/finder/pseudo_class.h +++ b/source/modest/finder/pseudo_class.h @@ -43,6 +43,7 @@ bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_child(modest bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_column(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); bool modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); bool modest_finder_selector_sub_type_pseudo_class_function_nth_of_type(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); +bool modest_finder_selector_sub_type_pseudo_class_function_contains(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); /* classes */ bool modest_finder_selector_sub_type_pseudo_class_undef(modest_finder_t* finder, myhtml_tree_node_t* base_node, mycss_selectors_entry_t* selector, mycss_selectors_specificity_t* spec); diff --git a/source/modest/finder/resource.h b/source/modest/finder/resource.h index 0d312ba..278ee4b 100644 --- a/source/modest/finder/resource.h +++ b/source/modest/finder/resource.h @@ -41,6 +41,7 @@ static const modest_finder_selector_type_f modest_finder_static_selector_sub_typ { modest_finder_selector_sub_type_pseudo_class_function_undef, /* UNDEF */ modest_finder_selector_sub_type_pseudo_class_function_undef, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNKNOWN */ + modest_finder_selector_sub_type_pseudo_class_function_contains, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CONTAINS */ modest_finder_selector_sub_type_pseudo_class_function_current, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT */ modest_finder_selector_sub_type_pseudo_class_function_dir, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR */ modest_finder_selector_sub_type_pseudo_class_function_drop, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP */ @@ -53,7 +54,7 @@ static const modest_finder_selector_type_f modest_finder_static_selector_sub_typ modest_finder_selector_sub_type_pseudo_class_function_nth_last_child, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD */ modest_finder_selector_sub_type_pseudo_class_function_nth_last_column, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN */ modest_finder_selector_sub_type_pseudo_class_function_nth_last_of_type, /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE */ - modest_finder_selector_sub_type_pseudo_class_function_nth_of_type /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE */ + modest_finder_selector_sub_type_pseudo_class_function_nth_of_type /* MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE */ }; diff --git a/source/mycss/selectors/function.c b/source/mycss/selectors/function.c index d291f9d..660e78a 100644 --- a/source/mycss/selectors/function.c +++ b/source/mycss/selectors/function.c @@ -110,6 +110,25 @@ void mycss_selectors_function_begin_has(mycss_entry_t* entry, mycss_selectors_en mycss_entry_parser_list_push(entry, mycss_selectors_function_parser_has, entry->parser_switch, entry->parser_ending_token, false); } +void mycss_selectors_function_begin_contains(mycss_entry_t* entry, mycss_selectors_entry_t* selector) +{ + selector->sub_type = MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CONTAINS; + + mycss_selectors_t *selectors = entry->selectors; + mycss_selectors_list_t **new_list = (mycss_selectors_list_t**)(&selectors->entry_last->value); + mycss_selectors_list_t *current_list = selectors->list_last; + + selectors->list = new_list; + selectors->list_last = NULL; + selectors->ending_token = entry->parser_ending_token; + + mycss_selectors_state_relative_selector_list(entry, NULL, true); + + (*new_list)->parent = current_list; + + mycss_entry_parser_list_push(entry, mycss_selectors_function_parser_contains, entry->parser_switch, entry->parser_ending_token, false); +} + void mycss_selectors_function_begin_nth_last_child(mycss_entry_t* entry, mycss_selectors_entry_t* selector) { selector->sub_type = MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD; diff --git a/source/mycss/selectors/function.h b/source/mycss/selectors/function.h index 7bf4f09..410d4ff 100644 --- a/source/mycss/selectors/function.h +++ b/source/mycss/selectors/function.h @@ -65,6 +65,7 @@ void mycss_selectors_function_begin_nth_last_child(mycss_entry_t* entry, mycss_s void mycss_selectors_function_begin_nth_last_of_type(mycss_entry_t* entry, mycss_selectors_entry_t* selector); void mycss_selectors_function_begin_has(mycss_entry_t* entry, mycss_selectors_entry_t* selector); void mycss_selectors_function_begin_nth_column(mycss_entry_t* entry, mycss_selectors_entry_t* selector); +void mycss_selectors_function_begin_contains(mycss_entry_t* entry, mycss_selectors_entry_t* selector); void mycss_selectors_begin_unknown(mycss_entry_t* entry, mycss_selectors_entry_t* selector); diff --git a/source/mycss/selectors/function_parser.c b/source/mycss/selectors/function_parser.c index 7aa9e34..b97a58e 100644 --- a/source/mycss/selectors/function_parser.c +++ b/source/mycss/selectors/function_parser.c @@ -223,6 +223,67 @@ bool mycss_selectors_function_parser_has(mycss_entry_t* entry, mycss_token_t* to return false; } +/////////////////////////////////////////////////////////// +////// CONTAINS +////// +/////////////////////////////////////////////////////////// +void mycss_selectors_function_parser_contains_find_bad_selector(mycss_selectors_list_t* selectors_list) +{ + for(size_t i = 0; i < selectors_list->entries_list_length; i++) { + mycss_selectors_entry_t* selector = selectors_list->entries_list[i].entry; + + while(selector) { + if(selector->type == MyCSS_SELECTORS_TYPE_PSEUDO_ELEMENT) { + if((selectors_list->flags & MyCSS_SELECTORS_FLAGS_SELECTOR_BAD) == 0) + selectors_list->flags |= MyCSS_SELECTORS_FLAGS_SELECTOR_BAD; + + return; + } + + selector = selector->next; + } + } +} + +bool mycss_selectors_function_parser_contains(mycss_entry_t* entry, mycss_token_t* token, bool last_response) +{ + mycss_selectors_t *selectors = entry->selectors; + mycss_selectors_list_t *selectors_list = selectors->list_last; + mycss_selectors_list_t *parent_list = selectors->list_last->parent; + + selectors->entry_last = mycss_selectors_list_last_entry(parent_list); + selectors->list_last = parent_list; + selectors->specificity = &parent_list->entries_list[ (parent_list->entries_list_length - 1) ].specificity; + + mycss_selectors_function_parser_contains_find_bad_selector(selectors_list); + selectors_list = mycss_selectors_parser_check_selector_list(selectors, selectors_list); + + if(selectors_list == NULL) { + if(selectors->entry_last) { + selectors->entry_last->value = NULL; + selectors->entry_last->flags |= MyCSS_SELECTORS_FLAGS_SELECTOR_BAD; + } + } + else if((selectors_list->flags & MyCSS_SELECTORS_FLAGS_SELECTOR_BAD) && selectors->entry_last) { + selectors->entry_last->flags |= MyCSS_SELECTORS_FLAGS_SELECTOR_BAD; + } + + if(token->type == entry->parser_ending_token) { + mycss_entry_parser_list_pop(entry); + return false; + } + + if(selectors_list) + selectors_list->flags |= MyCSS_SELECTORS_FLAGS_SELECTOR_BAD; + + if(selectors->entry_last) + selectors->entry_last->flags |= MyCSS_SELECTORS_FLAGS_SELECTOR_BAD; + + entry->parser = mycss_selectors_function_parser_state_drop_component_value; + + return false; +} + /////////////////////////////////////////////////////////// ////// NTH OF SELECTORS ////// diff --git a/source/mycss/selectors/function_parser.h b/source/mycss/selectors/function_parser.h index 8005872..1dac131 100644 --- a/source/mycss/selectors/function_parser.h +++ b/source/mycss/selectors/function_parser.h @@ -38,6 +38,8 @@ bool mycss_selectors_unknown_parser(mycss_entry_t* entry, mycss_token_t* token, bool mycss_selectors_function_parser_not_or_matches_or_current_parser(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_selectors_function_parser_has(mycss_entry_t* entry, mycss_token_t* token, bool last_response); +bool mycss_selectors_function_parser_contains(mycss_entry_t* entry, mycss_token_t* token, bool last_response); + bool mycss_selectors_function_parser_nth_with_selectors(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_selectors_function_parser_nth_with_selectors_need_of(mycss_entry_t* entry, mycss_token_t* token, bool last_response); bool mycss_selectors_function_parser_nth_with_selectors_need_of_after(mycss_entry_t* entry, mycss_token_t* token, bool last_response); diff --git a/source/mycss/selectors/function_resource.h b/source/mycss/selectors/function_resource.h index 67c48ac..08aff1d 100644 --- a/source/mycss/selectors/function_resource.h +++ b/source/mycss/selectors/function_resource.h @@ -24,7 +24,7 @@ #define MyCSS_SELECTORS_FUNCTION_NAME_STATIC_SIZE 57 -static const mycss_selectots_function_begin_entry_t mycss_selectors_function_begin_map_index[] = +static const mycss_selectots_function_begin_entry_t mycss_selectors_function_begin_map_index[] = { {NULL, 0, NULL, 0, 0}, {"dir", 3, mycss_selectors_function_begin_dir, 0, 1}, @@ -78,7 +78,7 @@ static const mycss_selectots_function_begin_entry_t mycss_selectors_function_beg {"nth-child", 9, mycss_selectors_function_begin_nth_child, 0, 49}, {NULL, 0, NULL, 0, 0}, {NULL, 0, NULL, 0, 0}, - {NULL, 0, NULL, 0, 0}, + {"contains", 8, mycss_selectors_function_begin_contains, 0, 52}, {NULL, 0, NULL, 0, 0}, {NULL, 0, NULL, 0, 0}, {NULL, 0, NULL, 0, 0}, diff --git a/source/mycss/selectors/init.c b/source/mycss/selectors/init.c index 4cec9cd..bb14772 100644 --- a/source/mycss/selectors/init.c +++ b/source/mycss/selectors/init.c @@ -127,7 +127,7 @@ mycss_selectors_list_t * mycss_selectors_parse_by_function(mycss_selectors_t* se mycss_selectors_list_t *list = NULL; selectors->list = &list; - + /* parsing */ mycss_encoding_set(entry, encoding); @@ -146,7 +146,7 @@ mycss_selectors_list_t * mycss_selectors_parse_by_function(mycss_selectors_t* se if(list) return list; - + return NULL; } diff --git a/source/mycss/selectors/myosi.h b/source/mycss/selectors/myosi.h index 3df9c38..3fa1a48 100644 --- a/source/mycss/selectors/myosi.h +++ b/source/mycss/selectors/myosi.h @@ -99,20 +99,21 @@ typedef mycss_selectors_sub_type_t; enum mycss_selectors_sub_type_pseudo_class_function { MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNDEF = 0x00, MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_UNKNOWN = 0x01, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT = 0x02, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR = 0x03, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP = 0x04, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_HAS = 0x05, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LANG = 0x06, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_MATCHES = 0x07, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NOT = 0x08, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_CHILD = 0x09, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_COLUMN = 0x0a, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD = 0x0b, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN = 0x0c, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE = 0x0d, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE = 0x0e, - MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY = 0x0f + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CONTAINS = 0x02, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CURRENT = 0x03, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DIR = 0x04, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_DROP = 0x05, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_HAS = 0x06, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LANG = 0x07, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_MATCHES = 0x08, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NOT = 0x09, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_CHILD = 0x0a, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_COLUMN = 0x0b, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_CHILD = 0x0c, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_COLUMN = 0x0d, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_LAST_OF_TYPE = 0x0e, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_NTH_OF_TYPE = 0x0f, + MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY = 0x10 } typedef mycss_selectors_sub_type_pseudo_class_function_t; diff --git a/source/mycss/selectors/serialization.c b/source/mycss/selectors/serialization.c index f451dcd..acd4ec9 100644 --- a/source/mycss/selectors/serialization.c +++ b/source/mycss/selectors/serialization.c @@ -49,6 +49,7 @@ bool mycss_selectors_serialization_list(mycss_selectors_t* selectors, mycss_sele mycore_callback_serialize_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]; @@ -149,8 +150,9 @@ bool mycss_selectors_serialization_selector(mycss_selectors_t* selectors, mycss_ } callback("(", 1, context); - + switch (selector->sub_type) { + case MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_CONTAINS: 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: diff --git a/source/mycss/selectors/value.c b/source/mycss/selectors/value.c index d0f0588..5cd97ce 100644 --- a/source/mycss/selectors/value.c +++ b/source/mycss/selectors/value.c @@ -147,6 +147,11 @@ void * mycss_selectors_value_pseudo_class_function_has_create(mycss_entry_t* ent return mycss_selectors_list_create(entry->selectors); } +void * mycss_selectors_value_pseudo_class_function_contains_create(mycss_entry_t* entry, bool set_clean) +{ + return mycss_selectors_list_create(entry->selectors); +} + void * mycss_selectors_value_pseudo_class_function_lang_create(mycss_entry_t* entry, bool set_clean) { mycss_selectors_value_lang_t* lang = (mycss_selectors_value_lang_t*) @@ -245,6 +250,11 @@ void * mycss_selectors_value_pseudo_class_function_has_destroy(mycss_entry_t* en return mycss_selectors_list_destroy(entry->selectors, value, self_destroy); } +void * mycss_selectors_value_pseudo_class_function_contains_destroy(mycss_entry_t* entry, void* value, bool self_destroy) +{ + return mycss_selectors_list_destroy(entry->selectors, value, self_destroy); +} + void * mycss_selectors_value_pseudo_class_function_lang_destroy(mycss_entry_t* entry, void* value, bool self_destroy) { if(value == NULL) @@ -366,3 +376,4 @@ void * mycss_selectors_value_pseudo_class_function_nth_of_type_destroy(mycss_ent } + diff --git a/source/mycss/selectors/value.h b/source/mycss/selectors/value.h index 8fd23f7..e61aab5 100644 --- a/source/mycss/selectors/value.h +++ b/source/mycss/selectors/value.h @@ -83,6 +83,7 @@ void * mycss_selectors_value_pseudo_class_function_nth_last_child_create(mycss_e void * mycss_selectors_value_pseudo_class_function_nth_last_column_create(mycss_entry_t* entry, bool set_clean); void * mycss_selectors_value_pseudo_class_function_nth_last_of_type_create(mycss_entry_t* entry, bool set_clean); void * mycss_selectors_value_pseudo_class_function_nth_of_type_create(mycss_entry_t* entry, bool set_clean); +void * mycss_selectors_value_pseudo_class_function_contains_create(mycss_entry_t* entry, bool set_clean); /* pseudo class function destroy */ void * mycss_selectors_value_pseudo_class_function_undef_destroy(mycss_entry_t* entry, void* value, bool self_destroy); @@ -99,6 +100,7 @@ void * mycss_selectors_value_pseudo_class_function_nth_last_child_destroy(mycss_ void * mycss_selectors_value_pseudo_class_function_nth_last_column_destroy(mycss_entry_t* entry, void* value, bool self_destroy); void * mycss_selectors_value_pseudo_class_function_nth_last_of_type_destroy(mycss_entry_t* entry, void* value, bool self_destroy); void * mycss_selectors_value_pseudo_class_function_nth_of_type_destroy(mycss_entry_t* entry, void* value, bool self_destroy); +void * mycss_selectors_value_pseudo_class_function_contains_destroy(mycss_entry_t* entry, void* value, bool self_destroy); #ifdef __cplusplus } /* extern "C" */ diff --git a/source/mycss/selectors/value_resource.h b/source/mycss/selectors/value_resource.h index c2e0eb2..2324af1 100644 --- a/source/mycss/selectors/value_resource.h +++ b/source/mycss/selectors/value_resource.h @@ -39,6 +39,7 @@ static const mycss_selectors_value_destroy_f mycss_selectors_value_destroy_map[M static const mycss_selectors_value_function_destroy_f mycss_selectors_value_function_destroy_map[MyCSS_SELECTORS_SUB_TYPE_PSEUDO_CLASS_FUNCTION_LAST_ENTRY] = { mycss_selectors_value_pseudo_class_function_undef_destroy, mycss_selectors_value_pseudo_class_function_undef_destroy, + mycss_selectors_value_pseudo_class_function_contains_destroy, mycss_selectors_value_pseudo_class_function_current_destroy, mycss_selectors_value_pseudo_class_function_dir_destroy, mycss_selectors_value_pseudo_class_function_drop_destroy, diff --git a/test/myhtml/pseudo_class_contains.c b/test/myhtml/pseudo_class_contains.c new file mode 100644 index 0000000..240142e --- /dev/null +++ b/test/myhtml/pseudo_class_contains.c @@ -0,0 +1,186 @@ +/* + 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DIE(msg, ...) do { fprintf(stderr, msg, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0) +#define CHECK_STATUS(msg, ...) do {if(status) DIE(msg, ##__VA_ARGS__);} while(0) + +mystatus_t serialization_callback(const char* data, size_t len, void* ctx) +{ + printf("%.*s", (int)len, data); + return MyCORE_STATUS_OK; +} + +mystatus_t serialization_bad_selectors(const char* buffer, size_t size, void* ctx) +{ + printf("%.*s", (int)size, buffer); + return MyCORE_STATUS_OK; +} + +myhtml_tree_t * parse_html(const char* data, size_t data_size) +{ + myhtml_t* myhtml = myhtml_create(); + mystatus_t status = myhtml_init(myhtml, MyHTML_OPTIONS_DEFAULT, 1, 0); + + CHECK_STATUS("Can't init MyHTML object\n"); + + myhtml_tree_t* tree = myhtml_tree_create(); + status = myhtml_tree_init(tree, myhtml); + + CHECK_STATUS("Can't init MyHTML Tree object\n"); + + status = myhtml_parse(tree, MyENCODING_UTF_8, data, data_size); + CHECK_STATUS("Can't parse HTML:\n%s\n", data); + + return tree; +} + +mycss_entry_t * create_css_parser(void) +{ + // base init + mycss_t *mycss = mycss_create(); + mystatus_t status = mycss_init(mycss); + + CHECK_STATUS("Can't init MyCSS object\n"); + + // currenr entry work init + mycss_entry_t *entry = mycss_entry_create(); + status = mycss_entry_init(mycss, entry); + + CHECK_STATUS("Can't init MyCSS Entry object\n"); + + return entry; +} + +mycss_selectors_list_t * prepare_selector(mycss_entry_t *css_entry, const char* selector, size_t selector_size) +{ + mystatus_t out_status; + mycss_selectors_list_t *list = mycss_selectors_parse(mycss_entry_selectors(css_entry), + MyENCODING_UTF_8, + selector, selector_size, + &out_status); + + // printf("\nprepare_selector()\n"); + // printf("\t%s\n", (list != NULL)?"has list":"no list"); + + /* check parsing errors */ + if(list == NULL || (list->flags & MyCSS_SELECTORS_FLAGS_SELECTOR_BAD)) { + fprintf(stderr, "Bad CSS Selectors\n"); + + if(list) { + mycss_selectors_serialization_list(mycss_entry_selectors(css_entry), list, + serialization_bad_selectors, NULL); + printf("\n"); + } + + exit(EXIT_FAILURE); + } + + // printf("\treturn list\n"); + return list; +} + +void print_found_result(myhtml_tree_t* html_tree, myhtml_collection_t *collection) +{ + if(collection) { + for(size_t i = 0; i < collection->length; i++) { + printf("\n\t"); + myhtml_serialization_node_callback(collection->list[i], serialization_callback, NULL); + } + + printf("\n"); + } + else { + printf("empty\n"); + } +} + +int main(int argc, const char * argv[]) +{ + const char *html = "
a

c d

c

"; + // const char *selector = ":has(p)"; + // const char *selector = ":contains(c d)"; + // const char *selector = ":contains(c)"; + const char *selector = ":contains(c,d)"; + // const char *selector = "p:contains('c d')"; // Bad Selector + // const char *selector = "p:contains(\"c d\")"; // Bad Selector + + /* init MyHTML and parse HTML */ + myhtml_tree_t *html_tree = parse_html(html, strlen(html)); + + /* create css parser and finder for selectors */ + mycss_entry_t *css_entry = create_css_parser(); + modest_finder_t *finder = modest_finder_create_simple(); + + /* parse selectors */ + mycss_selectors_list_t *selectors_list = prepare_selector(css_entry, selector, strlen(selector)); + + /* find nodes by selector */ + myhtml_collection_t *collection = NULL; + modest_finder_by_selectors_list(finder, html_tree->node_html, selectors_list, &collection); + + /* print result */ + /* print selector */ + printf("Incoming selector:\n\t"); + mycss_selectors_serialization_list(mycss_entry_selectors(css_entry), + selectors_list, serialization_callback, NULL); + printf("\n\n"); + + /* print tree */ + printf("Incoming tree:\n\t"); + myhtml_serialization_tree_callback(html_tree->node_html, serialization_callback, NULL); + + /* print found result */ + printf("\n\nFound nodes:"); + print_found_result(html_tree, collection); + + /* destroy all */ + myhtml_collection_destroy(collection); + + /* destroy selector list */ + mycss_selectors_list_destroy(mycss_entry_selectors(css_entry), selectors_list, true); + + /* destroy Modest Finder */ + modest_finder_destroy(finder, true); + + /* destroy MyCSS */ + mycss_t *mycss = css_entry->mycss; + mycss_entry_destroy(css_entry, true); + mycss_destroy(mycss, true); + + /* destroy MyHTML */ + myhtml_t* myhtml = html_tree->myhtml; + myhtml_tree_destroy(html_tree); + myhtml_destroy(myhtml); + + return 0; +} + + diff --git a/utils/MyCSS/functions.pl b/utils/MyCSS/functions.pl index 331d6bd..b4660d3 100755 --- a/utils/MyCSS/functions.pl +++ b/utils/MyCSS/functions.pl @@ -22,7 +22,8 @@ BEGIN 'nth-of-type' => "", 'nth-last-of-type' => "", 'nth-column' => "", - 'nth-last-column' => "" + 'nth-last-column' => "", + 'contains' => "" }; my $INDEX_OF_NAMES = print_functions();