//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
// Created: MBN 06/06/89 -- Initial implementation
// Updated: LGO 09/19/89 -- Split into one file per method
// Updated: MBN 10/12/89 -- Changed "current_position" to "curpos"; converted
//                          state from bit set to #define macros for get/set
// Updated: MBN 01/10/89 -- Fixed iteration problem

#include <cool/Generic.h>
#include <cool/Base_Hash.h>

// prev -- Decrement current position. If INVALID, set to last
// Input:  this*
// Output: TRUE/FALSE

Boolean Hash_Table::prev () {
  long prime = this->get_bucket_count ();	// Prime number of buckets
  if (this->curpos == INVALID) {		// If INVALID current position
    if (this->entry_count == 0)			// If no entries in table
      return FALSE;				// Return failure
    for (long i = prime-1; i >= 0; i--)		// For each bucket, search
      if (this->get_count_in_bucket (i) != 0)	// If the bucket has an item
	break;
    this->curpos = SET_BUCKET_NUMBER (i);	// Set bucket number
    this->curpos |= SET_BUCKET_INDEX ((this->get_count_in_bucket (i)-1));
    return TRUE;				// Return success
  }
  else if (TRAVERSED(this->curpos))		// If already traversed set
    return FALSE;				// Inidicate failure
  else {
    long hash = BUCKET_NUMBER(this->curpos);	// Get bucket number
    long index = BUCKET_INDEX(this->curpos);	// Get index in bucket
    if (index > 0) {				// If more items in bucket
      this->curpos = SET_BUCKET_NUMBER (hash);	// Update bucket hash bits
      this->curpos |= SET_BUCKET_INDEX ((index-1)); // Update bucket index bits
      return TRUE;				// And return success
    }
    for (long i = hash-1; i >= 0; i--)		// For remaining buckets
      if (this->items_in_buckets[i] != 0)	// If the bucket has an item
	break;
    if (i < 0) {				// If no more items
      this->curpos = INVALID;			// Invalidate pointer
      return FALSE;				// Return failure
    }
    this->curpos = SET_BUCKET_NUMBER(i);	// Set bucket number
    this->curpos |= SET_BUCKET_INDEX((this->get_count_in_bucket (i)-1));
    return TRUE;				// Return success
  }
}
