LCOV - code coverage report
Current view: top level - dom/base - nsTextFragment.h (source / functions) Hit Total Coverage
Test: output.info Lines: 22 45 48.9 %
Date: 2017-07-14 16:53:18 Functions: 8 12 66.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13