/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

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 3 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, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
#include "hsUtils.h"
#include "plRingBuffer.h"

plRingBuffer::plRingBuffer(int size)
:   plMemBuffer(size)
{            
    fEndPos = 0;
    fStartPos = 0;
}

void plRingBuffer::FullCompress()
{
    if (fStartPos == fEndPos)
    {
        fStartPos = 0;
        fEndPos = 0;
    }
    else 
    {
        ForceWindowSlide();
    }    
}

void plRingBuffer::Compress()
{
    if (fStartPos == fEndPos)
    {
        fStartPos = 0;
        fEndPos = 0;
    }
    else if(fStartPos >= GetBufferSize() / 2) 
    {
        ForceWindowSlide();
    }    
}

bool plRingBuffer::Put(const char * data, int len)
{
    bool ans = false;
    
    if (len > BufferAvailable())
        Compress();
    
    if (len <= BufferAvailable())
    {
        memcpy(GetBufferOpen(), data, len);
        fEndPos += len;
        ans = true;
    }
    return ans;
}

bool plRingBuffer::Get(char * data, int len)
{
    bool ans = false;
    
    if (len < AmountBuffered())
    {
        memcpy(data, GetBufferStart(), len);
        fStartPos += len;
        Compress();
        ans = true;
    }
    return ans;
}

int plRingBuffer::AmountBuffered() 
{ 
    return fEndPos - fStartPos; 
}

int plRingBuffer::BufferAvailable() 
{ 
    return GetBufferSize() - fEndPos; 
}

void plRingBuffer::Reset() 
{ 
    fStartPos = 0; 
    fEndPos = 0; 
}

char * plRingBuffer::GetBufferStart() 
{ 
    return fBuffer+fStartPos;
}

char * plRingBuffer::GetBufferOpen() 
{
    return fBuffer+fEndPos; 
}

void plRingBuffer::ForceWindowSlide()
{
    int len = AmountBuffered();
    if(len > 0 && fStartPos != 0)
    {
        memmove(fBuffer, GetBufferStart(), len);
        fStartPos = 0;
        fEndPos = len;        
    }
}

bool plRingBuffer::PutFast(const char * data, int len)
{
    // no checking be careful
    memcpy(GetBufferOpen(), data, len); // or memmove?
    fEndPos += len;
    return true;
}