///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoGroupEntry.cc
// -----------------
// Cego group entry class implementation
//     
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2010 Bjoern Lemke
//
// 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 2, 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; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// IMPLEMENTATION MODULE
//
// Class: CegoGroupEntry
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

// base includes
#include <lfc/Exception.h>

// cego includes
#include "CegoGroupEntry.h"

#include <string.h>
#include <stdlib.h>

CegoGroupEntry::CegoGroupEntry()
{
    _pEntry = 0;
    _len = 0;
    _isAllocated = false;
}

CegoGroupEntry::~CegoGroupEntry()
{
    if ( _pEntry && _isAllocated )
	free(_pEntry);
}

void CegoGroupEntry::initEntry(char* keyPtr, int keyLen, char* tupPtr, int tupLen, const CegoDataPointer& l,
			       const CegoDataPointer& r,
			       const CegoDataPointer& p)
{
    
    _len = keyLen + tupLen + 2 * sizeof(int) + l.getEncodingLength() + r.getEncodingLength() + p.getEncodingLength();

    _pEntry = malloc(_len);
    
    if (_pEntry == 0 )
    {
	throw Exception(EXLOC, "Cannot allocate order entry");
    }

    _isAllocated=true;
    
    memcpy((void*)((long)_pEntry + sizeof(int)), keyPtr, keyLen);
    setKeyLen(keyLen);

    memcpy((void*)((long)_pEntry + keyLen + 2 * sizeof(int)), tupPtr, tupLen);
    setTupLen(tupLen);

    setLeft(l);
    setRight(r);
    setParent(p);
}

void* CegoGroupEntry::getKeyPtr()
{
    return (void*)((long)_pEntry + sizeof(int));
}

void* CegoGroupEntry::getTupPtr()
{
    int keyLen = getKeyLen();
 
    return (void*)((long)_pEntry + sizeof(int) + keyLen + sizeof(int));
}

void CegoGroupEntry::setKeyLen(int keyLen)
{
    memcpy( (void*)((long)_pEntry), &keyLen, sizeof(int));
}

int CegoGroupEntry::getKeyLen() const
{
    int keyLen;
    memcpy(&keyLen, (void*)((long)_pEntry), sizeof(int));
    return keyLen;
}

void CegoGroupEntry::setTupLen(int tupLen)
{
    int keyLen = getKeyLen();
    memcpy( (void*)((long)_pEntry + sizeof(int) + keyLen), &tupLen, sizeof(int));
}

int CegoGroupEntry::getTupLen() const
{
    int tupLen;

    int keyLen = getKeyLen();
    memcpy(&tupLen, (void*)((long)_pEntry + sizeof(int) + keyLen), sizeof(int));
    return tupLen;
}

void CegoGroupEntry::setPtr(char* p, int len)
{
    if ( _isAllocated && _pEntry )
	free(_pEntry);
    _isAllocated = false;
    _pEntry = p;
    _len = len;
}

void* CegoGroupEntry::getPtr()
{
    return _pEntry;
}

int CegoGroupEntry::getLen() const
{
    return _len;
}

void CegoGroupEntry::setLeft(const CegoDataPointer& dp)
{   
    int keyLen = getKeyLen();
    int tupLen = getTupLen();
    dp.encode((void*) ( (long)_pEntry + sizeof(int) + keyLen + sizeof(int) + tupLen ));
}

void CegoGroupEntry::setRight(const CegoDataPointer& dp)
{
    CegoDataPointer l;
    int keyLen = getKeyLen();
    int tupLen = getTupLen();
    dp.encode((void*) ( (long)_pEntry + sizeof(int) + keyLen + sizeof(int) + tupLen + l.getEncodingLength()));
}


void CegoGroupEntry::setParent(const CegoDataPointer& dp)
{
    CegoDataPointer l;
    CegoDataPointer r;
    int keyLen = getKeyLen();
    int tupLen = getTupLen();
    dp.encode((void*) ( (long)_pEntry + sizeof(int) + keyLen + sizeof(int) + tupLen 
			+ l.getEncodingLength() + r.getEncodingLength()));
}

CegoDataPointer CegoGroupEntry::getLeft() const
{
    CegoDataPointer dp;
    int keyLen = getKeyLen();
    int tupLen = getTupLen();
    dp.decode((void*) ( (long)_pEntry + sizeof(int) + keyLen + sizeof(int) + tupLen ));
    return dp;
}


CegoDataPointer CegoGroupEntry::getRight() const
{
    CegoDataPointer dp;
    CegoDataPointer l;
    int keyLen = getKeyLen();
    int tupLen = getTupLen();
    dp.decode((void*) ( (long)_pEntry + sizeof(int) + keyLen + sizeof(int) + tupLen + l.getEncodingLength() ));
    return dp;
}


CegoDataPointer CegoGroupEntry::getParent() const
{
    CegoDataPointer dp;
    CegoDataPointer l;
    CegoDataPointer r;

    int keyLen = getKeyLen();
    int tupLen = getTupLen();
    
    dp.decode((void*) ( (long)_pEntry + sizeof(int) + keyLen + sizeof(int) + tupLen + 
			l.getEncodingLength() + r.getEncodingLength() ));    
    return dp;
}


CegoGroupEntry& CegoGroupEntry::operator = (const CegoGroupEntry& oe)
{
    _pEntry = oe._pEntry;
    _len = oe._len;
    _isAllocated = false;
    return (*this);
}

