LCOV - code coverage report
Current view: top level - dom/bindings - FakeString.h (source / functions) Hit Total Coverage
Test: output.info Lines: 47 55 85.5 %
Date: 2017-07-14 16:53:18 Functions: 12 13 92.3 %
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 file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_dom_FakeString_h__
       8             : #define mozilla_dom_FakeString_h__
       9             : 
      10             : #include "nsString.h"
      11             : #include "nsStringBuffer.h"
      12             : #include "mozilla/RefPtr.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace dom {
      16             : namespace binding_detail {
      17             : // A struct that has the same layout as an nsString but much faster
      18             : // constructor and destructor behavior. FakeString uses inline storage
      19             : // for small strings and a nsStringBuffer for longer strings.
      20             : struct FakeString {
      21        1768 :   FakeString() :
      22             :     mDataFlags(nsString::DataFlags::TERMINATED),
      23        1768 :     mClassFlags(nsString::ClassFlags(0))
      24             :   {
      25        1768 :   }
      26             : 
      27        3536 :   ~FakeString() {
      28        1768 :     if (mDataFlags & nsString::DataFlags::SHARED) {
      29           4 :       nsStringBuffer::FromData(mData)->Release();
      30             :     }
      31        1768 :   }
      32             : 
      33           4 :   void Rebind(const nsString::char_type* aData, nsString::size_type aLength) {
      34           4 :     MOZ_ASSERT(mDataFlags == nsString::DataFlags::TERMINATED);
      35           4 :     mData = const_cast<nsString::char_type*>(aData);
      36           4 :     mLength = aLength;
      37           4 :   }
      38             : 
      39             :   // Share aString's string buffer, if it has one; otherwise, make this string
      40             :   // depend upon aString's data.  aString should outlive this instance of
      41             :   // FakeString.
      42           0 :   void ShareOrDependUpon(const nsAString& aString) {
      43           0 :     RefPtr<nsStringBuffer> sharedBuffer = nsStringBuffer::FromString(aString);
      44           0 :     if (!sharedBuffer) {
      45           0 :       Rebind(aString.Data(), aString.Length());
      46             :     } else {
      47           0 :       AssignFromStringBuffer(sharedBuffer.forget());
      48           0 :       mLength = aString.Length();
      49             :     }
      50           0 :   }
      51             : 
      52           6 :   void Truncate() {
      53           6 :     MOZ_ASSERT(mDataFlags == nsString::DataFlags::TERMINATED);
      54           6 :     mData = nsString::char_traits::sEmptyBuffer;
      55           6 :     mLength = 0;
      56           6 :   }
      57             : 
      58           6 :   void SetIsVoid(bool aValue) {
      59           6 :     MOZ_ASSERT(aValue,
      60             :                "We don't support SetIsVoid(false) on FakeString!");
      61           6 :     Truncate();
      62           6 :     mDataFlags |= nsString::DataFlags::VOIDED;
      63           6 :   }
      64             : 
      65           8 :   const nsString::char_type* Data() const
      66             :   {
      67           8 :     return mData;
      68             :   }
      69             : 
      70        1738 :   nsString::char_type* BeginWriting()
      71             :   {
      72        1738 :     return mData;
      73             :   }
      74             : 
      75           8 :   nsString::size_type Length() const
      76             :   {
      77           8 :     return mLength;
      78             :   }
      79             : 
      80             :   // Reserve space to write aLength chars, not including null-terminator.
      81        1730 :   bool SetLength(nsString::size_type aLength, mozilla::fallible_t const&) {
      82             :     // Use mInlineStorage for small strings.
      83        1730 :     if (aLength < sInlineCapacity) {
      84        1726 :       SetData(mInlineStorage);
      85             :     } else {
      86           8 :       RefPtr<nsStringBuffer> buf = nsStringBuffer::Alloc((aLength + 1) * sizeof(nsString::char_type));
      87           4 :       if (MOZ_UNLIKELY(!buf)) {
      88           0 :         return false;
      89             :       }
      90             : 
      91           4 :       AssignFromStringBuffer(buf.forget());
      92             :     }
      93        1730 :     mLength = aLength;
      94        1730 :     mData[mLength] = char16_t(0);
      95        1730 :     return true;
      96             :   }
      97             : 
      98             :   // If this ever changes, change the corresponding code in the
      99             :   // Optional<nsAString> specialization as well.
     100             :   const nsAString* ToAStringPtr() const {
     101             :     return reinterpret_cast<const nsString*>(this);
     102             :   }
     103             : 
     104        1740 : operator const nsAString& () const {
     105        1740 :     return *reinterpret_cast<const nsString*>(this);
     106             :   }
     107             : 
     108             : private:
     109             :   nsAString* ToAStringPtr() {
     110             :     return reinterpret_cast<nsString*>(this);
     111             :   }
     112             : 
     113             :   nsString::char_type* mData;
     114             :   nsString::size_type mLength;
     115             :   nsString::DataFlags mDataFlags;
     116             :   nsString::ClassFlags mClassFlags;
     117             : 
     118             :   static const size_t sInlineCapacity = 64;
     119             :   nsString::char_type mInlineStorage[sInlineCapacity];
     120             : 
     121             :   FakeString(const FakeString& other) = delete;
     122             :   void operator=(const FakeString& other) = delete;
     123             : 
     124        1730 :   void SetData(nsString::char_type* aData) {
     125        1730 :     MOZ_ASSERT(mDataFlags == nsString::DataFlags::TERMINATED);
     126        1730 :     mData = const_cast<nsString::char_type*>(aData);
     127        1730 :   }
     128           4 :   void AssignFromStringBuffer(already_AddRefed<nsStringBuffer> aBuffer) {
     129           4 :     SetData(static_cast<nsString::char_type*>(aBuffer.take()->Data()));
     130           4 :     mDataFlags = nsString::DataFlags::SHARED | nsString::DataFlags::TERMINATED;
     131           4 :   }
     132             : 
     133             :   friend class NonNull<nsAString>;
     134             : 
     135             :   // A class to use for our static asserts to ensure our object layout
     136             :   // matches that of nsString.
     137             :   class StringAsserter;
     138             :   friend class StringAsserter;
     139             : 
     140             :   class StringAsserter : public nsString {
     141             :   public:
     142             :     static void StaticAsserts() {
     143             :       static_assert(offsetof(FakeString, mInlineStorage) ==
     144             :                       sizeof(nsString),
     145             :                     "FakeString should include all nsString members");
     146             :       static_assert(offsetof(FakeString, mData) ==
     147             :                       offsetof(StringAsserter, mData),
     148             :                     "Offset of mData should match");
     149             :       static_assert(offsetof(FakeString, mLength) ==
     150             :                       offsetof(StringAsserter, mLength),
     151             :                     "Offset of mLength should match");
     152             :       static_assert(offsetof(FakeString, mDataFlags) ==
     153             :                       offsetof(StringAsserter, mDataFlags),
     154             :                     "Offset of mDataFlags should match");
     155             :       static_assert(offsetof(FakeString, mClassFlags) ==
     156             :                       offsetof(StringAsserter, mClassFlags),
     157             :                     "Offset of mClassFlags should match");
     158             :     }
     159             :   };
     160             : };
     161             : } // namespace binding_detail
     162             : } // namespace dom
     163             : } // namespace mozilla
     164             : 
     165             : #endif /* mozilla_dom_FakeString_h__ */

Generated by: LCOV version 1.13