#include "ltx2mathmlclasses.h"
#include <stdio.h>

Buffer::Buffer()
{
       m_buf   = NULL;
       m_index = 0;
       m_size  = 0;
}

Buffer::~Buffer()
{
       destroy();
}

void Buffer::destroy()
{
       if( m_buf != NULL )
               free( m_buf );

       m_buf   = NULL;
       m_index = 0;
}

void Buffer::setlength( size_t len )
{
       char *tmp = (char *) realloc( m_buf, len + 1 );

       if( tmp != NULL )
       {
               m_buf = tmp;

               m_size = len;
               if( m_index > len )     // truncated
               {
                       m_index = len;
               }
               else
               {
                       ZeroMemory( &m_buf[ m_index ], ( len - m_index ) );
               }
       }
       else
               throw ex_out_of_memory;
}

size_t  Buffer::length()
{
       return m_index;
}

void Buffer::format( const char *fmt, ... )
{
       va_list list;
       size_t len;
       char s[256];

       va_start( list, fmt );
       //len = vsprintf_s( s, sizeof( s ) - 1, fmt, list );
       len = vsprintf( s, fmt, list );
       va_end( list );
       _write( m_index, s, len );
}


void Buffer::_write( size_t index, const char *s, size_t len )
{
       if( !s || ( len <= 0 ) )
       {
               return;
       }

       if( ( m_size - m_index ) <= len )
       {
               setlength( m_size + len + 1);

       }

       memcpy( &m_buf[ index ], s, len );


       m_index += len;
}


void Buffer::write( const char *s, size_t len )
{
       _write( m_index, s, len );
}

void Buffer::write( const char *s )
{
       _write( m_index, s, strlen( s ) );
}

char *Buffer::data( size_t *len )
{
       if( len != NULL )
       {
               *len = m_index;
       }

       return m_buf;
}


void Buffer::append( Buffer &buf, bool transfer )
{
       if( transfer && m_index == 0 )
       {
               BufferStruct temp;

               buf.releaseBuffer( temp );

               m_buf   = temp.m_buf;
               m_index = temp.m_index;
               m_size  = temp.m_size;
       }
       else
       {
               _write( m_index, buf.m_buf, buf.m_index );
       }
}

void Buffer::releaseBuffer( BufferStruct &buf )
{
       buf.m_buf   = m_buf;
       buf.m_index = m_index;
       buf.m_size  = m_size;

       m_size  = 0;
       m_index = 0;
       m_buf   = NULL;
}

void Buffer::reset()
{
       ZeroMemory( m_buf, m_index );
       m_index  = 0;
}

char *Buffer::release()
{
       char *temp;

       temp    = m_buf;
       m_size  = 0;
       m_index = 0;
       m_buf   = NULL;

       return temp;
}

void Buffer::insertAt( size_t index, const char *s )
{
       size_t len, count;
       char *src, *dest;

       len = strlen( s );

       if( len == 0 )
         return;

       if( index >= m_index )
       {
               _write( index, s, len );
               return;
       }

       if( ( m_size - m_index ) <= len )
       {
               setlength( m_size + len + 1);
       }
       src = m_buf + index;
       dest = src + len;

       count = m_index - index;

       //memmove_s( dest, m_size, src, count );

       memmove( dest, src, count );
       memcpy( m_buf + index, s, len );
       m_index += len;
}