1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef builtin_intl_StringAsciiChars_h 8 #define builtin_intl_StringAsciiChars_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Attributes.h" 12 #include "mozilla/Maybe.h" 13 #include "mozilla/Span.h" 14 #include "mozilla/TextUtils.h" 15 16 #include <stddef.h> 17 18 #include "js/GCAPI.h" 19 #include "js/TypeDecls.h" 20 #include "js/Vector.h" 21 22 #include "vm/StringType.h" 23 24 namespace js::intl { 25 26 /** 27 * String view of an ASCII-only string. 28 * 29 * This holds a reference to a JSLinearString and can produce a string view 30 * into that string. If the string is represented by Latin1 characters, the 31 * span is returned directly. If the string is represented by UTF-16 32 * characters, it copies the char16_t characters into a char array, and then 33 * returns a span based on the copy. 34 * 35 * This allows us to avoid copying for the common use case that the ASCII 36 * characters are represented in Latin1. 37 */ 38 class MOZ_STACK_CLASS StringAsciiChars final { 39 // When copying string characters, use this many bytes of inline storage. 40 static const size_t InlineCapacity = 24; 41 42 JS::AutoCheckCannotGC nogc_; 43 44 JSLinearString* str_; 45 46 mozilla::Maybe<Vector<Latin1Char, InlineCapacity>> ownChars_; 47 48 public: StringAsciiChars(JSLinearString * str)49 explicit StringAsciiChars(JSLinearString* str) : str_(str) { 50 MOZ_ASSERT(StringIsAscii(str)); 51 } 52 53 operator mozilla::Span<const char>() const { 54 if (str_->hasLatin1Chars()) { 55 return mozilla::AsChars(str_->latin1Range(nogc_)); 56 } 57 return mozilla::AsChars(mozilla::Span<const Latin1Char>(*ownChars_)); 58 } 59 init(JSContext * cx)60 [[nodiscard]] bool init(JSContext* cx) { 61 if (str_->hasLatin1Chars()) { 62 return true; 63 } 64 65 ownChars_.emplace(cx); 66 if (!ownChars_->resize(str_->length())) { 67 return false; 68 } 69 70 js::CopyChars(ownChars_->begin(), *str_); 71 72 return true; 73 } 74 }; 75 76 } // namespace js::intl 77 78 #endif // builtin_intl_StringAsciiChars_h 79