1// table.cpp -- 2// $Id: table.cpp 1230 2007-03-09 15:58:53Z jcw $ 3// This is part of Metakit, the homepage is http://www.equi4.com/metakit.html 4 5/** @file 6 * Loose ends, these should be moved 7 */ 8 9#include "header.h" 10#include "handler.h" 11#include "store.h" 12#include "field.h" 13#include "format.h" 14#include "persist.h" 15 16///////////////////////////////////////////////////////////////////////////// 17// Implemented in this file 18 19class c4_Bytes; 20class c4_HandlerSeq; 21 22///////////////////////////////////////////////////////////////////////////// 23 24/** @class c4_Bytes 25 * 26 * Generic data buffer, with optional automatic clean up. 27 * 28 * These objects are used to pass around untyped data without concern about 29 * clean-up. They know whether the bytes need to be de-allocated when these 30 * objects go out of scope. Small amounts of data are stored in the object. 31 * 32 * Objects of this class are used a lot within Metakit to manipulate its own 33 * data items generically. The c4_BytesProp class allows storing binary 34 * data explicitly in a file. If such data files must be portable, then the 35 * application itself must define a generic format to deal with byte order. 36 * 37 * How to store an object in binary form in a row (this is not portable): 38 * @code 39 * struct MyStruct { ... }; 40 * MyStruct something; 41 * 42 * c4_BytesProp pData ("Data"); 43 * c4_Row row; 44 * 45 * pData (row) = c4_Bytes (&something, sizeof something); 46 * @endcode 47 */ 48 49/// Construct an object with contents, optionally as a copy 50c4_Bytes::c4_Bytes(const void *buf_, int len_, bool copy_): _size(len_), _copy 51 (copy_) { 52 _contents = (t4_byte*)buf_; // moved out of intializers for DEC CXX 5.7 53 if (_copy) 54 _MakeCopy(); 55} 56 57/// Copy constructor 58c4_Bytes::c4_Bytes(const c4_Bytes &src_): _size(src_._size), _copy(src_._copy) { 59 _contents = src_._contents; // moved out of intializers for DEC CXX 5.7 60 if (_copy || _contents == src_._buffer) 61 _MakeCopy(); 62} 63 64/// Assignment, this may make a private copy of contents 65c4_Bytes &c4_Bytes::operator = (const c4_Bytes &src_) { 66 if (&src_ != this) { 67 _LoseCopy(); 68 69 _contents = src_._contents; 70 _size = src_._size; 71 _copy = src_._copy; 72 73 if (_copy || _contents == src_._buffer) 74 _MakeCopy(); 75 } 76 77 return *this; 78} 79 80/// Swap the contents and ownership of two byte objects 81void c4_Bytes::Swap(c4_Bytes &bytes_) { 82 t4_byte *p = _contents; 83 int s = _size; 84 bool c = _copy; 85 86 _contents = bytes_._contents; 87 _size = bytes_._size; 88 _copy = bytes_._copy; 89 90 bytes_._contents = p; 91 bytes_._size = s; 92 bytes_._copy = c; 93 94 // if either one is using its local buffer, swap those too 95 if (_contents == bytes_._buffer || p == _buffer) { 96 t4_byte t[sizeof _buffer]; 97 98 memcpy(t, _buffer, sizeof _buffer); 99 memcpy(_buffer, bytes_._buffer, sizeof _buffer); 100 memcpy(bytes_._buffer, t, sizeof _buffer); 101 102 if (_contents == bytes_._buffer) 103 _contents = _buffer; 104 105 if (bytes_._contents == _buffer) 106 bytes_._contents = bytes_._buffer; 107 } 108} 109 110/// Define contents as a freshly allocated buffer of given size 111t4_byte *c4_Bytes::SetBuffer(int length_) { 112 /* No substantial improvement measured: 113 Perhaps keep a correctly sized c4_Bytes object in each property? 114 It means c4_...Ref objects would need to store a pointer, not an id. 115 116 if (length_ == _size) 117 return _contents; // no work needed, get out fast 118 */ 119 _LoseCopy(); 120 121 _size = length_; 122 _copy = _size > (int)sizeof _buffer; 123 124 return _contents = _copy ? d4_new t4_byte[_size]: _buffer; 125} 126 127/// Allocate a buffer and fills its contents with zero bytes 128t4_byte *c4_Bytes::SetBufferClear(int length_) { 129 return (t4_byte*)memset(SetBuffer(length_), 0, length_); 130} 131 132void c4_Bytes::_MakeCopy() { 133 d4_assert(_contents != 0); 134 135 _copy = _size > (int)sizeof _buffer; 136 137 if (_size > 0) 138 _contents = (t4_byte*)memcpy(_copy ? d4_new t4_byte[_size]: _buffer, 139 _contents, _size); 140} 141 142/// Return true if the contents of both objects are equal 143bool operator == (const c4_Bytes &a_, const c4_Bytes &b_) { 144 return a_._contents == b_._contents || (a_._size == b_._size && memcmp 145 (a_._contents, b_._contents, a_._size) == 0); 146} 147 148///////////////////////////////////////////////////////////////////////////// 149