/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Mozilla strings. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * Scott Collins (original author) * */ #ifndef nsSlidingString_h___ #define nsSlidingString_h___ #ifndef nsAString_h___ #include "nsAString.h" #endif #ifndef nsSharedBufferList_h___ #include "nsSharedBufferList.h" #endif /* * nsFreeProc : A pointer to the free function used by nsSlidingString */ typedef void nsFreeProc(void *ptr, void *clientdata); /** * Maintains the sequence from the prev-most referenced buffer to the last buffer. * As prev-most buffers become un-referenced, they are unlinked from the list * and destroyed. * * One or more |nsSlidingSubstring|s may reference into the list. Each |nsSlidingSubstring| * holds a reference into the prev-most buffer intersecting the * substring it describes. The destructor of a |nsSlidingSubstring| releases this * reference, allowing the buffer list to destroy the contiguous prefix of * unreferenced buffers. * * A single instance of |nsSlidingString| may reference this list. * Through that interface, new data can be appended onto the next-most end * of the list. |nsSlidingString| also the client to advance its starting point. * */ class NS_COM nsSlidingSharedBufferList : public nsSharedBufferList { public: nsSlidingSharedBufferList( Buffer* aBuffer ) : nsSharedBufferList(aBuffer), mRefCount(0), mFreeProc(nsnull), mClientData(nsnull) { } nsSlidingSharedBufferList( Buffer* aBuffer, nsFreeProc *aFreeproc, void *aClientData = NULL ) : nsSharedBufferList(aBuffer), mRefCount(0), mFreeProc(aFreeproc), mClientData(aClientData) { } void AcquireReference() { ++mRefCount; } void ReleaseReference() { if ( !--mRefCount ) delete this; } void DiscardUnreferencedPrefix( Buffer* ); private: PRUint32 mRefCount; nsFreeProc *mFreeProc; void *mClientData; }; class nsSlidingString; /** * a substring over a buffer list, this */ class NS_COM nsSlidingSubstring : virtual public nsAString { friend class nsSlidingString; public: typedef nsSlidingSharedBufferList::Buffer Buffer; typedef nsSlidingSharedBufferList::Position Position; nsSlidingSubstring() : mStart(0,0), mEnd(0,0), mBufferList(0), mLength(0) { // nothing else to do here } nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor nsSlidingSubstring( const nsSlidingSubstring& aString, const nsAString::const_iterator& aStart, const nsAString::const_iterator& aEnd ); nsSlidingSubstring( const nsSlidingString& ); nsSlidingSubstring( const nsSlidingString& aString, const nsAString::const_iterator& aStart, const nsAString::const_iterator& aEnd ); explicit nsSlidingSubstring( const nsAString& ); // copy the supplied string into a new buffer ... there will be no modifying instance over this buffer list void Rebind( const nsSlidingSubstring& ); void Rebind( const nsSlidingSubstring&, const nsAString::const_iterator&, const nsAString::const_iterator& ); void Rebind( const nsSlidingString& ); void Rebind( const nsSlidingString&, const nsAString::const_iterator&, const nsAString::const_iterator& ); void Rebind( const nsAString& ); ~nsSlidingSubstring(); virtual PRUint32 Length() const { return mLength; } protected: nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ); virtual const PRUnichar* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 ) const; virtual PRUnichar* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 ) { return 0; } private: // can't assign into me, I'm a read-only reference void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED void init_range_from_buffer_list() // used only from constructors { mStart.PointBefore(mBufferList->GetFirstBuffer()); mEnd.PointAfter(mBufferList->GetLastBuffer()); mLength = PRUint32(Position::Distance(mStart, mEnd)); } void acquire_ownership_of_buffer_list() const // used only from constructors and |Rebind|, requires |mStart| already be initialized { mBufferList->AcquireReference(); mStart.mBuffer->AcquireNonOwningReference(); } void release_ownership_of_buffer_list() { if ( mBufferList ) { mStart.mBuffer->ReleaseNonOwningReference(); mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer); mBufferList->ReleaseReference(); } } protected: Position mStart; Position mEnd; nsSlidingSharedBufferList* mBufferList; PRUint32 mLength; }; /** * An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class. * */ class NS_COM nsSlidingString : virtual public nsAString, private nsSlidingSubstring { friend class nsSlidingSubstring; public: nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); // ...created by consuming ownership of a buffer ... |aStorageStart| must point to something // that it will be OK for the sliding string to call |nsMemory::Free| on nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd, nsFreeProc *aFreeProc, void *aClientData = NULL); // ...created by consuming ownership of a buffer ... |aStorageStart| must point to something // that it will be OK for the sliding string to call (*aFreeProc)(ptr, aClientData) on virtual PRUint32 Length() const { return mLength; } // you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); // void Append( ... ); do you want some |Append|s that copy the supplied data? void DiscardPrefix( const nsAString::const_iterator& ); // any other way you want to do this? protected: virtual const PRUnichar* GetReadableFragment( nsReadableFragment&, nsFragmentRequest, PRUint32 ) const; virtual PRUnichar* GetWritableFragment( nsWritableFragment&, nsFragmentRequest, PRUint32 ) { return 0; } void InsertReadable( const nsAString&, const nsAString::const_iterator& ); // ...to implement |nsScannerString::UngetReadable| private: void acquire_ownership_of_buffer_list() const // used only from constructors and |Rebind|, requires |mStart| already be initialized { mBufferList->AcquireReference(); mStart.mBuffer->AcquireNonOwningReference(); } nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED }; #endif // !defined(nsSlidingString_h___)