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

  1 martin 1.14 //%LICENSE////////////////////////////////////////////////////////////////
  2 martin 1.15 //
  3 martin 1.14 // Licensed to The Open Group (TOG) under one or more contributor license
  4             // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5             // this work for additional information regarding copyright ownership.
  6             // Each contributor licenses this file to you under the OpenPegasus Open
  7             // Source License; you may not use this file except in compliance with the
  8             // License.
  9 martin 1.15 //
 10 martin 1.14 // Permission is hereby granted, free of charge, to any person obtaining a
 11             // copy of this software and associated documentation files (the "Software"),
 12             // to deal in the Software without restriction, including without limitation
 13             // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14             // and/or sell copies of the Software, and to permit persons to whom the
 15             // Software is furnished to do so, subject to the following conditions:
 16 martin 1.15 //
 17 martin 1.14 // The above copyright notice and this permission notice shall be included
 18             // in all copies or substantial portions of the Software.
 19 martin 1.15 //
 20 martin 1.14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21 martin 1.15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 martin 1.14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23             // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24             // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25             // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26             // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27 martin 1.15 //
 28 martin 1.14 //////////////////////////////////////////////////////////////////////////
 29 mike   1.2  //
 30             //%/////////////////////////////////////////////////////////////////////////////
 31             
 32             #include <cstring>
 33             #include "Buffer.h"
 34 kumpf  1.5  #include "Pegasus/Common/InternalException.h"
 35 mike   1.2  
 36             PEGASUS_NAMESPACE_BEGIN
 37             
 38 gs.keenan 1.7  //
 39                // Note: _empty_rep is the only BufferRep object that may have a zero capacity.
 40                // So "_rep->cap == 0" implies "_rep == _empty_rep". But some platforms produce
 41 kumpf     1.10 // more than one instance of _empty_rep (strangely). Therefore, it is safer to
 42 gs.keenan 1.7  // use the former test rather than the latter.
 43                //
 44 kumpf     1.10 BufferRep Buffer::_empty_rep =
 45                {
 46 gs.keenan 1.7      0, /* size */
 47                    0, /* cap (zero implies it is the _empty_rep) */
 48                    {0} /* data[0] */
 49                };
 50 mike      1.2  
 51 marek     1.13 static Uint32 _next_pow_2(Uint32 x, Uint32 minCap)
 52 mike      1.2  {
 53 dave.sudlik 1.6      // Check for potential overflow in x.
 54                      PEGASUS_CHECK_CAPACITY_OVERFLOW(x);
 55                  
 56 marek       1.13     if (x < minCap)
 57                          return minCap;
 58 mike        1.2  
 59                      x--;
 60                      x |= (x >> 1);
 61                      x |= (x >> 2);
 62                      x |= (x >> 4);
 63                      x |= (x >> 8);
 64                      x |= (x >> 16);
 65                      x++;
 66                  
 67                      return x;
 68                  }
 69                  
 70 marek       1.13 static inline BufferRep* _allocate(Uint32 cap, Uint32 minCap)
 71 mike        1.2  {
 72 marek       1.13     if (cap < minCap)
 73                          cap = minCap;
 74 gs.keenan   1.7  
 75                      // Allocate an extra byte for null-termination performed by getData().
 76                      BufferRep* rep = (BufferRep*)malloc(sizeof(BufferRep) + cap + 1);
 77                  
 78 kumpf       1.5      if (!rep)
 79                      {
 80                          throw PEGASUS_STD(bad_alloc)();
 81                      }
 82 mike        1.2      rep->cap = cap;
 83                      return rep;
 84                  }
 85                  
 86 kumpf       1.12 static inline BufferRep* _reallocate(BufferRep* rep, Uint32 cap)
 87 mike        1.2  {
 88 gs.keenan   1.7      // Allocate an extra byte for null-termination performed by getData().
 89                      rep = (BufferRep*)realloc(rep, sizeof(BufferRep) + cap + 1);
 90                  
 91 kumpf       1.5      if (!rep)
 92                      {
 93                          throw PEGASUS_STD(bad_alloc)();
 94                      }
 95 mike        1.2      rep->cap = cap;
 96                      return rep;
 97                  }
 98                  
 99                  Buffer::Buffer(const Buffer& x)
