more work towards a working |nsSlidingString|, |nsSlidingSubstring| for the parser, these files are not yet part of the build

This commit is contained in:
scc%mozilla.org 2000-09-09 04:42:19 +00:00
parent cff3c8e744
commit 59389ddca9
9 changed files with 315 additions and 162 deletions

View File

@ -25,6 +25,18 @@
#ifndef nsBufferHandle_h___
#define nsBufferHandle_h___
#include <stddef.h>
// for |ptrdiff_t|
#include "prtypes.h"
// for |PRBool|
#include "nsDebug.h"
// for |NS_ASSERTION|
#include "nsMemory.h"
// for |nsMemory::Free|
/**
*
*/
@ -32,28 +44,22 @@ template <class CharT>
class nsBufferHandle
{
public:
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
ptrdiff_t
DataLength() const
{
return mDataEnd - mDataStart;
}
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
CharT* DataStart() { return mDataStart; }
const CharT* DataStart() const { return mDataStart; }
const CharT*
DataStart() const
{
return mDataStart;
}
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
CharT* DataEnd() { return mDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
const CharT*
DataEnd() const
{
return mDataEnd;
}
// void DataLength( ptrdiff_t aNewDataLength ) { mDataEnd = mDataStart+aNewDataLength; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
const CharT* mDataStart;
const CharT* mDataEnd;
CharT* mDataStart;
CharT* mDataEnd;
};
@ -63,7 +69,7 @@ class nsBufferHandle
*/
template <class CharT>
class nsSharedBufferHandle
: public nsStringFragmentHandle<CharT>
: public nsBufferHandle<CharT>
{
protected:
enum
@ -77,6 +83,12 @@ class nsSharedBufferHandle
};
public:
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
: nsBufferHandle(aDataStart, aDataEnd)
{
mFlags |= kIsShared;
}
~nsSharedBufferHandle();
void
@ -124,11 +136,28 @@ class nsXXXBufferHandle
: public nsSharedBufferHandle<CharT>
{
public:
nsXXXBufferHandle() { mFlags |= kIsStorageDefinedSeparately; }
nsXXXBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
: nsSharedBufferHandle(aDataStart, aDataEnd),
mStorageStart(aStorageStart),
mStorageEnd(aStorageEnd)
{
mFlags |= kIsStorageDefinedSeparately;
}
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
CharT* StorageStart() { return mStorageStart; }
const CharT* StorageStart() const { return mStorageStart; }
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
CharT* StorageEnd() { return mStorageEnd; }
const CharT* StorageEnd() const { return mStorageEnd; }
// void StorageLength( ptrdiff_t aNewStorageLength ) { mStorageEnd = mStorageStart+aNewStorageLength; }
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
protected:
const CharT* mStorageStart;
const CharT* mStorageEnd;
CharT* mStorageStart;
CharT* mStorageEnd;
};
template <class CharT>
@ -141,7 +170,7 @@ nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
{
CharT* string_storage = mDataStart;
if ( mFlags & kIsStorageDefinedSeparately )
string_storage = NS_STATIC_CAST(nsXXXBufferHandle*, this)->mStorageStart;
string_storage = NS_REINTERPRET_CAST(typename nsXXXBufferHandle<CharT>*, this)->StorageStart();
nsMemory::Free(string_storage);
}
}

View File

