//   (c) J. Dean Brock, 1998, 1999, 2002
//   Written for UNCA CSCI 343
//   Various useful routines for the B+-tree

#include <fstream>
using namespace std ;

#include <string.h>

#include "btree.hxx"

// Search for slot less then or equal to key 
void bTree::findLEslot(
	const blockRecT &b,		// Block to search
	const char key[KEYSIZE],	// Key to search for
	int &pos,			// index of the found slot,
					//  set to getUsedRecords(b) if search
					//   key exceeds all slot values
	int &eq)			// set to 1 iff key is exact match
{
  int i, lc ;
  for (i=0; i < getUsedRecords(&b) &&
            (lc=strncmp(b.recs[i].name, key, KEYSIZE)) < 0; ++i) ;
  pos = i ;
  eq = !lc ;
}

void bTree::insertRec(
	blockRecT &b,		// Block to contain new record
	int pos,		// Place for insertion
	const simpRecT &r)	// Record to insert
{
  int j ;
  if (! isLeaf(&b))
    b.recs[getUsedRecords(&b)+1].value = b.recs[getUsedRecords(&b)].value ;
  for (j = getUsedRecords(&b); j > pos; --j)
    b.recs[j] = b.recs[j-1] ;
  b.recs[pos] = r ;
  setUsedRecords(&b, getUsedRecords(&b)+1) ;
}

void bTree::splitBlock(
        blockRecT &xBlock,	// The existing block to be split
	blockRecT &nBlock,	// New block -- other half of split
	char splitKey[KEYSIZE],	// Split key name
	const simpRecT &nRec,	// New Record
	int i)			// Place for inserting new record
{
  const int h = RECSINBLK/2 ;
  int j ;
  // ain't this a mess
  nBlock.recs[h+1].value = xBlock.recs[METAPNTR].value ;
  if (i<=h) {
    // New record goes in first half -- that is, in old block
    // Move last half of old block to first half of new block
    for (j = 0; j <= h; ++j)
      nBlock.recs[j] = xBlock.recs[j+h] ;
    // Move elements in old block above i, up a slot
    for (j = h; i < j; --j)
      xBlock.recs[j] = xBlock.recs[j-1] ;
    // Insert the new record
    xBlock.recs[i] = nRec;
  } else {
    // New record goes in the second half -- that is, in new block
    // Move part of old block below i into the new
    for (j = h+1; j < i; ++j)
      nBlock.recs[j-h-1] = xBlock.recs[j] ;
    // Move in new block i
    nBlock.recs[i-h-1] = nRec ;
    // Move part of old block above i into the new
    for (j = i; j < RECSINBLK; ++j)
      nBlock.recs[j-h] = xBlock.recs[j] ;
  }
  (void) strncpy(splitKey, xBlock.recs[h].name, KEYSIZE) ;
  setUsedRecords(&nBlock, h+1) ;
  if (isLeaf(&xBlock)) {
    setLeaf(&nBlock) ;
    nBlock.recs[METAPNTR].value = xBlock.recs[METAPNTR].value ;
    setUsedRecords(&xBlock, h+1) ;
  } else {
    clearLeaf(&nBlock) ;
    setUsedRecords(&xBlock, h) ;
  }
}
