273 lines
5.8 KiB
C
Executable File
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;
|
|
}
|