/*
 * Emunation Plugin for MD-API 
 *
 * This code 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 code 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.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 */
#include "dataparser.h"

cDataParser::cDataParser()
{
    m_buf=0;
    m_buflength=0;
    m_data=0;
}

cDataParser::cDataParser(unsigned char* buffer,int length)
{
    m_buf=buffer;
    m_buflength=length;
    m_data=0;
}

cDataParser::~cDataParser()
{
    if (m_data)
        delete m_data;
}
void cDataParser::SetBuffer(unsigned char* buffer,int length)
{
    m_buf=buffer;
    m_buflength=length;
}
unsigned long cDataParser::GetBits (int byte_offset, int startbit, int bitlen)
{
 unsigned char *b;
 unsigned long  v;
 unsigned long mask;
 unsigned long tmp_long;
 int           bitHigh;

 if(!m_buf)return 0xFEFEFEFE;

 b = &m_buf[byte_offset + (startbit >> 3)];
 startbit %= 8;

 switch ((bitlen-1) >> 3) {
	 case -1:	// -- <=0 bits: always 0
		return 0L;
		break;

	case 0:		// -- 1..8 bit
 		tmp_long = (unsigned long)(
			(*(b  )<< 8) +  *(b+1) );
		bitHigh = 16;
		break;

	case 1:		// -- 9..16 bit
 		tmp_long = (unsigned long)(
		 	(*(b  )<<16) + (*(b+1)<< 8) +  *(b+2) );
		bitHigh = 24;
		break;

	case 2:		// -- 17..24 bit
 		tmp_long = (unsigned long)(
		 	(*(b  )<<24) + (*(b+1)<<16) +
			(*(b+2)<< 8) +  *(b+3) );
		bitHigh = 32;
		break;

	case 3:		// -- 25..32 bit
			// -- to be safe, we need 32+8 bit as shift range 
		return (unsigned long) GetBits48 (0, startbit, bitlen);
		break;

	default:	// -- 33.. bits: fail, deliver constant fail value
		return (unsigned long) 0xFEFEFEFE;
		break;
 }

 startbit = bitHigh - startbit - bitlen;
 tmp_long = tmp_long >> startbit;
 mask     = (1ULL << bitlen) - 1;  // 1ULL !!!
 v        = tmp_long & mask;

 return v;
}

long long cDataParser::GetBits48 (int byte_offset, int startbit, int bitlen)
{
 unsigned char *b;
 unsigned long long v;
 unsigned long long mask;
 unsigned long long tmp;

 if (bitlen > 48) {
	return 0xFEFEFEFEFEFEFEFELL;
 }
 if(!m_buf)return 0xFEFEFEFE;

 b = &m_buf[byte_offset + (startbit / 8)];
 startbit %= 8;


 // -- safe is 48 bitlen
 tmp = (unsigned long long)(
	 ((unsigned long long)*(b  )<<48) + ((unsigned long long)*(b+1)<<40) +
	 ((unsigned long long)*(b+2)<<32) + ((unsigned long long)*(b+3)<<24) +
	 (*(b+4)<<16) + (*(b+5)<< 8) + *(b+6) );

 startbit = 56 - startbit - bitlen;
 tmp      = tmp >> startbit;
 mask     = (1ULL << bitlen) - 1;	// 1ULL !!!
 v        = tmp & mask;

 return v;
}

unsigned long long cDataParser::GetBits64 (int byte_offset, int startbit, int bitlen)
{
  unsigned long long x1,x2,x3;

  if (bitlen <= 32) {
     x3 = GetBits (byte_offset,startbit,bitlen); 
  } else {
     x1 = GetBits (byte_offset,startbit,32); 
     x2 = GetBits (byte_offset,startbit+32,bitlen-32); 
     x3 = (x1<<(bitlen-32)) + x2;
  }
  return x3;
}

cListBase*  cDataParser::GetData()
{
    return m_data;
}
bool cDataParser::Parse()
{
    return false;
}
