1 /*
2  * (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc.
4  * All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_STRING_H_
24 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_STRING_H_
25 
26 // This file would be called String.h, but that conflicts with <string.h>
27 // on systems without case-sensitive file systems.
28 
29 #include <iosfwd>
30 #include "base/containers/span.h"
31 #include "build/build_config.h"
32 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
33 #include "third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h"
34 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
35 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
36 #include "third_party/blink/renderer/platform/wtf/wtf_export.h"
37 #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
38 
39 #ifdef __OBJC__
40 #include <objc/objc.h>
41 #endif
42 
43 namespace WTF {
44 
45 struct StringHash;
46 
47 enum UTF8ConversionMode {
48   kLenientUTF8Conversion,
49   kStrictUTF8Conversion,
50   kStrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD
51 };
52 
53 #define DISPATCH_CASE_OP(caseSensitivity, op, args)     \
54   ((caseSensitivity == kTextCaseSensitive)              \
55        ? op args                                        \
56        : (caseSensitivity == kTextCaseASCIIInsensitive) \
57              ? op##IgnoringASCIICase args               \
58              : op##IgnoringCase args)
59 
60 // You can find documentation about this class in README.md in this directory.
61 class WTF_EXPORT String {
62   USING_FAST_MALLOC(String);
63 
64  public:
65   // Construct a null string, distinguishable from an empty string.
String()66   String() {}
67 
68   // Construct a string with UTF-16 data.
69   String(const UChar* characters, unsigned length);
70 
71   // Construct a string by copying the contents of a vector.
72   // This method will never create a null string. Vectors with size() == 0
73   // will return the empty string.
74   // NOTE: This is different from String(vector.data(), vector.size())
75   // which will sometimes return a null string when vector.data() is null
76   // which can only occur for vectors without inline capacity.
77   // See: https://bugs.webkit.org/show_bug.cgi?id=109792
78   template <wtf_size_t inlineCapacity>
79   explicit String(const Vector<UChar, inlineCapacity>&);
80 
81   // Construct a string with UTF-16 data, from a null-terminated source.
82   String(const UChar*);
String(const char16_t * chars)83   String(const char16_t* chars)
84       : String(reinterpret_cast<const UChar*>(chars)) {}
85 
86   // Construct a string with latin1 data.
87   String(const LChar* characters, unsigned length);
88   String(const char* characters, unsigned length);
89 
90 #if defined(ARCH_CPU_64_BITS)
91   // Only define a size_t constructor if size_t is 64 bit otherwise
92   // we'd have a duplicate define.
93   String(const char* characters, size_t length);
94 #endif  // defined(ARCH_CPU_64_BITS)
95 
96   // Construct a string with latin1 data, from a null-terminated source.
String(const LChar * characters)97   String(const LChar* characters)
98       : String(reinterpret_cast<const char*>(characters)) {}
String(const char * characters)99   String(const char* characters)
100       : String(characters, characters ? strlen(characters) : 0) {}
101 
102   // Construct a string referencing an existing StringImpl.
String(StringImpl * impl)103   String(StringImpl* impl) : impl_(impl) {}
String(scoped_refptr<StringImpl> impl)104   String(scoped_refptr<StringImpl> impl) : impl_(std::move(impl)) {}
105 
swap(String & o)106   void swap(String& o) { impl_.swap(o.impl_); }
107 
108   template <typename CharType>
Adopt(StringBuffer<CharType> & buffer)109   static String Adopt(StringBuffer<CharType>& buffer) {
110     if (!buffer.length())
111       return StringImpl::empty_;
112     return String(buffer.Release());
113   }
114 
115   explicit operator bool() const { return !IsNull(); }
IsNull()116   bool IsNull() const { return !impl_; }
IsEmpty()117   bool IsEmpty() const { return !impl_ || !impl_->length(); }
118 
Impl()119   StringImpl* Impl() const { return impl_.get(); }
ReleaseImpl()120   scoped_refptr<StringImpl> ReleaseImpl() { return std::move(impl_); }
121 
length()122   unsigned length() const {
123     if (!impl_)
124       return 0;
125     return impl_->length();
126   }
127 
128   // Prefer Span8() and Span16() to Characters8() and Characters16().
Span8()129   base::span<const LChar> Span8() const {
130     if (!impl_)
131       return {};
132     DCHECK(impl_->Is8Bit());
133     return impl_->Span8();
134   }
135 
Span16()136   base::span<const UChar> Span16() const {
137     if (!impl_)
138       return {};
139     DCHECK(!impl_->Is8Bit());
140     return impl_->Span16();
141   }
142 
Characters8()143   const LChar* Characters8() const {
144     if (!impl_)
145       return nullptr;
146     DCHECK(impl_->Is8Bit());
147     return impl_->Characters8();
148   }
149 
Characters16()150   const UChar* Characters16() const {
151     if (!impl_)
152       return nullptr;
153     DCHECK(!impl_->Is8Bit());
154     return impl_->Characters16();
155   }
156 
Bytes()157   ALWAYS_INLINE const void* Bytes() const {
158     if (!impl_)
159       return nullptr;
160     return impl_->Bytes();
161   }
162 
163   // Return characters8() or characters16() depending on CharacterType.
164   template <typename CharacterType>
165   inline const CharacterType* GetCharacters() const;
166 
Is8Bit()167   bool Is8Bit() const { return impl_->Is8Bit(); }
168 
169   std::string Ascii() const WARN_UNUSED_RESULT;
170   std::string Latin1() const WARN_UNUSED_RESULT;
171   std::string Utf8(UTF8ConversionMode = kLenientUTF8Conversion) const
172       WARN_UNUSED_RESULT;
173 
174   UChar operator[](unsigned index) const {
175     if (!impl_ || index >= impl_->length())
176       return 0;
177     return (*impl_)[index];
178   }
179 
180   template <typename IntegerType>
Number(IntegerType number)181   static String Number(IntegerType number) {
182     IntegerToStringConverter<IntegerType> converter(number);
183     return StringImpl::Create(converter.Characters8(), converter.length());
184   }
185 
186   static String Number(float) WARN_UNUSED_RESULT;
187 
188   static String Number(double, unsigned precision = 6) WARN_UNUSED_RESULT;
189 
190   // Number to String conversion following the ECMAScript definition.
191   static String NumberToStringECMAScript(double) WARN_UNUSED_RESULT;
192   static String NumberToStringFixedWidth(double, unsigned decimal_places)
193       WARN_UNUSED_RESULT;
194 
195   // Find characters.
196   wtf_size_t find(UChar c, unsigned start = 0) const {
197     return impl_ ? impl_->Find(c, start) : kNotFound;
198   }
199   wtf_size_t find(LChar c, unsigned start = 0) const {
200     return impl_ ? impl_->Find(c, start) : kNotFound;
201   }
202   wtf_size_t find(char c, unsigned start = 0) const {
203     return find(static_cast<LChar>(c), start);
204   }
205   wtf_size_t Find(CharacterMatchFunctionPtr match_function,
206                   unsigned start = 0) const {
207     return impl_ ? impl_->Find(match_function, start) : kNotFound;
208   }
209 
210   // Find substrings.
211   wtf_size_t Find(
212       const StringView& value,
213       unsigned start = 0,
214       TextCaseSensitivity case_sensitivity = kTextCaseSensitive) const {
215     return impl_
216                ? DISPATCH_CASE_OP(case_sensitivity, impl_->Find, (value, start))
217                : kNotFound;
218   }
219 
220   // Unicode aware case insensitive string matching. Non-ASCII characters might
221   // match to ASCII characters. This function is rarely used to implement web
222   // platform features.
223   wtf_size_t FindIgnoringCase(const StringView& value,
224                               unsigned start = 0) const {
225     return impl_ ? impl_->FindIgnoringCase(value, start) : kNotFound;
226   }
227 
228   // ASCII case insensitive string matching.
229   wtf_size_t FindIgnoringASCIICase(const StringView& value,
230                                    unsigned start = 0) const {
231     return impl_ ? impl_->FindIgnoringASCIICase(value, start) : kNotFound;
232   }
233 
Contains(char c)234   bool Contains(char c) const { return find(c) != kNotFound; }
235   bool Contains(
236       const StringView& value,
237       TextCaseSensitivity case_sensitivity = kTextCaseSensitive) const {
238     return Find(value, 0, case_sensitivity) != kNotFound;
239   }
240 
241   // Find the last instance of a single character or string.
242   wtf_size_t ReverseFind(UChar c, unsigned start = UINT_MAX) const {
243     return impl_ ? impl_->ReverseFind(c, start) : kNotFound;
244   }
245   wtf_size_t ReverseFind(const StringView& value,
246                          unsigned start = UINT_MAX) const {
247     return impl_ ? impl_->ReverseFind(value, start) : kNotFound;
248   }
249 
250   UChar32 CharacterStartingAt(unsigned) const;
251 
252   bool StartsWith(
253       const StringView& prefix,
254       TextCaseSensitivity case_sensitivity = kTextCaseSensitive) const {
255     return impl_
256                ? DISPATCH_CASE_OP(case_sensitivity, impl_->StartsWith, (prefix))
257                : prefix.IsEmpty();
258   }
StartsWithIgnoringCase(const StringView & prefix)259   bool StartsWithIgnoringCase(const StringView& prefix) const {
260     return impl_ ? impl_->StartsWithIgnoringCase(prefix) : prefix.IsEmpty();
261   }
StartsWithIgnoringASCIICase(const StringView & prefix)262   bool StartsWithIgnoringASCIICase(const StringView& prefix) const {
263     return impl_ ? impl_->StartsWithIgnoringASCIICase(prefix)
264                  : prefix.IsEmpty();
265   }
StartsWith(UChar character)266   bool StartsWith(UChar character) const {
267     return impl_ ? impl_->StartsWith(character) : false;
268   }
269 
270   bool EndsWith(
271       const StringView& suffix,
272       TextCaseSensitivity case_sensitivity = kTextCaseSensitive) const {
273     return impl_ ? DISPATCH_CASE_OP(case_sensitivity, impl_->EndsWith, (suffix))
274                  : suffix.IsEmpty();
275   }
EndsWithIgnoringCase(const StringView & prefix)276   bool EndsWithIgnoringCase(const StringView& prefix) const {
277     return impl_ ? impl_->EndsWithIgnoringCase(prefix) : prefix.IsEmpty();
278   }
EndsWithIgnoringASCIICase(const StringView & prefix)279   bool EndsWithIgnoringASCIICase(const StringView& prefix) const {
280     return impl_ ? impl_->EndsWithIgnoringASCIICase(prefix) : prefix.IsEmpty();
281   }
EndsWith(UChar character)282   bool EndsWith(UChar character) const {
283     return impl_ ? impl_->EndsWith(character) : false;
284   }
285 
286   // TODO(esprehn): replace strangely both modifies this String *and* return a
287   // value. It should only do one of those.
Replace(UChar pattern,UChar replacement)288   String& Replace(UChar pattern, UChar replacement) {
289     if (impl_)
290       impl_ = impl_->Replace(pattern, replacement);
291     return *this;
292   }
Replace(UChar pattern,const StringView & replacement)293   String& Replace(UChar pattern, const StringView& replacement) {
294     if (impl_)
295       impl_ = impl_->Replace(pattern, replacement);
296     return *this;
297   }
Replace(const StringView & pattern,const StringView & replacement)298   String& Replace(const StringView& pattern, const StringView& replacement) {
299     if (impl_)
300       impl_ = impl_->Replace(pattern, replacement);
301     return *this;
302   }
replace(unsigned index,unsigned length_to_replace,const StringView & replacement)303   String& replace(unsigned index,
304                   unsigned length_to_replace,
305                   const StringView& replacement) {
306     if (impl_)
307       impl_ = impl_->Replace(index, length_to_replace, replacement);
308     return *this;
309   }
310 
Fill(UChar c)311   void Fill(UChar c) {
312     if (impl_)
313       impl_ = impl_->Fill(c);
314   }
315 
316   void Ensure16Bit();
317 
318   void Truncate(unsigned length);
319   void Remove(unsigned start, unsigned length = 1);
320 
321   String Substring(unsigned pos,
322                    unsigned len = UINT_MAX) const WARN_UNUSED_RESULT;
Left(unsigned len)323   String Left(unsigned len) const WARN_UNUSED_RESULT {
324     return Substring(0, len);
325   }
Right(unsigned len)326   String Right(unsigned len) const WARN_UNUSED_RESULT {
327     return Substring(length() - len, len);
328   }
329 
330   // Returns a lowercase version of the string. This function might convert
331   // non-ASCII characters to ASCII characters. For example, DeprecatedLower()
332   // for U+212A is 'k'.
333   // This function is rarely used to implement web platform features. See
334   // crbug.com/627682.
335   // This function is deprecated. We should use LowerASCII() or CaseMap.
336   String DeprecatedLower() const WARN_UNUSED_RESULT;
337 
338   // Returns a lowercase version of the string.
339   // This function converts ASCII characters only.
340   String LowerASCII() const WARN_UNUSED_RESULT;
341   // Returns a uppercase version of the string.
342   // This function converts ASCII characters only.
343   String UpperASCII() const WARN_UNUSED_RESULT;
344 
345   String StripWhiteSpace() const WARN_UNUSED_RESULT;
346   String StripWhiteSpace(IsWhiteSpaceFunctionPtr) const WARN_UNUSED_RESULT;
347   String SimplifyWhiteSpace(StripBehavior = kStripExtraWhiteSpace) const
348       WARN_UNUSED_RESULT;
349   String SimplifyWhiteSpace(IsWhiteSpaceFunctionPtr,
350                             StripBehavior = kStripExtraWhiteSpace) const
351       WARN_UNUSED_RESULT;
352 
353   String RemoveCharacters(CharacterMatchFunctionPtr) const WARN_UNUSED_RESULT;
354   template <bool isSpecialCharacter(UChar)>
355   bool IsAllSpecialCharacters() const;
356 
357   // Return the string with case folded for case insensitive comparison.
358   String FoldCase() const WARN_UNUSED_RESULT;
359 
360   // Takes a printf format and args and prints into a String.
361   // This function supports Latin-1 characters only.
362   PRINTF_FORMAT(1, 2)
363   static String Format(const char* format, ...) WARN_UNUSED_RESULT;
364 
365   // Returns a version suitable for gtest and base/logging.*.  It prepends and
366   // appends double-quotes, and escapes characters other than ASCII printables.
367   String EncodeForDebugging() const WARN_UNUSED_RESULT;
368 
369   // Returns an uninitialized string. The characters needs to be written
370   // into the buffer returned in data before the returned string is used.
371   // Failure to do this will have unpredictable results.
CreateUninitialized(unsigned length,UChar * & data)372   static String CreateUninitialized(unsigned length,
373                                     UChar*& data) WARN_UNUSED_RESULT {
374     return StringImpl::CreateUninitialized(length, data);
375   }
CreateUninitialized(unsigned length,LChar * & data)376   static String CreateUninitialized(unsigned length,
377                                     LChar*& data) WARN_UNUSED_RESULT {
378     return StringImpl::CreateUninitialized(length, data);
379   }
380 
381   void Split(const StringView& separator,
382              bool allow_empty_entries,
383              Vector<String>& result) const;
Split(const StringView & separator,Vector<String> & result)384   void Split(const StringView& separator, Vector<String>& result) const {
385     Split(separator, false, result);
386   }
387   void Split(UChar separator,
388              bool allow_empty_entries,
389              Vector<String>& result) const;
Split(UChar separator,Vector<String> & result)390   void Split(UChar separator, Vector<String>& result) const {
391     Split(separator, false, result);
392   }
393 
394   // Copy characters out of the string. See StringImpl.h for detailed docs.
CopyTo(UChar * buffer,unsigned start,unsigned max_length)395   unsigned CopyTo(UChar* buffer, unsigned start, unsigned max_length) const {
396     return impl_ ? impl_->CopyTo(buffer, start, max_length) : 0;
397   }
398   template <typename BufferType>
399   void AppendTo(BufferType&,
400                 unsigned start = 0,
401                 unsigned length = UINT_MAX) const;
402   template <typename BufferType>
403   void PrependTo(BufferType&,
404                  unsigned start = 0,
405                  unsigned length = UINT_MAX) const;
406 
407   // Convert the string into a number.
408 
409   // The following ToFooStrict functions accept:
410   //  - leading '+'
411   //  - leading Unicode whitespace
412   //  - trailing Unicode whitespace
413   //  - no "-0" (ToUIntStrict and ToUInt64Strict)
414   //  - no out-of-range numbers which the resultant type can't represent
415   //
416   // If the input string is not acceptable, 0 is returned and |*ok| becomes
417   // |false|.
418   //
419   // We can use these functions to implement a Web Platform feature only if the
420   // input string is already valid according to the specification of the
421   // feature.
422   int ToIntStrict(bool* ok = nullptr) const;
423   unsigned ToUIntStrict(bool* ok = nullptr) const;
424   unsigned HexToUIntStrict(bool* ok) const;
425   uint64_t HexToUInt64Strict(bool* ok) const;
426   int64_t ToInt64Strict(bool* ok = nullptr) const;
427   uint64_t ToUInt64Strict(bool* ok = nullptr) const;
428 
429   // The following ToFoo functions accept:
430   //  - leading '+'
431   //  - leading Unicode whitespace
432   //  - trailing garbage
433   //  - no "-0" (ToUInt and ToUInt64)
434   //  - no out-of-range numbers which the resultant type can't represent
435   //
436   // If the input string is not acceptable, 0 is returned and |*ok| becomes
437   // |false|.
438   //
439   // We can use these functions to implement a Web Platform feature only if the
440   // input string is already valid according to the specification of the
441   // feature.
442   int ToInt(bool* ok = nullptr) const;
443   unsigned ToUInt(bool* ok = nullptr) const;
444 
445   // These functions accepts:
446   //  - leading '+'
447   //  - numbers without leading zeros such as ".5"
448   //  - numbers ending with "." such as "3."
449   //  - scientific notation
450   //  - leading whitespace (IsASCIISpace, not IsHTMLSpace)
451   //  - no trailing whitespace
452   //  - no trailing garbage
453   //  - no numbers such as "NaN" "Infinity"
454   //
455   // A huge absolute number which a double/float can't represent is accepted,
456   // and +Infinity or -Infinity is returned.
457   //
458   // A small absolute numbers which a double/float can't represent is accepted,
459   // and 0 is returned
460   //
461   // If the input string is not acceptable, 0.0 is returned and |*ok| becomes
462   // |false|.
463   //
464   // We can use these functions to implement a Web Platform feature only if the
465   // input string is already valid according to the specification of the
466   // feature.
467   //
468   // FIXME: Like the strict functions above, these give false for "ok" when
469   // there is trailing garbage.  Like the non-strict functions above, these
470   // return the value when there is trailing garbage.  It would be better if
471   // these were more consistent with the above functions instead.
472   double ToDouble(bool* ok = nullptr) const;
473   float ToFloat(bool* ok = nullptr) const;
474 
475   String IsolatedCopy() const WARN_UNUSED_RESULT;
476   bool IsSafeToSendToAnotherThread() const;
477 
478 #ifdef __OBJC__
479   String(NSString*);
480 
481   // This conversion maps null string to "", which loses the meaning of null
482   // string, but we need this mapping because AppKit crashes when passed nil
483   // NSStrings.
484   operator NSString*() const {
485     if (!impl_)
486       return @"";
487     return *impl_;
488   }
489 #endif
490 
491   static String Make8BitFrom16BitSource(const UChar*,
492                                         wtf_size_t) WARN_UNUSED_RESULT;
493   template <wtf_size_t inlineCapacity>
494   static WARN_UNUSED_RESULT String
Make8BitFrom16BitSource(const Vector<UChar,inlineCapacity> & buffer)495   Make8BitFrom16BitSource(const Vector<UChar, inlineCapacity>& buffer) {
496     return Make8BitFrom16BitSource(buffer.data(), buffer.size());
497   }
498 
499   static String Make16BitFrom8BitSource(const LChar*,
500                                         wtf_size_t) WARN_UNUSED_RESULT;
501 
502   // String::fromUTF8 will return a null string if
503   // the input data contains invalid UTF-8 sequences.
504   // Does not strip BOMs.
505   static String FromUTF8(const LChar*, size_t) WARN_UNUSED_RESULT;
506   static String FromUTF8(const LChar*) WARN_UNUSED_RESULT;
FromUTF8(const char * s,size_t length)507   static String FromUTF8(const char* s, size_t length) WARN_UNUSED_RESULT {
508     return FromUTF8(reinterpret_cast<const LChar*>(s), length);
509   }
FromUTF8(const char * s)510   static String FromUTF8(const char* s) WARN_UNUSED_RESULT {
511     return FromUTF8(reinterpret_cast<const LChar*>(s));
512   }
513   static String FromUTF8(base::StringPiece) WARN_UNUSED_RESULT;
514 
515   // Tries to convert the passed in string to UTF-8, but will fall back to
516   // Latin-1 if the string is not valid UTF-8.
517   static String FromUTF8WithLatin1Fallback(const LChar*,
518                                            size_t) WARN_UNUSED_RESULT;
FromUTF8WithLatin1Fallback(const char * s,size_t length)519   static String FromUTF8WithLatin1Fallback(const char* s,
520                                            size_t length) WARN_UNUSED_RESULT {
521     return FromUTF8WithLatin1Fallback(reinterpret_cast<const LChar*>(s),
522                                       length);
523   }
524 
ContainsOnlyASCIIOrEmpty()525   bool ContainsOnlyASCIIOrEmpty() const {
526     return !impl_ || impl_->ContainsOnlyASCIIOrEmpty();
527   }
528   bool ContainsOnlyLatin1OrEmpty() const;
ContainsOnlyWhitespaceOrEmpty()529   bool ContainsOnlyWhitespaceOrEmpty() const {
530     return !impl_ || impl_->ContainsOnlyWhitespaceOrEmpty();
531   }
532 
CharactersSizeInBytes()533   size_t CharactersSizeInBytes() const {
534     return impl_ ? impl_->CharactersSizeInBytes() : 0;
535   }
536 
537 #ifndef NDEBUG
538   // For use in the debugger.
539   void Show() const;
540 #endif
541 
542  private:
543   friend struct HashTraits<String>;
544 
545   scoped_refptr<StringImpl> impl_;
546 };
547 
548 #undef DISPATCH_CASE_OP
549 
550 inline bool operator==(const String& a, const String& b) {
551   // We don't use equalStringView here since we want the isAtomic() fast path
552   // inside WTF::equal.
553   return Equal(a.Impl(), b.Impl());
554 }
555 inline bool operator==(const String& a, const char* b) {
556   return EqualStringView(a, b);
557 }
558 inline bool operator==(const char* a, const String& b) {
559   return b == a;
560 }
561 
562 inline bool operator!=(const String& a, const String& b) {
563   return !(a == b);
564 }
565 inline bool operator!=(const String& a, const char* b) {
566   return !(a == b);
567 }
568 inline bool operator!=(const char* a, const String& b) {
569   return !(a == b);
570 }
571 
572 inline bool EqualIgnoringNullity(const String& a, const String& b) {
573   return EqualIgnoringNullity(a.Impl(), b.Impl());
574 }
575 
576 template <wtf_size_t inlineCapacity>
577 inline bool EqualIgnoringNullity(const Vector<UChar, inlineCapacity>& a,
578                                  const String& b) {
579   return EqualIgnoringNullity(a, b.Impl());
580 }
581 
582 inline void swap(String& a, String& b) {
583   a.swap(b);
584 }
585 
586 // Definitions of string operations
587 
588 template <wtf_size_t inlineCapacity>
589 String::String(const Vector<UChar, inlineCapacity>& vector)
590     : impl_(vector.size() ? StringImpl::Create(vector.data(), vector.size())
591                           : StringImpl::empty_) {}
592 
593 template <>
594 inline const LChar* String::GetCharacters<LChar>() const {
595   DCHECK(Is8Bit());
596   return Characters8();
597 }
598 
599 template <>
600 inline const UChar* String::GetCharacters<UChar>() const {
601   DCHECK(!Is8Bit());
602   return Characters16();
603 }
604 
605 inline bool String::ContainsOnlyLatin1OrEmpty() const {
606   if (IsEmpty())
607     return true;
608 
609   if (Is8Bit())
610     return true;
611 
612   const UChar* characters = Characters16();
613   UChar ored = 0;
614   for (wtf_size_t i = 0; i < impl_->length(); ++i)
615     ored |= characters[i];
616   return !(ored & 0xFF00);
617 }
618 
619 #ifdef __OBJC__
620 // This is for situations in WebKit where the long standing behavior has been
621 // "nil if empty", so we try to maintain longstanding behavior for the sake of
622 // entrenched clients
623 inline NSString* NsStringNilIfEmpty(const String& str) {
624   return str.IsEmpty() ? nil : (NSString*)str;
625 }
626 #endif
627 
628 // Compare strings using code units, matching Javascript string ordering.  See
629 // https://infra.spec.whatwg.org/#code-unit-less-than.
630 WTF_EXPORT int CodeUnitCompare(const String&, const String&);
631 
632 inline bool CodeUnitCompareLessThan(const String& a, const String& b) {
633   return CodeUnitCompare(a.Impl(), b.Impl()) < 0;
634 }
635 
636 WTF_EXPORT int CodeUnitCompareIgnoringASCIICase(const String&, const char*);
637 
638 template <bool isSpecialCharacter(UChar)>
639 inline bool String::IsAllSpecialCharacters() const {
640   return StringView(*this).IsAllSpecialCharacters<isSpecialCharacter>();
641 }
642 
643 template <typename BufferType>
644 void String::AppendTo(BufferType& result,
645                       unsigned position,
646                       unsigned length) const {
647   if (!impl_)
648     return;
649   impl_->AppendTo(result, position, length);
650 }
651 
652 template <typename BufferType>
653 void String::PrependTo(BufferType& result,
654                        unsigned position,
655                        unsigned length) const {
656   if (!impl_)
657     return;
658   impl_->PrependTo(result, position, length);
659 }
660 
661 // StringHash is the default hash for String
662 template <typename T>
663 struct DefaultHash;
664 template <>
665 struct DefaultHash<String> {
666   typedef StringHash Hash;
667 };
668 
669 // Shared global empty string.
670 WTF_EXPORT extern const String& g_empty_string;
671 WTF_EXPORT extern const String& g_empty_string16_bit;
672 WTF_EXPORT extern const String& g_xmlns_with_colon;
673 
674 // Pretty printer for gtest and base/logging.*.  It prepends and appends
675 // double-quotes, and escapes characters other than ASCII printables.
676 WTF_EXPORT std::ostream& operator<<(std::ostream&, const String&);
677 
678 inline StringView::StringView(const String& string,
679                               unsigned offset,
680                               unsigned length)
681     : StringView(string.Impl(), offset, length) {}
682 inline StringView::StringView(const String& string, unsigned offset)
683     : StringView(string.Impl(), offset) {}
684 inline StringView::StringView(const String& string)
685     : StringView(string.Impl()) {}
686 
687 }  // namespace WTF
688 
689 WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(String)
690 
691 using WTF::kStrictUTF8Conversion;
692 using WTF::kStrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD;
693 using WTF::String;
694 using WTF::g_empty_string;
695 using WTF::g_empty_string16_bit;
696 using WTF::Equal;
697 using WTF::Find;
698 using WTF::IsSpaceOrNewline;
699 
700 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
701 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_WTF_STRING_H_
702