Rapicorn - Experimental UI Toolkit - Source Code  13.07.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
selector.hh
Go to the documentation of this file.
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__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines