Home | History | Annotate | Download | only in css
      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 WebCore {
     32 
     33 class CSSValue;
     34 class QualifiedName;
     35 
     36 struct CSSParserString {
     37     void init(const LChar* characters, unsigned length)
     38     {
     39         m_data.characters8 = characters;
     40         m_length = length;
     41         m_is8Bit = true;
     42     }
     43 
     44     void init(const UChar* characters, unsigned length)
     45     {
     46         m_data.characters16 = characters;
     47         m_length = length;
     48         m_is8Bit = false;
     49     }
     50 
     51     void init(const String& string)
     52     {
     53         init(string, 0, string.length());
     54     }
     55 
     56     void init(const String& string, unsigned startOffset, unsigned length)
     57     {
     58         m_length = length;
     59         if (!m_length) {
     60             m_data.characters8 = 0;
     61             m_is8Bit = true;
     62             return;
     63         }
     64         if (string.is8Bit()) {
     65             m_data.characters8 = const_cast<LChar*>(string.characters8()) + startOffset;
     66             m_is8Bit = true;
     67         } else {
     68             m_data.characters16 = const_cast<UChar*>(string.characters16()) + startOffset;
     69             m_is8Bit = false;
     70         }
     71     }
     72 
     73     void clear()
     74     {
     75         m_data.characters8 = 0;
     76         m_length = 0;
     77         m_is8Bit = true;
     78     }
     79 
     80     bool is8Bit() const { return m_is8Bit; }
     81     const LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; }
     82     const UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; }
     83     template <typename CharacterType>
     84     const CharacterType* characters() const;
     85 
     86     unsigned length() const { return m_length; }
     87     void setLength(unsigned length) { m_length = length; }
     88 
     89     UChar operator[](unsigned i) const
     90     {
     91         ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
     92         if (is8Bit())
     93             return m_data.characters8[i];
     94         return m_data.characters16[i];
     95     }
     96 
     97     bool equalIgnoringCase(const char* str) const
     98     {
     99         bool match = is8Bit() ? WTF::equalIgnoringCase(str, characters8(), length()) : WTF::equalIgnoringCase(str, characters16(), length());
    100         if (!match)
    101             return false;
    102         ASSERT(strlen(str) >= length());
    103         return str[length()] == '\0';
    104     }
    105 
    106     template <size_t strLength>
    107     bool startsWithIgnoringCase(const char (&str)[strLength]) const
    108     {
    109         return startsWithIgnoringCase(str, strLength - 1);
    110     }
    111 
    112     bool startsWithIgnoringCase(const char* str, size_t strLength) const
    113     {
    114         if (length() < strLength)
    115             return false;
    116         return is8Bit() ? WTF::equalIgnoringCase(str, characters8(), strLength) : WTF::equalIgnoringCase(str, characters16(), strLength);
    117     }
    118 
    119     operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : StringImpl::create8BitIfPossible(m_data.characters16, m_length); }
    120     operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); }
    121 
    122     bool isFunction() const { return length() > 0 && (*this)[length() - 1] == '('; }
    123 
    124     union {
    125         const LChar* characters8;
    126         const UChar* characters16;
    127     } m_data;
    128     unsigned m_length;
    129     bool m_is8Bit;
    130 };
    131 
    132 template <>
    133 inline const LChar* CSSParserString::characters<LChar>() const { return characters8(); }
    134 
    135 template <>
    136 inline const UChar* CSSParserString::characters<UChar>() const { return characters16(); }
    137 
    138 struct CSSParserFunction;
    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     PassRefPtrWillBeRawPtr<CSSValue> createCSSValue();
    163 };
    164 
    165 class CSSParserValueList {
    166     WTF_MAKE_FAST_ALLOCATED;
    167 public:
    168     CSSParserValueList()
    169         : m_current(0)
    170     {
    171     }
    172     ~CSSParserValueList();
    173 
    174     void addValue(const CSSParserValue&);
    175     void insertValueAt(unsigned, const CSSParserValue&);
    176     void stealValues(CSSParserValueList&);
    177 
    178     unsigned size() const { return m_values.size(); }
    179     unsigned currentIndex() { return m_current; }
    180     CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
    181     CSSParserValue* next() { ++m_current; return current(); }
    182     CSSParserValue* previous()
    183     {
    184         if (!m_current)
    185             return 0;
    186         --m_current;
    187         return current();
    188     }
    189     void setCurrentIndex(unsigned index)
    190     {
    191         ASSERT(index < m_values.size());
    192         if (index < m_values.size())
    193             m_current = index;
    194     }
    195 
    196     CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
    197 
    198     void clearAndLeakValues() { m_values.clear(); m_current = 0;}
    199     void destroyAndClear();
    200 
    201 private:
    202     unsigned m_current;
    203     Vector<CSSParserValue, 4> m_values;
    204 };
    205 
    206 struct CSSParserFunction {
    207     WTF_MAKE_FAST_ALLOCATED;
    208 public:
    209     CSSParserString name;
    210     OwnPtr<CSSParserValueList> args;
    211 };
    212 
    213 class CSSParserSelector {
    214     WTF_MAKE_NONCOPYABLE(CSSParserSelector); WTF_MAKE_FAST_ALLOCATED;
    215 public:
    216     CSSParserSelector();
    217     explicit CSSParserSelector(const QualifiedName&);
    218     ~CSSParserSelector();
    219 
    220     PassOwnPtr<CSSSelector> releaseSelector() { return m_selector.release(); }
    221 
    222     CSSSelector::Relation relation() const { return m_selector->relation(); }
    223     void setValue(const AtomicString& value) { m_selector->setValue(value); }
    224     void setAttribute(const QualifiedName& value) { m_selector->setAttribute(value); }
    225     void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
    226     void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); }
    227     void setRelation(CSSSelector::Relation value) { m_selector->setRelation(value); }
    228     void setForPage() { m_selector->setForPage(); }
    229     void setRelationIsAffectedByPseudoContent() { m_selector->setRelationIsAffectedByPseudoContent(); }
    230     bool relationIsAffectedByPseudoContent() const { return m_selector->relationIsAffectedByPseudoContent(); }
    231 
    232     void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
    233 
    234     bool hasHostPseudoSelector() const;
    235     bool isContentPseudoElement() const { return m_selector->isContentPseudoElement(); }
    236 
    237     CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); }
    238     bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); }
    239     bool crossesTreeScopes() const { return isCustomPseudoElement() || pseudoType() == CSSSelector::PseudoCue || pseudoType() == CSSSelector::PseudoShadow; }
    240 
    241     bool isSimple() const;
    242     bool hasShadowPseudo() const;
    243 
    244     CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
    245     void setTagHistory(PassOwnPtr<CSSParserSelector> selector) { m_tagHistory = selector; }
    246     void clearTagHistory() { m_tagHistory.clear(); }
    247     void insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector>, CSSSelector::Relation after);
    248     void appendTagHistory(CSSSelector::Relation, PassOwnPtr<CSSParserSelector>);
    249     void prependTagSelector(const QualifiedName&, bool tagIsForNamespaceRule = false);
    250 
    251 private:
    252     OwnPtr<CSSSelector> m_selector;
    253     OwnPtr<CSSParserSelector> m_tagHistory;
    254 };
    255 
    256 inline bool CSSParserSelector::hasShadowPseudo() const
    257 {
    258     return m_selector->relation() == CSSSelector::ShadowPseudo;
    259 }
    260 
    261 inline void CSSParserValue::setFromNumber(double value, int unit)
    262 {
    263     id = CSSValueInvalid;
    264     isInt = false;
    265     if (std::isfinite(value))
    266         fValue = value;
    267     else
    268         fValue = 0;
    269     this->unit = unit;
    270 }
    271 
    272 inline void CSSParserValue::setFromFunction(CSSParserFunction* function)
    273 {
    274     id = CSSValueInvalid;
    275     this->function = function;
    276     unit = Function;
    277     isInt = false;
    278 }
    279 
    280 inline void CSSParserValue::setFromValueList(PassOwnPtr<CSSParserValueList> valueList)
    281 {
    282     id = CSSValueInvalid;
    283     this->valueList = valueList.leakPtr();
    284     unit = ValueList;
    285     isInt = false;
    286 }
    287 
    288 }
    289 
    290 #endif
    291