#ifndef _UINT64_ // -*-c++-*-
#define _UINT64_

//----------------------------------------------------------------------
//  UINT64.h
//
// (c) Copyright 1995  Hewlett-Packard Company.
// The contents of this software are proprietary and confidential to
// the Hewlett- Packard Company, and are limited in distribution to
// those with a direct need to know.  Individuals having access to
// this software are responsible for maintaining the confidentiality
// of the content and for keeping the software secure when not in use.
// Transfer to any party is strictly forbidden other than as expressly
// permitted in writing by Hewlett-Packard Company.  Unauthorized
// transfer to or possession by any unauthorized party may be a
// criminal offense.
//
//                  RESTRICTED RIGHTS LEGEND
//
//      Use,  duplication,  or disclosure by the Government  is
//      subject to restrictions as set forth in subdivision (b)
//      (3)  (ii)  of the Rights in Technical Data and Computer
//      Software clause at 52.227-7013.
//
//                      HEWLETT-PACKARD COMPANY
//                      3000 Hanover St.
//                      Palo Alto, CA  94304
//
//----------------------------------------------------------------------
// $Source: /projects/HMS/nsr/udfCore/sys/UINT64.h,v $
// $Revision: 1.4 $     $Author: hmgr $
// $State: Exp $        $Locker:  $
// $Date: 96/01/15 11:13:00 $

//----------------------------------------------------------------------
// CLASS: UINT64     --CSB
//
//  Simple UINT64 class to emulate 64 bit integers.
//
//  NOTE:  This class should go away if the platform supports
//    native 64 bit integers!  This class is only provided so
//    we have the convenience of interacting with a 64 bit
//    integer for 64 bit fields, such as Node::uniqueID, 
//    FileEntry::infoLen, etc.
//  NOTE:  We define UINT32_OTHER because we are unable to
//    rely on the UINT32 that the nsrTypes.h defines (because
//    that file is after this file in the nsrLib.h).
//----------------------------------------------------------------------
// NOTE:  The following types are only so we can compile
//   independantly of NSR types!
// (Later, this entire class should be replaced).
typedef unsigned long UINT32_OTHER;
typedef unsigned char Bool;

#define NO_UINT64 // Don't do the class.

class UINT64
{
  protected:
    UINT32_OTHER mostSignificant32_;
    UINT32_OTHER leastSignificant32_;
  public:
    UINT64(const UINT32_OTHER leastSignificant32=0, const UINT32_OTHER mostSignificant32=0)
    {
      leastSignificant32_ = leastSignificant32;
      mostSignificant32_  = mostSignificant32;
    }
    ~UINT64(void){}
    UINT64(const UINT64& other64)
    {
      operator=(other64);
    }
    const UINT64& operator=(const UINT64& other64)
    {
      leastSignificant32_ = other64.leastSignificant32_;
      mostSignificant32_  = other64.mostSignificant32_;
      return *this;
    }
    // NOTE:  We need to convert ourselves to a regular UIN32
    //   because we are sometimes assigned to one.
    operator const UINT32_OTHER(void) const 
    {
      return leastSignificant32_;
    }

    const UINT32_OTHER mostSignificant32(void) const 
    {
      return mostSignificant32_;
    }
    const UINT32_OTHER leastSignificant32(void) const 
    {
      return leastSignificant32_;
    }

    const UINT64& operator+=(const UINT64 other64)
    {
      UINT32_OTHER temp = leastSignificant32_;
      leastSignificant32_ += other64.leastSignificant32_;
      if(leastSignificant32_ < temp)
      { // If we over-flowed our lower order 32, add to the 
        //   upper order 32.
        mostSignificant32_++;
        // !!! NOTE:  We should throw an exception here!
        //   (range violation).
      }
      mostSignificant32_ += other64.mostSignificant32_;
      return *this; 
    }
    const UINT64& operator-=(const UINT64 other64)
    {
      UINT32_OTHER temp = leastSignificant32_;
      leastSignificant32_ -= other64.leastSignificant32_;
      if(leastSignificant32_ > temp)
      { // If we under-flowed our lower order 32, subtract from 
        //   the upper order 32.
        mostSignificant32_--;
        // !!! NOTE:  We should throw an exception here!
        //   (range violation).
      }
      mostSignificant32_ -= other64.mostSignificant32_;
      return *this; 
    }
    const UINT64 operator*(const UINT64 other64) const
    {
      // !!! WARNING!  We need to add REAL 64-bit logic here!
      // For now, for time's sake, just do 32-bit logic.
      // 32 BIT LOGIC ONLY!
      UINT32_OTHER temp = leastSignificant32_;
      temp *= other64.leastSignificant32_;
      return UINT64(temp);
    }
    const UINT64 operator/(const UINT64 other64) const
    {
      // !!! WARNING!  We need to add REAL 64-bit logic here!
      // For now, for time's sake, just do 32-bit logic.
      // 32 BIT LOGIC ONLY!
      UINT32_OTHER temp = leastSignificant32_;
      temp /= other64.leastSignificant32_;
      return UINT64(temp);
    }
    const UINT64 operator+(const UINT64 other64) const
    {
      UINT64 temp(*this);  // Make one like us.
      temp += other64;     // Add the other one.
      return temp;         // Return it.
    }
    const UINT64 operator-(const UINT64 other64) const
    {
      UINT64 temp(*this);  // Make one like us.
      temp -= other64;     // Subtract the other one.
      return temp;         // Return it.
    }
    Bool operator==(const UINT64 other64) const
    {
      Bool result = 0;
      if(mostSignificant32_ == other64.mostSignificant32_)
        if(leastSignificant32_ == other64.leastSignificant32_)
          result = 1;
      return result;
    }
    Bool operator<=(const UINT64 other64) const
    {
      // Set the default to false, unless we determine this to
      //   be true. 
      Bool result = 0;

      if((result = operator<(other64)) == 0)
      { // If we are not less than, are we equal?
        result = operator==(other64);
      }
      // If we are less than, we have been set to 1. 
      return result;
    }
    Bool operator<(const UINT64 other64) const
    {
      // Set the default to false, unless we determine this to
      //   be true. 
      Bool result = 0;

      if(mostSignificant32_ < other64.mostSignificant32_)
      { // The most significant bits decide who is greater.
        result = 1;
      }
      else if(mostSignificant32_ == other64.mostSignificant32_)
      { // Determine on the least significant, because most
        //   significant is the same for both.
        if(leastSignificant32_ < other64.leastSignificant32_)
        { // We have the most significant the same, the least
          //   is less, though.
          result = 1;
        }
        // Otherwise, 0 stands.
      }
      return result;
    }
    Bool operator>=(const UINT64 other64) const
    {
      return (operator<(other64)) == 1 ? 0:1;
    }
    Bool operator>(const UINT64 other64) const
    {
      return (operator<=(other64)) == 1 ? 0:1;
    }

    // These functions are needed to re-order the parameters in
    //   the source code.
    friend const UINT64 operator+(UINT32_OTHER other32, UINT64 other64)
    { return other64.operator+(other32); }
    friend const UINT64 operator-(UINT32_OTHER other32, UINT64 other64)
    { return other64.operator-(other32); }
};


#endif