@ -26,36 +26,43 @@
#define nsSharedBufferList_h___
#include "nsBufferHandle.h"
// for |nsSharedBufferHandle|
#include "nscore.h"
// for |PRUnichar|
/**
* This class forms the basis for several multi-fragment string classes, in
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
*
* This class is not templated. It is provided only for |PRUnichar|-based strings.
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
* or else duplicate this class.
*/
class nsSharedBufferList
{
public:
class Buffer
: public nsSharedBufferHandle<PRUnichar>
: public nsXXXBufferHandle<PRUnichar>
{
friend class nsSharedBufferList;
public:
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd ) : nsXXXBufferHandle(aDataStart, aDataEnd, aStorageStart, aStorageEnd) { }
private:
Buffer* mPrev;
Buffer* mNext;
};
struct Position
{
nsSharedBufferList::Buffer* mBuffer;
nsSharedBufferList::PRUnichar* mPosInBuffer;
nsSharedBufferList::Buffer* mBuffer;
PRUnichar* mPosInBuffer;
};
public:
nsSharedBufferList() : mFirstBuffer(0), mLastBuffer(0), mTotalLength(0) { }
nsSharedBufferList() : mFirstBuffer(0), mLastBuffer(0), mTotalDataLength(0) { }
virtual ~nsSharedBufferList();
private:
@ -68,8 +75,18 @@ class nsSharedBufferList
Buffer* UnlinkBuffer( Buffer* );
void SplitBuffer( const Position& );
Buffer* First() { return mFirstBuffer; }
Buffer* Last() { return mLastBuffer; }
static Buffer* NewBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 );
void DiscardSuffix( PRUint32 );
// need other discards: prefix, and by iterator or pointer or something
Buffer* GetFirstBuffer() { return mFirstBuffer; }
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
Buffer* GetLastBuffer() { return mLastBuffer; }
const Buffer* GetLastBuffer() const { return mLastBuffer; }
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
protected:
void DestroyBuffers();
@ -77,8 +94,7 @@ class nsSharedBufferList
protected:
Buffer* mFirstBuffer;
Buffer* mLastBuffer;
PRUint32 mTotalLength;
ptrdiff_t mTotalDataLength;
};
#endif // !defined(nsSharedBufferList_h___)

View File

@ -23,6 +23,9 @@
*/
#include "nsSharedBufferList.h"
#include "nsAlgorithm.h"
// for |copy_string|
#include <new.h>
void
@ -45,25 +48,24 @@ nsSharedBufferList::~nsSharedBufferList()
}
template <class CharT>
nsSharedBufferList::Buffer*
nsSharedBufferList::NewBuffer( const CharT* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
nsSharedBufferList::NewBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
{
size_t object_size = ((sizeof(Buffer) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
PRUint32 buffer_length = aDataLength + aAdditionalSpace;
size_t buffer_size = size_t(buffer_length) * sizeof(CharT);
size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar);
void* object_ptr = operator new(object_size + buffer_size);
if ( object_ptr )
{
typedef CharT* CharT_ptr;
CharT* buffer_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
typedef PRUnichar* PRUnichar_ptr;
PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
if ( aDataLength )
{
CharT* toBegin = buffer_ptr;
PRUnichar* toBegin = buffer_ptr;
copy_string(aData, aData+aDataLength, toBegin);
}
return new (object_ptr) Buffer(buffer_ptr, buffer_length, aDataLength);
return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length);
}
return 0;
@ -80,12 +82,12 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer*
NS_ASSERTION(aNextBuffer || mLastBuffer == aPrevBuffer, "aNextBuffer || mLastBuffer == aPrevBuffer");
NS_ASSERTION(!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer, "!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer");
if ( aNewBuffer->mPrev = aPrevBuffer )
if ( (aNewBuffer->mPrev = aPrevBuffer) )
aPrevBuffer->mNext = aNewBuffer;
else
mFirstBuffer = aNewBuffer;
if ( aNewBuffer->mNext = aNextBuffer )
if ( (aNewBuffer->mNext = aNextBuffer) )
aNextBuffer->mPrev = aNewBuffer;
else
mLastBuffer = aNewBuffer;
@ -94,23 +96,27 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer*
}
void
nsSharedBufferList::SplitBuffer( Buffer* aBufferToSplit, PRUint32 aSplitPosition )
nsSharedBufferList::SplitBuffer( const Position& aSplitPosition )
{
NS_ASSERTION(aBufferToSplit, "aBufferToSplit");
NS_ASSERTION(aSplitPosition <= aBufferToSplit->DataLength(), "aSplitPosition <= aBufferToSplit->DataLength()");
Buffer* bufferToSplit = aSplitPosition.mBuffer;
if ( (aBufferToSplit->DataLength() >> 1) > aSplitPosition )
NS_ASSERTION(bufferToSplit, "bufferToSplit");
ptrdiff_t splitOffset = aSplitPosition.mPosInBuffer - bufferToSplit->DataStart();
NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer");
if ( (bufferToSplit->DataLength() >> 1) > splitOffset )
{
Buffer* new_buffer = NewBuffer(aBufferToSplit->DataStart(), aSplitPosition);
LinkBuffer(aBufferToSplit->mPrev, new_buffer, aBufferToSplit);
aBufferToSplit->mDataStart += aSplitPosition;
aBufferToSplit->DataLength() -= aSplitPosition;
Buffer* new_buffer = NewBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset));
LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit);
bufferToSplit->DataStart(aSplitPosition.mPosInBuffer);
}
else
{
Buffer* new_buffer = NewBuffer(aBufferToSplit->mDataStart+aSplitPosition, aBufferToSplit->DataLength()-aSplitPosition);
LinkBuffer(aBufferToSplit, new_buffer, aBufferToSplit->mNext);
aBufferToSplit->DataLength() = aSplitPosition;
Buffer* new_buffer = NewBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset));
LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext);
bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer);
}
}

