Exemplo n.º 1
0
bool
nsTSubstring_CharT::Assign( const substring_tuple_type& tuple, const fallible_t& )
  {
    if (tuple.IsDependentOn(mData, mData + mLength))
      {
        // take advantage of sharing here...
        return Assign(string_type(tuple), fallible_t());
      }

    size_type length = tuple.Length();

    // don't use ReplacePrep here because it changes the length
    char_type* oldData;
    uint32_t oldFlags;
    if (!MutatePrep(length, &oldData, &oldFlags))
      return false;

    if (oldData)
      ::ReleaseData(oldData, oldFlags);

    tuple.WriteTo(mData, length);
    mData[length] = 0;
    mLength = length;
    return true;
  }
Exemplo n.º 2
0
bool
nsTSubstring_CharT::ReplacePrepInternal(index_type cutStart, size_type cutLen,
                                        size_type fragLen, size_type newLen)
  {
    char_type* oldData;
    uint32_t oldFlags;
    if (!MutatePrep(newLen, &oldData, &oldFlags))
      return false; // out-of-memory

    if (oldData)
      {
        // determine whether or not we need to copy part of the old string
        // over to the new string.

        if (cutStart > 0)
          {
            // copy prefix from old string
            char_traits::copy(mData, oldData, cutStart);
          }

        if (cutStart + cutLen < mLength)
          {
            // copy suffix from old string to new offset
            size_type from = cutStart + cutLen;
            size_type fromLen = mLength - from;
            uint32_t to = cutStart + fragLen;
            char_traits::copy(mData + to, oldData + from, fromLen);
          }

        ::ReleaseData(oldData, oldFlags);
      }
    else
      {
        // original data remains intact

        // determine whether or not we need to move part of the existing string
        // to make room for the requested hole.
        if (fragLen != cutLen && cutStart + cutLen < mLength)
          {
            uint32_t from = cutStart + cutLen;
            uint32_t fromLen = mLength - from;
            uint32_t to = cutStart + fragLen;
            char_traits::move(mData + to, mData + from, fromLen);
          }
      }

    // add null terminator (mutable mData always has room for the null-
    // terminator).
    mData[newLen] = char_type(0);
    mLength = newLen;

    return true;
  }
Exemplo n.º 3
0
PRBool
nsTSubstring_CharT::SetCapacity( size_type capacity )
  {
    // capacity does not include room for the terminating null char

    // if our capacity is reduced to zero, then free our buffer.
    if (capacity == 0)
      {
        ::ReleaseData(mData, mFlags);
        mData = char_traits::sEmptyBuffer;
        mLength = 0;
        SetDataFlags(F_TERMINATED);
      }
    else
      {
        char_type* oldData;
        PRUint32 oldFlags;
        if (!MutatePrep(capacity, &oldData, &oldFlags))
          return PR_FALSE; // out-of-memory

        // compute new string length
        size_type newLen = NS_MIN(mLength, capacity);

        if (oldData)
          {
            // preserve old data
            if (mLength > 0)
              char_traits::copy(mData, oldData, newLen);

            ::ReleaseData(oldData, oldFlags);
          }

        // adjust mLength if our buffer shrunk down in size
        if (newLen < mLength)
          mLength = newLen;

        // always null-terminate here, even if the buffer got longer.  this is
        // for backwards compat with the old string implementation.
        mData[capacity] = char_type(0);
      }

    return PR_TRUE;
  }
Exemplo n.º 4
0
void
nsTSubstring_CharT::Assign( const substring_tuple_type& tuple )
  {
    if (tuple.IsDependentOn(mData, mData + mLength))
      {
        // take advantage of sharing here...
        Assign(string_type(tuple));
        return;
      }

    size_type length = tuple.Length();

    // don't use ReplacePrep here because it changes the length
    char_type* oldData;
    PRUint32 oldFlags;
    if (MutatePrep(length, &oldData, &oldFlags)) {
      if (oldData)
        ::ReleaseData(oldData, oldFlags);

      tuple.WriteTo(mData, length);
      mData[length] = 0;
      mLength = length;
    }
  }
