Remove all uses of deprecatedCharacters from WebKit2
[WebKit-https.git] / Source / WTF / wtf / text / StringView.h
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef StringView_h
27 #define StringView_h
28
29 #include <wtf/text/WTFString.h>
30
31 namespace WTF {
32
33 // StringView is a non-owning reference to a string, similar to the proposed std::string_view.
34 // Whether the string is 8-bit or 16-bit is encoded in the upper bit of the length member.
35 // This means that strings longer than 2 Gigabytes can not be represented. If that turns out to be
36 // a problem we can investigate alternative solutions.
37
38 class StringView {
39 public:
40     StringView()
41         : m_characters(nullptr)
42         , m_length(0)
43     {
44     }
45
46     StringView(const LChar* characters, unsigned length)
47     {
48         initialize(characters, length);
49     }
50
51     StringView(const UChar* characters, unsigned length)
52     {
53         initialize(characters, length);
54     }
55
56     StringView(const String& string)
57         : m_characters(nullptr)
58         , m_length(0)
59     {
60         if (!string.impl())
61             return;
62         
63         if (string.is8Bit())
64             initialize(string.characters8(), string.length());
65         else
66             initialize(string.characters16(), string.length());
67     }
68
69     static StringView empty()
70     {
71         return StringView(reinterpret_cast<const LChar*>(""), 0);
72     }
73
74     const LChar* characters8() const
75     {
76         ASSERT(is8Bit());
77
78         return static_cast<const LChar*>(m_characters);
79     }
80
81     const UChar* characters16() const
82     {
83         ASSERT(!is8Bit());
84
85         return static_cast<const UChar*>(m_characters);
86     }
87
88     void getCharactersWithUpconvert(LChar*) const;
89     void getCharactersWithUpconvert(UChar*) const;
90
91     class UpconvertedCharacters {
92     public:
93         explicit UpconvertedCharacters(const StringView&);
94         operator const UChar*() const { return m_characters; }
95         const UChar* get() const { return m_characters; }
96     private:
97         Vector<UChar, 32> m_upconvertedCharacters;
98         const UChar* m_characters;
99     };
100     UpconvertedCharacters upconvertedCharacters() const { return UpconvertedCharacters(*this); }
101
102     bool isNull() const { return !m_characters; }
103     bool isEmpty() const { return !length(); }
104     unsigned length() const { return m_length & ~is16BitStringFlag; }
105
106     explicit operator bool() const { return !isNull(); }
107
108     bool is8Bit() const { return !(m_length & is16BitStringFlag); }
109
110     StringView substring(unsigned start, unsigned length = std::numeric_limits<unsigned>::max()) const
111     {
112         if (start >= this->length())
113             return empty();
114         unsigned maxLength = this->length() - start;
115
116         if (length >= maxLength) {
117             if (!start)
118                 return *this;
119             length = maxLength;
120         }
121
122         if (is8Bit())
123             return StringView(characters8() + start, length);
124
125         return StringView(characters16() + start, length);
126     }
127
128     String toString() const
129     {
130         if (is8Bit())
131             return String(characters8(), length());
132
133         return String(characters16(), length());
134     }
135
136     String toStringWithoutCopying() const
137     {
138         if (is8Bit())
139             return StringImpl::createWithoutCopying(characters8(), length());
140
141         return StringImpl::createWithoutCopying(characters16(), length());
142     }
143
144     UChar operator[](unsigned index) const
145     {
146         ASSERT(index < length());
147         if (is8Bit())
148             return characters8()[index];
149         return characters16()[index];
150     }
151
152     size_t find(UChar character, unsigned start = 0) const
153     {
154         if (is8Bit())
155             return WTF::find(characters8(), length(), character, start);
156         return WTF::find(characters16(), length(), character, start);
157     }
158
159 #if USE(CF)
160     // This function converts null strings to empty strings.
161     WTF_EXPORT_STRING_API RetainPtr<CFStringRef> createCFStringWithoutCopying() const;
162 #endif
163
164 #ifdef __OBJC__
165     // These functions convert null strings to empty strings.
166     WTF_EXPORT_STRING_API RetainPtr<NSString> createNSString() const;
167     WTF_EXPORT_STRING_API RetainPtr<NSString> createNSStringWithoutCopying() const;
168 #endif
169
170 private:
171     void initialize(const LChar* characters, unsigned length)
172     {
173         ASSERT(!(length & is16BitStringFlag));
174         
175         m_characters = characters;
176         m_length = length;
177     }
178
179     void initialize(const UChar* characters, unsigned length)
180     {
181         ASSERT(!(length & is16BitStringFlag));
182         
183         m_characters = characters;
184         m_length = is16BitStringFlag | length;
185     }
186
187     static const unsigned is16BitStringFlag = 1u << 31;
188
189     const void* m_characters;
190     unsigned m_length;
191 };
192
193 inline void StringView::getCharactersWithUpconvert(LChar* destination) const
194 {
195     ASSERT(is8Bit());
196     memcpy(destination, characters8(), length());
197 }
198
199 inline void StringView::getCharactersWithUpconvert(UChar* destination) const
200 {
201     if (is8Bit()) {
202         const LChar* characters8 = this->characters8();
203         unsigned length = this->length();
204         for (unsigned i = 0; i < length; ++i)
205             destination[i] = characters8[i];
206         return;
207     }
208     memcpy(destination, characters16(), length() * sizeof(UChar));
209 }
210
211 inline StringView::UpconvertedCharacters::UpconvertedCharacters(const StringView& string)
212 {
213     if (!string.is8Bit()) {
214         m_characters = string.characters16();
215         return;
216     }
217     const LChar* characters8 = string.characters8();
218     unsigned length = string.length();
219     m_upconvertedCharacters.reserveInitialCapacity(length);
220     for (unsigned i = 0; i < length; ++i)
221         m_upconvertedCharacters.uncheckedAppend(characters8[i]);
222     m_characters = m_upconvertedCharacters.data();
223 }
224
225 } // namespace WTF
226
227 using WTF::StringView;
228
229 #endif // StringView_h