You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
161 lines
4.2 KiB
161 lines
4.2 KiB
// table.cpp --
|
|
// $Id$
|
|
// This is part of Metakit, the homepage is http://www.equi4.com/metakit/
|
|
|
|
/** @file
|
|
* Loose ends, these should be moved
|
|
*/
|
|
|
|
#include "header.h"
|
|
#include "handler.h"
|
|
#include "store.h"
|
|
#include "field.h"
|
|
#include "format.h"
|
|
#include "persist.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Implemented in this file
|
|
|
|
class c4_Bytes;
|
|
class c4_HandlerSeq;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/** @class c4_Bytes
|
|
*
|
|
* Generic data buffer, with optional automatic clean up.
|
|
*
|
|
* These objects are used to pass around untyped data without concern about
|
|
* clean-up. They know whether the bytes need to be de-allocated when these
|
|
* objects go out of scope. Small amounts of data are stored in the object.
|
|
*
|
|
* Objects of this class are used a lot within Metakit to manipulate its own
|
|
* data items generically. The c4_BytesProp class allows storing binary
|
|
* data explicitly in a file. If such data files must be portable, then the
|
|
* application itself must define a generic format to deal with byte order.
|
|
*
|
|
* How to store an object in binary form in a row (this is not portable):
|
|
* @code
|
|
* struct MyStruct { ... };
|
|
* MyStruct something;
|
|
*
|
|
* c4_BytesProp pData ("Data");
|
|
* c4_Row row;
|
|
*
|
|
* pData (row) = c4_Bytes (&something, sizeof something);
|
|
* @endcode
|
|
*/
|
|
|
|
/// Construct an object with contents, optionally as a copy
|
|
c4_Bytes::c4_Bytes (const void* buf_, int len_, bool copy_)
|
|
: _size (len_), _copy (copy_)
|
|
{
|
|
_contents = (t4_byte*) buf_; // moved out of intializers for DEC CXX 5.7
|
|
if (_copy)
|
|
_MakeCopy();
|
|
}
|
|
|
|
/// Copy constructor
|
|
c4_Bytes::c4_Bytes (const c4_Bytes& src_)
|
|
: _size (src_._size), _copy (src_._copy)
|
|
{
|
|
_contents = src_._contents; // moved out of intializers for DEC CXX 5.7
|
|
if (_copy || _contents == src_._buffer)
|
|
_MakeCopy();
|
|
}
|
|
|
|
/// Assignment, this may make a private copy of contents
|
|
c4_Bytes& c4_Bytes::operator= (const c4_Bytes& src_)
|
|
{
|
|
if (&src_ != this)
|
|
{
|
|
_LoseCopy();
|
|
|
|
_contents = src_._contents;
|
|
_size = src_._size;
|
|
_copy = src_._copy;
|
|
|
|
if (_copy || _contents == src_._buffer)
|
|
_MakeCopy();
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// Swap the contents and ownership of two byte objects
|
|
void c4_Bytes::Swap(c4_Bytes& bytes_)
|
|
{
|
|
t4_byte* p = _contents;
|
|
int s = _size;
|
|
bool c = _copy;
|
|
|
|
_contents = bytes_._contents;
|
|
_size = bytes_._size;
|
|
_copy = bytes_._copy;
|
|
|
|
bytes_._contents = p;
|
|
bytes_._size = s;
|
|
bytes_._copy = c;
|
|
|
|
// if either one is using its local buffer, swap those too
|
|
if (_contents == bytes_._buffer || p == _buffer)
|
|
{
|
|
t4_byte t [sizeof _buffer];
|
|
|
|
memcpy(t, _buffer, sizeof _buffer);
|
|
memcpy(_buffer, bytes_._buffer, sizeof _buffer);
|
|
memcpy(bytes_._buffer, t, sizeof _buffer);
|
|
|
|
if (_contents == bytes_._buffer)
|
|
_contents = _buffer;
|
|
|
|
if (bytes_._contents == _buffer)
|
|
bytes_._contents = bytes_._buffer;
|
|
}
|
|
}
|
|
|
|
/// Define contents as a freshly allocated buffer of given size
|
|
t4_byte* c4_Bytes::SetBuffer(int length_)
|
|
{
|
|
/* No substantial improvement measured:
|
|
Perhaps keep a correctly sized c4_Bytes object in each property?
|
|
It means c4_...Ref objects would need to store a pointer, not an id.
|
|
|
|
if (length_ == _size)
|
|
return _contents; // no work needed, get out fast
|
|
*/
|
|
_LoseCopy();
|
|
|
|
_size = length_;
|
|
_copy = _size > (int) sizeof _buffer;
|
|
|
|
return _contents = _copy ? d4_new t4_byte [_size] : _buffer;
|
|
}
|
|
|
|
/// Allocate a buffer and fills its contents with zero bytes
|
|
t4_byte* c4_Bytes::SetBufferClear(int length_)
|
|
{
|
|
return (t4_byte*) memset(SetBuffer(length_), 0, length_);
|
|
}
|
|
|
|
void c4_Bytes::_MakeCopy()
|
|
{
|
|
d4_assert(_contents != 0);
|
|
|
|
_copy = _size > (int) sizeof _buffer;
|
|
|
|
if (_size > 0)
|
|
_contents = (t4_byte*) memcpy(_copy ? d4_new t4_byte [_size]
|
|
: _buffer, _contents, _size);
|
|
}
|
|
|
|
/// Return true if the contents of both objects are equal
|
|
bool operator== (const c4_Bytes& a_, const c4_Bytes& b_)
|
|
{
|
|
return a_._contents == b_._contents ||
|
|
(a_._size == b_._size &&
|
|
memcmp(a_._contents, b_._contents, a_._size) == 0);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|