Home | History | Annotate | Download | only in parser
      1 /*
      2  * Copyright (C) 2003 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #ifndef CSSParserValues_h
     22 #define CSSParserValues_h
     23 
     24 #include "core/CSSValueKeywords.h"
     25 #include "core/css/CSSPrimitiveValue.h"
     26 #include "core/css/CSSSelector.h"
     27 #include "core/css/CSSValueList.h"
     28 #include "wtf/text/AtomicString.h"
     29 #include "wtf/text/WTFString.h"
     30 
     31 namespace blink {
     32 
     33 class QualifiedName;
     34 
     35 struct CSSParserString {
     36     void init(const LChar* characters, unsigned length)
     37     {
     38         m_data.characters8 = characters;
     39         m_length = length;
     40         m_is8Bit = true;
     41     }
     42 
     43     void init(const UChar* characters, unsigned length)
     44     {
     45         m_data.characters16 = characters;
     46         m_length = length;
     47         m_is8Bit = false;
     48     }
     49 
     50     void init(const String& string)
     51     {
     52         init(string, 0, string.length());
     53     }
     54 
     55     void init(const String& string, unsigned startOffset, unsigned length)
     56     {
     57         m_length = length;
     58         if (!m_length) {
     59             m_data.characters8 = 0;
     60             m_is8Bit = true;
     61             return;
     62         }
     63         if (string.is8Bit()) {
     64             m_data.characters8 = const_cast<LChar*>(string.characters8()) + startOffset;
     65             m_is8Bit = true;
     66         } else {
     67             m_data.characters16 = const_cast<UChar*>(string.characters16()) + startOffset;
     68             m_is8Bit = false;
     69         }
     70     }
     71 
     72     void clear()
     73     {
     74         m_data.characters8 = 0;
     75         m_length = 0;
     76         m_is8Bit = true;
     77     }
     78 
     79     bool is8Bit() const { return m_is8Bit; }
     80     const LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
     81     const UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
     82     template <typename CharacterType>
     83     const CharacterType* characters() const;
     84 
     85     unsigned length() const { return m_length; }
     86     void setLength(unsigned length) { m_length = length; }
     87 
     88     UChar operator[](unsigned i) const
     89     {
     90         ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
     91         if (is8Bit())
     92             return m_data.characters8[i];
     93         return m_data.characters16[i];
     94     }
     95 
     96     bool equalIgnoringCase(const char* str) const
     97     {
     98         bool match = is8Bit() ? WTF::equalIgnoringCase(str, characters8(), length()) : WTF::equalIgnoringCase(str, characters16(), length());
     99         if (!match)
    100             return false;
    101         ASSERT(strlen(str) >= length());
    102         return str[length()] == '\0';
    103     }
    104 
    105     template <size_t strLength>
    106     bool startsWithIgnoringCase(const char (&str)[strLength]) const
    107     {
    108         return startsWithIgnoringCase(str, strLength - 1);
    109     }
    110 
    111     bool startsWithIgnoringCase(const char* str, size_t strLength) const
    112     {
    113         if (length() < strLength)
    114             return false;
    115         return is8Bit() ? WTF::equalIgnoringCase(str, characters8(), strLength) : WTF::equalIgnoringCase(str, characters16(), strLength);
    116     }
    117 
    118     operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : StringImpl::create8BitIfPossible(m_data.characters16, m_length); }
    119     operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); }
    120 
    121     bool isFunction() const { return length() > 0 && (*this)[length() - 1] == '('; }
    122 
    123     union {
    124         const LChar* characters8;
    125         const UChar* characters16;
    126     } m_data;
    127     unsigned m_length;
    128     bool m_is8Bit;
    129 };
    130 
    131 template <>
    132 inline const LChar* CSSParserString::characters<LChar>() const { return characters8(); }
    133 
    134 template <>
    135 inline const UChar* CSSParserString::characters<UChar>() const { return characters16(); }
    136 
    137 struct CSSParserFunction;
    138 class CSSParserValueList;
    139 
    140 struct CSSParserValue {
    141     CSSValueID id;
    142     bool isInt;
    143     union {
    144         double fValue;
    145         int iValue;
    146         CSSParserString string;
    147         CSSParserFunction* function;
    148         CSSParserValueList* valueList;
    149     };
    150     enum {
    151         Operator  = 0x100000,
    152         Function  = 0x100001,
    153         ValueList = 0x100002,
    154         Q_EMS     = 0x100003,
    155     };
    156     int unit;
    157 
    158     inline void setFromNumber(double value, int unit = CSSPrimitiveValue::CSS_NUMBER);
    159     inline void setFromFunction(CSSParserFunction*);
    160     inline void setFromValueList(PassOwnPtr<CSSParserValueList>);
    161 };
    162 
    163 class CSSParserValueList {
    164     WTF_MAKE_FAST_ALLOCATED;
    165 public:
    166     CSSParserValueList()
    167         : m_current(0)
    168     {
    169     }
    170     ~CSSParserValueList();
    171 
    172     void addValue(const CSSParserValue&);
    173     void insertValueAt(unsigned, const CSSParserValue&);
    174     void stealValues(CSSParserValueList&);
    175 
    176     unsigned size() const { return m_values.size(); }
    177     unsigned currentIndex() { return m_current; }
    178     CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
    179     CSSParserValue* next() { ++m_current; return current(); }
    180     CSSParserValue* previous()
    181     {
    182         if (!m_current)
    183             return 0;
    184         --m_current;
    185         return current();
    186     }
    187     void setCurrentIndex(unsigned index)
    188     {
    189         ASSERT(index < m_values.size());
    190         if (index < m_values.size())
    191             m_current = index;
    192     }
    193 
    194     CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
    195 
    196     void clearAndLeakValues() { m_values.clear(); m_current = 0;}
    197     void destroyAndClear();
    198 
    199 private:
    200     unsigned m_current;
    201     Vector<CSSParserValue, 4> m_values;
    202 };
    203 
    204 struct CSSParserFunction {
    205     WTF_MAKE_FAST_ALLOCATED;
    206 public:
    207     CSSParserString name;
    208     OwnPtr<CSSParserValueList> args;
    209 };
    210 
    211 class CSSParserSelector {
    212     WTF_MAKE_NONCOPYABLE(CSSParserSelector); WTF_MAKE_FAST_ALLOCATED;
    213 public:
    214     CSSParserSelector();
    215     explicit CSSParserSelector(const QualifiedName&);
    216     ~CSSParserSelector();
    217 
    218     PassOwnPtr<CSSSelector> releaseSelector() { return m_selector.release(); }
    219 
    220     CSSSelector::Relation relation() const { return m_selector->relation(); }
    221     void setValue(const AtomicString& value) { m_selector->setValue(value); }
    222     void setAttribute(const QualifiedName& value, CSSSelector::AttributeMatchType matchType) { m_selector->setAttribute(value, matchType); }
    223     void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
    224     void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); }
    225     void setRelation(CSSSelector::Relation value) { m_selector->setRelation(value); }
    226     void setForPage() { m_selector->setForPage(); }
    227     void setRelationIsAffectedByPseudoContent() { m_selector->setRelationIsAffectedByPseudoContent(); }
    228     bool relationIsAffectedByPseudoContent() const { return m_selector->relationIsAffectedByPseudoContent(); }
    229 
    230     void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
    231 
    232     bool hasHostPseudoSelector() const;
    233     bool isContentPseudoElement() const { return m_selector->isContentPseudoElement(); }
    234 
    235     CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); }
    236     bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
    237     bool crossesTreeScopes() const { return isCustomPseudoElement() || pseudoType() == CSSSelector::PseudoCue || pseudoType() == CSSSelector::PseudoShadow; }
    238 
    239     bool isSimple() const;
    240     bool hasShadowPseudo() const;
    241 
    242     CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
    243     void setTagHistory(PassOwnPtr<CSSParserSelector> selector) { m_tagHistory = selector; }
    244     void clearTagHistory() { m_tagHistory.clear(); }
    245     void insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector>, CSSSelector::Relation after);
    246     void appendTagHistory(CSSSelector::Relation, PassOwnPtr<CSSParserSelector>);
    247     void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
    248 
    249 private:
    250     OwnPtr<CSSSelector> m_selector;
    251     OwnPtr<CSSParserSelector> m_tagHistory;
    252 };
    253 
    254 inline bool CSSParserSelector::hasShadowPseudo() const
    255 {
    256     return m_selector->relation() == CSSSelector::ShadowPseudo;
    257 }
    258 
    259 inline void CSSParserValue::setFromNumber(double value, int unit)
    260 {
    261     id = CSSValueInvalid;
    262     isInt = false;
    263     if (std::isfinite(value))
    264         fValue = value;
    265     else
    266         fValue = 0;
    267     this->unit = unit;
    268 }
    269 
    270 inline void CSSParserValue::setFromFunction(CSSParserFunction* function)
    271 {
    272     id = CSSValueInvalid;
    273     this->function = function;
    274     unit = Function;
    275     isInt = false;
    276 }
    277 
    278 inline void CSSParserValue::setFromValueList(PassOwnPtr<CSSParserValueList> valueList)
    279 {
    280     id = CSSValueInvalid;
    281     this->valueList = valueList.leakPtr();
    282     unit = ValueList;
    283     isInt = false;
    284 }
    285 
    286 }
    287 
    288 #endif
    289