os/kernelhwsrv/kernel/eka/euser/cbase/ub_buf.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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