Remove convenience constructors for TextRun
[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 <unicode/utypes.h>
30 #include <wtf/Forward.h>
31 #include <wtf/RetainPtr.h>
32 #include <wtf/Vector.h>
33 #include <wtf/text/LChar.h>
34 #include <wtf/text/StringCommon.h>
35
36 // FIXME: Enabling the StringView lifetime checking causes the MSVC build to fail. Figure out why.
37 // FIXME: Enable StringView lifetime checking once the underlying assertions have been fixed.
38 #if defined(NDEBUG) || COMPILER(MSVC) || 1
39 #define CHECK_STRINGVIEW_LIFETIME 0
40 #else
41 #define CHECK_STRINGVIEW_LIFETIME 1
42 #endif
43
44 namespace WTF {
45
46 // StringView is a non-owning reference to a string, similar to the proposed std::string_view.
47 // Whether the string is 8-bit or 16-bit is encoded in the upper bit of the length member.
48 // This means that strings longer than 2 gigacharacters cannot be represented.
49
50 class StringView {
51 public:
52     StringView();
53     ~StringView();
54     StringView(StringView&&);
55     StringView(const StringView&);
56     StringView& operator=(StringView&&);
57     StringView& operator=(const StringView&);
58
59     StringView(const String&);
60     StringView(const StringImpl&);
61     StringView(const StringImpl*);
62     StringView(const LChar*, unsigned length);
63     StringView(const UChar*, unsigned length);
64
65     static StringView empty();
66
67     unsigned length() const;
68     bool isEmpty() const;
69
70     explicit operator bool() const;
71     bool isNull() const;
72
73     UChar operator[](unsigned index) const;
74
75     class CodeUnits;
76     CodeUnits codeUnits() const;
77
78     class CodePoints;
79     CodePoints codePoints() const;
80
81     bool is8Bit() const;
82     const LChar* characters8() const;
83     const UChar* characters16() const;
84
85     String toString() const;
86     String toStringWithoutCopying() const;
87
88 #if USE(CF)
89     // This function converts null strings to empty strings.
90     WTF_EXPORT_STRING_API RetainPtr<CFStringRef> createCFStringWithoutCopying() const;
91 #endif
92
93 #ifdef __OBJC__
94     // These functions convert null strings to empty strings.
95     WTF_EXPORT_STRING_API RetainPtr<NSString> createNSString() const;
96     WTF_EXPORT_STRING_API RetainPtr<NSString> createNSStringWithoutCopying() const;
97 #endif
98
99     class UpconvertedCharacters;
100     UpconvertedCharacters upconvertedCharacters() const;
101
102     void getCharactersWithUpconvert(LChar*) const;
103     void getCharactersWithUpconvert(UChar*) const;
104
105     StringView substring(unsigned start, unsigned length = std::numeric_limits<unsigned>::max()) const;
106
107     size_t find(UChar, unsigned start = 0) const;
108     WTF_EXPORT_STRING_API size_t findIgnoringASCIICase(const StringView&) const;
109     WTF_EXPORT_STRING_API size_t findIgnoringASCIICase(const StringView&, unsigned startOffset) const;
110
111     bool contains(UChar) const;
112     WTF_EXPORT_STRING_API bool containsIgnoringASCIICase(const StringView&) const;
113     WTF_EXPORT_STRING_API bool containsIgnoringASCIICase(const StringView&, unsigned startOffset) const;
114
115     WTF_EXPORT_STRING_API bool startsWith(const StringView&) const;
116     WTF_EXPORT_STRING_API bool startsWithIgnoringASCIICase(const StringView&) const;
117
118     WTF_EXPORT_STRING_API bool endsWith(const StringView&) const;
119     WTF_EXPORT_STRING_API bool endsWithIgnoringASCIICase(const StringView&) const;
120
121     int toInt(bool& isValid) const;
122     float toFloat(bool& isValid) const;
123
124     static void invalidate(const StringImpl&);
125
126     struct UnderlyingString;
127
128 private:
129     void initialize(const LChar*, unsigned length);
130     void initialize(const UChar*, unsigned length);
131
132 #if CHECK_STRINGVIEW_LIFETIME
133     WTF_EXPORT_STRING_API bool underlyingStringIsValid() const;
134     WTF_EXPORT_STRING_API void setUnderlyingString(const StringImpl*);
135     WTF_EXPORT_STRING_API void setUnderlyingString(const StringView&);
136 #else
137     bool underlyingStringIsValid() const { return true; }
138     void setUnderlyingString(const StringImpl*) { }
139     void setUnderlyingString(const StringView&) { }
140 #endif
141
142     static const unsigned is16BitStringFlag = 1u << 31;
143
144     const void* m_characters { nullptr };
145     unsigned m_length { 0 };
146
147 #if CHECK_STRINGVIEW_LIFETIME
148     void adoptUnderlyingString(UnderlyingString*);
149     UnderlyingString* m_underlyingString { nullptr };
150 #endif
151 };
152
153 template<typename CharacterType, size_t inlineCapacity> void append(Vector<CharacterType, inlineCapacity>&, StringView);
154
155 bool equal(StringView, StringView);
156 bool equal(StringView, const LChar*);
157 bool equal(StringView, const char*);
158 bool equalIgnoringASCIICase(StringView, StringView);
159
160 inline bool operator==(StringView a, StringView b) { return equal(a, b); }
161 inline bool operator==(StringView a, const LChar* b) { return equal(a, b); }
162 inline bool operator==(StringView a, const char* b) { return equal(a, b); }
163 inline bool operator==(const LChar* a, StringView b) { return equal(b, a); }
164 inline bool operator==(const char* a, StringView b) { return equal(b, a); }
165
166 inline bool operator!=(StringView a, StringView b) { return !equal(a, b); }
167 inline bool operator!=(StringView a, const LChar* b) { return !equal(a, b); }
168 inline bool operator!=(StringView a, const char* b) { return !equal(a, b); }
169 inline bool operator!=(const LChar* a, StringView b) { return !equal(b, a); }
170 inline bool operator!=(const char* a, StringView b) { return !equal(b, a); }
171
172 }
173
174 #include <wtf/text/WTFString.h>
175
176 namespace WTF {
177
178 inline StringView::StringView()
179 {
180     // FIXME: It's peculiar that null strings are 16-bit and empty strings return 8-bit (according to the is8Bit function).
181 }
182
183 inline StringView::~StringView()
184 {
185     setUnderlyingString(nullptr);
186 }
187
188 inline StringView::StringView(StringView&& other)
189     : m_characters(other.m_characters)
190     , m_length(other.m_length)
191 {
192     ASSERT(other.underlyingStringIsValid());
193
194     other.m_characters = nullptr;
195     other.m_length = 0;
196
197     setUnderlyingString(other);
198     other.setUnderlyingString(nullptr);
199 }
200
201 inline StringView::StringView(const StringView& other)
202     : m_characters(other.m_characters)
203     , m_length(other.m_length)
204 {
205     ASSERT(other.underlyingStringIsValid());
206
207     setUnderlyingString(other);
208 }
209
210 inline StringView& StringView::operator=(StringView&& other)
211 {
212     ASSERT(other.underlyingStringIsValid());
213
214     m_characters = other.m_characters;
215     m_length = other.m_length;
216
217     other.m_characters = nullptr;
218     other.m_length = 0;
219
220     setUnderlyingString(other);
221     other.setUnderlyingString(nullptr);
222
223     return *this;
224 }
225
226 inline StringView& StringView::operator=(const StringView& other)
227 {
228     ASSERT(other.underlyingStringIsValid());
229
230     m_characters = other.m_characters;
231     m_length = other.m_length;
232
233     setUnderlyingString(other);
234
235     return *this;
236 }
237
238 inline void StringView::initialize(const LChar* characters, unsigned length)
239 {
240     // FIXME: We need a better solution here, because there is no guarantee that
241     // the length here won't be too long. Maybe at least a RELEASE_ASSERT?
242     ASSERT(!(length & is16BitStringFlag));
243     m_characters = characters;
244     m_length = length;
245 }
246
247 inline void StringView::initialize(const UChar* characters, unsigned length)
248 {
249     // FIXME: We need a better solution here, because there is no guarantee that
250     // the length here won't be too long. Maybe at least a RELEASE_ASSERT?
251     ASSERT(!(length & is16BitStringFlag));
252     m_characters = characters;
253     m_length = is16BitStringFlag | length;
254 }
255
256 inline StringView::StringView(const LChar* characters, unsigned length)
257 {
258     initialize(characters, length);
259 }
260
261 inline StringView::StringView(const UChar* characters, unsigned length)
262 {
263     initialize(characters, length);
264 }
265
266 inline StringView::StringView(const StringImpl& string)
267 {
268     setUnderlyingString(&string);
269     if (string.is8Bit())
270         initialize(string.characters8(), string.length());
271     else
272         initialize(string.characters16(), string.length());
273 }
274
275 inline StringView::StringView(const StringImpl* string)
276 {
277     if (!string)
278         return;
279
280     setUnderlyingString(string);
281     if (string->is8Bit())
282         initialize(string->characters8(), string->length());
283     else
284         initialize(string->characters16(), string->length());
285 }
286
287 inline StringView::StringView(const String& string)
288 {
289     setUnderlyingString(string.impl());
290     if (!string.impl()) {
291         m_characters = nullptr;
292         m_length = 0;
293         return;
294     }
295     if (string.is8Bit()) {
296         initialize(string.characters8(), string.length());
297         return;
298     }
299     initialize(string.characters16(), string.length());
300 }
301
302 inline StringView StringView::empty()
303 {
304     return StringView(reinterpret_cast<const LChar*>(""), 0);
305 }
306
307 inline const LChar* StringView::characters8() const
308 {
309     ASSERT(is8Bit());
310     ASSERT(underlyingStringIsValid());
311     return static_cast<const LChar*>(m_characters);
312 }
313
314 inline const UChar* StringView::characters16() const
315 {
316     ASSERT(!is8Bit());
317     ASSERT(underlyingStringIsValid());
318     return static_cast<const UChar*>(m_characters);
319 }
320
321 class StringView::UpconvertedCharacters {
322 public:
323     explicit UpconvertedCharacters(const StringView&);
324     operator const UChar*() const { return m_characters; }
325     const UChar* get() const { return m_characters; }
326 private:
327     Vector<UChar, 32> m_upconvertedCharacters;
328     const UChar* m_characters;
329 };
330
331 inline StringView::UpconvertedCharacters StringView::upconvertedCharacters() const
332 {
333     return UpconvertedCharacters(*this);
334 }
335
336 inline bool StringView::isNull() const
337 {
338     return !m_characters;
339 }
340
341 inline bool StringView::isEmpty() const
342 {
343     return !length();
344 }
345
346 inline unsigned StringView::length() const
347 {
348     return m_length & ~is16BitStringFlag;
349 }
350
351 inline StringView::operator bool() const
352 {
353     return !isNull();
354 }
355
356 inline bool StringView::is8Bit() const
357 {
358     return !(m_length & is16BitStringFlag);
359 }
360
361 inline StringView StringView::substring(unsigned start, unsigned length) const
362 {
363     if (start >= this->length())
364         return empty();
365     unsigned maxLength = this->length() - start;
366
367     if (length >= maxLength) {
368         if (!start)
369             return *this;
370         length = maxLength;
371     }
372
373     if (is8Bit()) {
374         StringView result(characters8() + start, length);
375         result.setUnderlyingString(*this);
376         return result;
377     }
378     StringView result(characters16() + start, length);
379     result.setUnderlyingString(*this);
380     return result;
381 }
382
383 inline UChar StringView::operator[](unsigned index) const
384 {
385     ASSERT(index < length());
386     if (is8Bit())
387         return characters8()[index];
388     return characters16()[index];
389 }
390
391 inline bool StringView::contains(UChar character) const
392 {
393     return find(character) != notFound;
394 }
395
396 inline void StringView::getCharactersWithUpconvert(LChar* destination) const
397 {
398     ASSERT(is8Bit());
399     memcpy(destination, characters8(), length());
400 }
401
402 inline void StringView::getCharactersWithUpconvert(UChar* destination) const
403 {
404     if (is8Bit()) {
405         const LChar* characters8 = this->characters8();
406         unsigned length = this->length();
407         for (unsigned i = 0; i < length; ++i)
408             destination[i] = characters8[i];
409         return;
410     }
411     memcpy(destination, characters16(), length() * sizeof(UChar));
412 }
413
414 inline StringView::UpconvertedCharacters::UpconvertedCharacters(const StringView& string)
415 {
416     if (!string.is8Bit()) {
417         m_characters = string.characters16();
418         return;
419     }
420     const LChar* characters8 = string.characters8();
421     unsigned length = string.length();
422     m_upconvertedCharacters.reserveInitialCapacity(length);
423     for (unsigned i = 0; i < length; ++i)
424         m_upconvertedCharacters.uncheckedAppend(characters8[i]);
425     m_characters = m_upconvertedCharacters.data();
426 }
427
428 inline String StringView::toString() const
429 {
430     if (is8Bit())
431         return String(characters8(), length());
432     return String(characters16(), length());
433 }
434
435 inline float StringView::toFloat(bool& isValid) const
436 {
437     if (is8Bit())
438         return charactersToFloat(characters8(), length(), &isValid);
439     return charactersToFloat(characters16(), length(), &isValid);
440 }
441
442 inline int StringView::toInt(bool& isValid) const
443 {
444     if (is8Bit())
445         return charactersToInt(characters8(), length(), &isValid);
446     return charactersToInt(characters16(), length(), &isValid);
447 }
448
449 inline String StringView::toStringWithoutCopying() const
450 {
451     if (is8Bit())
452         return StringImpl::createWithoutCopying(characters8(), length());
453     return StringImpl::createWithoutCopying(characters16(), length());
454 }
455
456 inline size_t StringView::find(UChar character, unsigned start) const
457 {
458     if (is8Bit())
459         return WTF::find(characters8(), length(), character, start);
460     return WTF::find(characters16(), length(), character, start);
461 }
462
463 #if !CHECK_STRINGVIEW_LIFETIME
464 inline void StringView::invalidate(const StringImpl&)
465 {
466 }
467 #endif
468
469 template<typename StringType> class StringTypeAdapter;
470
471 template<> class StringTypeAdapter<StringView> {
472 public:
473     StringTypeAdapter<StringView>(StringView string)
474         : m_string(string)
475     {
476     }
477
478     unsigned length() { return m_string.length(); }
479     bool is8Bit() { return m_string.is8Bit(); }
480     void writeTo(LChar* destination) { m_string.getCharactersWithUpconvert(destination); }
481     void writeTo(UChar* destination) { m_string.getCharactersWithUpconvert(destination); }
482
483 private:
484     StringView m_string;
485 };
486
487 template<typename CharacterType, size_t inlineCapacity> void append(Vector<CharacterType, inlineCapacity>& buffer, StringView string)
488 {
489     unsigned oldSize = buffer.size();
490     buffer.grow(oldSize + string.length());
491     string.getCharactersWithUpconvert(buffer.data() + oldSize);
492 }
493
494 inline bool equal(StringView a, StringView b)
495 {
496     return equalCommon(a, b);
497 }
498
499 inline bool equal(StringView a, const LChar* b)
500 {
501     if (!b)
502         return !a.isEmpty();
503     if (a.isEmpty())
504         return !b;
505     unsigned aLength = a.length();
506     if (a.is8Bit())
507         return equal(a.characters8(), b, aLength);
508     return equal(a.characters16(), b, aLength);
509 }
510
511 inline bool equal(StringView a, const char* b) 
512 {
513     return equal(a, reinterpret_cast<const LChar*>(b)); 
514 }
515
516 inline bool equalIgnoringASCIICase(StringView a, StringView b)
517 {
518     return equalIgnoringASCIICaseCommon(a, b);
519 }
520
521 class StringView::CodePoints {
522 public:
523     explicit CodePoints(const StringView&);
524
525     class Iterator;
526     Iterator begin() const;
527     Iterator end() const;
528
529 private:
530     StringView m_stringView;
531 };
532
533 class StringView::CodeUnits {
534 public:
535     explicit CodeUnits(const StringView&);
536
537     class Iterator;
538     Iterator begin() const;
539     Iterator end() const;
540
541 private:
542     StringView m_stringView;
543 };
544
545 class StringView::CodePoints::Iterator {
546 public:
547     Iterator(const StringView&, unsigned index);
548
549     UChar32 operator*() const;
550     Iterator& operator++();
551
552     bool operator==(const Iterator&) const;
553     bool operator!=(const Iterator&) const;
554
555 private:
556     const StringView& m_stringView;
557     mutable unsigned m_index;
558 #if !ASSERT_DISABLED
559     mutable bool m_alreadyIncremented { false };
560 #endif
561 };
562
563 class StringView::CodeUnits::Iterator {
564 public:
565     Iterator(const StringView&, unsigned index);
566
567     UChar operator*() const;
568     Iterator& operator++();
569
570     bool operator==(const Iterator&) const;
571     bool operator!=(const Iterator&) const;
572
573 private:
574     const StringView& m_stringView;
575     unsigned m_index;
576 };
577
578 inline auto StringView::codePoints() const -> CodePoints
579 {
580     return CodePoints(*this);
581 }
582
583 inline auto StringView::codeUnits() const -> CodeUnits
584 {
585     return CodeUnits(*this);
586 }
587
588 inline StringView::CodePoints::CodePoints(const StringView& stringView)
589     : m_stringView(stringView)
590 {
591 }
592
593 inline StringView::CodePoints::Iterator::Iterator(const StringView& stringView, unsigned index)
594     : m_stringView(stringView)
595     , m_index(index)
596 {
597 }
598
599 inline auto StringView::CodePoints::Iterator::operator++() -> Iterator&
600 {
601 #if !ASSERT_DISABLED
602     ASSERT(m_alreadyIncremented);
603     m_alreadyIncremented = false;
604 #endif
605     return *this;
606 }
607
608 inline UChar32 StringView::CodePoints::Iterator::operator*() const
609 {
610 #if !ASSERT_DISABLED
611     ASSERT(!m_alreadyIncremented);
612     m_alreadyIncremented = true;
613 #endif
614
615     if (m_stringView.is8Bit())
616         return m_stringView.characters8()[m_index++];
617
618     UChar32 codePoint;
619     U16_NEXT(m_stringView.characters16(), m_index, m_stringView.length(), codePoint);
620     return codePoint;
621 }
622
623 inline bool StringView::CodePoints::Iterator::operator==(const Iterator& other) const
624 {
625     ASSERT(&m_stringView == &other.m_stringView);
626     ASSERT(!m_alreadyIncremented);
627     return m_index == other.m_index;
628 }
629
630 inline bool StringView::CodePoints::Iterator::operator!=(const Iterator& other) const
631 {
632     return !(*this == other);
633 }
634
635 inline auto StringView::CodePoints::begin() const -> Iterator
636 {
637     return Iterator(m_stringView, 0);
638 }
639
640 inline auto StringView::CodePoints::end() const -> Iterator
641 {
642     return Iterator(m_stringView, m_stringView.length());
643 }
644
645 inline StringView::CodeUnits::CodeUnits(const StringView& stringView)
646     : m_stringView(stringView)
647 {
648 }
649
650 inline StringView::CodeUnits::Iterator::Iterator(const StringView& stringView, unsigned index)
651     : m_stringView(stringView)
652     , m_index(index)
653 {
654 }
655
656 inline auto StringView::CodeUnits::Iterator::operator++() -> Iterator&
657 {
658     ++m_index;
659     return *this;
660 }
661
662 inline UChar StringView::CodeUnits::Iterator::operator*() const
663 {
664     return m_stringView[m_index];
665 }
666
667 inline bool StringView::CodeUnits::Iterator::operator==(const Iterator& other) const
668 {
669     ASSERT(&m_stringView == &other.m_stringView);
670     return m_index == other.m_index;
671 }
672
673 inline bool StringView::CodeUnits::Iterator::operator!=(const Iterator& other) const
674 {
675     return !(*this == other);
676 }
677
678 inline auto StringView::CodeUnits::begin() const -> Iterator
679 {
680     return Iterator(m_stringView, 0);
681 }
682
683 inline auto StringView::CodeUnits::end() const -> Iterator
684 {
685     return Iterator(m_stringView, m_stringView.length());
686 }
687
688 } // namespace WTF
689
690 using WTF::append;
691 using WTF::equal;
692 using WTF::StringView;
693
694 #endif // StringView_h