Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
00001 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __RAPICORN_SELECTOR_HH__ 00003 #define __RAPICORN_SELECTOR_HH__ 00004 00005 #include <rapicorn-core.hh> 00006 00007 namespace Rapicorn { 00008 namespace Selector { 00009 00010 enum Kind { 00011 NONE, 00012 SUBJECT, TYPE, UNIVERSAL, // element selectors 00013 CLASS, ID, PSEUDO_ELEMENT, PSEUDO_CLASS, // class, id, pseudo selectors 00014 DESCENDANT, CHILD, ADJACENT, NEIGHBORING, // selector combinators 00015 ATTRIBUTE_EXISTS, ATTRIBUTE_EXISTS_I, // attributes with match types 00016 ATTRIBUTE_EQUALS, ATTRIBUTE_EQUALS_I, ATTRIBUTE_UNEQUALS, ATTRIBUTE_UNEQUALS_I, 00017 ATTRIBUTE_PREFIX, ATTRIBUTE_PREFIX_I, ATTRIBUTE_SUFFIX, ATTRIBUTE_SUFFIX_I, 00018 ATTRIBUTE_DASHSTART, ATTRIBUTE_DASHSTART_I, ATTRIBUTE_SUBSTRING, ATTRIBUTE_SUBSTRING_I, 00019 ATTRIBUTE_INCLUDES, ATTRIBUTE_INCLUDES_I, 00020 }; 00021 inline bool is_combinator (Kind kind) { return kind >= DESCENDANT && kind <= NEIGHBORING; } 00022 00023 class CustomPseudoRegistry { 00024 CustomPseudoRegistry *next_; 00025 String ident_, blurb_; 00026 static Atomic<CustomPseudoRegistry*> stack_head; 00027 RAPICORN_CLASS_NON_COPYABLE (CustomPseudoRegistry); 00028 public: 00029 const String& ident () const { return ident_; } 00030 const String& blurb () const { return blurb_; } 00031 explicit CustomPseudoRegistry (const String &id, const String &b = "") : 00032 next_ (NULL), ident_ (string_tolower (id)), blurb_ (b) 00033 { stack_head.push_link (&next_, this); } 00034 CustomPseudoRegistry* next () const { return next_; } 00035 static CustomPseudoRegistry* head () { return stack_head; } 00036 }; 00037 00038 bool parse_spaces (const char **stringp, int min_spaces = 1); 00039 bool skip_spaces (const char **stringp); 00040 bool scan_nested (const char **stringp, const char *pairflags, const char term); 00041 bool parse_case_word (const char **stringp, const char *word); 00042 bool parse_unsigned_integer (const char **stringp, uint64 *up); 00043 bool parse_signed_integer (const char **stringp, int64 *ip); 00044 bool parse_css_nth (const char **stringp, int64 *ap, int64 *bp); 00045 bool match_css_nth (int64 pos, int64 a, int64 b); 00046 00047 bool parse_identifier (const char **stringp, String &ident); 00048 bool parse_string (const char **stringp, String &ident); 00049 00050 struct SelectorNode { 00051 Kind kind; 00052 String ident; 00053 String arg; 00054 SelectorNode (Kind k = NONE, const String &i = "", const String &a = "") : kind (k), ident (i), arg (a) {} 00055 bool operator== (const SelectorNode &o) const { return kind == o.kind && ident == o.ident && arg == o.arg; } 00056 bool operator!= (const SelectorNode &o) const { return !operator== (o); } 00057 }; 00058 struct SelectorChain : public vector<SelectorNode> { 00059 bool parse (const char **stringp, bool with_combinators = true); 00060 String string (size_t first = 0); 00061 }; 00062 00063 class Selob { // Matchable Objects 00064 public: 00065 typedef std::vector<std::string> Strings; 00066 typedef const StringVector ConstTypes; 00067 virtual ~Selob () {} 00068 virtual String get_id () = 0; 00069 virtual String get_type () = 0; // Factory::factory_context_type (selob.factory_context()) 00070 virtual ConstTypes& get_type_list () = 0; 00071 virtual bool has_property (const String &name) = 0; // widget.lookup_property 00072 virtual String get_property (const String &name) = 0; 00073 virtual Selob* get_parent () = 0; 00074 virtual Selob* get_sibling (int64 dir) = 0; 00075 virtual bool has_children () = 0; 00076 virtual int64 n_children () = 0; 00077 virtual Selob* get_child (int64 index) = 0; 00078 virtual bool is_nth_child (int64 nth1based) = 0; 00079 virtual Selob* pseudo_selector (const String &ident, const String &arg, String &error) = 0; 00080 static Selob* true_match (); 00081 static bool is_true_match (Selob *selob) { return selob == true_match(); } 00082 }; 00083 00084 class Matcher { 00085 SelectorChain chain; 00086 uint subject_index, last_combinator, first_pseudo_element; 00087 /*ctor*/ Matcher() : subject_index (UINT_MAX), last_combinator (UINT_MAX), first_pseudo_element (UINT_MAX) {} 00088 bool match_attribute_selector (Selob &selob, const SelectorNode &snode); 00089 Selob* match_pseudo_element (Selob &selob, const SelectorNode &snode); 00090 bool match_pseudo_class (Selob &selob, const SelectorNode &snode); 00091 bool match_element_selector (Selob &selob, const SelectorNode &snode); 00092 template<int CDIR> Selob* match_selector_stepwise (Selob &selob, const size_t chain_index); 00093 Selob* match_selector_descendants (Selob &selob, const size_t chain_index); 00094 Selob* match_selector_chain (Selob &selob); 00095 template<size_t COUNT> 00096 vector<Selob*> recurse_selector (Selob &selob); 00097 bool parse_selector (const String &selector, bool with_combinators, String *errorp = NULL); 00098 public: 00099 static bool query_selector_bool (const String &selector, Selob &selob, String *errorp = NULL); 00100 static Selob* query_selector_first (const String &selector, Selob &selob, String *errorp = NULL); 00101 static Selob* query_selector_unique (const String &selector, Selob &selob, String *errorp = NULL); 00102 static vector<Selob*> query_selector_all (const String &selector, Selob &selob, String *errorp = NULL); 00103 template<class Iter> 00104 static vector<Selob*> query_selector_objects (const String &selector, Iter first, Iter last, String *errorp = NULL); 00105 }; 00106 00107 // Implementations 00108 template<class Iter> vector<Selob*> 00109 Matcher::query_selector_objects (const String &selector, Iter first, Iter last, String *errorp) 00110 { 00111 Matcher matcher; 00112 vector<Selob*> rvector; 00113 if (matcher.parse_selector (selector, true, errorp)) 00114 for (Iter it = first; it != last; it++) 00115 { 00116 Selob *selob = *it; 00117 if (!selob) 00118 continue; 00119 Selob *result = matcher.match_selector_chain (*selob); 00120 if (result) 00121 rvector.push_back (result); 00122 } 00123 return rvector; 00124 } 00125 00126 } // Selector 00127 } // Rapicorn 00128 00129 #endif /* __RAPICORN_SELECTOR_HH__ */