View File

@ -25,6 +25,18 @@
#ifndef nsBufferHandle_h___
#define nsBufferHandle_h___
#include <stddef.h>
// for |ptrdiff_t|
#include "prtypes.h"
// for |PRBool|
#include "nsDebug.h"
// for |NS_ASSERTION|
#include "nsMemory.h"
// for |nsMemory::Free|
/**
*
*/
@ -32,28 +44,22 @@ template <class CharT>
class nsBufferHandle
{
public:
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
ptrdiff_t
DataLength() const
{
return mDataEnd - mDataStart;
}
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
CharT* DataStart() { return mDataStart; }
const CharT* DataStart() const { return mDataStart; }
const CharT*
DataStart() const
{
return mDataStart;
}
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
CharT* DataEnd() { return mDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
const CharT*
DataEnd() const
{
return mDataEnd;
}
// void DataLength( ptrdiff_t aNewDataLength ) { mDataEnd = mDataStart+aNewDataLength; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
const CharT* mDataStart;
const CharT* mDataEnd;
CharT* mDataStart;
CharT* mDataEnd;
};
@ -63,7 +69,7 @@ class nsBufferHandle
*/
template <class CharT>
class nsSharedBufferHandle
: public nsStringFragmentHandle<CharT>
: public nsBufferHandle<CharT>
{
protected:
enum
@ -77,6 +83,12 @@ class nsSharedBufferHandle
};
public:
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
: nsBufferHandle(aDataStart, aDataEnd)
{
mFlags |= kIsShared;
}
~nsSharedBufferHandle();
void
@ -124,11 +136,28 @@ class nsXXXBufferHandle
: public nsSharedBufferHandle<CharT>
{
public:
nsXXXBufferHandle() { mFlags |= kIsStorageDefinedSeparately; }
nsXXXBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
: nsSharedBufferHandle(aDataStart, aDataEnd),
mStorageStart(aStorageStart),
mStorageEnd(aStorageEnd)
{
mFlags |= kIsStorageDefinedSeparately;
}
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
CharT* StorageStart() { return mStorageStart; }
const CharT* StorageStart() const { return mStorageStart; }
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
CharT* StorageEnd() { return mStorageEnd; }
const CharT* StorageEnd() const { return mStorageEnd; }
// void StorageLength( ptrdiff_t aNewStorageLength ) { mStorageEnd = mStorageStart+aNewStorageLength; }
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
protected:
const CharT* mStorageStart;
const CharT* mStorageEnd;
CharT* mStorageStart;
CharT* mStorageEnd;
};
template <class CharT>
@ -141,7 +170,7 @@ nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
{
CharT* string_storage = mDataStart;
if ( mFlags & kIsStorageDefinedSeparately )
string_storage = NS_STATIC_CAST(nsXXXBufferHandle*, this)->mStorageStart;
string_storage = NS_REINTERPRET_CAST(typename nsXXXBufferHandle<CharT>*, this)->StorageStart();
nsMemory::Free(string_storage);
}
}

View File

