- acf-03.zip
- Acf
- docs
- lib
- samples
- Corlib
- Arrays
- Boxing
- Delegate
- Environment
- Event
- FileSystem
- Foreach
- MFCReadWrite
- ReadWrite
- RegViewer
- Samples.sln
- Samples.txt
- Strings
- Threads
- Timer
- src
- Corlib
- Acf.Collections
- Acf.Globalization
- Acf.IO
- Acf.Microsoft.Win32
- Acf.Text
- Acf.Threading
- Acf
- AcfCorlib.H
- Corlib.sln
- Corlib.vcproj
- StdAfx.cpp
- StdAfx.h
- Pal
- tests
- Corlib
- Double
- ToString
- Int32
- Parse
- ToString
- tools
- vcide
- AppWizards
- ConsoleApp
- ConsoleApp.txt
- VCProjects
- ACF
- AcfAppWiz.vsdir
- AcfAppWiz.ico
- AcfAppWiz.vsdir
- AcfAppWiz.vsz
- VCWizards
- AcfAppWiz
- Scripts
- 1033
- Templates
- 1033
- readme.txt
- usertype.dat
|
//---------------------------------------------------------------------
//
// Copyright (C) 2004 Yingle Jia
//
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// AcfAutoBuffer.h - defines class AutoBuffer
//
#ifndef __Acf_AutoBuffer__
#define __Acf_AutoBuffer__
namespace Acf {
//---------------------------------------------------------------------
// class AutoBuffer
//
// Implements a resizable buffer which automatically switchs between
// stack-based buffer and heap-based buffer. The stack buffer length
// can be specified at compile-time.
//
// This class is internally used by Array, String and StringBuilder.
//
template<typename T, int StackBufferLength = 128 / sizeof(T)>
class AutoBuffer
{
// Constants
private:
static const int StackBufferByteLength = StackBufferLength * sizeof(T);
static const int DataByteLength = StackBufferByteLength > sizeof(T*) ?
StackBufferByteLength : sizeof(T*);
// Fields
private:
#ifdef _DEBUG
T* _ptr; // pointer to the buffer (for debugging)
#endif // #ifdef _DEBUG
int _length;
byte _data[DataByteLength]; // heap pointer or stack buffer, i.e.
// union {
// T* _heapPtr;
// byte _buffer[StackBufferLength * sizeof(T)];
// };
T* ReinterpretGetStackBuffer()
{
return reinterpret_cast<T*>(this->_data);
}
T*& ReinterpretGetHeapPtrRef()
{
return *reinterpret_cast<T**>(this->_data);
}
T* InternalGetBuffer()
{
ACFASSERT(this->_length != 0);
if (StackBufferLength == 0)
return ReinterpretGetHeapPtrRef();
if (this->_length > StackBufferLength)
return ReinterpretGetHeapPtrRef();
else
return ReinterpretGetStackBuffer();
}
// Constructors
public:
AutoBuffer() : _length(0)
{
}
explicit AutoBuffer(int length) : _length(0)
{
SetLength(length);
}
// Destructor
public:
~AutoBuffer()
{
SetLength(0);
}
// Properties
public:
// Length
__declspec(property(get=get_Length)) int Length;
int get_Length()
{
return this->_length;
}
// []
const T& operator[](int index) const
{
if (index < 0 || index >= this->_length)
throw IndexOutOfRangeException();
return *(InternalGetBuffer() + index);
}
T& operator[](int index)
{
if (index < 0 || index >= this->_length)
throw IndexOutOfRangeException();
return *(InternalGetBuffer() + index);
}
// Methods
public:
T* GetBuffer()
{
if (this->_length == 0)
throw InvalidOperationException();
return InternalGetBuffer();
}
void SetLength(int value)
{
if (value < 0)
throw ArgumentOutOfRangeException();
if (this->_length == value)
return;
if (value > this->_length)
{
// Grow
if (value > StackBufferLength)
{
// New buffer on heap (old buffer can be stack or heap)
T* pOld = (this->_length == 0) ? null : InternalGetBuffer();
T* pNew = Acf::Alloc<T>(value);
// Copy old elements (may throw)
if (this->_length != 0)
{
try
{
Acf::Language::Construct(pNew, this->_length, pOld);
}
catch (...)
{
Acf::Free(pNew);
throw;
}
}
// Destruct old elements and free memory
if (this->_length != 0)
Acf::Language::Destruct(pOld, this->_length);
if (this->_length > StackBufferLength)
Acf::Free(pOld);
ReinterpretGetHeapPtrRef() = pNew;
}
else
{
// Both on stack (no need to copy, just call default constructors for
// the new elements)
T* p = ReinterpretGetStackBuffer();
memset(p + this->_length, 0, (value - this->_length) * sizeof(T));
Acf::Language::Construct(p + this->_length, value - this->_length);
}
}
else
{
// Shrink
if (this->_length > StackBufferLength)
{
// Old buffer on heap (new buffer can be stack or heap)
T* pOld = InternalGetBuffer();
T* pNew = null;
if (value > StackBufferLength)
{
pNew = Acf::Alloc<T>(value);
}
else
{
pNew = ReinterpretGetStackBuffer();
memset(pNew, 0, value * sizeof(T));
}
// Copy old elements
if (value != 0)
{
try
{
Acf::Language::Construct(pNew, value, pOld);
}
catch (...)
{
if (value > StackBufferLength)
Acf::Free(pNew);
throw;
}
}
// Destruct old elements and free memory
Acf::Language::Destruct(pOld, this->_length);
Acf::Free(pOld);
if (value > StackBufferLength)
ReinterpretGetHeapPtrRef() = pNew;
}
else
{
// Both on stack (no need to copy, just destruct the extra elements)
T* p = ReinterpretGetStackBuffer();
Acf::Language::Destruct(p + value, this->_length - value);
}
}
this->_length = value;
#ifdef _DEBUG
this->_ptr = (this->_length == 0) ? null : InternalGetBuffer();
#endif // #ifdef _DEBUG
}
private:
AutoBuffer(const AutoBuffer& src);
AutoBuffer& operator=(const AutoBuffer& src);
};
} // namespace Acf
#endif // #ifndef __Acf_AutoBuffer__
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here
Yingle Jia is a software engineer located in Beijing, China. He currently works at IBM CSDL (China Software Development Lab). His interests include C++/COM/C#/.NET/XML, etc. He likes coding and writing.
He is the creator of ACF (Another C++ Framework) project. See
http://acfproj.sourceforge.net/.
He also has a blog at
http://blogs.wwwcoder.com/yljia/