(file) Return to Buffer.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  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.5 #include "Pegasus/Common/InternalException.h"
 39 mike  1.2 
 40           PEGASUS_NAMESPACE_BEGIN
 41           
 42 gs.keenan 1.7 //
 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.6     // 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.7     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.5     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.7     // Allocate an extra byte for null-termination performed by getData().
 95                     rep = (BufferRep*)realloc(rep, sizeof(BufferRep) + cap + 1);
 96                 
 97 kumpf       1.5     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.7 	    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.7     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.7     if (_rep->cap == 0)
151 mike        1.2     {
152                 	_rep = _allocate(MIN_CAPACITY);
153                 	_rep->size = 0;
154                     }
155                     else
156 dave.sudlik 1.6     {
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.7 	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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2