@ -23,6 +23,9 @@
*/
#include "nsSharedBufferList.h"
#include "nsAlgorithm.h"
// for |copy_string|
#include <new.h>
void
@ -45,25 +48,24 @@ nsSharedBufferList::~nsSharedBufferList()
}
template <class CharT>
nsSharedBufferList::Buffer*
nsSharedBufferList::NewBuffer( const CharT* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
nsSharedBufferList::NewBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
{
size_t object_size = ((sizeof(Buffer) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
PRUint32 buffer_length = aDataLength + aAdditionalSpace;
size_t buffer_size = size_t(buffer_length) * sizeof(CharT);
size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar);
void* object_ptr = operator new(object_size + buffer_size);
if ( object_ptr )
{
typedef CharT* CharT_ptr;
CharT* buffer_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
typedef PRUnichar* PRUnichar_ptr;
PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
if ( aDataLength )
{
CharT* toBegin = buffer_ptr;
PRUnichar* toBegin = buffer_ptr;
copy_string(aData, aData+aDataLength, toBegin);
}
return new (object_ptr) Buffer(buffer_ptr, buffer_length, aDataLength);
return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length);
}
return 0;
@ -80,12 +82,12 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer*
NS_ASSERTION(aNextBuffer || mLastBuffer == aPrevBuffer, "aNextBuffer || mLastBuffer == aPrevBuffer");
NS_ASSERTION(!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer, "!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer");
if ( aNewBuffer->mPrev = aPrevBuffer )
if ( (aNewBuffer->mPrev = aPrevBuffer) )
aPrevBuffer->mNext = aNewBuffer;
else
mFirstBuffer = aNewBuffer;
if ( aNewBuffer->mNext = aNextBuffer )
if ( (aNewBuffer->mNext = aNextBuffer) )
aNextBuffer->mPrev = aNewBuffer;
else
mLastBuffer = aNewBuffer;
@ -94,23 +96,27 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer*
}
void
nsSharedBufferList::SplitBuffer( Buffer* aBufferToSplit, PRUint32 aSplitPosition )
nsSharedBufferList::SplitBuffer( const Position& aSplitPosition )
{
NS_ASSERTION(aBufferToSplit, "aBufferToSplit");
NS_ASSERTION(aSplitPosition <= aBufferToSplit->DataLength(), "aSplitPosition <= aBufferToSplit->DataLength()");
Buffer* bufferToSplit = aSplitPosition.mBuffer;
if ( (aBufferToSplit->DataLength() >> 1) > aSplitPosition )
NS_ASSERTION(bufferToSplit, "bufferToSplit");
ptrdiff_t splitOffset = aSplitPosition.mPosInBuffer - bufferToSplit->DataStart();
NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer");
if ( (bufferToSplit->DataLength() >> 1) > splitOffset )
{
Buffer* new_buffer = NewBuffer(aBufferToSplit->DataStart(), aSplitPosition);
LinkBuffer(aBufferToSplit->mPrev, new_buffer, aBufferToSplit);
aBufferToSplit->mDataStart += aSplitPosition;
aBufferToSplit->DataLength() -= aSplitPosition;
Buffer* new_buffer = NewBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset));
LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit);
bufferToSplit->DataStart(aSplitPosition.mPosInBuffer);
}
else
{
Buffer* new_buffer = NewBuffer(aBufferToSplit->mDataStart+aSplitPosition, aBufferToSplit->DataLength()-aSplitPosition);
LinkBuffer(aBufferToSplit, new_buffer, aBufferToSplit->mNext);
aBufferToSplit->DataLength() = aSplitPosition;
Buffer* new_buffer = NewBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset));
LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext);
bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer);
}
}

View File

