sl@0
|
1 |
// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
// e32\euser\cbase\ub_buf.cpp
|
sl@0
|
15 |
//
|
sl@0
|
16 |
//
|
sl@0
|
17 |
|
sl@0
|
18 |
#include "ub_std.h"
|
sl@0
|
19 |
|
sl@0
|
20 |
class TBufSegLink : public TDblQueLink
|
sl@0
|
21 |
{
|
sl@0
|
22 |
public:
|
sl@0
|
23 |
inline TBufSegLink() : iLen(0) {}
|
sl@0
|
24 |
inline TBufSegLink *Next() const {return((TBufSegLink *)iNext);}
|
sl@0
|
25 |
inline TBufSegLink *Prev() const {return((TBufSegLink *)iPrev);}
|
sl@0
|
26 |
public:
|
sl@0
|
27 |
TInt iLen;
|
sl@0
|
28 |
};
|
sl@0
|
29 |
|
sl@0
|
30 |
EXPORT_C CBufBase::CBufBase(TInt anExpandSize)
|
sl@0
|
31 |
//
|
sl@0
|
32 |
// Constructor
|
sl@0
|
33 |
//
|
sl@0
|
34 |
/**
|
sl@0
|
35 |
@internalComponent
|
sl@0
|
36 |
*/
|
sl@0
|
37 |
{
|
sl@0
|
38 |
|
sl@0
|
39 |
__ASSERT_ALWAYS(anExpandSize>=0,Panic(EBufExpandSizeNegative));
|
sl@0
|
40 |
// iSize=0;
|
sl@0
|
41 |
iExpandSize=anExpandSize;
|
sl@0
|
42 |
}
|
sl@0
|
43 |
|
sl@0
|
44 |
EXPORT_C CBufBase::~CBufBase()
|
sl@0
|
45 |
/**
|
sl@0
|
46 |
Destructor
|
sl@0
|
47 |
*/
|
sl@0
|
48 |
{
|
sl@0
|
49 |
}
|
sl@0
|
50 |
|
sl@0
|
51 |
EXPORT_C void CBufBase::Reset()
|
sl@0
|
52 |
/**
|
sl@0
|
53 |
Deletes all data in the buffer.
|
sl@0
|
54 |
|
sl@0
|
55 |
Its behaviour is the same as calling Delete(0,Size()).
|
sl@0
|
56 |
The buffer is compressed before the function returns.
|
sl@0
|
57 |
*/
|
sl@0
|
58 |
{
|
sl@0
|
59 |
|
sl@0
|
60 |
if (iSize)
|
sl@0
|
61 |
Delete(0,iSize);
|
sl@0
|
62 |
Compress();
|
sl@0
|
63 |
}
|
sl@0
|
64 |
|
sl@0
|
65 |
EXPORT_C void CBufBase::Read(TInt aPos,TDes8 &aDes) const
|
sl@0
|
66 |
//
|
sl@0
|
67 |
// Read up to aDes.MaxLength() bytes.
|
sl@0
|
68 |
//
|
sl@0
|
69 |
/**
|
sl@0
|
70 |
Reads data from the buffer into a descriptor.
|
sl@0
|
71 |
|
sl@0
|
72 |
Data, starting at the specified buffer position is written to the descriptor,
|
sl@0
|
73 |
filling the descriptor.
|
sl@0
|
74 |
|
sl@0
|
75 |
@param aPos Buffer position from which data is read: must be in range zero
|
sl@0
|
76 |
to Size().
|
sl@0
|
77 |
@param aDes On return, contains the data read from the buffer; its MaxLength()
|
sl@0
|
78 |
specifies the amount of data to be read.
|
sl@0
|
79 |
*/
|
sl@0
|
80 |
{
|
sl@0
|
81 |
|
sl@0
|
82 |
Read(aPos,aDes,aDes.MaxLength());
|
sl@0
|
83 |
}
|
sl@0
|
84 |
|
sl@0
|
85 |
EXPORT_C void CBufBase::Read(TInt aPos,TDes8 &aDes,TInt aLength) const
|
sl@0
|
86 |
/**
|
sl@0
|
87 |
Reads the specified number of bytes of data from the buffer into a descriptor.
|
sl@0
|
88 |
|
sl@0
|
89 |
@param aPos Buffer position from which data is read: must be in range zero
|
sl@0
|
90 |
to (Size() minus the length of the data to be read).
|
sl@0
|
91 |
@param aDes On return, contains data read from the buffer.
|
sl@0
|
92 |
@param aLength The length of the data to be read.
|
sl@0
|
93 |
*/
|
sl@0
|
94 |
{
|
sl@0
|
95 |
|
sl@0
|
96 |
aDes.SetLength(aLength);
|
sl@0
|
97 |
Read(aPos,(TAny *)aDes.Ptr(),aLength);
|
sl@0
|
98 |
}
|
sl@0
|
99 |
|
sl@0
|
100 |
EXPORT_C void CBufBase::Read(TInt aPos,TAny *aPtr,TInt aLength) const
|
sl@0
|
101 |
/**
|
sl@0
|
102 |
Reads the specified number of bytes of data from the buffer into a specified
|
sl@0
|
103 |
address.
|
sl@0
|
104 |
|
sl@0
|
105 |
@param aPos Buffer position from which data is read: must be in range zero
|
sl@0
|
106 |
to (Size() minus the length of the data to be read).
|
sl@0
|
107 |
@param aPtr The address into which the data should be read.
|
sl@0
|
108 |
@param aLength The length of the data to be read.
|
sl@0
|
109 |
*/
|
sl@0
|
110 |
{
|
sl@0
|
111 |
|
sl@0
|
112 |
if (aLength==0)
|
sl@0
|
113 |
return;
|
sl@0
|
114 |
__ASSERT_ALWAYS(aLength>0,Panic(EBufReadLengthNegative));
|
sl@0
|
115 |
__ASSERT_ALWAYS((aPos+aLength)<=iSize,Panic(EBufReadBeyondEnd));
|
sl@0
|
116 |
TUint8 *pT=(TUint8 *)aPtr;
|
sl@0
|
117 |
while (aLength)
|
sl@0
|
118 |
{
|
sl@0
|
119 |
TPtr8 p=((CBufBase *)this)->Ptr(aPos);
|
sl@0
|
120 |
TInt s=Min(p.Length(),aLength);
|
sl@0
|
121 |
pT=Mem::Copy(pT,p.Ptr(),s);
|
sl@0
|
122 |
aLength-=s;
|
sl@0
|
123 |
aPos+=s;
|
sl@0
|
124 |
}
|
sl@0
|
125 |
}
|
sl@0
|
126 |
|
sl@0
|
127 |
EXPORT_C void CBufBase::Write(TInt aPos,const TDesC8 &aDes)
|
sl@0
|
128 |
//
|
sl@0
|
129 |
// Write aDes.Length() characters to the buffer. Does not cause any expansion.
|
sl@0
|
130 |
//
|
sl@0
|
131 |
/**
|
sl@0
|
132 |
Writes data from a descriptor to the buffer.
|
sl@0
|
133 |
|
sl@0
|
134 |
The data in the descriptor overwrites the data in the buffer from the insertion
|
sl@0
|
135 |
point onwards.
|
sl@0
|
136 |
|
sl@0
|
137 |
No new space is allocated; this function cannot fail (provided the parameters
|
sl@0
|
138 |
are specified within the bounds of the buffer and descriptor).
|
sl@0
|
139 |
|
sl@0
|
140 |
No shuffling occurs; new data is written to the memory locations occupied
|
sl@0
|
141 |
by the data it overwrites.
|
sl@0
|
142 |
|
sl@0
|
143 |
@param aPos Buffer position at which data will begin to be written; must be
|
sl@0
|
144 |
in range zero to (Size() minus the length of the data
|
sl@0
|
145 |
to be written).
|
sl@0
|
146 |
@param aDes Contains the data to be written. The length of data to be written
|
sl@0
|
147 |
is the descriptor length.
|
sl@0
|
148 |
*/
|
sl@0
|
149 |
{
|
sl@0
|
150 |
|
sl@0
|
151 |
Write(aPos,aDes.Ptr(),aDes.Length());
|
sl@0
|
152 |
}
|
sl@0
|
153 |
|
sl@0
|
154 |
EXPORT_C void CBufBase::Write(TInt aPos,const TDesC8 &aDes,TInt aLength)
|
sl@0
|
155 |
//
|
sl@0
|
156 |
// Write aDes.Length() characters to the buffer. Does not cause any expansion.
|
sl@0
|
157 |
//
|
sl@0
|
158 |
/**
|
sl@0
|
159 |
Writes the specified number of bytes of data from a descriptor to the buffer.
|
sl@0
|
160 |
|
sl@0
|
161 |
The data in the descriptor overwrites the data in the buffer from the insertion
|
sl@0
|
162 |
point onwards.
|
sl@0
|
163 |
|
sl@0
|
164 |
No new space is allocated; this function cannot fail (provided the parameters
|
sl@0
|
165 |
are specified within the bounds of the buffer and descriptor).
|
sl@0
|
166 |
|
sl@0
|
167 |
No shuffling occurs; new data is written to the memory locations occupied
|
sl@0
|
168 |
by the data it overwrites.
|
sl@0
|
169 |
|
sl@0
|
170 |
@param aPos Buffer position at which data will begin to be written; must be
|
sl@0
|
171 |
in range zero to (Size() minus the length of the data to
|
sl@0
|
172 |
be written).
|
sl@0
|
173 |
@param aDes Contains the data to be written.
|
sl@0
|
174 |
@param aLength The length of the data to be written.
|
sl@0
|
175 |
*/
|
sl@0
|
176 |
{
|
sl@0
|
177 |
|
sl@0
|
178 |
Write(aPos,aDes.Ptr(),aLength);
|
sl@0
|
179 |
}
|
sl@0
|
180 |
|
sl@0
|
181 |
EXPORT_C void CBufBase::Write(TInt aPos,const TAny *aPtr,TInt aLength)
|
sl@0
|
182 |
/**
|
sl@0
|
183 |
Writes the specified number of bytes of data from the specified address to the
|
sl@0
|
184 |
buffer.
|
sl@0
|
185 |
|
sl@0
|
186 |
The data in the buffer is overwritten from the insertion point onwards.
|
sl@0
|
187 |
|
sl@0
|
188 |
No new space is allocated; this function cannot fail (provided the parameters
|
sl@0
|
189 |
are specified within the bounds of the buffer and descriptor).
|
sl@0
|
190 |
|
sl@0
|
191 |
No shuffling occurs: new data is written to the memory locations occupied
|
sl@0
|
192 |
by the data it overwrites.
|
sl@0
|
193 |
|
sl@0
|
194 |
@param aPos Buffer position at which data will begin to be written; must be
|
sl@0
|
195 |
in range zero to (Size() minus the length of the data to
|
sl@0
|
196 |
be written).
|
sl@0
|
197 |
@param aPtr The address of the data to be written.
|
sl@0
|
198 |
@param aLength The length of the data to be written.
|
sl@0
|
199 |
|
sl@0
|
200 |
@panic E32USER-CBase 7, if aLength is not positive
|
sl@0
|
201 |
@panic E32USER-CBase 5, if aPos + aLength is greater than the number of
|
sl@0
|
202 |
data bytes in the buffer, i.e. if the target appears
|
sl@0
|
203 |
to be outside the buffer.
|
sl@0
|
204 |
*/
|
sl@0
|
205 |
{
|
sl@0
|
206 |
|
sl@0
|
207 |
if (aLength==0)
|
sl@0
|
208 |
return;
|
sl@0
|
209 |
__ASSERT_ALWAYS(aLength>0,Panic(EBufWriteLengthNegative));
|
sl@0
|
210 |
__ASSERT_ALWAYS((aPos+aLength)<=iSize,Panic(EBufWriteBeyondEnd));
|
sl@0
|
211 |
const TUint8 *pS=(const TUint8 *)aPtr;
|
sl@0
|
212 |
while (aLength)
|
sl@0
|
213 |
{
|
sl@0
|
214 |
TPtr8 p=Ptr(aPos);
|
sl@0
|
215 |
TInt s=Min(p.Length(),aLength);
|
sl@0
|
216 |
Mem::Copy((TAny *)p.Ptr(),pS,s);
|
sl@0
|
217 |
pS+=s;
|
sl@0
|
218 |
aLength-=s;
|
sl@0
|
219 |
aPos+=s;
|
sl@0
|
220 |
}
|
sl@0
|
221 |
}
|
sl@0
|
222 |
|
sl@0
|
223 |
EXPORT_C void CBufBase::InsertL(TInt aPos,const TDesC8 &aDes)
|
sl@0
|
224 |
//
|
sl@0
|
225 |
// Insert aDes.Length() bytes into the buffer.
|
sl@0
|
226 |
//
|
sl@0
|
227 |
/**
|
sl@0
|
228 |
Inserts data into the buffer.
|
sl@0
|
229 |
|
sl@0
|
230 |
Data at and beyond the insertion position is moved to make way for the inserted
|
sl@0
|
231 |
data. Data before the insertion position remains in place.
|
sl@0
|
232 |
|
sl@0
|
233 |
Notes:
|
sl@0
|
234 |
|
sl@0
|
235 |
1. Insertion may require more buffer space to be allocated.
|
sl@0
|
236 |
|
sl@0
|
237 |
2. In the case of flat buffers, the buffer is extended by a ReAllocL() of the
|
sl@0
|
238 |
buffer's heap cell, to the smallest multiple of the granularity that will
|
sl@0
|
239 |
contain the data required. If this reallocation fails, the insertion is
|
sl@0
|
240 |
impossible and a leave occurs.
|
sl@0
|
241 |
|
sl@0
|
242 |
3. In the case of segmented buffers, a reallocation is performed if the segment
|
sl@0
|
243 |
containing the insertion position has insufficient space, and
|
sl@0
|
244 |
immediately-neighbouring segments cannot be used to contain the new data.
|
sl@0
|
245 |
As many new segments as are necessary to contain the inserted data are
|
sl@0
|
246 |
allocated. Each new segment's length is the buffer's granularity.
|
sl@0
|
247 |
If extension or new allocation fails, a leave occurs.
|
sl@0
|
248 |
|
sl@0
|
249 |
4. Insertion may also require data to be shuffled. In the case of flat buffers,
|
sl@0
|
250 |
data beyond the insertion point is shuffled up to create a gap; the new data
|
sl@0
|
251 |
is then inserted into this gap. In the case of segmented buffers, shuffling
|
sl@0
|
252 |
is minimised by inserting the new data into newly-allocated buffers, and
|
sl@0
|
253 |
shuffling only immediately-neighbouring buffers if possible. This may result
|
sl@0
|
254 |
in some wastage of space, but is much more time-efficient for large amounts
|
sl@0
|
255 |
of data.
|
sl@0
|
256 |
|
sl@0
|
257 |
@param aPos Buffer position before which the data will be inserted; must be
|
sl@0
|
258 |
in range zero to Size().
|
sl@0
|
259 |
@param aDes The data to be inserted; the length of the data is the descriptor
|
sl@0
|
260 |
length.
|
sl@0
|
261 |
|
sl@0
|
262 |
@leave KErrNoMemory If the insertion requires a bigger buffer, and the
|
sl@0
|
263 |
necessary allocation or re-allocation fails.
|
sl@0
|
264 |
*/
|
sl@0
|
265 |
{
|
sl@0
|
266 |
|
sl@0
|
267 |
InsertL(aPos,aDes.Ptr(),aDes.Length());
|
sl@0
|
268 |
}
|
sl@0
|
269 |
|
sl@0
|
270 |
EXPORT_C void CBufBase::InsertL(TInt aPos,const TDesC8 &aDes,TInt aLength)
|
sl@0
|
271 |
//
|
sl@0
|
272 |
// Insert aLength bytes into the buffer.
|
sl@0
|
273 |
//
|
sl@0
|
274 |
/**
|
sl@0
|
275 |
Inserts the specified number of bytes of data from a descriptor into
|
sl@0
|
276 |
the buffer.
|
sl@0
|
277 |
|
sl@0
|
278 |
aLength bytes of data from aDes are inserted into the buffer at aPos. Data at
|
sl@0
|
279 |
and beyond the insertion position is moved to make way for the inserted data.
|
sl@0
|
280 |
Data before the insertion position remains in place.
|
sl@0
|
281 |
|
sl@0
|
282 |
Notes:
|
sl@0
|
283 |
|
sl@0
|
284 |
1. Insertion may require more buffer space to be allocated.
|
sl@0
|
285 |
|
sl@0
|
286 |
2. In the case of flat buffers, the buffer is extended by a ReAllocL() of the
|
sl@0
|
287 |
buffer's heap cell, to the smallest multiple of the granularity that will
|
sl@0
|
288 |
contain the data required. If this reallocation fails, the insertion is
|
sl@0
|
289 |
impossible and a leave occurs.
|
sl@0
|
290 |
|
sl@0
|
291 |
3. In the case of segmented buffers, a reallocation is performed if the segment
|
sl@0
|
292 |
containing the insertion position has insufficient space, and
|
sl@0
|
293 |
immediately-neighbouring segments cannot be used to contain the new data.
|
sl@0
|
294 |
As many new segments as are necessary to contain the inserted data are
|
sl@0
|
295 |
allocated. Each new segment's length is the buffer's granularity.
|
sl@0
|
296 |
If extension or new allocation fails, a leave occurs.
|
sl@0
|
297 |
|
sl@0
|
298 |
4. Insertion may also require data to be shuffled. In the case of flat buffers,
|
sl@0
|
299 |
data beyond the insertion point is shuffled up to create a gap: the new data
|
sl@0
|
300 |
is then inserted into this gap. In the case of segmented buffers, shuffling
|
sl@0
|
301 |
is minimised by inserting the new data into newly-allocated buffers,
|
sl@0
|
302 |
and shuffling only immediately-neighbouring buffers if possible.
|
sl@0
|
303 |
This may result in some wastage of space, but is much more time-efficient
|
sl@0
|
304 |
for large amounts of data.
|
sl@0
|
305 |
|
sl@0
|
306 |
@param aPos Buffer position before which the data will be inserted; must be
|
sl@0
|
307 |
in range zero to Size().
|
sl@0
|
308 |
@param aDes The data to be inserted.
|
sl@0
|
309 |
@param aLength The length of data to be inserted.
|
sl@0
|
310 |
|
sl@0
|
311 |
@leave KErrNoMemory If the insertion requires a bigger buffer, and the
|
sl@0
|
312 |
necessary allocation or re-allocation fails.
|
sl@0
|
313 |
*/
|
sl@0
|
314 |
{
|
sl@0
|
315 |
|
sl@0
|
316 |
InsertL(aPos,aDes.Ptr(),aLength);
|
sl@0
|
317 |
}
|
sl@0
|
318 |
|
sl@0
|
319 |
EXPORT_C void CBufBase::InsertL(TInt aPos,const TAny *aPtr,TInt aLength)
|
sl@0
|
320 |
/**
|
sl@0
|
321 |
Inserts bytes of data from the specified address into the buffer.
|
sl@0
|
322 |
|
sl@0
|
323 |
Inserts aLength bytes of data found at address aPtr into the buffer at aPos.
|
sl@0
|
324 |
Data at and beyond the insertion position is moved to make way for the inserted
|
sl@0
|
325 |
data. Data before the insertion position remains in place.
|
sl@0
|
326 |
|
sl@0
|
327 |
Notes:
|
sl@0
|
328 |
|
sl@0
|
329 |
1. Insertion may require more buffer space to be allocated.
|
sl@0
|
330 |
|
sl@0
|
331 |
2. In the case of flat buffers, the buffer is extended by a ReAllocL() of the
|
sl@0
|
332 |
buffer's heap cell, to the smallest multiple of the granularity that will
|
sl@0
|
333 |
contain the data required. If this reallocation fails, the insertion is
|
sl@0
|
334 |
impossible and a leave occurs.
|
sl@0
|
335 |
|
sl@0
|
336 |
2. In the case of segmented buffers, a reallocation is performed if the segment
|
sl@0
|
337 |
containing the insertion position has insufficient space, and
|
sl@0
|
338 |
immediately-neighbouring segments cannot be used to contain the new data.
|
sl@0
|
339 |
As many new segments as are necessary to contain the inserted data are
|
sl@0
|
340 |
allocated. Each new segment's length is the buffer's granularity.
|
sl@0
|
341 |
If extension or new allocation fails, a leave occurs.
|
sl@0
|
342 |
|
sl@0
|
343 |
4. Insertion may also require data to be shuffled. In the case of flat buffers,
|
sl@0
|
344 |
data beyond the insertion point is shuffled up to create a gap: the new data
|
sl@0
|
345 |
is then inserted into this gap. In the case of segmented buffers, shuffling
|
sl@0
|
346 |
is minimised by inserting the new data into newly-allocated buffers, and
|
sl@0
|
347 |
shuffling only immediately-neighbouring buffers if possible. This may result
|
sl@0
|
348 |
in some wastage of space, but is much more time-efficient for large amounts
|
sl@0
|
349 |
of data.
|
sl@0
|
350 |
|
sl@0
|
351 |
@param aPos Buffer position before which the data will be inserted: must be
|
sl@0
|
352 |
in range zero to Size().
|
sl@0
|
353 |
@param aPtr The address of the data to be inserted.
|
sl@0
|
354 |
@param aLength The length of the data to be inserted.
|
sl@0
|
355 |
|
sl@0
|
356 |
@leave KErrNoMemory If the insertion requires a bigger buffer, and the
|
sl@0
|
357 |
necessary allocation or re-allocation fails.
|
sl@0
|
358 |
*/
|
sl@0
|
359 |
{
|
sl@0
|
360 |
|
sl@0
|
361 |
if (aLength==0)
|
sl@0
|
362 |
return;
|
sl@0
|
363 |
__ASSERT_ALWAYS(aLength>0,Panic(EBufInsertLengthNegative));
|
sl@0
|
364 |
__ASSERT_ALWAYS(aPtr,Panic(EBufInsertBadPtr));
|
sl@0
|
365 |
DoInsertL(aPos,aPtr,aLength);
|
sl@0
|
366 |
}
|
sl@0
|
367 |
|
sl@0
|
368 |
EXPORT_C void CBufBase::ExpandL(TInt aPos,TInt aLength)
|
sl@0
|
369 |
/**
|
sl@0
|
370 |
Inserts an uninitialised region into the buffer.
|
sl@0
|
371 |
|
sl@0
|
372 |
Data at and beyond the insertion position is moved to make way for the inserted
|
sl@0
|
373 |
region. Data before the insertion position remains in place.
|
sl@0
|
374 |
|
sl@0
|
375 |
Note:
|
sl@0
|
376 |
|
sl@0
|
377 |
1. The inserted region is not initialised. After using ExpandL(), you should
|
sl@0
|
378 |
then use a series of Write()s to fill this region with data.
|
sl@0
|
379 |
|
sl@0
|
380 |
2. Use ExpandL() followed by a series of Write()s when you know the amount of
|
sl@0
|
381 |
data to be inserted, in advance. It is more efficient than a series of
|
sl@0
|
382 |
InsertL()s. In addition, once the result of the ExpandL() has been checked,
|
sl@0
|
383 |
it is guaranteed that the Write()s do not leave, which can sometimes be
|
sl@0
|
384 |
useful.
|
sl@0
|
385 |
|
sl@0
|
386 |
@param aPos Buffer position before which the region will be inserted; must
|
sl@0
|
387 |
be in range zero to Size().
|
sl@0
|
388 |
@param aLength The length of the region to be inserted.
|
sl@0
|
389 |
*/
|
sl@0
|
390 |
{
|
sl@0
|
391 |
|
sl@0
|
392 |
if (aLength==0)
|
sl@0
|
393 |
return;
|
sl@0
|
394 |
__ASSERT_ALWAYS(aLength>0,Panic(EBufInsertLengthNegative));
|
sl@0
|
395 |
DoInsertL(aPos,NULL,aLength);
|
sl@0
|
396 |
}
|
sl@0
|
397 |
|
sl@0
|
398 |
EXPORT_C void CBufBase::ResizeL(TInt aSize)
|
sl@0
|
399 |
/**
|
sl@0
|
400 |
Re-sizes the buffer to the specified size.
|
sl@0
|
401 |
|
sl@0
|
402 |
The new size can be larger or smaller than the existing size.
|
sl@0
|
403 |
|
sl@0
|
404 |
If the new size is larger than the existing size, the buffer is expanded by
|
sl@0
|
405 |
adding uninitialised data to the end of it.
|
sl@0
|
406 |
|
sl@0
|
407 |
If the new size is smaller than the existing size, the buffer is reduced;
|
sl@0
|
408 |
any data at the end of the buffer is lost.
|
sl@0
|
409 |
|
sl@0
|
410 |
Notes:
|
sl@0
|
411 |
|
sl@0
|
412 |
1. If the new size is larger than the existing size, the function is equivalent
|
sl@0
|
413 |
to Delete(aSize,Size()-aSize).
|
sl@0
|
414 |
|
sl@0
|
415 |
2. If the new size is smaller than the existing size, the function is equivalent
|
sl@0
|
416 |
to ExpandL((Size(),aSize-Size()).
|
sl@0
|
417 |
|
sl@0
|
418 |
3. The motivations for using ResizeL() are the same as those for using Delete()
|
sl@0
|
419 |
and ExpandL().
|
sl@0
|
420 |
|
sl@0
|
421 |
@param aSize The new size of the buffer; this value must be greater than or
|
sl@0
|
422 |
equal to zero.
|
sl@0
|
423 |
*/
|
sl@0
|
424 |
{
|
sl@0
|
425 |
|
sl@0
|
426 |
TInt excess=iSize-aSize;
|
sl@0
|
427 |
if (excess>0)
|
sl@0
|
428 |
Delete(aSize,excess);
|
sl@0
|
429 |
else
|
sl@0
|
430 |
ExpandL(iSize,-excess);
|
sl@0
|
431 |
}
|
sl@0
|
432 |
|
sl@0
|
433 |
EXPORT_C CBufFlat *CBufFlat::NewL(TInt anExpandSize)
|
sl@0
|
434 |
/**
|
sl@0
|
435 |
Allocates and constructs a flat buffer.
|
sl@0
|
436 |
|
sl@0
|
437 |
If there is insufficient memory available to allocate the flat buffer, the
|
sl@0
|
438 |
function leaves.
|
sl@0
|
439 |
|
sl@0
|
440 |
@param anExpandSize The granularity of buffer expansion. Additional space,
|
sl@0
|
441 |
when required, is always allocated in multiples of
|
sl@0
|
442 |
this number. Note: although a value of zero is permitted
|
sl@0
|
443 |
by this interface, it has no meaning, and risks raising
|
sl@0
|
444 |
panics later during execution. We suggest that you pass
|
sl@0
|
445 |
a positive value.
|
sl@0
|
446 |
|
sl@0
|
447 |
@return A pointer to the flat buffer object.
|
sl@0
|
448 |
|
sl@0
|
449 |
@panic E32USER-CBase 3 if the granularity is negative.
|
sl@0
|
450 |
*/
|
sl@0
|
451 |
{
|
sl@0
|
452 |
|
sl@0
|
453 |
return(new(ELeave) CBufFlat(anExpandSize));
|
sl@0
|
454 |
}
|
sl@0
|
455 |
|
sl@0
|
456 |
EXPORT_C CBufFlat::CBufFlat(TInt anExpandSize)
|
sl@0
|
457 |
//
|
sl@0
|
458 |
// Constructor
|
sl@0
|
459 |
//
|
sl@0
|
460 |
/**
|
sl@0
|
461 |
@internalComponent
|
sl@0
|
462 |
*/
|
sl@0
|
463 |
: CBufBase(anExpandSize)
|
sl@0
|
464 |
{
|
sl@0
|
465 |
|
sl@0
|
466 |
// iMaxSize=0;
|
sl@0
|
467 |
// iPtr=NULL;
|
sl@0
|
468 |
}
|
sl@0
|
469 |
|
sl@0
|
470 |
EXPORT_C CBufFlat::~CBufFlat()
|
sl@0
|
471 |
/**
|
sl@0
|
472 |
Destructor.
|
sl@0
|
473 |
|
sl@0
|
474 |
Frees all resources owned by the object, prior to its destruction.
|
sl@0
|
475 |
Specifically, it frees the allocated cell used as a buffer.
|
sl@0
|
476 |
*/
|
sl@0
|
477 |
{
|
sl@0
|
478 |
|
sl@0
|
479 |
User::Free(iPtr);
|
sl@0
|
480 |
}
|
sl@0
|
481 |
|
sl@0
|
482 |
EXPORT_C void CBufFlat::Compress()
|
sl@0
|
483 |
/**
|
sl@0
|
484 |
Compresses the buffer so as to occupy minimal space.
|
sl@0
|
485 |
|
sl@0
|
486 |
This frees any unused memory at the end of the buffer.
|
sl@0
|
487 |
|
sl@0
|
488 |
@see CBufBase::Compress
|
sl@0
|
489 |
*/
|
sl@0
|
490 |
{
|
sl@0
|
491 |
|
sl@0
|
492 |
SetReserveL(iSize);
|
sl@0
|
493 |
}
|
sl@0
|
494 |
|
sl@0
|
495 |
EXPORT_C void CBufFlat::SetReserveL(TInt aSize)
|
sl@0
|
496 |
/**
|
sl@0
|
497 |
Specifies a minimum amount of space which the flat buffer should occupy.
|
sl@0
|
498 |
|
sl@0
|
499 |
If the required size is zero, the heap cell is deleted. If it is different
|
sl@0
|
500 |
from the current size, the heap cell is rellocated accordingly.
|
sl@0
|
501 |
|
sl@0
|
502 |
@param aSize The size of the buffer required. If there is no data in the
|
sl@0
|
503 |
buffer, i.e. Size() returns zero, then this value
|
sl@0
|
504 |
can be zero, which causes the buffer's allocated heap cell
|
sl@0
|
505 |
to be deleted.
|
sl@0
|
506 |
|
sl@0
|
507 |
@panic E32USER-CBase 10, if aSize is negative.
|
sl@0
|
508 |
@panic E32USER-CBase 11, if there is data in the buffer, and aSize is less than
|
sl@0
|
509 |
the value returned by Size().
|
sl@0
|
510 |
*/
|
sl@0
|
511 |
{
|
sl@0
|
512 |
|
sl@0
|
513 |
__ASSERT_ALWAYS(aSize>=0,Panic(EBufFlatReserveNegative));
|
sl@0
|
514 |
__ASSERT_ALWAYS(aSize>=iSize,Panic(EBufFlatReserveSetTooSmall));
|
sl@0
|
515 |
if (!aSize)
|
sl@0
|
516 |
{
|
sl@0
|
517 |
User::Free(iPtr);
|
sl@0
|
518 |
iPtr=NULL;
|
sl@0
|
519 |
}
|
sl@0
|
520 |
else
|
sl@0
|
521 |
iPtr=(TUint8 *)User::ReAllocL(iPtr,aSize);
|
sl@0
|
522 |
iMaxSize=aSize;
|
sl@0
|
523 |
}
|
sl@0
|
524 |
|
sl@0
|
525 |
EXPORT_C void CBufFlat::DoInsertL(TInt aPos,const TAny *aPtr,TInt aLength)
|
sl@0
|
526 |
//
|
sl@0
|
527 |
// Insert into the buffer. Can cause expansion.
|
sl@0
|
528 |
//
|
sl@0
|
529 |
{
|
sl@0
|
530 |
|
sl@0
|
531 |
__ASSERT_ALWAYS(aPos>=0 && aPos<=iSize,Panic(EBufFlatPosOutOfRange));
|
sl@0
|
532 |
TInt len=iSize+aLength;
|
sl@0
|
533 |
if (len>iMaxSize)
|
sl@0
|
534 |
{
|
sl@0
|
535 |
TInt r=len-iMaxSize;
|
sl@0
|
536 |
r=((r/iExpandSize)+1)*iExpandSize;
|
sl@0
|
537 |
SetReserveL(iMaxSize+r);
|
sl@0
|
538 |
}
|
sl@0
|
539 |
Mem::Copy(iPtr+aPos+aLength,iPtr+aPos,iSize-aPos);
|
sl@0
|
540 |
if (aPtr)
|
sl@0
|
541 |
Mem::Copy(iPtr+aPos,aPtr,aLength);
|
sl@0
|
542 |
iSize+=aLength;
|
sl@0
|
543 |
}
|
sl@0
|
544 |
|
sl@0
|
545 |
EXPORT_C void CBufFlat::Delete(TInt aPos,TInt aLength)
|
sl@0
|
546 |
/**
|
sl@0
|
547 |
Deletes data from the buffer.
|
sl@0
|
548 |
|
sl@0
|
549 |
During deletion, any data beyond the deleted data is shuffled up so that
|
sl@0
|
550 |
the buffer contents are contiguous. No memory is freed.
|
sl@0
|
551 |
|
sl@0
|
552 |
@param aPos Buffer position where the deletion will begin; must be in the
|
sl@0
|
553 |
range zero to (Size() minus the length of the data
|
sl@0
|
554 |
to be deleted).
|
sl@0
|
555 |
@param aLength The number of bytes to be deleted.
|
sl@0
|
556 |
|
sl@0
|
557 |
@panic E32USER-CBase 12, if aPos is negative or is greater than the
|
sl@0
|
558 |
current size of the buffer.
|
sl@0
|
559 |
@panic E32USER-CBase 13, if aPos + aLength is greater than the
|
sl@0
|
560 |
current size of the buffer.
|
sl@0
|
561 |
|
sl@0
|
562 |
@see CBufBase::Delete
|
sl@0
|
563 |
*/
|
sl@0
|
564 |
{
|
sl@0
|
565 |
|
sl@0
|
566 |
__ASSERT_ALWAYS(aPos>=0 && aPos<=iSize,Panic(EBufFlatPosOutOfRange));
|
sl@0
|
567 |
__ASSERT_ALWAYS((aPos+aLength)<=iSize,Panic(EBufFlatDeleteBeyondEnd));
|
sl@0
|
568 |
Mem::Copy(iPtr+aPos,iPtr+aPos+aLength,iSize-aLength-aPos);
|
sl@0
|
569 |
iSize-=aLength;
|
sl@0
|
570 |
}
|
sl@0
|
571 |
|
sl@0
|
572 |
EXPORT_C TPtr8 CBufFlat::Ptr(TInt aPos)
|
sl@0
|
573 |
/**
|
sl@0
|
574 |
Gets a pointer descriptor to represent the data starting at the specified
|
sl@0
|
575 |
data byte through to the end of the contiguous region containing that byte.
|
sl@0
|
576 |
|
sl@0
|
577 |
Calculation of the pointer and length involves only a few machine instructions
|
sl@0
|
578 |
and is independent of the data contained in the buffer.
|
sl@0
|
579 |
|
sl@0
|
580 |
@param aPos Buffer position: must be in range zero to Size().
|
sl@0
|
581 |
|
sl@0
|
582 |
@return Descriptor representing the data starting at aPos to the end of
|
sl@0
|
583 |
the buffer.
|
sl@0
|
584 |
*/
|
sl@0
|
585 |
{
|
sl@0
|
586 |
|
sl@0
|
587 |
__ASSERT_ALWAYS(aPos>=0 && aPos<=iSize,Panic(EBufFlatPosOutOfRange));
|
sl@0
|
588 |
TInt len=iSize-aPos;
|
sl@0
|
589 |
return(TPtr8(iPtr+aPos,len,len));
|
sl@0
|
590 |
}
|
sl@0
|
591 |
|
sl@0
|
592 |
EXPORT_C TPtr8 CBufFlat::BackPtr(TInt aPos)
|
sl@0
|
593 |
//
|
sl@0
|
594 |
// Return a pointer to the buffer which has the maximum amount of data
|
sl@0
|
595 |
// before aPos, and the amount of data remaining.
|
sl@0
|
596 |
//
|
sl@0
|
597 |
/**
|
sl@0
|
598 |
Gets a pointer descriptor to represent the data starting at the beginning
|
sl@0
|
599 |
of the contiguous region containing that byte through to the byte immediately
|
sl@0
|
600 |
preceding the specified byte.
|
sl@0
|
601 |
|
sl@0
|
602 |
The descriptor always points to the beginning of the buffer containing
|
sl@0
|
603 |
the specified byte. Calculation of the pointer and length involves only a few
|
sl@0
|
604 |
machine instructions and is independent of the data contained in the buffer.
|
sl@0
|
605 |
|
sl@0
|
606 |
@param aPos Buffer position: must be in range zero to Size().
|
sl@0
|
607 |
|
sl@0
|
608 |
@return Descriptor representing the back contiguous region.
|
sl@0
|
609 |
|
sl@0
|
610 |
@see CBufBase::BackPtr
|
sl@0
|
611 |
*/
|
sl@0
|
612 |
{
|
sl@0
|
613 |
|
sl@0
|
614 |
__ASSERT_ALWAYS(aPos>=0 && aPos<=iSize,Panic(EBufFlatPosOutOfRange));
|
sl@0
|
615 |
return(TPtr8(iPtr,aPos,aPos));
|
sl@0
|
616 |
}
|
sl@0
|
617 |
|
sl@0
|
618 |
void CBufSeg::InsertIntoSegment(TBufSegLink *aSeg,TInt anOffset,const TAny *aPtr,TInt aLength)
|
sl@0
|
619 |
//
|
sl@0
|
620 |
// Insert into the segment.
|
sl@0
|
621 |
//
|
sl@0
|
622 |
{
|
sl@0
|
623 |
|
sl@0
|
624 |
if (aLength)
|
sl@0
|
625 |
{
|
sl@0
|
626 |
TUint8 *pS=((TUint8 *)(aSeg+1))+anOffset;
|
sl@0
|
627 |
Mem::Copy(pS+aLength,pS,aSeg->iLen-anOffset);
|
sl@0
|
628 |
if (aPtr)
|
sl@0
|
629 |
Mem::Copy(pS,aPtr,aLength);
|
sl@0
|
630 |
aSeg->iLen+=aLength;
|
sl@0
|
631 |
}
|
sl@0
|
632 |
}
|
sl@0
|
633 |
|
sl@0
|
634 |
void CBufSeg::DeleteFromSegment(TBufSegLink *aSeg,TInt anOffset,TInt aLength)
|
sl@0
|
635 |
//
|
sl@0
|
636 |
// Delete from the segment.
|
sl@0
|
637 |
//
|
sl@0
|
638 |
{
|
sl@0
|
639 |
|
sl@0
|
640 |
if (aLength)
|
sl@0
|
641 |
{
|
sl@0
|
642 |
TUint8 *pS=((TUint8 *)(aSeg+1))+anOffset;
|
sl@0
|
643 |
Mem::Copy(pS,pS+aLength,aSeg->iLen-anOffset-aLength);
|
sl@0
|
644 |
aSeg->iLen-=aLength;
|
sl@0
|
645 |
}
|
sl@0
|
646 |
}
|
sl@0
|
647 |
|
sl@0
|
648 |
void CBufSeg::FreeSegment(TBufSegLink *aSeg)
|
sl@0
|
649 |
//
|
sl@0
|
650 |
// Free an entire segment.
|
sl@0
|
651 |
//
|
sl@0
|
652 |
{
|
sl@0
|
653 |
|
sl@0
|
654 |
aSeg->Deque();
|
sl@0
|
655 |
User::Free(aSeg);
|
sl@0
|
656 |
}
|
sl@0
|
657 |
|
sl@0
|
658 |
void CBufSeg::SetSBO(TInt aPos)
|
sl@0
|
659 |
//
|
sl@0
|
660 |
// Set a segment-base-offset struct (SBO) to a new pos.
|
sl@0
|
661 |
// If the initial psbo->seg is not NULL, it assumes that it is a valid
|
sl@0
|
662 |
// SBO for a different position and counts relative to the initial SBO
|
sl@0
|
663 |
// to set the desired position. If the initial psbo->seg is NULL, it starts
|
sl@0
|
664 |
// scanning from the beginning ie pos=0.
|
sl@0
|
665 |
// When the position is between segments A and B, there are two equivalent
|
sl@0
|
666 |
// positions: (1) at the beginning of B and (2) at the end of A.
|
sl@0
|
667 |
// Option (1) is suitable for referencing the data and deleting.
|
sl@0
|
668 |
// Option (2) is best for insertion when A is not full.
|
sl@0
|
669 |
// This function uses option (1) and will always set the SBO to the
|
sl@0
|
670 |
// beginning of the next segment. It does however set to the end of the
|
sl@0
|
671 |
// last segment when pos is equal to the number of bytes in the buffer.
|
sl@0
|
672 |
//
|
sl@0
|
673 |
{
|
sl@0
|
674 |
|
sl@0
|
675 |
__ASSERT_ALWAYS(aPos>=0 && aPos<=iSize,Panic(EBufSegPosOutOfRange));
|
sl@0
|
676 |
if (aPos==iSize)
|
sl@0
|
677 |
{ // Positioning to end is treated as a special case
|
sl@0
|
678 |
iSeg=0;
|
sl@0
|
679 |
if (iSize)
|
sl@0
|
680 |
iBase=aPos-(iOffset=(iSeg=iQue.Last())->iLen);
|
sl@0
|
681 |
return;
|
sl@0
|
682 |
}
|
sl@0
|
683 |
TInt base=iBase;
|
sl@0
|
684 |
TBufSegLink *next;
|
sl@0
|
685 |
if ((next=iSeg)==NULL)
|
sl@0
|
686 |
{ // anSbo is not valid - set to pos=0
|
sl@0
|
687 |
next=iQue.First();
|
sl@0
|
688 |
base=0;
|
sl@0
|
689 |
}
|
sl@0
|
690 |
if (aPos<base)
|
sl@0
|
691 |
{ // Look to the left
|
sl@0
|
692 |
do
|
sl@0
|
693 |
{
|
sl@0
|
694 |
next=next->Prev();
|
sl@0
|
695 |
base-=next->iLen;
|
sl@0
|
696 |
} while (aPos<base);
|
sl@0
|
697 |
}
|
sl@0
|
698 |
else
|
sl@0
|
699 |
{ // Look to the right
|
sl@0
|
700 |
TBufSegLink *nn;
|
sl@0
|
701 |
while (aPos>=(base+next->iLen) && !iQue.IsHead(nn=next->Next()))
|
sl@0
|
702 |
{
|
sl@0
|
703 |
base+=next->iLen;
|
sl@0
|
704 |
next=nn;
|
sl@0
|
705 |
}
|
sl@0
|
706 |
}
|
sl@0
|
707 |
iSeg=next;
|
sl@0
|
708 |
iBase=base;
|
sl@0
|
709 |
iOffset=aPos-base;
|
sl@0
|
710 |
__ASSERT_DEBUG(iOffset<=iExpandSize,Panic(EBufSegSetSBO));
|
sl@0
|
711 |
}
|
sl@0
|
712 |
|
sl@0
|
713 |
void CBufSeg::AllocSegL(TBufSegLink *aSeg,TInt aNumber)
|
sl@0
|
714 |
//
|
sl@0
|
715 |
// Allocate a number of segments.
|
sl@0
|
716 |
//
|
sl@0
|
717 |
{
|
sl@0
|
718 |
|
sl@0
|
719 |
for (TInt i=0;i<aNumber;i++)
|
sl@0
|
720 |
{
|
sl@0
|
721 |
TBufSegLink *pL=(TBufSegLink *)User::Alloc(sizeof(TBufSegLink)+iExpandSize);
|
sl@0
|
722 |
if (pL==NULL)
|
sl@0
|
723 |
{ // alloc failed - tidy up
|
sl@0
|
724 |
while (i--)
|
sl@0
|
725 |
FreeSegment(aSeg->Next());
|
sl@0
|
726 |
User::Leave(KErrNoMemory);
|
sl@0
|
727 |
}
|
sl@0
|
728 |
new(pL) TBufSegLink;
|
sl@0
|
729 |
pL->Enque(aSeg);
|
sl@0
|
730 |
}
|
sl@0
|
731 |
}
|
sl@0
|
732 |
|
sl@0
|
733 |
EXPORT_C CBufSeg *CBufSeg::NewL(TInt anExpandSize)
|
sl@0
|
734 |
/**
|
sl@0
|
735 |
Allocates and constructs a segmented buffer.
|
sl@0
|
736 |
|
sl@0
|
737 |
If there is insufficient memory available to allocate the segmented buffer,
|
sl@0
|
738 |
the function leaves.
|
sl@0
|
739 |
|
sl@0
|
740 |
@param anExpandSize The granularity of the buffer. Each segment contains (in
|
sl@0
|
741 |
addition to 16 bytes of overhead) this number of bytes for
|
sl@0
|
742 |
data. Note: although a value of zero is permitted by this
|
sl@0
|
743 |
interface, it has no meaning, and risks raising panics later
|
sl@0
|
744 |
during execution. We suggest that you pass a positive value.
|
sl@0
|
745 |
|
sl@0
|
746 |
@return If successful, a pointer to the segmented buffer object.
|
sl@0
|
747 |
|
sl@0
|
748 |
@panic E32USER-CBase 3 if the granularity is negative.
|
sl@0
|
749 |
*/
|
sl@0
|
750 |
{
|
sl@0
|
751 |
|
sl@0
|
752 |
return(new(ELeave) CBufSeg(anExpandSize));
|
sl@0
|
753 |
}
|
sl@0
|
754 |
|
sl@0
|
755 |
EXPORT_C CBufSeg::CBufSeg(TInt anExpandSize)
|
sl@0
|
756 |
//
|
sl@0
|
757 |
// Constructor
|
sl@0
|
758 |
//
|
sl@0
|
759 |
: CBufBase(anExpandSize)
|
sl@0
|
760 |
{
|
sl@0
|
761 |
|
sl@0
|
762 |
// iSeg=NULL;
|
sl@0
|
763 |
}
|
sl@0
|
764 |
|
sl@0
|
765 |
EXPORT_C CBufSeg::~CBufSeg()
|
sl@0
|
766 |
/**
|
sl@0
|
767 |
Destructor.
|
sl@0
|
768 |
|
sl@0
|
769 |
Frees all resources owned by the object, prior to its destruction.
|
sl@0
|
770 |
|
sl@0
|
771 |
Specifically, it frees all segments allocated to the buffer.
|
sl@0
|
772 |
*/
|
sl@0
|
773 |
{
|
sl@0
|
774 |
|
sl@0
|
775 |
Delete(0,iSize);
|
sl@0
|
776 |
}
|
sl@0
|
777 |
|
sl@0
|
778 |
EXPORT_C void CBufSeg::Compress()
|
sl@0
|
779 |
/**
|
sl@0
|
780 |
Compresses the buffer so as to occupy minimal space.
|
sl@0
|
781 |
|
sl@0
|
782 |
Fills any space in each segment of the buffer by moving contents from the next
|
sl@0
|
783 |
segment to the current one. Where this activity results in empty segments,
|
sl@0
|
784 |
it frees the memory associated with these segments.
|
sl@0
|
785 |
|
sl@0
|
786 |
@see CBufBase::Compress
|
sl@0
|
787 |
*/
|
sl@0
|
788 |
{
|
sl@0
|
789 |
|
sl@0
|
790 |
if (!iSize)
|
sl@0
|
791 |
return;
|
sl@0
|
792 |
iSeg=NULL; // Invalidate current position
|
sl@0
|
793 |
TBufSegLink *p1=iQue.First();
|
sl@0
|
794 |
TBufSegLink *p2;
|
sl@0
|
795 |
while (!iQue.IsHead(p2=p1->Next()))
|
sl@0
|
796 |
{
|
sl@0
|
797 |
TInt rem=iExpandSize-p1->iLen;
|
sl@0
|
798 |
if (rem==0)
|
sl@0
|
799 |
{
|
sl@0
|
800 |
p1=p2;
|
sl@0
|
801 |
continue; // Full
|
sl@0
|
802 |
}
|
sl@0
|
803 |
if (rem>=p2->iLen)
|
sl@0
|
804 |
{ // Zap the next segment
|
sl@0
|
805 |
InsertIntoSegment(p1,p1->iLen,p2+1,p2->iLen);
|
sl@0
|
806 |
FreeSegment(p2);
|
sl@0
|
807 |
continue;
|
sl@0
|
808 |
}
|
sl@0
|
809 |
InsertIntoSegment(p1,p1->iLen,p2+1,rem); // Make full
|
sl@0
|
810 |
DeleteFromSegment(p2,0,rem);
|
sl@0
|
811 |
p1=p2;
|
sl@0
|
812 |
}
|
sl@0
|
813 |
}
|
sl@0
|
814 |
|
sl@0
|
815 |
EXPORT_C void CBufSeg::DoInsertL(TInt aPos,const TAny *aPtr,TInt aLength)
|
sl@0
|
816 |
//
|
sl@0
|
817 |
// Insert data at the specified position. This is quite tricky.
|
sl@0
|
818 |
// In general, the data to be copied may be broken down into the
|
sl@0
|
819 |
// following elements:
|
sl@0
|
820 |
// s1 bytes into the current segment (p1)
|
sl@0
|
821 |
// nseg-1 segments of self->sgbuf.hd.len (ie full segments)
|
sl@0
|
822 |
// s2 bytes into segment nseg
|
sl@0
|
823 |
// s3 bytes into the next segment (p2)
|
sl@0
|
824 |
// where p2 is the next segment before the insertion of nseg new segments.
|
sl@0
|
825 |
// In addition, any remaining data to the right of the insertion point must
|
sl@0
|
826 |
// be moved appropriately. In general, r1 bytes must be moved into segment
|
sl@0
|
827 |
// nseg (r2 bytes) and segment p2 (r3 bytes) where r1=r2+r3.
|
sl@0
|
828 |
//
|
sl@0
|
829 |
{
|
sl@0
|
830 |
|
sl@0
|
831 |
SetSBO(aPos);
|
sl@0
|
832 |
TInt slen=iExpandSize;
|
sl@0
|
833 |
TInt ofs=iOffset;
|
sl@0
|
834 |
TInt ll=0;
|
sl@0
|
835 |
TInt s1=0;
|
sl@0
|
836 |
TInt r1=0;
|
sl@0
|
837 |
TBufSegLink *p1=(TBufSegLink *)(&iQue);
|
sl@0
|
838 |
TBufSegLink *p2=p1->Next();
|
sl@0
|
839 |
TUint8 *pR=NULL;
|
sl@0
|
840 |
if (iSize)
|
sl@0
|
841 |
{
|
sl@0
|
842 |
p1=iSeg;
|
sl@0
|
843 |
if (!iQue.IsHead(p2=p1->Prev()) && ofs==0 && p2->iLen<slen)
|
sl@0
|
844 |
{
|
sl@0
|
845 |
iSeg=p1=p2;
|
sl@0
|
846 |
iOffset=ofs=p1->iLen;
|
sl@0
|
847 |
iBase-=ofs;
|
sl@0
|
848 |
}
|
sl@0
|
849 |
s1=slen-ofs;
|
sl@0
|
850 |
if (s1>aLength)
|
sl@0
|
851 |
s1=aLength;
|
sl@0
|
852 |
TInt r2=slen-p1->iLen;
|
sl@0
|
853 |
if (aLength>r2)
|
sl@0
|
854 |
{
|
sl@0
|
855 |
pR=((TUint8 *)(p1+1))+ofs;
|
sl@0
|
856 |
r1=aLength-r2;
|
sl@0
|
857 |
r2=p1->iLen-ofs;
|
sl@0
|
858 |
if (r1>r2)
|
sl@0
|
859 |
r1=r2;
|
sl@0
|
860 |
else
|
sl@0
|
861 |
pR+=(r2-r1);
|
sl@0
|
862 |
}
|
sl@0
|
863 |
p2=p1->Next();
|
sl@0
|
864 |
ll=slen-p1->iLen;
|
sl@0
|
865 |
if (!iQue.IsHead(p2))
|
sl@0
|
866 |
ll+=slen-p2->iLen;
|
sl@0
|
867 |
}
|
sl@0
|
868 |
TUint8 *pB=((TUint8 *)aPtr)+s1;
|
sl@0
|
869 |
TInt lrem=aLength-s1;
|
sl@0
|
870 |
TBufSegLink *pP=p1;
|
sl@0
|
871 |
if (aLength>ll)
|
sl@0
|
872 |
{// Need some more segments
|
sl@0
|
873 |
TInt nseg=(slen-1+aLength-ll)/slen;
|
sl@0
|
874 |
AllocSegL(p1,nseg); // Could leave
|
sl@0
|
875 |
while (nseg--)
|
sl@0
|
876 |
{ // Copy into allocated segments
|
sl@0
|
877 |
pP=pP->Next();
|
sl@0
|
878 |
TInt gap=slen;
|
sl@0
|
879 |
if (lrem<gap)
|
sl@0
|
880 |
gap=lrem;
|
sl@0
|
881 |
InsertIntoSegment(pP,0,aPtr==NULL ? NULL : pB,gap);
|
sl@0
|
882 |
pB+=gap;
|
sl@0
|
883 |
lrem-=gap;
|
sl@0
|
884 |
}
|
sl@0
|
885 |
}
|
sl@0
|
886 |
if (lrem)
|
sl@0
|
887 |
{
|
sl@0
|
888 |
InsertIntoSegment(p2,0,aPtr==NULL ? NULL : pB,lrem);
|
sl@0
|
889 |
InsertIntoSegment(p2,lrem,pR,r1);
|
sl@0
|
890 |
}
|
sl@0
|
891 |
else
|
sl@0
|
892 |
{
|
sl@0
|
893 |
TInt r2=0;
|
sl@0
|
894 |
if (pP!=p1)
|
sl@0
|
895 |
{
|
sl@0
|
896 |
r2=slen-pP->iLen;
|
sl@0
|
897 |
if (r2>r1)
|
sl@0
|
898 |
r2=r1;
|
sl@0
|
899 |
}
|
sl@0
|
900 |
InsertIntoSegment(pP,pP->iLen,pR,r2); // Moved from p1
|
sl@0
|
901 |
InsertIntoSegment(p2,0,pR+r2,r1-r2); // Also moved from p1
|
sl@0
|
902 |
}
|
sl@0
|
903 |
p1->iLen-=r1;
|
sl@0
|
904 |
InsertIntoSegment(p1,ofs,aPtr,s1);
|
sl@0
|
905 |
iSize+=aLength;
|
sl@0
|
906 |
}
|
sl@0
|
907 |
|
sl@0
|
908 |
EXPORT_C void CBufSeg::Delete(TInt aPos,TInt aLength)
|
sl@0
|
909 |
/**
|
sl@0
|
910 |
Deletes data from the buffer.
|
sl@0
|
911 |
|
sl@0
|
912 |
During deletion, shuffling is minimised by deleting intermediate segments
|
sl@0
|
913 |
and allowing segments to contain less data than the buffer granularity.
|
sl@0
|
914 |
|
sl@0
|
915 |
@param aPos Buffer position where the deletion will begin; must be in the
|
sl@0
|
916 |
range zero to (Size() minus the length of the data
|
sl@0
|
917 |
to be deleted).
|
sl@0
|
918 |
@param aLength The number of bytes to be deleted.
|
sl@0
|
919 |
|
sl@0
|
920 |
@see CBufBase::Delete
|
sl@0
|
921 |
*/
|
sl@0
|
922 |
{
|
sl@0
|
923 |
|
sl@0
|
924 |
if (aLength==0)
|
sl@0
|
925 |
return;
|
sl@0
|
926 |
SetSBO(aPos);
|
sl@0
|
927 |
TInt ofs=iOffset;
|
sl@0
|
928 |
__ASSERT_ALWAYS((iBase+ofs+aLength)<=iSize,Panic(EBufSegDeleteBeyondEnd));
|
sl@0
|
929 |
iSize-=aLength;
|
sl@0
|
930 |
TBufSegLink *p1=iSeg;
|
sl@0
|
931 |
TBufSegLink *p2;
|
sl@0
|
932 |
TInt rem=p1->iLen-ofs;
|
sl@0
|
933 |
FOREVER
|
sl@0
|
934 |
{
|
sl@0
|
935 |
p2=p1->Next();
|
sl@0
|
936 |
TInt gap=aLength;
|
sl@0
|
937 |
if (gap>rem)
|
sl@0
|
938 |
gap=rem;
|
sl@0
|
939 |
DeleteFromSegment(p1,ofs,gap);
|
sl@0
|
940 |
if (p1->iLen==0)
|
sl@0
|
941 |
{
|
sl@0
|
942 |
iSeg=NULL;
|
sl@0
|
943 |
FreeSegment(p1);
|
sl@0
|
944 |
}
|
sl@0
|
945 |
p1=p2;
|
sl@0
|
946 |
if ((aLength-=gap)==0)
|
sl@0
|
947 |
break;
|
sl@0
|
948 |
rem=p1->iLen;
|
sl@0
|
949 |
ofs=0;
|
sl@0
|
950 |
}
|
sl@0
|
951 |
if (iSize)
|
sl@0
|
952 |
{
|
sl@0
|
953 |
p1=p2->Prev();
|
sl@0
|
954 |
if (!iQue.IsHead(p1) && !iQue.IsHead(p2))
|
sl@0
|
955 |
{
|
sl@0
|
956 |
if ((p1->iLen+p2->iLen)<=iExpandSize)
|
sl@0
|
957 |
{ // Join to the right
|
sl@0
|
958 |
InsertIntoSegment(p1,p1->iLen,p2+1,p2->iLen);
|
sl@0
|
959 |
FreeSegment(p2);
|
sl@0
|
960 |
}
|
sl@0
|
961 |
}
|
sl@0
|
962 |
}
|
sl@0
|
963 |
SetSBO(aPos);
|
sl@0
|
964 |
}
|
sl@0
|
965 |
|
sl@0
|
966 |
EXPORT_C TPtr8 CBufSeg::Ptr(TInt aPos)
|
sl@0
|
967 |
/**
|
sl@0
|
968 |
Gets a pointer descriptor to represent the data starting at the specified
|
sl@0
|
969 |
data byte through to the end of the contiguous region containing that byte.
|
sl@0
|
970 |
|
sl@0
|
971 |
The time needed for calculation of the pointer depends on how many segments
|
sl@0
|
972 |
there are in the buffer, and how near the target segment is to the segment
|
sl@0
|
973 |
which was last used in the buffer.
|
sl@0
|
974 |
|
sl@0
|
975 |
@param aPos Buffer position: must be in range zero to Size().
|
sl@0
|
976 |
|
sl@0
|
977 |
@return Descriptor representing the data starting at aPos to the end of
|
sl@0
|
978 |
the contiguous region containing that byte.
|
sl@0
|
979 |
*/
|
sl@0
|
980 |
{
|
sl@0
|
981 |
|
sl@0
|
982 |
if (iSize==0)
|
sl@0
|
983 |
return(TPtr8(NULL,0,0));
|
sl@0
|
984 |
SetSBO(aPos);
|
sl@0
|
985 |
TInt len=iSeg->iLen-iOffset;
|
sl@0
|
986 |
return(TPtr8(((TUint8 *)(iSeg+1))+iOffset,len,len));
|
sl@0
|
987 |
}
|
sl@0
|
988 |
|
sl@0
|
989 |
EXPORT_C TPtr8 CBufSeg::BackPtr(TInt aPos)
|
sl@0
|
990 |
//
|
sl@0
|
991 |
// Return a pointer to the buffer which has the maximum amount of data
|
sl@0
|
992 |
// before aPos, and the amount of data remaining.
|
sl@0
|
993 |
//
|
sl@0
|
994 |
/**
|
sl@0
|
995 |
Gets a pointer descriptor to represent the data starting at the beginning
|
sl@0
|
996 |
of the contiguous region containing that byte through to the byte immediately
|
sl@0
|
997 |
preceding the specified byte.
|
sl@0
|
998 |
|
sl@0
|
999 |
The descriptor always points to the beginning of the segment containing the
|
sl@0
|
1000 |
specified byte. The time needed for calculation of the pointer depends on how
|
sl@0
|
1001 |
many segments there are in the buffer, and how near the target segment is to
|
sl@0
|
1002 |
the segment which was last used in the buffer.
|
sl@0
|
1003 |
|
sl@0
|
1004 |
@param aPos Buffer position: must be in range zero to Size().
|
sl@0
|
1005 |
|
sl@0
|
1006 |
@return Descriptor representing the back contiguous region.
|
sl@0
|
1007 |
|
sl@0
|
1008 |
@see CBufBase::BackPtr
|
sl@0
|
1009 |
*/
|
sl@0
|
1010 |
|
sl@0
|
1011 |
|
sl@0
|
1012 |
{
|
sl@0
|
1013 |
|
sl@0
|
1014 |
if (aPos==0)
|
sl@0
|
1015 |
return(TPtr8(NULL,0,0));
|
sl@0
|
1016 |
SetSBO(aPos);
|
sl@0
|
1017 |
if (iOffset)
|
sl@0
|
1018 |
return(TPtr8((TUint8 *)(iSeg+1),iOffset,iOffset));
|
sl@0
|
1019 |
TBufSegLink *pL=iSeg->Prev();
|
sl@0
|
1020 |
TInt len=pL->iLen;
|
sl@0
|
1021 |
return(TPtr8((TUint8 *)(pL+1),len,len));
|
sl@0
|
1022 |
}
|
sl@0
|
1023 |
|