1 karl 1.4 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.4 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 // Author: Michael E. Brasher (mike-brasher@austin.rr.com -- Inova Europe)
33 //
34 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
35
36 #include <cstring>
37 #include "Buffer.h"
|
38 kumpf 1.4.2.1 #include "Pegasus/Common/InternalException.h"
|
39 mike 1.2
40 PEGASUS_NAMESPACE_BEGIN
41
|
42 gs.keenan 1.4.2.3 //
43 // Note: _empty_rep is the only BufferRep object that may have a zero capacity.
44 // So "_rep->cap == 0" implies "_rep == _empty_rep". But some platforms produce
45 // more than one instance of _empty_rep (strangely). Therefore, it is safer to
46 // use the former test rather than the latter.
47 //
48 BufferRep Buffer::_empty_rep =
49 {
50 0, /* size */
51 0, /* cap (zero implies it is the _empty_rep) */
52 {0} /* data[0] */
53 };
|
54 mike 1.2
|
55 mike 1.3 static const size_t MIN_CAPACITY = 2048;
|
56 mike 1.2
57 static Uint32 _next_pow_2(Uint32 x)
58 {
|
59 dave.sudlik 1.4.2.2 // Check for potential overflow in x.
60 PEGASUS_CHECK_CAPACITY_OVERFLOW(x);
61
|
62 mike 1.2 if (x < MIN_CAPACITY)
63 return MIN_CAPACITY;
64
65 x--;
66 x |= (x >> 1);
67 x |= (x >> 2);
68 x |= (x >> 4);
69 x |= (x >> 8);
70 x |= (x >> 16);
71 x++;
72
73 return x;
74 }
75
76 static inline BufferRep* _allocate(size_t cap)
77 {
|
78 gs.keenan 1.4.2.3 if (cap < MIN_CAPACITY)
79 cap = MIN_CAPACITY;
80
81 // Allocate an extra byte for null-termination performed by getData().
82 BufferRep* rep = (BufferRep*)malloc(sizeof(BufferRep) + cap + 1);
83
|
84 kumpf 1.4.2.1 if (!rep)
85 {
86 throw PEGASUS_STD(bad_alloc)();
87 }
|
88 mike 1.2 rep->cap = cap;
89 return rep;
90 }
91
92 static inline BufferRep* _reallocate(BufferRep* rep, size_t cap)
93 {
|
94 gs.keenan 1.4.2.3 // Allocate an extra byte for null-termination performed by getData().
95 rep = (BufferRep*)realloc(rep, sizeof(BufferRep) + cap + 1);
96
|
97 kumpf 1.4.2.1 if (!rep)
98 {
99 throw PEGASUS_STD(bad_alloc)();
100 }
|
101 mike 1.2 rep->cap = cap;
102 return rep;
103 }
104
105 Buffer::Buffer(const Buffer& x)
106 {
107 _rep = _allocate(x._rep->cap);
108 memcpy(_rep->data, x._rep->data, x._rep->size);
109 _rep->size = x._rep->size;
110 }
111
112 Buffer::Buffer(const char* data, size_t size)
113 {
114 _rep = _allocate(size);
115 _rep->size = size;
116 memcpy(_rep->data, data, size);
117 }
118
119 Buffer& Buffer::operator=(const Buffer& x)
120 {
121 if (&x != this)
122 mike 1.2 {
123 if (x._rep->size > _rep->cap)
124 {
|
125 gs.keenan 1.4.2.3 if (_rep->cap != 0)
|
126 mike 1.2 free(_rep);
127
128 _rep = _allocate(x._rep->cap);
129 }
130
131 memcpy(_rep->data, x._rep->data, x._rep->size);
132 _rep->size = x._rep->size;
133 }
134 return *this;
135 }
136
137 void Buffer::_reserve_aux(size_t cap)
138 {
|
139 gs.keenan 1.4.2.3 if (_rep->cap == 0)
|
140 mike 1.2 {
141 _rep = _allocate(cap);
142 _rep->size = 0;
143 }
144 else
145 _rep = _reallocate(_rep, _next_pow_2(cap));
146 }
147
148 void Buffer::_append_char_aux()
149 {
|
150 gs.keenan 1.4.2.3 if (_rep->cap == 0)
|
151 mike 1.2 {
152 _rep = _allocate(MIN_CAPACITY);
153 _rep->size = 0;
154 }
155 else
|
156 dave.sudlik 1.4.2.2 {
157 // Check for potential overflow.
158 PEGASUS_CHECK_CAPACITY_OVERFLOW(_rep->cap);
159 _rep = _reallocate(_rep, _rep->cap ? (2 * _rep->cap) : MIN_CAPACITY);
160 }
|
161 mike 1.2 }
162
163 void Buffer::insert(size_t pos, const char* data, size_t size)
164 {
165 if (pos > _rep->size)
166 return;
167
168 size_t cap = _rep->size + size;
169 size_t rem = _rep->size - pos;
170
171 if (cap > _rep->cap)
172 {
173 BufferRep* rep = _allocate(cap);
174 rep->size = cap;
175
176 memcpy(rep->data, _rep->data, pos);
177 memcpy(rep->data + pos, data, size);
178 memcpy(rep->data + pos + size, _rep->data + pos, rem);
179
|
180 gs.keenan 1.4.2.3 if (_rep->cap != 0)
|
181 mike 1.2 free(_rep);
182
183 _rep = rep;
184 }
185 else
186 {
187 memmove(_rep->data + pos + size, _rep->data + pos, rem);
188 memcpy(_rep->data + pos, data, size);
189 _rep->size += size;
190 }
191 }
192
193 void Buffer::remove(size_t pos, size_t size)
194 {
195 if (pos + size > _rep->size)
196 return;
197
198 size_t rem = _rep->size - (pos + size);
199
200 if (rem)
201 memmove(_rep->data + pos, _rep->data + pos + size, rem);
202 mike 1.2
203 _rep->size -= size;
204 }
205
206 PEGASUS_NAMESPACE_END
|