100                  {
101 marek       1.13     _rep = _allocate(x._rep->cap, x._minCap);
102 mike        1.2      memcpy(_rep->data, x._rep->data, x._rep->size);
103                      _rep->size = x._rep->size;
104 marek       1.13     _minCap=x._minCap;
105 mike        1.2  }
106                  
107 marek       1.13 Buffer::Buffer(const char* data, Uint32 size, Uint32 minCap): _minCap(minCap)
108 mike        1.2  {
109 marek       1.13     _rep = _allocate(size, _minCap);
110 mike        1.2      _rep->size = size;
111                      memcpy(_rep->data, data, size);
112                  }
113                  
114                  Buffer& Buffer::operator=(const Buffer& x)
115                  {
116                      if (&x != this)
117                      {
118 kumpf       1.10         if (x._rep->size > _rep->cap)
119                          {
120                              if (_rep->cap != 0)
121                                  free(_rep);
122 mike        1.2  
123 marek       1.13             _rep = _allocate(x._rep->cap, x._minCap);
124 kumpf       1.10         }
125 mike        1.2  
126 kumpf       1.10         memcpy(_rep->data, x._rep->data, x._rep->size);
127                          _rep->size = x._rep->size;
128 marek       1.13         _minCap = x._minCap;
129 mike        1.2      }
130                      return *this;
131                  }
132                  
133 kumpf       1.12 void Buffer::_reserve_aux(Uint32 cap)
134 mike        1.2  {
135 gs.keenan   1.7      if (_rep->cap == 0)
136 mike        1.2      {
137 marek       1.13         _rep = _allocate(cap, _minCap);
138 kumpf       1.10         _rep->size = 0;
139 mike        1.2      }
140                      else
141 marek       1.13         _rep = _reallocate(_rep, _next_pow_2(cap, _minCap));
142 mike        1.2  }
143                  
144                  void Buffer::_append_char_aux()
145                  {
146 gs.keenan   1.7      if (_rep->cap == 0)
147 mike        1.2      {
148 marek       1.13         _rep = _allocate(_minCap, _minCap);
149 kumpf       1.10         _rep->size = 0;
150 mike        1.2      }
151                      else
152 dave.sudlik 1.6      {
153                          // Check for potential overflow.
154                          PEGASUS_CHECK_CAPACITY_OVERFLOW(_rep->cap);
155 marek       1.13         _rep = _reallocate(_rep, _rep->cap ? (2 * _rep->cap) : _minCap);
156 dave.sudlik 1.6      }
157 mike        1.2  }
158                  
159 kumpf       1.12 void Buffer::insert(Uint32 pos, const char* data, Uint32 size)
160 mike        1.2  {
161                      if (pos > _rep->size)
162 kumpf       1.10         return;
163 mike        1.2  
164 kumpf       1.12     Uint32 cap = _rep->size + size;
165                      Uint32 rem = _rep->size - pos;
166 mike        1.2  
167                      if (cap > _rep->cap)
168                      {
169 marek       1.13         BufferRep* rep = _allocate(cap, _minCap);
170 kumpf       1.10         rep->size = cap;
171 mike        1.2  
172 kumpf       1.10         memcpy(rep->data, _rep->data, pos);
173                          memcpy(rep->data + pos, data, size);
174                          memcpy(rep->data + pos + size, _rep->data + pos, rem);
175 mike        1.2  
176 kumpf       1.10         if (_rep->cap != 0)
177                              free(_rep);
178 mike        1.2  
179 kumpf       1.10         _rep = rep;
180 mike        1.2      }
181                      else
182                      {
183                          memmove(_rep->data + pos + size, _rep->data + pos, rem);
184 kumpf       1.10         memcpy(_rep->data + pos, data, size);
185                          _rep->size += size;
186 mike        1.2      }
187                  }
188                  
189 marek       1.16 void Buffer::insertWithOverlay(
190                      Uint32 pos,
191                      const char* data,
192                      Uint32 size,
193                      Uint32 overlay)
194                  {
195                      if (pos > _rep->size)
196                          return;
197                  
198                      Uint32 rem = _rep->size - pos;
199                  
200                      memmove(_rep->data + pos + size - overlay, _rep->data + pos, rem);
201                      memcpy(_rep->data + pos, data, size);
202                  
203                      _rep->size += (size-overlay);
204                  }
205                  
206 kumpf       1.12 void Buffer::remove(Uint32 pos, Uint32 size)
207 mike        1.2  {
208                      if (pos + size > _rep->size)
209 kumpf       1.10         return;
210 mike        1.2  
211 kumpf       1.12     Uint32 rem = _rep->size - (pos + size);
212 mike        1.2  
213                      if (rem)
214 kumpf       1.10         memmove(_rep->data + pos, _rep->data + pos + size, rem);
215 mike        1.2  
216                      _rep->size -= size;
217                  }
218                  
219                  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2