@ -26,36 +26,43 @@
#define nsSharedBufferList_h___
#include "nsBufferHandle.h"
// for |nsSharedBufferHandle|
#include "nscore.h"
// for |PRUnichar|
/**
* This class forms the basis for several multi-fragment string classes, in
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
*
* This class is not templated. It is provided only for |PRUnichar|-based strings.
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
* or else duplicate this class.
*/
class nsSharedBufferList
{
public:
class Buffer
: public nsSharedBufferHandle<PRUnichar>
: public nsXXXBufferHandle<PRUnichar>
{
friend class nsSharedBufferList;
public:
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd ) : nsXXXBufferHandle(aDataStart, aDataEnd, aStorageStart, aStorageEnd) { }
private:
Buffer* mPrev;
Buffer* mNext;
};
struct Position
{
nsSharedBufferList::Buffer* mBuffer;
nsSharedBufferList::PRUnichar* mPosInBuffer;
nsSharedBufferList::Buffer* mBuffer;
PRUnichar* mPosInBuffer;
};
public:
nsSharedBufferList() : mFirstBuffer(0), mLastBuffer(0), mTotalLength(0) { }
nsSharedBufferList() : mFirstBuffer(0), mLastBuffer(0), mTotalDataLength(0) { }
virtual ~nsSharedBufferList();
private:
@ -68,8 +75,18 @@ class nsSharedBufferList
Buffer* UnlinkBuffer( Buffer* );
void SplitBuffer( const Position& );
Buffer* First() { return mFirstBuffer; }
Buffer* Last() { return mLastBuffer; }
static Buffer* NewBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 );
void DiscardSuffix( PRUint32 );
// need other discards: prefix, and by iterator or pointer or something
Buffer* GetFirstBuffer() { return mFirstBuffer; }
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
Buffer* GetLastBuffer() { return mLastBuffer; }
const Buffer* GetLastBuffer() const { return mLastBuffer; }
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
protected:
void DestroyBuffers();
@ -77,8 +94,7 @@ class nsSharedBufferList
protected:
Buffer* mFirstBuffer;
Buffer* mLastBuffer;
PRUint32 mTotalLength;
ptrdiff_t mTotalDataLength;
};
#endif // !defined(nsSharedBufferList_h___)

View File

@ -25,6 +25,18 @@
#ifndef nsBufferHandle_h___
#define nsBufferHandle_h___
#include <stddef.h>
// for |ptrdiff_t|
#include "prtypes.h"
// for |PRBool|
#include "nsDebug.h"
// for |NS_ASSERTION|
#include "nsMemory.h"
// for |nsMemory::Free|
/**
*
*/
@ -32,28 +44,22 @@ template <class CharT>
class nsBufferHandle
{
public:
nsBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : mDataStart(aDataStart), mDataEnd(aDataEnd) { }
ptrdiff_t
DataLength() const
{
return mDataEnd - mDataStart;
}
void DataStart( CharT* aNewDataStart ) { mDataStart = aNewDataStart; }
CharT* DataStart() { return mDataStart; }
const CharT* DataStart() const { return mDataStart; }
const CharT*
DataStart() const
{
return mDataStart;
}
void DataEnd( CharT* aNewDataEnd ) { mDataEnd = aNewDataEnd; }
CharT* DataEnd() { return mDataEnd; }
const CharT* DataEnd() const { return mDataEnd; }
const CharT*
DataEnd() const
{
return mDataEnd;
}
// void DataLength( ptrdiff_t aNewDataLength ) { mDataEnd = mDataStart+aNewDataLength; }
ptrdiff_t DataLength() const { return mDataEnd - mDataStart; }
protected:
const CharT* mDataStart;
const CharT* mDataEnd;
CharT* mDataStart;
CharT* mDataEnd;
};
@ -63,7 +69,7 @@ class nsBufferHandle
*/
template <class CharT>
class nsSharedBufferHandle
: public nsStringFragmentHandle<CharT>
: public nsBufferHandle<CharT>
{
protected:
enum
@ -77,6 +83,12 @@ class nsSharedBufferHandle
};
public:
nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd )
: nsBufferHandle(aDataStart, aDataEnd)
{
mFlags |= kIsShared;
}
~nsSharedBufferHandle();
void
@ -124,11 +136,28 @@ class nsXXXBufferHandle
: public nsSharedBufferHandle<CharT>
{
public:
nsXXXBufferHandle() { mFlags |= kIsStorageDefinedSeparately; }
nsXXXBufferHandle( CharT* aDataStart, CharT* aDataEnd, CharT* aStorageStart, CharT* aStorageEnd )
: nsSharedBufferHandle(aDataStart, aDataEnd),
mStorageStart(aStorageStart),
mStorageEnd(aStorageEnd)
{
mFlags |= kIsStorageDefinedSeparately;
}
void StorageStart( CharT* aNewStorageStart ) { mStorageStart = aNewStorageStart; }
CharT* StorageStart() { return mStorageStart; }
const CharT* StorageStart() const { return mStorageStart; }
void StorageEnd( CharT* aNewStorageEnd ) { mStorageEnd = aNewStorageEnd; }
CharT* StorageEnd() { return mStorageEnd; }
const CharT* StorageEnd() const { return mStorageEnd; }
// void StorageLength( ptrdiff_t aNewStorageLength ) { mStorageEnd = mStorageStart+aNewStorageLength; }
ptrdiff_t StorageLength() const { return mStorageEnd - mStorageStart; }
protected:
const CharT* mStorageStart;
const CharT* mStorageEnd;
CharT* mStorageStart;
CharT* mStorageEnd;
};
template <class CharT>
@ -141,7 +170,7 @@ nsSharedBufferHandle<CharT>::~nsSharedBufferHandle()
{
CharT* string_storage = mDataStart;
if ( mFlags & kIsStorageDefinedSeparately )
string_storage = NS_STATIC_CAST(nsXXXBufferHandle*, this)->mStorageStart;
string_storage = NS_REINTERPRET_CAST(typename nsXXXBufferHandle<CharT>*, this)->StorageStart();
nsMemory::Free(string_storage);
}
}