Exemplo n.º 5
0
bool
nsTString_CharT::ReplaceSubstring(const self_type& aTarget,
                                  const self_type& aNewValue,
                                  const fallible_t&)
{
  if (aTarget.Length() == 0)
    return true;

  // Remember all of the non-matching parts.
  AutoTArray<Segment, 16> nonMatching;
  uint32_t i = 0;
  uint32_t newLength = 0;
  while (true)
  {
    int32_t r = FindSubstring(mData + i, mLength - i, static_cast<const char_type*>(aTarget.Data()), aTarget.Length(), false);
    int32_t until = (r == kNotFound) ? mLength - i : r;
    nonMatching.AppendElement(Segment(i, until));
    newLength += until;
    if (r == kNotFound) {
      break;
    }

    newLength += aNewValue.Length();
    i += r + aTarget.Length();
    if (i >= mLength) {
      // Add an auxiliary entry at the end of the list to help as an edge case
      // for the algorithms below.
      nonMatching.AppendElement(Segment(mLength, 0));
      break;
    }
  }

  // If there's only one non-matching segment, then the target string was not
  // found, and there's nothing to do.
  if (nonMatching.Length() == 1) {
    MOZ_ASSERT(nonMatching[0].mBegin == 0 && nonMatching[0].mLength == mLength,
               "We should have the correct non-matching segment.");
    return true;
  }

  // Make sure that we can mutate our buffer.
  // Note that we always allocate at least an mLength sized buffer, because the
  // rest of the algorithm relies on having access to all of the original
  // string.  In other words, we over-allocate in the shrinking case.
  char_type* oldData;
  uint32_t oldFlags;
  if (!MutatePrep(XPCOM_MAX(mLength, newLength), &oldData, &oldFlags))
    return false;
  if (oldData) {
    // Copy all of the old data to the new buffer.
    char_traits::copy(mData, oldData, mLength);
    ::ReleaseData(oldData, oldFlags);
  }

  if (aTarget.Length() >= aNewValue.Length()) {
    // In the shrinking case, start filling the buffer from the beginning.
    const uint32_t delta = (aTarget.Length() - aNewValue.Length());
    for (i = 1; i < nonMatching.Length(); ++i) {
      // When we move the i'th non-matching segment into position, we need to
      // account for the characters deleted by the previous |i| replacements by
      // subtracting |i * delta|.
      const char_type* sourceSegmentPtr = mData + nonMatching[i].mBegin;
      char_type* destinationSegmentPtr = mData + nonMatching[i].mBegin - i * delta;
      // Write the i'th replacement immediately before the new i'th non-matching
      // segment.
      char_traits::copy(destinationSegmentPtr - aNewValue.Length(),
                        aNewValue.Data(), aNewValue.Length());
      char_traits::move(destinationSegmentPtr, sourceSegmentPtr,
                        nonMatching[i].mLength);
    }
  } else {
    // In the growing case, start filling the buffer from the end.
    const uint32_t delta = (aNewValue.Length() - aTarget.Length());
    for (i = nonMatching.Length() - 1; i > 0; --i) {
      // When we move the i'th non-matching segment into position, we need to
      // account for the characters added by the previous |i| replacements by
      // adding |i * delta|.
      const char_type* sourceSegmentPtr = mData + nonMatching[i].mBegin;
      char_type* destinationSegmentPtr = mData + nonMatching[i].mBegin + i * delta;
      char_traits::move(destinationSegmentPtr, sourceSegmentPtr,
                        nonMatching[i].mLength);
      // Write the i'th replacement immediately before the new i'th non-matching
      // segment.
      char_traits::copy(destinationSegmentPtr - aNewValue.Length(),
                        aNewValue.Data(), aNewValue.Length());
    }
  }

  // Adjust the length and make sure the string is null terminated.
  mLength = newLength;
  mData[mLength] = char_type(0);

  return true;
}