    // ------------------------------- //
    // -------- Start of File -------- //
    // ------------------------------- //
    // ----------------------------------------------------------- //
    // C++ Source Code File Name: edscfg.cpp
    // C++ Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC
    // Produced By: glNET Software
    // File Creation Date: 10/15/1999
    // Date Last Modified: 05/25/2001
    // Copyright (c) 2001 glNET Software
    // ----------------------------------------------------------- //
    // ------------- 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

    Code used to test the eds configuration manager.
    */
    // ----------------------------------------------------------- //
    #include <iostream.h>
    #include "edscfg.h"

    #ifdef __MSVC_DEBUG__
    #include "leaktest.h"
    #endif

    // Data structure use to store program configuration values
    struct ProgramConfig
    {
      ProgramConfig() { // Set the default values
        s_val = "YES";
        i_val = 32768;
        l_val = 2147483647;
        d_val = 1.12345;
      }
      ProgramConfig(const ProgramConfig &ob) {
        s_val = ob.s_val; i_val = ob.i_val; l_val = ob.l_val; d_val = ob.d_val;
      }

      UString s_val;
      int i_val;
      long l_val;
      double d_val;
    };

    void PausePrg()
    {
      cout << endl;
      cout << "Press <Enter> to continue..." << endl;
      cin.get();
    }

    void DumpConfig(edsConfig *edscfg)
    {
      edsConfigListNode *ptr = (edsConfigListNode *)edscfg->GetHead();
      while(ptr) {
        cout << ptr->node_data.str << ' ' << endl;
        ptr = ptr->GetNext();
      }
    }

    void DisplayConfig(edsConfig *CfgData, ProgramConfig *cfg)
    // Display the program configuration and load config values
    {
      char *v1 = CfgData->GetStrValue("String");
      if(!v1) {
        cout << "String section missing from config file" << endl;
      }
      else {
        cout << "String section of config file = " << v1 << endl;
        cfg->s_val = v1;
      }

      int v2 = CfgData->GetIntValue("Int");
      if(!v2) {
        cout << "Int section missing from config file" << endl;
      }
      else {
        cout << "Integer section of config file = " << v2 << endl;
        cfg->i_val = v2;
      }

      double v3 = CfgData->GetFloatValue("Float");
      if(!v3) {
        cout << "Float section missing from config file" << endl;
      }
      else {
        cout << "Floating Point number section of config file = "
    	 << v3 << endl;
        cfg->d_val = v3;
      }

      long v4 = CfgData->GetLongValue("Long");
      if(!v4) {
        cout << "Long int section missing from config file" << endl;
      }
      else {
        cout << "Long int section of config file = " << v4 << endl;
        cfg->l_val = v4;
      }

      cout << endl;
    }

    void MultipleRead(edsConfig *CfgData)
    {
      char *ServerName = CfgData->GetStrValue("ServerName");
      if(!ServerName) {
        cout << "ServerName value is not set in the config file" << endl;
        return;
      }
      else
        cout << "Server name = " << ServerName << endl;

      char *FullPathName = CfgData->GetStrValue("FullPathName0");
      if(!FullPathName) {
        cout << "No path names are set in the config file" << endl;
        return;
      }

      char cfgValue[255];
      char *cfgName = "FullPathName";
      long file_num = -1;

      while(1) {
        file_num++;
        sprintf(cfgValue, "FullPathName%d", file_num);
        char *buf = CfgData->GetStrValue(cfgValue);
        if(!buf) break;

        UString sbuf(buf);
        unsigned offset = 0;
        unsigned index = 0;
        while(1) {
        offset = sbuf.Find("/", offset);
        if(offset != -1) index = offset;
        if(offset == -1) break;
        offset++;
        }
        if(index > 0) sbuf.DeleteAt(0, ++index);

        if(sbuf.length() == 0) {
          cout << "Invalid file name for " << cfgValue << endl;
          return;
        }

        cout << "Reading: " << buf << endl;
        cout << "Copying to: " << sbuf << endl;

        buf = 0;
        for(int i = 0; i < 255; i++) cfgValue[i] = 0;
      }
      cout << endl;
    }

    void NewParmID(edsConfig *CfgData)
    {
      CfgData->UnLoad();
      CfgData->SetParmID("://");
      UString parmName("http");
      CfgData->ReadComments();
      CfgData->ReLoad();

      edsConfigListNode *ptr = (edsConfigListNode *)CfgData->GetHead();
      while(ptr) { // Scan until end of list
        unsigned offset = 0;
        offset = ptr->node_data.str.Find(parmName);
        if(offset != -1) {
          UString ServerName(ptr->GetNext()->node_data.str);
          UString FullPathName(ptr->GetNext()->node_data.str);
          unsigned offset = ServerName.Find("/");
          if(offset != -1) {
    	ServerName.DeleteAt(offset, (ServerName.length() - offset));
    	FullPathName.DeleteAt(0, offset);
    	cout << "Server: " << ServerName << " Path: " << FullPathName << endl;
          }
        }
        ptr = ptr->GetNext();
      }
    }

    void WriteNewConfig(edsConfig *CfgData)
    {
      CfgData->WriteConfigLine("Long", "2147483647");
      CfgData->WriteConfigLine("Int", "32768");
      CfgData->WriteConfigLine("Float", "1.12345");
      CfgData->WriteConfigLine("String", "YES");
      CfgData->WriteConfigLine("ServerName", "www.myserver.net");
      CfgData->WriteConfigLine("FullPathName0", "/home1/webpages/index.html");
      CfgData->WriteConfigLine("FullPathName1",
    			   "/home1/webpages/images/brick.jpg");
      CfgData->WriteConfigLine("FullPathName2", "/home3/mail_list/list_add.htm");
      CfgData->WriteConfigLine("FullPathName3",
    			   "/home3/mail_list/list_remove.htm");
      CfgData->WriteConfigLine("FullPathName4",
    			   "/home1/webpages/images/button_bar.jpg");
      CfgData->WriteConfigLine("FullPathName5",
    			   "/pub/docs/release_notes/mod1.txt");
      CfgData->WriteConfigLine("FullPathName6",
    			   "/pub/docs/release_notes/mod2.txt");
      CfgData->WriteConfigLine("FullPathName7",
    			   "/pub/docs/release_notes/mod3.txt");
      CfgData->WriteLine("http://www.myserver.net/home1/webpages/index.html");
      CfgData->WriteLine("http://www.myserver.net/home1/webpages/images/ \
    brick.jpg");
      CfgData->WriteLine("http://www.myserver.net/home3/mail_list/list_add.htm");
      CfgData->WriteLine("http://www.myserver.net/home3/mail_list/ \
    list_remove.htm");
      CfgData->WriteLine("http://www.myserver.net/home1/webpages/images/ \
    button_bar.jpg");
      CfgData->WriteLine("http://www.myserver.net/pub/docs/release_notes/ \
    mod1.txt");
      CfgData->WriteLine("http://www.myserver.net/pub/docs/release_notes/ \
    mod2.txt");
      CfgData->WriteLine("http://www.myserver.net/pub/docs/release_notes/ \
    mod3.txt");
    }

    int main()
    {
    #ifdef __MSVC_DEBUG__
      InitLeakTest();
    #endif

      edsConfig *CfgData = new edsConfig("testfile.eds");
      ProgramConfig *cfg = new ProgramConfig;

      if(!CfgData->Exists()) {
        cout << endl;
        cout << "The eds config file does not exist!" << endl;
        cout << "Writing new config file..." << endl;
        WriteNewConfig(CfgData);
        cout << endl;
      }

      cout << "Processing the config file" << endl;

      if(CfgData->OpenDatabase()->GetDatabaseError() != gxDBASE_NO_ERROR) {
        cout << CfgData->OpenDatabase()->DatabaseExceptionMessage() << endl;
        delete CfgData;
        delete cfg;
        return 1;
      }

      CfgData->Load();
      cout << endl;

      DisplayConfig(CfgData, cfg);
      ProgramConfig org_config(*cfg); // Record the original values

      cout << "Testing reload function" << endl;
      PausePrg();
      CfgData->ReLoad();
      DisplayConfig(CfgData, cfg);

      cout << "Writing new values to the file" << endl;
      PausePrg();
      if(!CfgData->ChangeConfigValue("String", "NO"))
        cout << "Could not change string value" << endl;
      if(!CfgData->ChangeConfigValue("Float", 1.98712))
        cout << "Could not change floating point value" << endl;
      if(!CfgData->ChangeConfigValue("Int", 12345))
        cout << "Could not change integer value" << endl;
      if(!CfgData->ChangeConfigValue("Long", 23889))
        cout << "Could not change long integer value" << endl;
      CfgData->ReLoad();
      DisplayConfig(CfgData, cfg);

      cout << "Restoring orignal values" << endl;
      PausePrg();
      CfgData->ChangeConfigValue("String", org_config.s_val);
      CfgData->ChangeConfigValue("Int", org_config.i_val);
      CfgData->ChangeConfigValue("Float", org_config.d_val);
      CfgData->ChangeConfigValue("Long", org_config.l_val);
      CfgData->ReLoad();
      DisplayConfig(CfgData, cfg);

      cout << "Performing a multiple read and parsing operation" << endl;
      PausePrg();
      MultipleRead(CfgData);

      cout << "Reloading the file with a new parameter ID string" << endl;
      PausePrg();
      NewParmID(CfgData);

      CfgData->UnLoad();

      delete CfgData;
      delete cfg;
      return 0;
    }
    // ----------------------------------------------------------- //
    // ------------------------------- //
    // --------- End of File --------- //
    // ------------------------------- //