SmartAudio/package/allwinner/liballwinner_tina/liballwinner/LIBRARY/DEMUX/BASE/CdxBuffer.c

287 lines
7.1 KiB
C
Executable File

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : CdxBuffer.c
* Description : Buffer
* History :
*
*/
#include <CdxTypes.h>
#include <CdxMemory.h>
#include <CdxLog.h>
#include <CdxAtomic.h>
//#include <CdxBaseErrno.h>
#include <CdxBuffer.h>
#include <CdxMeta.h>
struct CdxBufferImplS
{
struct CdxBufferS base;
AwPoolT *pool;
cdx_bool selfPool;
CdxMetaT *mMeta;
cdx_uint8 *mData;
cdx_uint32 mCapacity;
cdx_uint32 mRangeOffset;
cdx_uint32 mRangeLen;
cdx_atomic_t mRef;
};
static cdx_uint32 Align2Power(cdx_uint32 val)
{
cdx_uint32 ret = 1024;
while (ret < val)
{
ret = ret << 2;
}
return ret;
}
static cdx_void onWrite(struct CdxBufferImplS *impl, cdx_uint32 offset,
const cdx_uint8 *data, cdx_uint32 len)
{
if (impl->mCapacity < offset + len)
{
impl->mCapacity = Align2Power(offset + len);
impl->mData = Prealloc(impl->pool, impl->mData, impl->mCapacity);
CDX_FORCE_CHECK(impl->mData);
}
memcpy(impl->mData + offset, data, len);
return ;
}
static cdx_void onSetRange(struct CdxBufferImplS *impl,
cdx_uint32 offset, cdx_uint32 len)
{
CDX_CHECK(offset + len <= impl->mCapacity);
impl->mRangeOffset = offset;
impl->mRangeLen = len;
return ;
}
static CdxBufferT *__CdxBufferIncRef(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
CdxAtomicInc(&impl->mRef);
return buf;
}
static cdx_void __CdxBufferDecRef(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
if (CdxAtomicDec(&impl->mRef) == 0)
{
CdxMetaDestroy(impl->mMeta);
Pfree(impl->pool, impl->mData);
if (impl->selfPool)
{
AwPoolT *pool = impl->pool;
Pfree(impl->pool, impl);
AwPoolDestroy(pool);
}
else
{
Pfree(impl->pool, impl);
}
}
return ;
}
static cdx_uint8 *__CdxBufferGetData(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
return impl->mData + impl->mRangeOffset;
}
static cdx_uint8 *__CdxBufferGetBase(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
return impl->mData;
}
static cdx_uint32 __CdxBufferGetSize(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
return impl->mRangeLen;
}
cdx_void __CdxBufferSetRange(CdxBufferT *buf, cdx_uint32 offset, cdx_uint32 len)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
onSetRange(impl, offset, len);
return ;
}
cdx_void __CdxBufferSeekRange(CdxBufferT *buf, cdx_int32 left, cdx_int32 right)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
impl->mRangeOffset = (cdx_uint32)((cdx_int32)impl->mRangeOffset + left);
impl->mRangeLen = (cdx_uint32)((cdx_int32)impl->mRangeLen + (right - left));
CDX_CHECK(impl->mRangeOffset + impl->mRangeLen <= impl->mCapacity);
return ;
}
static cdx_void __CdxBufferAppend(CdxBufferT *buf, const cdx_uint8 *data,
cdx_uint32 len)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
onWrite(impl, impl->mRangeOffset + impl->mRangeLen, data, len);
onSetRange(impl, impl->mRangeOffset, impl->mRangeLen + len);
return ;
}
static cdx_void __CdxBufferInsert(CdxBufferT *buf, const cdx_uint8 *data, cdx_uint32 len)
{
struct CdxBufferImplS *impl = NULL;
cdx_uint8 *tmpData = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
if (len <= impl->mRangeOffset) /*lucky have enough buf before range*/
{
impl->mRangeOffset -= len;
impl->mRangeLen += len;
memcpy(impl->mData + impl->mRangeOffset, data, len);
return ;
}
/*not enough buf before range*/
if (impl->mCapacity >= impl->mRangeLen + len) /*capacity is enough*/
{
memmove(impl->mData + len, impl->mData + impl->mRangeOffset,
impl->mRangeLen);
memcpy(impl->mData, data, len);
impl->mRangeOffset = 0;
impl->mRangeLen += len;
return ;
}
impl->mCapacity = Align2Power(impl->mRangeLen + len);
tmpData = Palloc(impl->pool, impl->mCapacity);
CDX_FORCE_CHECK(tmpData);
memcpy(tmpData, data, len);
memcpy(tmpData + len, impl->mData + impl->mRangeOffset, impl->mRangeLen);
Pfree(impl->pool, impl->mData);
impl->mData = tmpData;
impl->mRangeOffset = 0;
impl->mRangeLen += len;
return ;
}
CdxMetaT *__CdxBufferGetMeta(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
return impl->mMeta;
}
static struct CdxBufferOpsS gBufferOps =
{
.incRef = __CdxBufferIncRef,
.decRef = __CdxBufferDecRef,
.getData = __CdxBufferGetData,
.getBase = __CdxBufferGetBase,
.getSize = __CdxBufferGetSize,
.append = __CdxBufferAppend,
.insert = __CdxBufferInsert,
.setRange = __CdxBufferSetRange,
.seekRange = __CdxBufferSeekRange,
.getMeta = __CdxBufferGetMeta
};
CdxBufferT *__CdxBufferCreate(AwPoolT *pool, cdx_uint32 capacity, cdx_uint8 *initData,
cdx_uint32 len, char *file, int line)
{
struct CdxBufferImplS *impl = NULL;
char *callFrom = file;
CDX_CHECK(capacity != 0);
CDX_CHECK(capacity >= len);
#ifdef MEMORY_LEAK_CHK
callFrom = malloc(512);
sprintf(callFrom, "%s:%s", file, __FUNCTION__);
#endif
if (pool)
{
impl = AwPalloc(pool, sizeof(struct CdxBufferImplS), callFrom, line);
memset(impl, 0x00, sizeof(struct CdxBufferImplS));
impl->pool = pool;
}
else
{
AwPoolT *privPool = __AwPoolCreate(NULL, callFrom, line);
impl = Palloc(pool, sizeof(struct CdxBufferImplS));
memset(impl, 0x00, sizeof(struct CdxBufferImplS));
impl->pool = privPool;
impl->selfPool = CDX_TRUE;
}
CDX_FORCE_CHECK(impl);
impl->mMeta = CdxMetaCreate(impl->pool);
impl->mCapacity = Align2Power(capacity);
impl->mData = Palloc(impl->pool, impl->mCapacity);
CDX_FORCE_CHECK(impl->mData);
impl->mRangeOffset = 0;
impl->mRangeLen = 0;
if (initData && (len > 0))
{
memcpy(impl->mData, initData, len);
impl->mRangeLen = len;
}
impl->base.ops = &gBufferOps;
CdxAtomicSet(&impl->mRef, 1);
return &impl->base;
}
cdx_void CdxBufferDestroy(CdxBufferT *buf)
{
struct CdxBufferImplS *impl = NULL;
CDX_CHECK(buf);
impl = CdxContainerOf(buf, struct CdxBufferImplS, base);
__CdxBufferDecRef(buf);
return ;
}