content/base/src/nsTextFragment.h

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 * A class which represents a fragment of text (eg inside a text
michael@0 7 * node); if only codepoints below 256 are used, the text is stored as
michael@0 8 * a char*; otherwise the text is stored as a char16_t*
michael@0 9 */
michael@0 10
michael@0 11 #ifndef nsTextFragment_h___
michael@0 12 #define nsTextFragment_h___
michael@0 13
michael@0 14 #include "mozilla/Attributes.h"
michael@0 15 #include "mozilla/MemoryReporting.h"
michael@0 16
michael@0 17 #include "nsString.h"
michael@0 18 #include "nsReadableUtils.h"
michael@0 19 #include "nsISupportsImpl.h"
michael@0 20
michael@0 21 class nsString;
michael@0 22 class nsCString;
michael@0 23
michael@0 24 // XXX should this normalize the code to keep a \u0000 at the end?
michael@0 25
michael@0 26 // XXX nsTextFragmentPool?
michael@0 27
michael@0 28 /**
michael@0 29 * A fragment of text. If mIs2b is 1 then the m2b pointer is valid
michael@0 30 * otherwise the m1b pointer is valid. If m1b is used then each byte
michael@0 31 * of data represents a single ucs2 character with the high byte being
michael@0 32 * zero.
michael@0 33 *
michael@0 34 * This class does not have a virtual destructor therefore it is not
michael@0 35 * meant to be subclassed.
michael@0 36 */
michael@0 37 class nsTextFragment MOZ_FINAL {
michael@0 38 public:
michael@0 39 static nsresult Init();
michael@0 40 static void Shutdown();
michael@0 41
michael@0 42 /**
michael@0 43 * Default constructor. Initialize the fragment to be empty.
michael@0 44 */
michael@0 45 nsTextFragment()
michael@0 46 : m1b(nullptr), mAllBits(0)
michael@0 47 {
michael@0 48 MOZ_COUNT_CTOR(nsTextFragment);
michael@0 49 NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!");
michael@0 50 }
michael@0 51
michael@0 52 ~nsTextFragment();
michael@0 53
michael@0 54 /**
michael@0 55 * Change the contents of this fragment to be a copy of the
michael@0 56 * the argument fragment, or to "" if unable to allocate enough memory.
michael@0 57 */
michael@0 58 nsTextFragment& operator=(const nsTextFragment& aOther);
michael@0 59
michael@0 60 /**
michael@0 61 * Return true if this fragment is represented by char16_t data
michael@0 62 */
michael@0 63 bool Is2b() const
michael@0 64 {
michael@0 65 return mState.mIs2b;
michael@0 66 }
michael@0 67
michael@0 68 /**
michael@0 69 * Return true if this fragment contains Bidi text
michael@0 70 * For performance reasons this flag is only set if explicitely requested (by
michael@0 71 * setting the aUpdateBidi argument on SetTo or Append to true).
michael@0 72 */
michael@0 73 bool IsBidi() const
michael@0 74 {
michael@0 75 return mState.mIsBidi;
michael@0 76 }
michael@0 77
michael@0 78 /**
michael@0 79 * Get a pointer to constant char16_t data.
michael@0 80 */
michael@0 81 const char16_t *Get2b() const
michael@0 82 {
michael@0 83 NS_ASSERTION(Is2b(), "not 2b text");
michael@0 84 return m2b;
michael@0 85 }
michael@0 86
michael@0 87 /**
michael@0 88 * Get a pointer to constant char data.
michael@0 89 */
michael@0 90 const char *Get1b() const
michael@0 91 {
michael@0 92 NS_ASSERTION(!Is2b(), "not 1b text");
michael@0 93 return (const char *)m1b;
michael@0 94 }
michael@0 95
michael@0 96 /**
michael@0 97 * Get the length of the fragment. The length is the number of logical
michael@0 98 * characters, not the number of bytes to store the characters.
michael@0 99 */
michael@0 100 uint32_t GetLength() const
michael@0 101 {
michael@0 102 return mState.mLength;
michael@0 103 }
michael@0 104
michael@0 105 bool CanGrowBy(size_t n) const
michael@0 106 {
michael@0 107 return n < (1 << 29) && mState.mLength + n < (1 << 29);
michael@0 108 }
michael@0 109
michael@0 110 /**
michael@0 111 * Change the contents of this fragment to be a copy of the given
michael@0 112 * buffer. If aUpdateBidi is true, contents of the fragment will be scanned,
michael@0 113 * and mState.mIsBidi will be turned on if it includes any Bidi characters.
michael@0 114 */
michael@0 115 bool SetTo(const char16_t* aBuffer, int32_t aLength, bool aUpdateBidi);
michael@0 116
michael@0 117 /**
michael@0 118 * Append aData to the end of this fragment. If aUpdateBidi is true, contents
michael@0 119 * of the fragment will be scanned, and mState.mIsBidi will be turned on if
michael@0 120 * it includes any Bidi characters.
michael@0 121 */
michael@0 122 bool Append(const char16_t* aBuffer, uint32_t aLength, bool aUpdateBidi);
michael@0 123
michael@0 124 /**
michael@0 125 * Append the contents of this string fragment to aString
michael@0 126 */
michael@0 127 void AppendTo(nsAString& aString) const {
michael@0 128 if (!AppendTo(aString, mozilla::fallible_t())) {
michael@0 129 NS_ABORT_OOM(GetLength());
michael@0 130 }
michael@0 131 }
michael@0 132
michael@0 133 /**
michael@0 134 * Append the contents of this string fragment to aString
michael@0 135 * @return false if an out of memory condition is detected, true otherwise
michael@0 136 */
michael@0 137 bool AppendTo(nsAString& aString,
michael@0 138 const mozilla::fallible_t&) const NS_WARN_UNUSED_RESULT {
michael@0 139 if (mState.mIs2b) {
michael@0 140 bool ok = aString.Append(m2b, mState.mLength, mozilla::fallible_t());
michael@0 141 if (!ok) {
michael@0 142 return false;
michael@0 143 }
michael@0 144
michael@0 145 return true;
michael@0 146 } else {
michael@0 147 return AppendASCIItoUTF16(Substring(m1b, mState.mLength), aString,
michael@0 148 mozilla::fallible_t());
michael@0 149 }
michael@0 150 }
michael@0 151
michael@0 152 /**
michael@0 153 * Append a substring of the contents of this string fragment to aString.
michael@0 154 * @param aOffset where to start the substring in this text fragment
michael@0 155 * @param aLength the length of the substring
michael@0 156 */
michael@0 157 void AppendTo(nsAString& aString, int32_t aOffset, int32_t aLength) const {
michael@0 158 if (!AppendTo(aString, aOffset, aLength, mozilla::fallible_t())) {
michael@0 159 NS_ABORT_OOM(aLength);
michael@0 160 }
michael@0 161 }
michael@0 162
michael@0 163 /**
michael@0 164 * Append a substring of the contents of this string fragment to aString.
michael@0 165 * @param aString the string in which to append
michael@0 166 * @param aOffset where to start the substring in this text fragment
michael@0 167 * @param aLength the length of the substring
michael@0 168 * @return false if an out of memory condition is detected, true otherwise
michael@0 169 */
michael@0 170 bool AppendTo(nsAString& aString, int32_t aOffset, int32_t aLength,
michael@0 171 const mozilla::fallible_t&) const NS_WARN_UNUSED_RESULT
michael@0 172 {
michael@0 173 if (mState.mIs2b) {
michael@0 174 bool ok = aString.Append(m2b + aOffset, aLength, mozilla::fallible_t());
michael@0 175 if (!ok) {
michael@0 176 return false;
michael@0 177 }
michael@0 178
michael@0 179 return true;
michael@0 180 } else {
michael@0 181 return AppendASCIItoUTF16(Substring(m1b + aOffset, aLength), aString,
michael@0 182 mozilla::fallible_t());
michael@0 183 }
michael@0 184 }
michael@0 185
michael@0 186 /**
michael@0 187 * Make a copy of the fragments contents starting at offset for
michael@0 188 * count characters. The offset and count will be adjusted to
michael@0 189 * lie within the fragments data. The fragments data is converted if
michael@0 190 * necessary.
michael@0 191 */
michael@0 192 void CopyTo(char16_t *aDest, int32_t aOffset, int32_t aCount);
michael@0 193
michael@0 194 /**
michael@0 195 * Return the character in the text-fragment at the given
michael@0 196 * index. This always returns a char16_t.
michael@0 197 */
michael@0 198 char16_t CharAt(int32_t aIndex) const
michael@0 199 {
michael@0 200 NS_ASSERTION(uint32_t(aIndex) < mState.mLength, "bad index");
michael@0 201 return mState.mIs2b ? m2b[aIndex] : static_cast<unsigned char>(m1b[aIndex]);
michael@0 202 }
michael@0 203
michael@0 204 struct FragmentBits {
michael@0 205 // uint32_t to ensure that the values are unsigned, because we
michael@0 206 // want 0/1, not 0/-1!
michael@0 207 // Making these bool causes Windows to not actually pack them,
michael@0 208 // which causes crashes because we assume this structure is no more than
michael@0 209 // 32 bits!
michael@0 210 uint32_t mInHeap : 1;
michael@0 211 uint32_t mIs2b : 1;
michael@0 212 uint32_t mIsBidi : 1;
michael@0 213 uint32_t mLength : 29;
michael@0 214 };
michael@0 215
michael@0 216 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
michael@0 217
michael@0 218 private:
michael@0 219 void ReleaseText();
michael@0 220
michael@0 221 /**
michael@0 222 * Scan the contents of the fragment and turn on mState.mIsBidi if it
michael@0 223 * includes any Bidi characters.
michael@0 224 */
michael@0 225 void UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength);
michael@0 226
michael@0 227 union {
michael@0 228 char16_t *m2b;
michael@0 229 const char *m1b; // This is const since it can point to shared data
michael@0 230 };
michael@0 231
michael@0 232 union {
michael@0 233 uint32_t mAllBits;
michael@0 234 FragmentBits mState;
michael@0 235 };
michael@0 236 };
michael@0 237
michael@0 238 #endif /* nsTextFragment_h___ */
michael@0 239

mercurial