/*
  CoreLinux++ 
  Copyright (C) 2000 CoreLinux Consortium
  
   The CoreLinux++ Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The CoreLinux++ Library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  
*/   

/** \example examp16.cpp
   This example is to show use of the basic Memory and MemoryStorage 
   implementations.
   
   1. Create a private storage region
   2. Write data to region
   3. Read data from region
   4. Destroy the region
   5. Handle all the exception potentials
   
*/                   


#include <Common.hpp>
#include <Memory.hpp>

using namespace corelinux;
using namespace std;

#include <iostream>
#include <exception>

//
// In module function prototypes
//

int   main( void );

//
// General Functions 
//

void  handleAssertion( AssertionCref );
void  handleException( ExceptionCref );

//
// Thread entry point declarations
//

//
// Global data
//

struct MyStruct
{
   int   va1;
   int   va2;
   int   va3;
};

//
// Main entry point
//


int main( void )
{

   cout << endl;

   //
   // Practice graceful exception management
   //

   MemoryStoragePtr  aMemoryBlock( NULLPTR );

   try
   {
      Int         regionSize(300);
      Byte        value(1);

      //
      // Test for write and read of simple types using
      // subscript addressing
      //

      aMemoryBlock =  Memory::createStorage( regionSize );
      --regionSize;

      for( Int x = 0; x < regionSize; ++x )
      {
         // Alternate the data changes 

         if( x % 2 )
         {
            (*aMemoryBlock)[x] = value;
         }
         else
         {
            ;  // do nothing
         }
      }

      for( Int x = 0; x < regionSize; ++x )
      {
         Byte   v = (*aMemoryBlock)[x];
         cout << ( v ? "*" : "." );
      }

      cout << endl;

      //
      // Test for more complex types
      //

      MyStruct    aCompoundTest={1,2,3};

      regionSize /= sizeof( MyStruct );

      for( Int x = 0; x < regionSize; ++x )
      {
         // Because the operator[] assumes an absolute address
         // in the MemoryStorage region

         (*aMemoryBlock)[sizeof(MyStruct)*x] = aCompoundTest;
      }

      // Read 'em out

      for( Int x = 0; x < regionSize; ++x )
      {
         MyStruct    retTest = (*aMemoryBlock)[sizeof(MyStruct)*x];
         cout << retTest.va1 << "," << retTest.va2 << "," << retTest.va3 << " ";
      }

      cout << endl;

      Memory::destroyStorage( aMemoryBlock );

      aMemoryBlock = NULLPTR;
   }

   catch( BoundsException aBoundsException )
   {
      cerr  << "Bounds exception occured referencing MemoryStorage" << endl;
      handleException(aBoundsException);
   }
   catch( StorageException aStorageException )
   {
      cerr  << "General storage exception received" << endl;
      handleException(aStorageException);
   }
   catch( AssertionRef aAssert )
   {
      handleAssertion(aAssert);
   }
   catch( ExceptionRef aException )
   {
      handleException(aException);
   }
   catch( std::exception & e )
   {
      cerr  << e.what() << endl;
   }
   catch( ... )
   {
      cerr  << "Unknown exception." << endl;
   }

   // Be sure to cleanup

   if( aMemoryBlock != NULLPTR )
   {
      Memory::destroyStorage( aMemoryBlock );
      aMemoryBlock = NULLPTR;
   }
   else
   {
      ;  // do nothing
   }

   return 0;               
}

//
// Error handlers
//

void  handleAssertion( AssertionCref aAssert )
{
   cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << 
      "Assertion: ";

   if( aAssert.getType() == Assertion::NEVERGETHERE )
   {
      cerr << "NEVER_GET_HERE";
   }
   else
   {
      if( aAssert.getType() == Assertion::REQUIRE )
      {
         cerr  << "REQUIRE";
      }
      else if( aAssert.getType() == Assertion::ENSURE )
      {
         cerr  << "ENSURE";
      }
      else if( aAssert.getType() == Assertion::CHECK )
      {
         cerr  << "CHECK";
      }
      else 
      {
         cerr  << "ASSERT";
      }
      cerr << "( " << aAssert.getWhy() << " )";
   }

   cerr << endl;
}

void  handleException( ExceptionCref aExcp )
{
   cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" <<
      "Exception: " << aExcp.getWhy() << endl;
}

/*
   Common rcs information do not modify
   $Author: prudhomm $
   $Revision: 1.4 $
   $Date: 2000/08/31 22:49:02 $
   $Locker:  $
*/