View File

@ -26,36 +26,43 @@
#define nsSharedBufferList_h___
#include "nsBufferHandle.h"
// for |nsSharedBufferHandle|
#include "nscore.h"
// for |PRUnichar|
/**
* This class forms the basis for several multi-fragment string classes, in
* particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|.
*
* This class is not templated. It is provided only for |PRUnichar|-based strings.
* If we turn out to have a need for multi-fragment ASCII strings, then perhaps we'll templatize
* or else duplicate this class.
*/
class nsSharedBufferList
{
public:
class Buffer
: public nsSharedBufferHandle<PRUnichar>
: public nsXXXBufferHandle<PRUnichar>
{
friend class nsSharedBufferList;
public:
Buffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageStart, PRUnichar* aStorageEnd ) : nsXXXBufferHandle(aDataStart, aDataEnd, aStorageStart, aStorageEnd) { }
private:
Buffer* mPrev;
Buffer* mNext;
};
struct Position
{
nsSharedBufferList::Buffer* mBuffer;
nsSharedBufferList::PRUnichar* mPosInBuffer;
nsSharedBufferList::Buffer* mBuffer;
PRUnichar* mPosInBuffer;
};
public:
nsSharedBufferList() : mFirstBuffer(0), mLastBuffer(0), mTotalLength(0) { }
nsSharedBufferList() : mFirstBuffer(0), mLastBuffer(0), mTotalDataLength(0) { }
virtual ~nsSharedBufferList();
private:
@ -68,8 +75,18 @@ class nsSharedBufferList
Buffer* UnlinkBuffer( Buffer* );
void SplitBuffer( const Position& );
Buffer* First() { return mFirstBuffer; }
Buffer* Last() { return mLastBuffer; }
static Buffer* NewBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 );
void DiscardSuffix( PRUint32 );
// need other discards: prefix, and by iterator or pointer or something
Buffer* GetFirstBuffer() { return mFirstBuffer; }
const Buffer* GetFirstBuffer() const { return mFirstBuffer; }
Buffer* GetLastBuffer() { return mLastBuffer; }
const Buffer* GetLastBuffer() const { return mLastBuffer; }
ptrdiff_t GetDataLength() const { return mTotalDataLength; }
protected:
void DestroyBuffers();
@ -77,8 +94,7 @@ class nsSharedBufferList
protected:
Buffer* mFirstBuffer;
Buffer* mLastBuffer;
PRUint32 mTotalLength;
ptrdiff_t mTotalDataLength;
};
#endif // !defined(nsSharedBufferList_h___)

View File

