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 marek 1.12.14.1 static Uint32 _next_pow_2(Uint32 x, Uint32 minCap)
|
54 mike 1.2 {
|
55 dave.sudlik 1.6 // Check for potential overflow in x.
56 PEGASUS_CHECK_CAPACITY_OVERFLOW(x);
57
|
58 marek 1.12.14.1 if (x < minCap)
59 return minCap;
|
60 mike 1.2
61 x--;
62 x |= (x >> 1);
63 x |= (x >> 2);
64 x |= (x >> 4);
65 x |= (x >> 8);
66 x |= (x >> 16);
67 x++;
68
69 return x;
70 }
71
|
72 marek 1.12.14.1 static inline BufferRep* _allocate(Uint32 cap, Uint32 minCap)
|
73 mike 1.2 {
|
74 marek 1.12.14.1 if (cap < minCap)
75 cap = minCap;
|
76 gs.keenan 1.7
77 // Allocate an extra byte for null-termination performed by getData().
78 BufferRep* rep = (BufferRep*)malloc(sizeof(BufferRep) + cap + 1);
79
|
80 kumpf 1.5 if (!rep)
81 {
82 throw PEGASUS_STD(bad_alloc)();
83 }
|
84 mike 1.2 rep->cap = cap;
85 return rep;
86 }
87
|
88 kumpf 1.12 static inline BufferRep* _reallocate(BufferRep* rep, Uint32 cap)
|
89 mike 1.2 {
|
90 gs.keenan 1.7 // Allocate an extra byte for null-termination performed by getData().
91 rep = (BufferRep*)realloc(rep, sizeof(BufferRep) + cap + 1);
92
|
93 kumpf 1.5 if (!rep)
94 {
95 throw PEGASUS_STD(bad_alloc)();
96 }
|
97 mike 1.2 rep->cap = cap;
98 return rep;
99 }
100
101 Buffer::Buffer(const Buffer& x)
102 {
|
103 marek 1.12.14.1 _rep = _allocate(x._rep->cap, x._minCap);
|
104 mike 1.2 memcpy(_rep->data, x._rep->data, x._rep->size);
105 _rep->size = x._rep->size;
|
106 marek 1.12.14.1 _minCap=x._minCap;
|
107 mike 1.2 }
108
|
109 marek 1.12.14.1 Buffer::Buffer(const char* data, Uint32 size, Uint32 minCap): _minCap(minCap)
|
110 mike 1.2 {
|
111 marek 1.12.14.1 _rep = _allocate(size, _minCap);
|
112 mike 1.2 _rep->size = size;
113 memcpy(_rep->data, data, size);
114 }
115
116 Buffer& Buffer::operator=(const Buffer& x)
117 {
118 if (&x != this)
119 {
|
120 kumpf 1.10 if (x._rep->size > _rep->cap)
121 {
122 if (_rep->cap != 0)
123 free(_rep);
|
124 mike 1.2
|
125 marek 1.12.14.1 _rep = _allocate(x._rep->cap, x._minCap);
|
126 kumpf 1.10 }
|
127 mike 1.2
|
128 kumpf 1.10 memcpy(_rep->data, x._rep->data, x._rep->size);
129 _rep->size = x._rep->size;
|
130 marek 1.12.14.1 _minCap = x._minCap;
|
131 mike 1.2 }
132 return *this;
133 }
134
|
135 kumpf 1.12 void Buffer::_reserve_aux(Uint32 cap)
|
136 mike 1.2 {
|
137 gs.keenan 1.7 if (_rep->cap == 0)
|
138 mike 1.2 {
|
139 marek 1.12.14.1 _rep = _allocate(cap, _minCap);
|
140 kumpf 1.10 _rep->size = 0;
|
141 mike 1.2 }
142 else
|
143 marek 1.12.14.1 _rep = _reallocate(_rep, _next_pow_2(cap, _minCap));
|
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 marek 1.12.14.1 _rep = _allocate(_minCap, _minCap);
|
151 kumpf 1.10 _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 marek 1.12.14.1 _rep = _reallocate(_rep, _rep->cap ? (2 * _rep->cap) : _minCap);
|
158 dave.sudlik 1.6 }
|
159 mike 1.2 }
160
|
161 kumpf 1.12 void Buffer::insert(Uint32 pos, const char* data, Uint32 size)
|
162 mike 1.2 {
163 if (pos > _rep->size)
|
164 kumpf 1.10 return;
|
165 mike 1.2
|
166 kumpf 1.12 Uint32 cap = _rep->size + size;
167 Uint32 rem = _rep->size - pos;
|
168 mike 1.2
169 if (cap > _rep->cap)
170 {
|
171 marek 1.12.14.1 BufferRep* rep = _allocate(cap, _minCap);
|
172 kumpf 1.10 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 kumpf 1.12 void Buffer::remove(Uint32 pos, Uint32 size)
|
192 mike 1.2 {
193 if (pos + size > _rep->size)
|
194 kumpf 1.10 return;
|
195 mike 1.2
|
196 kumpf 1.12 Uint32 rem = _rep->size - (pos + size);
|
197 mike 1.2
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
|