nsStringBuffer*
nsStringBuffer::Realloc(nsStringBuffer* hdr, size_t size)
  {
    STRING_STAT_INCREMENT(Realloc);

    NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
    NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(uint32_t(-1)) &&
                 sizeof(nsStringBuffer) + size > size,
                 "mStorageSize will truncate");

    // no point in trying to save ourselves if we hit this assertion
    NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");

    // Treat this as a release and addref for refcounting purposes, since we
    // just asserted that the refcount is 1.  If we don't do that, refcount
    // logging will claim we've leaked all sorts of stuff.
    NS_LOG_RELEASE(hdr, 0, "nsStringBuffer");
    
    hdr = (nsStringBuffer*) realloc(hdr, sizeof(nsStringBuffer) + size);
    if (hdr) {
      NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
      hdr->mStorageSize = size;
    }

    return hdr;
  }
void
nsStringBuffer::AddRef()
  {
    PR_ATOMIC_INCREMENT(&mRefCount);
    STRING_STAT_INCREMENT(Share);
    NS_LOG_ADDREF(this, mRefCount, "nsStringBuffer", sizeof(*this));
  }
void
nsTSubstring_CharT::Adopt( char_type* data, size_type length )
  {
    if (data)
      {
        ::ReleaseData(mData, mFlags);

        if (length == size_type(-1))
          length = char_traits::length(data);

        mData = data;
        mLength = length;
        SetDataFlags(F_TERMINATED | F_OWNED);

        STRING_STAT_INCREMENT(Adopt);
#ifdef NS_BUILD_REFCNT_LOGGING
        // Treat this as construction of a "StringAdopt" object for leak
        // tracking purposes.        
        NS_LogCtor(mData, "StringAdopt", 1);
#endif // NS_BUILD_REFCNT_LOGGING
      }
    else
      {
        SetIsVoid(true);
      }
  }
void
nsStringBuffer::Release()
  {
    int32_t count = PR_ATOMIC_DECREMENT(&mRefCount);
    NS_LOG_RELEASE(this, count, "nsStringBuffer");
    if (count == 0)
      {
        STRING_STAT_INCREMENT(Free);
        free(this); // we were allocated with |malloc|
      }
  }
nsTSubstring_CharT::nsTSubstring_CharT( char_type *data, size_type length,
                                        uint32_t flags)
  : mData(data),
    mLength(length),
    mFlags(flags)
  {
    if (flags & F_OWNED) {
      STRING_STAT_INCREMENT(Adopt);
#ifdef NS_BUILD_REFCNT_LOGGING
      NS_LogCtor(mData, "StringAdopt", 1);
#endif
    }
  }
inline void
ReleaseData( void* data, uint32_t flags )
  {
    if (flags & nsSubstring::F_SHARED)
      {
        nsStringBuffer::FromData(data)->Release();
      }
    else if (flags & nsSubstring::F_OWNED)
      {
        nsMemory::Free(data);
        STRING_STAT_INCREMENT(AdoptFree);
#ifdef NS_BUILD_REFCNT_LOGGING
        // Treat this as destruction of a "StringAdopt" object for leak
        // tracking purposes.
        NS_LogDtor(data, "StringAdopt", 1);
#endif // NS_BUILD_REFCNT_LOGGING
      }
    // otherwise, nothing to do.
  }
  /**
   * Alloc returns a pointer to a new string header with set capacity.
   */
already_AddRefed<nsStringBuffer>
nsStringBuffer::Alloc(size_t size)
  {
    NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
    NS_ASSERTION(sizeof(nsStringBuffer) + size <= size_t(uint32_t(-1)) &&
                 sizeof(nsStringBuffer) + size > size,
                 "mStorageSize will truncate");

    nsStringBuffer *hdr =
        (nsStringBuffer *) malloc(sizeof(nsStringBuffer) + size);
    if (hdr)
      {
        STRING_STAT_INCREMENT(Alloc);

        hdr->mRefCount = 1;
        hdr->mStorageSize = size;
        NS_LOG_ADDREF(hdr, 1, "nsStringBuffer", sizeof(*hdr));
      }
    return dont_AddRef(hdr);
  }