    // ------------------------------- //
    // -------- Start of File -------- //
    // ------------------------------- //
    // ----------------------------------------------------------- //
    // C++ Source Code File Name: testprog.cpp
    // Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC
    // Produced By: DataReel Software Development Team
    // File Creation Date: 08/22/2000
    // Date Last Modified: 06/17/2016
    // Copyright (c) 2001-2024 DataReel Software Development
    // ----------------------------------------------------------- //
    // ------------- Program Description and Details ------------- //
    // ----------------------------------------------------------- //
    /*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA

    This is a test program for the B-tree node class.
    */
    // ----------------------------------------------------------- //
    #include "gxdlcode.h"

    #if defined (__USE_ANSI_CPP__) // Use the ANSI Standard C++ library
    #include <iostream>
    using namespace std; // Use unqualified names for Standard C++ library
    #else // Use the old iostream library by default
    #include <iostream.h>
    #endif // __USE_ANSI_CPP__

    #include "btnode.h"
    #include "gxdbase.h"

    // Set the node order and maximum key size for this key class
    const BtreeNodeOrder_t MyKeyClassOrder = 8;
    const __WORD__ MyKeyNameSize = 26;

    // Key class for this database
    class MyKeyClass : public DatabaseKeyB
    {
    public:
      MyKeyClass();
      MyKeyClass(const char *name);
      void operator=(const char *name);
      ~MyKeyClass() { }

    public: // Base class interface
      size_t KeySize() { return sizeof(key_name); }
      int operator==(const DatabaseKeyB& key) const;
      int operator>(const DatabaseKeyB& key) const;

      // NOTE: This comparison function is only used if the
      // __USE_SINGLE_COMPARE__ preprocessor directive is
      // defined when the program is compiled.
      int CompareKey(const DatabaseKeyB& key) const;

    public: // Persistent data member
      char key_name[MyKeyNameSize];
    };

    MyKeyClass::MyKeyClass() : DatabaseKeyB((char *)key_name)
    {
      for(int i = 0; i < MyKeyNameSize; i++) key_name[i] = 0;
    }

    MyKeyClass::MyKeyClass(const char *name) : DatabaseKeyB((char *)key_name)
    {
      for(int i = 0; i < MyKeyNameSize; i++) key_name[i] = 0;
      strcpy(key_name, name);
    }

    void MyKeyClass::operator=(const char *name)
    {
      for(int i = 0; i < MyKeyNameSize; i++) key_name[i] = 0;
      strcpy(key_name, name);
    }

    int MyKeyClass::operator==(const DatabaseKeyB& key) const
    {
      const MyKeyClass *kptr = (const MyKeyClass *)(&key);
      return (strcmp(key_name, (char *)kptr->db_key) == 0);
    }

    int MyKeyClass::operator>(const DatabaseKeyB& key) const
    {
      const MyKeyClass *kptr = (const MyKeyClass *)(&key);
      return (strcmp(key_name, (char *)kptr->db_key) > 0);
    }

    int MyKeyClass::CompareKey(const DatabaseKeyB& key) const
    // NOTE: This comparison function is only used if the
    // __USE_SINGLE_COMPARE__ preprocessor directive is
    // defined when the program is compiled.
    {
      const MyKeyClass *kptr = (const MyKeyClass *)(&key);
      return strcmp(key_name, (char *)kptr->db_key);
    }

    void PrintNode(BtreeNode &n)
    // Print a Btree node.
    {
      MyKeyClass kbuf;
      BtreeKeyLocation_t key_location = (BtreeKeyLocation_t)0;
      for(BtreeKeyCount_t i = (BtreeKeyCount_t)0; i < n.key_count; i++) {
        n.LoadKey(kbuf, key_location++);
        cout << (char *)kbuf.key_name << ' ' << (long)kbuf.right_child << ' ';
        // NOTE: The right child FAU is cast to a long for compilers
        // with native 64-bit int ostream overloads
      }
      cout << "\n";
      cout << "Key count = " << n.key_count << "\n";
      cout << "Left child = " << (long)n.left_child << "\n";
      // NOTE: The left child FAU is cast to a long for compilers
      // with native 64-bit int ostream overloads
    }

    void PausePrg()
    // Pause the program.
    {
      cout << "\n";
      cout << "Press enter to continue..." << "\n";
      cin.get();
    }

    gxDatabaseError WriteNode(gxDatabase *f, const BtreeNode &n, FAU_t na)
    // Function used to write a Btree node to an open database file.
    // Returns zero if successful or a non-zero value to indicate a
    // failure.
    {
      gxDatabaseError rv;
      rv = f->Write(&n.key_count, sizeof(n.key_count), na);
      if(rv != gxDBASE_NO_ERROR) return rv;
      rv = f->Write(&n.left_child, sizeof(n.left_child));
      if(rv != gxDBASE_NO_ERROR) return rv;
      rv = f->Write(n.key_entries, (n.key_size * n.node_order));
      if(rv != gxDBASE_NO_ERROR) return rv;
      return rv;
    }

    gxDatabaseError ReadNode(gxDatabase *f, BtreeNode &n, FAU_t na)
    // Function used to read a Btree node from an open database file.
    // Returns zero if successful or a non-zero value to indicate a
    // failure.
    {
      gxDatabaseError rv;
      rv = f->Read(&n.key_count, sizeof(n.key_count), na);
      if(rv != gxDBASE_NO_ERROR) return rv;
      rv = f->Read(&n.left_child, sizeof(n.left_child));
      if(rv != gxDBASE_NO_ERROR) return rv;
      rv = f->Read(n.key_entries, (n.key_size * n.node_order));
      if(rv != gxDBASE_NO_ERROR) return rv;
      return rv;
    }

    int main()
    {
      MyKeyClass key, compare_key;

      cout << "--------- Key and B-tree Node Statistics ---------" << "\n";
      cout << "Key name size     = " << key.KeySize() << "\n";
      cout << "Database key size = " << key.SizeOfDatabaseKey() << "\n";
      cout << "Key entry size    = "
           << (key.SizeOfDatabaseKey() * (MyKeyClassOrder-1)) << "\n";
      BtreeNode n(key.SizeOfDatabaseKey(), MyKeyClassOrder);
      cout << "B-tree order      = " << n.node_order << "\n";
      cout << "B-tree node size  = " << n.SizeOfBtreeNode() << "\n";

      PausePrg();

      BtreeKeyLocation_t key_location = (BtreeKeyLocation_t)0;
      int i, rv;
      const char *strings[7] = { // Array matching the Btree order
        "DOG", "CAT", "PIG", "COW", "FISH", "ZEBRA", "HORSE"
      };

      cout << "Inserting " << n.node_order << " entries into the Btree node"
           << "\n";
      for(i = 0; i < n.node_order; i++) {
        key = strings[i];

        rv = n.FindKeyLocation(key, compare_key, key_location);

        // Do not insert duplicate keys
        if(rv != 0) {
          key_location++;
          n.InsertDatabaseKey(key, key_location);
        }
      }

      cout << "Reading back the database keys" << "\n";
      PrintNode(n);

      PausePrg();

      cout << "Testing database read/write operations" << "\n";
      gxDatabase *f = new gxDatabase();
      f->Create("testfile.gxd");
      FAU_t node_address = f->Alloc(n.SizeOfBtreeNode());
      WriteNode(f, n, node_address);
      BtreeNode nbuf(key.SizeOfDatabaseKey(), MyKeyClassOrder);
      ReadNode(f, nbuf, node_address);
      PrintNode(nbuf);
      delete f;

      PausePrg();

      cout << "Testing the delete function" << "\n";
      n.DeleteDatabaseKey((BtreeKeyLocation_t)0);
      PrintNode(n);

      PausePrg();

      cout << "Testing the split fucntion" << "\n";
      BtreeNode r(key.SizeOfDatabaseKey(), MyKeyClassOrder);
      n.SplitNode(r, n.node_order/2);
      PrintNode(n);
      cout << "\n";
      PrintNode(r);

      cout << "\n";
      cout << "Exiting..." << "\n";
      return 0;
    }
    // ----------------------------------------------------------- //
    // ------------------------------- //
    // --------- End of File --------- //
    // ------------------------------- //