| /* |
| * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
| * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
| * Copyright (C) 2009 Google Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #ifndef UString_h |
| #define UString_h |
| |
| #include <wtf/text/StringImpl.h> |
| |
| namespace JSC { |
| |
| class UString { |
| public: |
| // Construct a null string, distinguishable from an empty string. |
| UString() { } |
| |
| // Construct a string with UTF-16 data. |
| UString(const UChar* characters, unsigned length); |
| |
| // Construct a string with UTF-16 data, from a null-terminated source. |
| UString(const UChar*); |
| |
| // Construct a string with latin1 data. |
| UString(const char* characters, unsigned length); |
| |
| // Construct a string with latin1 data, from a null-terminated source. |
| UString(const char* characters); |
| |
| // Construct a string referencing an existing StringImpl. |
| UString(StringImpl* impl) : m_impl(impl) { } |
| UString(PassRefPtr<StringImpl> impl) : m_impl(impl) { } |
| UString(RefPtr<StringImpl> impl) : m_impl(impl) { } |
| |
| // Inline the destructor. |
| ALWAYS_INLINE ~UString() { } |
| |
| void swap(UString& o) { m_impl.swap(o.m_impl); } |
| |
| template<size_t inlineCapacity> |
| static UString adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); } |
| |
| bool isNull() const { return !m_impl; } |
| bool isEmpty() const { return !m_impl || !m_impl->length(); } |
| |
| StringImpl* impl() const { return m_impl.get(); } |
| |
| unsigned length() const |
| { |
| if (!m_impl) |
| return 0; |
| return m_impl->length(); |
| } |
| |
| const UChar* characters() const |
| { |
| if (!m_impl) |
| return 0; |
| return m_impl->characters(); |
| } |
| |
| CString ascii() const; |
| CString latin1() const; |
| CString utf8(bool strict = false) const; |
| |
| UChar operator[](unsigned index) const |
| { |
| if (!m_impl || index >= m_impl->length()) |
| return 0; |
| return m_impl->characters()[index]; |
| } |
| |
| static UString number(int); |
| static UString number(unsigned); |
| static UString number(long); |
| static UString number(long long); |
| static UString number(double); |
| |
| // Find a single character or string, also with match function & latin1 forms. |
| size_t find(UChar c, unsigned start = 0) const |
| { return m_impl ? m_impl->find(c, start) : notFound; } |
| size_t find(const UString& str, unsigned start = 0) const |
| { return m_impl ? m_impl->find(str.impl(), start) : notFound; } |
| size_t find(const char* str, unsigned start = 0) const |
| { return m_impl ? m_impl->find(str, start) : notFound; } |
| |
| // Find the last instance of a single character or string. |
| size_t reverseFind(UChar c, unsigned start = UINT_MAX) const |
| { return m_impl ? m_impl->reverseFind(c, start) : notFound; } |
| size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const |
| { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } |
| |
| UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; |
| |
| private: |
| RefPtr<StringImpl> m_impl; |
| }; |
| |
| ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) |
| { |
| StringImpl* rep1 = s1.impl(); |
| StringImpl* rep2 = s2.impl(); |
| unsigned size1 = 0; |
| unsigned size2 = 0; |
| |
| if (rep1 == rep2) // If they're the same rep, they're equal. |
| return true; |
| |
| if (rep1) |
| size1 = rep1->length(); |
| |
| if (rep2) |
| size2 = rep2->length(); |
| |
| if (size1 != size2) // If the lengths are not the same, we're done. |
| return false; |
| |
| if (!size1) |
| return true; |
| |
| // At this point we know |
| // (a) that the strings are the same length and |
| // (b) that they are greater than zero length. |
| const UChar* d1 = rep1->characters(); |
| const UChar* d2 = rep2->characters(); |
| |
| if (d1 == d2) // Check to see if the data pointers are the same. |
| return true; |
| |
| // Do quick checks for sizes 1 and 2. |
| switch (size1) { |
| case 1: |
| return d1[0] == d2[0]; |
| case 2: |
| return (d1[0] == d2[0]) & (d1[1] == d2[1]); |
| default: |
| return memcmp(d1, d2, size1 * sizeof(UChar)) == 0; |
| } |
| } |
| |
| |
| inline bool operator!=(const UString& s1, const UString& s2) |
| { |
| return !JSC::operator==(s1, s2); |
| } |
| |
| bool operator<(const UString& s1, const UString& s2); |
| bool operator>(const UString& s1, const UString& s2); |
| |
| bool operator==(const UString& s1, const char* s2); |
| |
| inline bool operator!=(const UString& s1, const char* s2) |
| { |
| return !JSC::operator==(s1, s2); |
| } |
| |
| inline bool operator==(const char *s1, const UString& s2) |
| { |
| return operator==(s2, s1); |
| } |
| |
| inline bool operator!=(const char *s1, const UString& s2) |
| { |
| return !JSC::operator==(s1, s2); |
| } |
| |
| inline int codePointCompare(const UString& s1, const UString& s2) |
| { |
| return codePointCompare(s1.impl(), s2.impl()); |
| } |
| |
| struct UStringHash { |
| static unsigned hash(StringImpl* key) { return key->hash(); } |
| static bool equal(const StringImpl* a, const StringImpl* b) |
| { |
| if (a == b) |
| return true; |
| if (!a || !b) |
| return false; |
| |
| unsigned aLength = a->length(); |
| unsigned bLength = b->length(); |
| if (aLength != bLength) |
| return false; |
| |
| // FIXME: perhaps we should have a more abstract macro that indicates when |
| // going 4 bytes at a time is unsafe |
| #if CPU(ARM) || CPU(SH4) || CPU(MIPS) |
| const UChar* aChars = a->characters(); |
| const UChar* bChars = b->characters(); |
| for (unsigned i = 0; i != aLength; ++i) { |
| if (*aChars++ != *bChars++) |
| return false; |
| } |
| return true; |
| #else |
| /* Do it 4-bytes-at-a-time on architectures where it's safe */ |
| const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters()); |
| const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters()); |
| |
| unsigned halfLength = aLength >> 1; |
| for (unsigned i = 0; i != halfLength; ++i) |
| if (*aChars++ != *bChars++) |
| return false; |
| |
| if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars)) |
| return false; |
| |
| return true; |
| #endif |
| } |
| |
| static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); } |
| static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) |
| { |
| return equal(a.get(), b.get()); |
| } |
| |
| static unsigned hash(const UString& key) { return key.impl()->hash(); } |
| static bool equal(const UString& a, const UString& b) |
| { |
| return equal(a.impl(), b.impl()); |
| } |
| |
| static const bool safeToCompareToEmptyOrDeleted = false; |
| }; |
| |
| } // namespace JSC |
| |
| namespace WTF { |
| |
| // UStringHash is the default hash for UString |
| template<typename T> struct DefaultHash; |
| template<> struct DefaultHash<JSC::UString> { |
| typedef JSC::UStringHash Hash; |
| }; |
| |
| template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits { }; |
| |
| } // namespace WTF |
| |
| #endif |
| |