tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StableStringChars.h (4221B)


      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/. */
      5 
      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 */
     10 
     11 #ifndef js_StableStringChars_h
     12 #define js_StableStringChars_h
     13 
     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
     18 
     19 #include <stddef.h>  // size_t
     20 #include <stdint.h>  // uint8_t
     21 
     22 #include "jstypes.h"  // JS_PUBLIC_API
     23 
     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
     29 
     30 class JSLinearString;
     31 
     32 namespace JS {
     33 
     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.
     41 */
     42 class MOZ_STACK_CLASS JS_PUBLIC_API AutoStableStringChars final {
     43  /*
     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.
     47   */
     48  static const size_t InlineCapacity = 24;
     49 
     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_;
     55  };
     56  MOZ_INIT_OUTSIDE_CTOR uint32_t length_;
     57  mozilla::Maybe<js::Vector<uint8_t, InlineCapacity>> ownChars_;
     58  enum State { Uninitialized, Latin1, TwoByte };
     59  State state_;
     60 
     61  // Prevent the string that owns s's chars from being collected (by storing it
     62  // in s_) or deduplicated.
     63  void holdStableChars(JSLinearString* s);
     64 
     65 public:
     66  explicit AutoStableStringChars(JSContext* cx)
     67      : s_(cx), state_(Uninitialized) {}
     68 
     69  [[nodiscard]] bool init(JSContext* cx, JSString* s);
     70 
     71  /* Like init(), but Latin1 chars are inflated to TwoByte. */
     72  [[nodiscard]] bool initTwoByte(JSContext* cx, JSString* s);
     73 
     74  bool isLatin1() const { return state_ == Latin1; }
     75  bool isTwoByte() const { return state_ == TwoByte; }
     76 
     77  const Latin1Char* latin1Chars() const {
     78    MOZ_ASSERT(state_ == Latin1);
     79    return latin1Chars_;
     80  }
     81  const char16_t* twoByteChars() const {
     82    MOZ_ASSERT(state_ == TwoByte);
     83    return twoByteChars_;
     84  }
     85 
     86  mozilla::Range<const Latin1Char> latin1Range() const {
     87    MOZ_ASSERT(state_ == Latin1);
     88    return mozilla::Range<const Latin1Char>(latin1Chars_, length());
     89  }
     90 
     91  mozilla::Range<const char16_t> twoByteRange() const {
     92    MOZ_ASSERT(state_ == TwoByte);
     93    return mozilla::Range<const char16_t>(twoByteChars_, length());
     94  }
     95 
     96  /* If we own the chars, transfer ownership to the caller. */
     97  bool maybeGiveOwnershipToCaller() {
     98    MOZ_ASSERT(state_ != Uninitialized);
     99    if (!ownChars_.isSome() || !ownChars_->extractRawBuffer()) {
    100      return false;
    101    }
    102    state_ = Uninitialized;
    103    ownChars_.reset();
    104    return true;
    105  }
    106 
    107  size_t length() const {
    108    MOZ_ASSERT(state_ != Uninitialized);
    109    return length_;
    110  }
    111 
    112 private:
    113  AutoStableStringChars(const AutoStableStringChars& other) = delete;
    114  void operator=(const AutoStableStringChars& other) = delete;
    115 
    116  template <typename T>
    117  T* allocOwnChars(JSContext* cx, size_t count);
    118  bool copyLatin1Chars(JSContext* cx, JSLinearString* linearString);
    119  bool copyTwoByteChars(JSContext* cx, JSLinearString* linearString);
    120  bool copyAndInflateLatin1Chars(JSContext*, JSLinearString* linearString);
    121 };
    122 
    123 }  // namespace JS
    124 
    125 #endif /* js_StableStringChars_h */