gps/GPSResources/tcpmp/common/buffer.c

273 lines
5.8 KiB
C
Executable File

/*****************************************************************************
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: buffer.c 432 2005-12-28 16:39:13Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "common.h"
void BufferClear(buffer* p)
{
free(p->Data);
p->Allocated = 0;
p->ReadPos = 0;
p->WritePos = 0;
p->Data = NULL;
}
bool_t BufferAlloc(buffer* p, size_t Size, size_t Align)
{
uint8_t* Data;
Align--;
Size = (Size + SAFETAIL + Align) & ~Align;
Data = realloc(p->Data,Size);
if (!Data)
return 0;
p->Data = Data;
p->Allocated = Size - SAFETAIL;
return 1;
}
void BufferDrop(buffer* p)
{
//drop previous packets
p->WritePos = 0;
p->ReadPos = 0;
}
bool_t BufferStream(buffer* p,stream* Stream)
{
if (p->WritePos > p->ReadPos+p->Allocated/2)
return 1;
if (p->ReadPos > p->Allocated/2)
BufferPack(p,0);
if (p->Allocated > p->WritePos)
{
int n = Stream->Read(Stream,p->Data+p->WritePos,p->Allocated - p->WritePos);
if (n > 0)
p->WritePos += n;
}
return p->WritePos > p->ReadPos;
}
bool_t BufferWrite(buffer* p, const void* Ptr, size_t Length, size_t Align)
{
//append new data to buffer
int WritePos = p->WritePos + (int)Length; //buffer!
if (WritePos > p->Allocated && !BufferAlloc(p,WritePos,Align))
return 0;
if (Ptr)
memcpy(p->Data+p->WritePos,Ptr,Length);
p->WritePos = WritePos;
return 1;
}
bool_t BufferRead(buffer* p, const uint8_t** Ptr, size_t Length)
{
if (p->WritePos < p->ReadPos + (int)Length) //buffer!
return 0;
*Ptr = p->Data + p->ReadPos;
p->ReadPos += (int)Length; //buffer!
return 1;
}
void BufferPack(buffer* p, size_t Length)
{
int Skip = p->ReadPos + (int)Length; //buffer!
if (p->WritePos > Skip)
{
p->WritePos -= Skip;
if (Skip)
memmove(p->Data,p->Data+Skip,p->WritePos); // move end part to the beginning
}
else
p->WritePos = 0;
p->ReadPos = 0;
}
void ArrayClear(array* p)
{
if (p->_Block.Ptr)
FreeBlock(&p->_Block);
else
free(p->_Begin);
p->_Begin = NULL;
p->_End = NULL;
p->_Allocated = 0;
}
void ArrayDrop(array* p)
{
p->_End = p->_Begin;
}
bool_t ArrayAlloc(array* p,size_t Total,size_t Align)
{
uint8_t* Data;
--Align;
Total = (Total + Align) & ~Align;
Data = realloc(p->_Begin,Total);
if (!Data)
return 0;
p->_End = Data + (p->_End - p->_Begin);
p->_Begin = Data;
p->_Allocated = Total;
return 1;
}
bool_t ArrayAppend(array* p, const void* Ptr, size_t Length, size_t Align)
{
size_t Total = p->_End - p->_Begin + Length;
if (Total > p->_Allocated && !ArrayAlloc(p,Total,Align))
return 0;
if (Ptr)
memcpy(p->_End,Ptr,Length);
p->_End += Length;
return 1;
}
void ArraySort(array* p, int Count, size_t Width, arraycmp Cmp)
{
qsort(p->_Begin,Count,Width,Cmp);
}
int ArrayFind(const array* p, int Count, size_t Width, const void* Data, arraycmp Cmp, bool_t* Found)
{
if (Cmp)
{
int i;
int Mid = 0;
int Lower = 0;
int Upper = Count-1;
while (Upper >= Lower)
{
Mid = (Upper + Lower) >> 1;
i = Cmp(p->_Begin+Width*Mid,Data);
if (i>0)
Upper = Mid-1;
else if (i<0)
Lower = Mid+1;
else
{
*Found = 1;
return Mid;
}
}
*Found = 0;
if (Upper == Mid - 1)
return Mid;
else
return Lower;
}
else
{
int No = 0;
const uint8_t* i;
for (i=p->_Begin;Count--;i+=Width,++No)
if (memcmp(i,Data,Width)==0)
{
*Found = 1;
return No;
}
*Found = 0;
return No;
}
}
bool_t ArrayAdd(array* p,int Count, size_t Width, const void* Data, arraycmp Cmp,size_t Align)
{
int Pos;
bool_t Found;
Pos = ArrayFind(p,Count,Width,Data,Cmp,&Found);
if (!Found)
{
if (!ArrayAppend(p,NULL,Width,Align))
return 0;
memmove(p->_Begin+Width*(Pos+1),p->_Begin+Width*Pos,(Count-Pos)*Width);
}
memcpy(p->_Begin+Width*Pos,Data,Width);
return 1;
}
bool_t ArrayRemove(array* p, int Count, size_t Width, const void* Data, arraycmp Cmp)
{
bool_t Found;
int Pos = ArrayFind(p,Count,Width,Data,Cmp,&Found);
if (Found)
{
memmove(p->_Begin+Pos*Width,p->_Begin+(Pos+1)*Width,(p->_End-p->_Begin)-(Pos+1)*Width);
p->_End -= Width;
}
return Found;
}
void ArrayLock(array* p)
{
#ifdef TARGET_PALMOS
if (!p->_Block.Ptr && p->_End != p->_Begin)
{
int n = p->_End-p->_Begin;
if (AllocBlock(n,&p->_Block,1,HEAP_STORAGE))
{
WriteBlock(&p->_Block,0,p->_Begin,n);
free(p->_Begin);
p->_Begin = (uint8_t*)p->_Block.Ptr;
p->_End = p->_Begin + n;
p->_Allocated = 0;
}
}
#endif
}
bool_t ArrayUnlock(array* p,size_t Align)
{
#ifdef TARGET_PALMOS
if (p->_Block.Ptr)
{
uint8_t* Mem;
size_t n = p->_End-p->_Begin;
size_t Total;
--Align;
Total = (n + Align) & ~Align;
Mem = (uint8_t*) malloc(Total);
if (!Mem)
return 0;
memcpy(Mem,p->_Begin,n);
FreeBlock(&p->_Block);
p->_Begin = Mem;
p->_End = p->_Begin + n;
p->_Allocated = Total;
}
#endif
return 1;
}