Home | History | Annotate | Download | only in text
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef AtomicString_h
     22 #define AtomicString_h
     23 
     24 #include "AtomicStringImpl.h"
     25 #include "WTFString.h"
     26 
     27 // Define 'NO_IMPLICIT_ATOMICSTRING' before including this header,
     28 // to disallow (expensive) implicit String-->AtomicString conversions.
     29 #ifdef NO_IMPLICIT_ATOMICSTRING
     30 #define ATOMICSTRING_CONVERSION explicit
     31 #else
     32 #define ATOMICSTRING_CONVERSION
     33 #endif
     34 
     35 namespace WTF {
     36 
     37 struct AtomicStringHash;
     38 
     39 class AtomicString {
     40 public:
     41     static void init();
     42 
     43     AtomicString() { }
     44     AtomicString(const char* s) : m_string(add(s)) { }
     45     AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { }
     46     AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { }
     47     AtomicString(const UChar* s) : m_string(add(s)) { }
     48     ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { }
     49     AtomicString(AtomicStringImpl* imp) : m_string(imp) { }
     50     ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { }
     51 
     52     // Hash table deleted values, which are only constructed and never copied or destroyed.
     53     AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { }
     54     bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); }
     55 
     56     static AtomicStringImpl* find(const UChar* s, unsigned length, unsigned existingHash);
     57 
     58     operator const String&() const { return m_string; }
     59     const String& string() const { return m_string; };
     60 
     61     AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); }
     62 
     63     const UChar* characters() const { return m_string.characters(); }
     64     unsigned length() const { return m_string.length(); }
     65 
     66     UChar operator[](unsigned int i) const { return m_string[i]; }
     67 
     68     bool contains(UChar c) const { return m_string.contains(c); }
     69     bool contains(const char* s, bool caseSensitive = true) const
     70         { return m_string.contains(s, caseSensitive); }
     71     bool contains(const String& s, bool caseSensitive = true) const
     72         { return m_string.contains(s, caseSensitive); }
     73 
     74     size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); }
     75     size_t find(const char* s, size_t start = 0, bool caseSentitive = true) const
     76         { return m_string.find(s, start, caseSentitive); }
     77     size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const
     78         { return m_string.find(s, start, caseSentitive); }
     79 
     80     bool startsWith(const String& s, bool caseSensitive = true) const
     81         { return m_string.startsWith(s, caseSensitive); }
     82     bool endsWith(const String& s, bool caseSensitive = true) const
     83         { return m_string.endsWith(s, caseSensitive); }
     84 
     85     AtomicString lower() const;
     86     AtomicString upper() const { return AtomicString(impl()->upper()); }
     87 
     88     int toInt(bool* ok = 0) const { return m_string.toInt(ok); }
     89     double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); }
     90     float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); }
     91     bool percentage(int& p) const { return m_string.percentage(p); }
     92 
     93     bool isNull() const { return m_string.isNull(); }
     94     bool isEmpty() const { return m_string.isEmpty(); }
     95 
     96     static void remove(StringImpl*);
     97 
     98 #if USE(CF)
     99     AtomicString(CFStringRef s) :  m_string(add(String(s).impl())) { }
    100     CFStringRef createCFString() const { return m_string.createCFString(); }
    101 #endif
    102 #ifdef __OBJC__
    103     AtomicString(NSString* s) : m_string(add(String(s).impl())) { }
    104     operator NSString*() const { return m_string; }
    105 #endif
    106 #if PLATFORM(QT)
    107     AtomicString(const QString& s) : m_string(add(String(s).impl())) { }
    108     operator QString() const { return m_string; }
    109 #endif
    110 
    111     // AtomicString::fromUTF8 will return a null string if
    112     // the input data contains invalid UTF-8 sequences.
    113     static AtomicString fromUTF8(const char*, size_t);
    114     static AtomicString fromUTF8(const char*);
    115 
    116 private:
    117     String m_string;
    118 
    119     static PassRefPtr<StringImpl> add(const char*);
    120     static PassRefPtr<StringImpl> add(const UChar*, unsigned length);
    121     static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash);
    122     static PassRefPtr<StringImpl> add(const UChar*);
    123     ALWAYS_INLINE PassRefPtr<StringImpl> add(StringImpl* r)
    124     {
    125         if (!r || r->isAtomic())
    126             return r;
    127         return addSlowCase(r);
    128     }
    129     static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
    130     static AtomicString fromUTF8Internal(const char*, const char*);
    131 };
    132 
    133 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
    134 bool operator==(const AtomicString& a, const char* b);
    135 bool operator==(const AtomicString& a, const Vector<UChar>& b);
    136 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
    137 inline bool operator==(const char* a, const AtomicString& b) { return b == a; }
    138 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
    139 inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
    140 
    141 inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
    142 inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); }
    143 inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
    144 inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
    145 inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); }
    146 inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
    147 inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
    148 
    149 inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    150 inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
    151 inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    152 inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); }
    153 inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
    154 
    155 // Define external global variables for the commonly used atomic strings.
    156 // These are only usable from the main thread.
    157 #ifndef ATOMICSTRING_HIDE_GLOBALS
    158 extern const JS_EXPORTDATA AtomicString nullAtom;
    159 extern const JS_EXPORTDATA AtomicString emptyAtom;
    160 extern const JS_EXPORTDATA AtomicString textAtom;
    161 extern const JS_EXPORTDATA AtomicString commentAtom;
    162 extern const JS_EXPORTDATA AtomicString starAtom;
    163 extern const JS_EXPORTDATA AtomicString xmlAtom;
    164 extern const JS_EXPORTDATA AtomicString xmlnsAtom;
    165 
    166 inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length)
    167 {
    168     if (!characters)
    169         return nullAtom;
    170     if (!length)
    171         return emptyAtom;
    172     return fromUTF8Internal(characters, characters + length);
    173 }
    174 
    175 inline AtomicString AtomicString::fromUTF8(const char* characters)
    176 {
    177     if (!characters)
    178         return nullAtom;
    179     if (!*characters)
    180         return emptyAtom;
    181     return fromUTF8Internal(characters, 0);
    182 }
    183 #endif
    184 
    185 // AtomicStringHash is the default hash for AtomicString
    186 template<typename T> struct DefaultHash;
    187 template<> struct DefaultHash<AtomicString> {
    188     typedef AtomicStringHash Hash;
    189 };
    190 
    191 } // namespace WTF
    192 
    193 #ifndef ATOMICSTRING_HIDE_GLOBALS
    194 using WTF::AtomicString;
    195 using WTF::nullAtom;
    196 using WTF::emptyAtom;
    197 using WTF::textAtom;
    198 using WTF::commentAtom;
    199 using WTF::starAtom;
    200 using WTF::xmlAtom;
    201 using WTF::xmlnsAtom;
    202 #endif
    203 
    204 #endif // AtomicString_h
    205