/*********************************************************************************
 * Copyright(C),Dalian Joynext Technology Co., Ltd.
 * FileName:    CAN_Buffer.c
 * Author:      huo_h1
 * Version :    Ver0.1
 * Date:        2020-10-15
 * Description:
 *
 *********************************************************************************/
/*********************************************************************************
 *                      Include                                                  *
**********************************************************************************/
#include "CAN_Buffer.h"

/*********************************************************************************
 *                      Typedef/Struct                                           *
**********************************************************************************/
struct BufferObj
{
    uint8_t*  data;            /* Signal Buffer */
    uint32_t  size;
    uint32_t  start_pos;
    uint32_t  current_pos;
    uint8_t   is_attach;    
};

/*********************************************************************************
*                      Function                                                  *
**********************************************************************************/
BufferObj* BufferObj_alloc()
{
    BufferObj* buffer = OS_malloc(sizeof(BufferObj));

    if(NULL != buffer)
    {
        memset(buffer, 0, sizeof(BufferObj));
    }

    return buffer;
}

void BufferObj_init(BufferObj* buffer, uint32_t size)
{
    if(NULL != buffer && NULL == buffer->data)
    {
        buffer->data = OS_malloc(size);
        buffer->start_pos = 0;
        buffer->current_pos = 0;

        if(buffer->data != NULL)
        {
            buffer->size = size;
        	memset(buffer->data, 0, buffer->size);
        }
    }
}

void BufferObj_release(BufferObj* buffer)
{
    if(NULL != buffer)
    {
        if(NULL != buffer->data && true != buffer->is_attach)
        {
            OS_free(buffer->data);
        }
        
        buffer->data = NULL;
        buffer->size = 0;
        buffer->current_pos = 0;
        buffer->is_attach = false;

        OS_free(buffer);
    }
}

void BufferObj_attach(BufferObj* buffer, uint8_t* data, uint32_t data_size)
{
    if(NULL != buffer && NULL != data && 0 != data_size)
    {
        if(NULL != buffer->data && true != buffer->is_attach)
        {
            OS_free(buffer->data);
        }

        buffer->data = data;
        buffer->size = data_size;
        buffer->start_pos = 0;
        buffer->current_pos = data_size;
        buffer->is_attach = true;
    }
}

void BufferObj_detach(BufferObj* buffer)
{
    if(NULL != buffer && true == buffer->is_attach)
    {
        buffer->data = 0;
        buffer->size = 0;
        buffer->start_pos = 0;
        buffer->current_pos = 0;
        buffer->is_attach = false;
    }
}

void BufferObj_clear(BufferObj* buffer)
{
    if(NULL != buffer)
    {
        if(true != buffer->is_attach)
        {
        	if(buffer->data != NULL)
        	{
        		memset(buffer->data, 0, buffer->size);
                buffer->current_pos = 0;
        	}
        }
        
        buffer->start_pos = 0;
    }
}

void BufferObj_pushBack(BufferObj* buffer, uint8_t* data, uint32_t data_size)
{
    if(NULL != buffer && NULL != data && 0 != data_size)
    {
        if(buffer->current_pos + data_size <= buffer->size)
        {
        	if(buffer->data != NULL)
        	{
        		memcpy(buffer->data + buffer->current_pos, data, data_size);
        		buffer->current_pos += data_size;
        	}
        }
    }
}

void BufferObj_popFront(BufferObj* buffer, uint8_t* data, uint32_t data_size)
{
    if(NULL != buffer && NULL != data && 0 != data_size)
    {
        if(buffer->start_pos + data_size <= buffer->current_pos)
        {
        	if(buffer->data != NULL)
        	{
        		memcpy(data, buffer->data + buffer->start_pos, data_size);
        		buffer->start_pos += data_size;
        	}
        }
    }
}

void BufferObj_update(BufferObj* buffer, uint8_t ubPos, uint8_t* data, uint32_t data_size)
{
    if(NULL != buffer && NULL != data && 0 != data_size)
    {
        if(ubPos + data_size <= buffer->size)
        {
        	if(buffer->data != NULL)
        	{
				memcpy(buffer->data + ubPos, data, data_size);

				if(buffer->current_pos < ubPos + data_size)
				{
					buffer->current_pos = ubPos + data_size;
				}
        	}
        }
    }
}

uint32_t BufferObj_getSpace(BufferObj* buffer)
{
    if(NULL != buffer)
    {
        return buffer->size - buffer->current_pos;
    }

    return 0;
}

uint8_t* BufferObj_getBuffer(BufferObj* buffer)
{
    if(NULL != buffer)
    {
        return buffer->data;
    }

    return NULL;
}

uint32_t BufferObj_getBufferSize(BufferObj* buffer)
{
    if(NULL != buffer)
    {
        return buffer->current_pos;
    }

    return 0;
}
