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 //%/////////////////////////////////////////////////////////////////////////////
33
34 mike 1.2 #include <cstring>
35 #include "Buffer.h"
|
36 kumpf 1.5 #include "Pegasus/Common/InternalException.h"
|
37 mike 1.2
38 PEGASUS_NAMESPACE_BEGIN
39
|
40 gs.keenan 1.7 //
41 // Note: _empty_rep is the only BufferRep object that may have a zero capacity.
42 // So "_rep->cap == 0" implies "_rep == _empty_rep". But some platforms produce
|
43 kumpf 1.10 // more than one instance of _empty_rep (strangely). Therefore, it is safer to
|
44 gs.keenan 1.7 // use the former test rather than the latter.
45 //
|
46 kumpf 1.10 BufferRep Buffer::_empty_rep =
47 {
|
48 gs.keenan 1.7 0, /* size */
49 0, /* cap (zero implies it is the _empty_rep) */
50 {0} /* data[0] */
51 };
|
52 mike 1.2
|
53 mike 1.3 static const size_t MIN_CAPACITY = 2048;
|
54 mike 1.2
55 static Uint32 _next_pow_2(Uint32 x)
56 {
|
57 dave.sudlik 1.6 // Check for potential overflow in x.
58 PEGASUS_CHECK_CAPACITY_OVERFLOW(x);
59
|
60 mike 1.2 if (x < MIN_CAPACITY)
|
61 kumpf 1.10 return MIN_CAPACITY;
|
62 mike 1.2
63 x--;
64 x |= (x >> 1);
65 x |= (x >> 2);
66 x |= (x >> 4);
67 x |= (x >> 8);
68 x |= (x >> 16);
69 x++;
70
71 return x;
72 }
73
74 static inline BufferRep* _allocate(size_t cap)
75 {
|
76 gs.keenan 1.7 if (cap < MIN_CAPACITY)
|
77 kumpf 1.10 cap = MIN_CAPACITY;
|
78 gs.keenan 1.7
79 // Allocate an extra byte for null-termination performed by getData().
80 BufferRep* rep = (BufferRep*)malloc(sizeof(BufferRep) + cap + 1);
81
|
82 kumpf 1.5 if (!rep)
83 {
84 throw PEGASUS_STD(bad_alloc)();
85 }
|
86 mike 1.2 rep->cap = cap;
87 return rep;
88 }
89
90 static inline BufferRep* _reallocate(BufferRep* rep, size_t cap)
91 {
|
92 gs.keenan 1.7 // Allocate an extra byte for null-termination performed by getData().
93 rep = (BufferRep*)realloc(rep, sizeof(BufferRep) + cap + 1);
94
|
95 kumpf 1.5 if (!rep)
96 {
97 throw PEGASUS_STD(bad_alloc)();
98 }
|
99 mike 1.2 rep->cap = cap;
100 return rep;
101 }
102
103 Buffer::Buffer(const Buffer& x)
104 {
105 _rep = _allocate(x._rep->cap);
106 memcpy(_rep->data, x._rep->data, x._rep->size);
107 _rep->size = x._rep->size;
108 }
109
110 Buffer::Buffer(const char* data, size_t size)
111 {
112 _rep = _allocate(size);
113 _rep->size = size;
114 memcpy(_rep->data, data, size);
115 }
116
117 Buffer& Buffer::operator=(const Buffer& x)
118 {
119 if (&x != this)
120 mike 1.2 {
|
121 kumpf 1.10 if (x._rep->size > _rep->cap)
122 {
123 if (_rep->cap != 0)
124 free(_rep);
|
125 mike 1.2
|
126 kumpf 1.10 _rep = _allocate(x._rep->cap);
127 }
|
128 mike 1.2
|
129 kumpf 1.10 memcpy(_rep->data, x._rep->data, x._rep->size);
130 _rep->size = x._rep->size;
|
131 mike 1.2 }
132 return *this;
133 }
134
135 void Buffer::_reserve_aux(size_t cap)
136 {
|
137 gs.keenan 1.7 if (_rep->cap == 0)
|
138 mike 1.2 {
|
139 kumpf 1.10 _rep = _allocate(cap);
140 _rep->size = 0;
|
141 mike 1.2 }
142 else
|
143 kumpf 1.10 _rep = _reallocate(_rep, _next_pow_2(cap));
|
144 mike 1.2 }
145
146 void Buffer::_append_char_aux()
147 {
|
148 gs.keenan 1.7 if (_rep->cap == 0)
|
149 mike 1.2 {
|
150 kumpf 1.10 _rep = _allocate(MIN_CAPACITY);
151 _rep->size = 0;
|
152 mike 1.2 }
153 else
|
154 dave.sudlik 1.6 {
155 // Check for potential overflow.
156 PEGASUS_CHECK_CAPACITY_OVERFLOW(_rep->cap);
157 _rep = _reallocate(_rep, _rep->cap ? (2 * _rep->cap) : MIN_CAPACITY);
158 }
|
159 mike 1.2 }
160
161 void Buffer::insert(size_t pos, const char* data, size_t size)
162 {
163 if (pos > _rep->size)
|
164 kumpf 1.10 return;
|
165 mike 1.2
|
166 kumpf 1.10 size_t cap = _rep->size + size;
|
167 mike 1.2 size_t rem = _rep->size - pos;
168
169 if (cap > _rep->cap)
170 {
|
171 kumpf 1.10 BufferRep* rep = _allocate(cap);
172 rep->size = cap;
|
173 mike 1.2
|
174 kumpf 1.10 memcpy(rep->data, _rep->data, pos);
175 memcpy(rep->data + pos, data, size);
176 memcpy(rep->data + pos + size, _rep->data + pos, rem);
|
177 mike 1.2
|
178 kumpf 1.10 if (_rep->cap != 0)
179 free(_rep);
|
180 mike 1.2
|
181 kumpf 1.10 _rep = rep;
|
182 mike 1.2 }
183 else
184 {
185 memmove(_rep->data + pos + size, _rep->data + pos, rem);
|
186 kumpf 1.10 memcpy(_rep->data + pos, data, size);
187 _rep->size += size;
|
188 mike 1.2 }
189 }
190
191 void Buffer::remove(size_t pos, size_t size)
192 {
193 if (pos + size > _rep->size)
|
194 kumpf 1.10 return;
|
195 mike 1.2
196 size_t rem = _rep->size - (pos + size);
197
198 if (rem)
|
199 kumpf 1.10 memmove(_rep->data + pos, _rep->data + pos + size, rem);
|
200 mike 1.2
201 _rep->size -= size;
202 }
203
204 PEGASUS_NAMESPACE_END
|