@ -23,6 +23,9 @@
*/
#include "nsSharedBufferList.h"
#include "nsAlgorithm.h"
// for |copy_string|
#include <new.h>
void
@ -45,25 +48,24 @@ nsSharedBufferList::~nsSharedBufferList()
}
template <class CharT>
nsSharedBufferList::Buffer*
nsSharedBufferList::NewBuffer( const CharT* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
nsSharedBufferList::NewBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace )
{
size_t object_size = ((sizeof(Buffer) + sizeof(CharT) - 1) / sizeof(CharT)) * sizeof(CharT);
size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar);
PRUint32 buffer_length = aDataLength + aAdditionalSpace;
size_t buffer_size = size_t(buffer_length) * sizeof(CharT);
size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar);
void* object_ptr = operator new(object_size + buffer_size);
if ( object_ptr )
{
typedef CharT* CharT_ptr;
CharT* buffer_ptr = CharT_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
typedef PRUnichar* PRUnichar_ptr;
PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size);
if ( aDataLength )
{
CharT* toBegin = buffer_ptr;
PRUnichar* toBegin = buffer_ptr;
copy_string(aData, aData+aDataLength, toBegin);
}
return new (object_ptr) Buffer(buffer_ptr, buffer_length, aDataLength);
return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length);
}
return 0;
@ -80,12 +82,12 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer*
NS_ASSERTION(aNextBuffer || mLastBuffer == aPrevBuffer, "aNextBuffer || mLastBuffer == aPrevBuffer");
NS_ASSERTION(!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer, "!aNextBuffer || aNextBuffer->mPrev == aPrevBuffer");
if ( aNewBuffer->mPrev = aPrevBuffer )
if ( (aNewBuffer->mPrev = aPrevBuffer) )
aPrevBuffer->mNext = aNewBuffer;
else
mFirstBuffer = aNewBuffer;
if ( aNewBuffer->mNext = aNextBuffer )
if ( (aNewBuffer->mNext = aNextBuffer) )
aNextBuffer->mPrev = aNewBuffer;
else
mLastBuffer = aNewBuffer;
@ -94,23 +96,27 @@ nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer*
}
void
nsSharedBufferList::SplitBuffer( Buffer* aBufferToSplit, PRUint32 aSplitPosition )
nsSharedBufferList::SplitBuffer( const Position& aSplitPosition )
{
NS_ASSERTION(aBufferToSplit, "aBufferToSplit");
NS_ASSERTION(aSplitPosition <= aBufferToSplit->DataLength(), "aSplitPosition <= aBufferToSplit->DataLength()");
Buffer* bufferToSplit = aSplitPosition.mBuffer;
if ( (aBufferToSplit->DataLength() >> 1) > aSplitPosition )
NS_ASSERTION(bufferToSplit, "bufferToSplit");
ptrdiff_t splitOffset = aSplitPosition.mPosInBuffer - bufferToSplit->DataStart();
NS_ASSERTION(0 <= splitOffset && splitOffset <= bufferToSplit->DataLength(), "|splitOffset| within buffer");
if ( (bufferToSplit->DataLength() >> 1) > splitOffset )
{
Buffer* new_buffer = NewBuffer(aBufferToSplit->DataStart(), aSplitPosition);
LinkBuffer(aBufferToSplit->mPrev, new_buffer, aBufferToSplit);
aBufferToSplit->mDataStart += aSplitPosition;
aBufferToSplit->DataLength() -= aSplitPosition;
Buffer* new_buffer = NewBuffer(bufferToSplit->DataStart(), PRUint32(splitOffset));
LinkBuffer(bufferToSplit->mPrev, new_buffer, bufferToSplit);
bufferToSplit->DataStart(aSplitPosition.mPosInBuffer);
}
else
{
Buffer* new_buffer = NewBuffer(aBufferToSplit->mDataStart+aSplitPosition, aBufferToSplit->DataLength()-aSplitPosition);
LinkBuffer(aBufferToSplit, new_buffer, aBufferToSplit->mNext);
aBufferToSplit->DataLength() = aSplitPosition;
Buffer* new_buffer = NewBuffer(bufferToSplit->DataStart()+splitOffset, PRUint32(bufferToSplit->DataLength()-splitOffset));
LinkBuffer(bufferToSplit, new_buffer, bufferToSplit->mNext);
bufferToSplit->DataEnd(aSplitPosition.mPosInBuffer);
}
}