Bug 1886451: Add missing ifdef Nightly guards. r=dminor
[gecko.git] / js / public / StableStringChars.h
blob5c50df18cb530008d469e73734185df6c8383a9d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * Safely access the contents of a string even as GC can cause the string's
8 * contents to move around in memory.
9 */
11 #ifndef js_StableStringChars_h
12 #define js_StableStringChars_h
14 #include "mozilla/Assertions.h" // MOZ_ASSERT
15 #include "mozilla/Attributes.h" // MOZ_INIT_OUTSIDE_CTOR, MOZ_STACK_CLASS
16 #include "mozilla/Maybe.h" // mozilla::Maybe
17 #include "mozilla/Range.h" // mozilla::Range
19 #include <stddef.h> // size_t
20 #include <stdint.h> // uint8_t
22 #include "jstypes.h" // JS_PUBLIC_API
24 #include "js/AllocPolicy.h"
25 #include "js/RootingAPI.h" // JS::Handle, JS::Rooted
26 #include "js/String.h" // JS::GetStringLength
27 #include "js/TypeDecls.h" // JSContext, JS::Latin1Char, JSString
28 #include "js/Vector.h" // js::Vector
30 class JSLinearString;
32 namespace JS {
34 /**
35 * This class provides safe access to a string's chars across a GC. When it
36 * has nursery-allocated out of lines chars, this class will have to make a
37 * copy, so it's best to avoid using this class unless you really need it. It's
38 * usually more efficient to use the latin1Chars/twoByteChars JSString methods
39 * and often the code can be rewritten so that only indexes instead of char
40 * pointers are used in parts of the code that can GC.
42 class MOZ_STACK_CLASS JS_PUBLIC_API AutoStableStringChars final {
44 * When copying string char, use this many bytes of inline storage. This is
45 * chosen to allow the inline string types to be copied without allocating.
46 * This is asserted in AutoStableStringChars::allocOwnChars.
48 static const size_t InlineCapacity = 24;
50 /* Ensure the string is kept alive while we're using its chars. */
51 Rooted<JSString*> s_;
52 union MOZ_INIT_OUTSIDE_CTOR {
53 const char16_t* twoByteChars_;
54 const Latin1Char* latin1Chars_;
56 mozilla::Maybe<js::Vector<uint8_t, InlineCapacity>> ownChars_;
57 enum State { Uninitialized, Latin1, TwoByte };
58 State state_;
60 public:
61 explicit AutoStableStringChars(JSContext* cx)
62 : s_(cx), state_(Uninitialized) {}
64 [[nodiscard]] bool init(JSContext* cx, JSString* s);
66 /* Like init(), but Latin1 chars are inflated to TwoByte. */
67 [[nodiscard]] bool initTwoByte(JSContext* cx, JSString* s);
69 bool isLatin1() const { return state_ == Latin1; }
70 bool isTwoByte() const { return state_ == TwoByte; }
72 const Latin1Char* latin1Chars() const {
73 MOZ_ASSERT(state_ == Latin1);
74 return latin1Chars_;
76 const char16_t* twoByteChars() const {
77 MOZ_ASSERT(state_ == TwoByte);
78 return twoByteChars_;
81 mozilla::Range<const Latin1Char> latin1Range() const {
82 MOZ_ASSERT(state_ == Latin1);
83 return mozilla::Range<const Latin1Char>(latin1Chars_, length());
86 mozilla::Range<const char16_t> twoByteRange() const {
87 MOZ_ASSERT(state_ == TwoByte);
88 return mozilla::Range<const char16_t>(twoByteChars_, length());
91 /* If we own the chars, transfer ownership to the caller. */
92 bool maybeGiveOwnershipToCaller() {
93 MOZ_ASSERT(state_ != Uninitialized);
94 if (!ownChars_.isSome() || !ownChars_->extractRawBuffer()) {
95 return false;
97 state_ = Uninitialized;
98 ownChars_.reset();
99 return true;
102 size_t length() const { return GetStringLength(s_); }
104 private:
105 AutoStableStringChars(const AutoStableStringChars& other) = delete;
106 void operator=(const AutoStableStringChars& other) = delete;
108 template <typename T>
109 T* allocOwnChars(JSContext* cx, size_t count);
110 bool copyLatin1Chars(JSContext* cx, Handle<JSLinearString*> linearString);
111 bool copyTwoByteChars(JSContext* cx, Handle<JSLinearString*> linearString);
112 bool copyAndInflateLatin1Chars(JSContext*,
113 Handle<JSLinearString*> linearString);
116 } // namespace JS
118 #endif /* js_StableStringChars_h */