///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoAVLIndexEntry.cc
// -----------------
// Cego index entry class implementation
//     
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2019 Bjoern Lemke
//
// IMPLEMENTATION MODULE
//
// Class: CegoAVLIndexEntry
// 
// Description: Implementation of tree entry for full balanced AVL index trees
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

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

// cego includes
#include "CegoAVLIndexEntry.h"

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

CegoAVLIndexEntry::CegoAVLIndexEntry()
{
    _pI = 0;
    _len = 0;
    _isLocal = false;
}

CegoAVLIndexEntry::~CegoAVLIndexEntry()
{
    if (_isLocal)
    {
	free (_pI);
    }
}

void CegoAVLIndexEntry::initEntry(const CegoDataPointer& dp, char* idxPtr, unsigned idxLen)
{   
    if (_isLocal)
	free(_pI);

    CegoDataPointer zp(0,0);

    _len = 4 * zp.getEncodingLength() + sizeof(char) + idxLen;

    _pI = malloc(_len);

    if (_pI == 0)
    {
	throw Exception(EXLOC, Chain("Cannot allocate index entry"));
    }

    _isLocal = true;

    setParent(zp);
    setLeftBranch(zp);
    setRightBranch(zp);
    setData(dp);
    setHeight(0);
    
    _idxDataPtr =  (char*)((long long)_pI + _len - idxLen);
    memcpy(_idxDataPtr, idxPtr, idxLen);
}

void CegoAVLIndexEntry::setPtr(void* p, unsigned len)
{
    _isLocal = false;
    _pI = p;
    _len = len;
    CegoDataPointer dp;
    _idxDataPtr = (char*)((long long)_pI + 4 * dp.getEncodingLength() + sizeof(char));
}

void* CegoAVLIndexEntry::getPtr()
{
    return _pI;
}

unsigned CegoAVLIndexEntry::getLen() const
{
    return _len;
}
   
void CegoAVLIndexEntry::setParent(const CegoDataPointer& dp)
{
    dp.encode(_pI);
}

CegoDataPointer CegoAVLIndexEntry::getParent() const
{
    CegoDataPointer dp;
    dp.decode(_pI);
    return dp;
}

void CegoAVLIndexEntry::setLeftBranch(const CegoDataPointer& dp)
{
    dp.encode((void*)((long long)_pI + dp.getEncodingLength()));    
}

CegoDataPointer CegoAVLIndexEntry::getLeftBranch() const
{
    CegoDataPointer dp;
    dp.decode((void*)((long long)_pI + dp.getEncodingLength()));
    return dp;    
}

void CegoAVLIndexEntry::setRightBranch(const CegoDataPointer& dp)
{
    dp.encode((void*)((long long)_pI + 2 * dp.getEncodingLength())); 
}

CegoDataPointer CegoAVLIndexEntry::getRightBranch() const
{
    CegoDataPointer dp;
    dp.decode((void*)((long long)_pI + 2 * dp.getEncodingLength()));
    return dp;
}

void CegoAVLIndexEntry::setData(const CegoDataPointer& dp)
{
    dp.encode((void*)((long long)_pI + 3 * dp.getEncodingLength()));
}

CegoDataPointer CegoAVLIndexEntry::getData() const
{
    CegoDataPointer dp;
    dp.decode((void*)((long long)_pI + 3 * dp.getEncodingLength()));
    return dp;
}

char* CegoAVLIndexEntry::getIdxPtr()
{
    return _idxDataPtr;
}

unsigned CegoAVLIndexEntry::getIdxLen()
{
    CegoDataPointer dp;
    return _len - 4 * dp.getEncodingLength() + sizeof(char);
}

void CegoAVLIndexEntry::setHeight(char h)
{   
    CegoDataPointer dp;
    char* p = (char*)((long long)_pI +  4 * dp.getEncodingLength() );
    *p = h;
}

char CegoAVLIndexEntry::getHeight() const
{
    CegoDataPointer dp;
    char h = *((char*)((long long)_pI +  4 * dp.getEncodingLength() ));
    return (h);
}

CegoAVLIndexEntry& CegoAVLIndexEntry::operator = (const CegoAVLIndexEntry& ie)
{
    _pI = ie._pI;
    _len = ie._len;
    _idxDataPtr = ie._idxDataPtr;
    return (*this);
}
