/*
 * (c) J. Dean Brock, 1998, 1999, 2002
 */

#ifndef _BTREE_H_
#define _BTREE_H_

#define KEYSIZE 12

typedef struct simpRec {
   int      value ;	/* MUST be stored in little endian order */
   char     name[KEYSIZE] ;
} simpRecT ;

#define RECSINBLK 7
#define METAPNTR  RECSINBLK

/* The first RECSINBLK simpRecT records of the block are
 * the real nodes.  The last record, indexed by METAPNTR,
 * is really a metadata field for recording information
 * documented below.  It would be better to use unions,
 * but not enough students have seen them.
 */

typedef struct blockRec {
  simpRecT recs[RECSINBLK+1] ;
} blockRecT ;

/*
 * These are the invariants used by this implementation
 * to maintain the btree.
 */

/* Within the last simpRecT of a node N, the last record
 * is used as follows:
 *   N.recs[METAPNTR].name[0]:
 *           number of records used within N,
 *   N.recs[METAPNTR].name[1]:
 *           type of the node -- interior and/or leaf
 */

/* Macros for accessing/setting metadata information */
#define getUsedRecords(NP) ( (int) (NP)->recs[METAPNTR].name[0] )
#define setUsedRecords(NP,X) ( (NP)->recs[METAPNTR].name[0] = (char) (X) )
#define isLeaf(NP) ( (NP)->recs[METAPNTR].name[1] )
#define setLeaf(NP) ( (NP)->recs[METAPNTR].name[1] = 1 )
#define clearLeaf(NP) ( (NP)->recs[METAPNTR].name[1] = 0 )

/* invariant for the node data structure, N
 *
 *   There are getUsedRecords(&N) elements of N.data that are in use
 *   These getUsedRecords(&N) elements are sorted by the X.rec[*].name field
 *   getUsedRecords(&N) <= RECSINBLK

 *   If ! isLeaf(&N)
 *      the block corresponds to an interior node
 *      for 0<=i<=getUsedRecords(&N)
 *        N.data[i].value points to a subtree that contains all database
 *          names greater than N.data[i-1].name (if i>0) and
 *          less than or equal to N.data[i].name (if i<getUsedRecords(&N))
 *   If isLeaf(&N)
 *      the block is a leaf node
 *      N.data[i].value is the value of the database element
 *          with key X.data[i].name
 *      N.data[METAPTR].value points to the next leaf node 
 */

#endif
