summaryrefslogtreecommitdiffstats
path: root/akregator/src/mk4storage/metakit/src/table.cpp
blob: a857cee097702ce4ca2db7c4b4dd0f213ac12142 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// 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);
}

/////////////////////////////////////////////////////////////////////////////