gecko-dev/extensions/transformiix/source/base/Map.cpp

289 строки
7.0 KiB
C++

/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is XSL:P XSLT processor.
*
* The Initial Developer of the Original Code is Keith Visco.
*
* Portions created by Keith Visco (C) 1999-2000 Keith Visco.
* All Rights Reserved.
*
* Contributor(s):
* Keith Visco, kvisco@ziplink.net
* -- original author.
*
* $Id: Map.cpp,v 1.2 2000/06/11 12:21:13 Peter.VanderBeken%pandora.be Exp $
*/
/*
* A Hashtable for TxObjects
* @version $Revision: 1.2 $ $Date: 2000/06/11 12:21:13 $
*/
#include "Map.h"
//-------------/
//- Constants -/
//-------------/
const int Map::DEFAULT_SIZE = 13;
//----------------/
//- Constructors -/
//----------------/
/**
* Creates a new Map with the default Size
**/
Map::Map() {
initialize(DEFAULT_SIZE);
} //-- Map
/**
* Creates a new Map with the specified number of buckets
**/
Map::Map(int size) {
initialize(size);
} //-- Map
/**
* Helper method for Constructors
**/
void Map::initialize(Int32 size) {
//-- by default the Map will not delete it's
//-- object references
doObjectDeletion = MB_FALSE;
//-- create a new array of bucket pointers
elements = new BucketItem*[size];
//-- initialize all elements to 0;
for ( Int32 i = 0; i < size; i++ ) elements[i] = 0;
numberOfBuckets = size;
numberOfElements = 0;
} //-- initialize
/**
* Destructor for Map
**/
Map::~Map() {
clear();
delete [] elements;
} //-- ~Map
/**
* Removes all elements from the Map. If the object deletion flag
* has been set to true (by a call to setObjectDeletion) objects
* will also be deleted as they are removed from the map
**/
void Map::clear() {
clear(doObjectDeletion);
} //-- clear
/**
* Removes all elements from the Map
* @param deleteObjects a flag indicating whether or not to delete the
* objects and keys currently in the map
**/
void Map::clear(MBool deleteObjects) {
for (int i = 0; i < numberOfBuckets; i++) {
BucketItem* bktItem = elements[i];
while (bktItem) {
BucketItem* tItem = bktItem;
bktItem = bktItem->next;
//-- repoint item to 0 to prevent deletion
if ( ! deleteObjects ) {
tItem->item = 0;
tItem->key = 0;
}
else {
delete tItem->item;
delete tItem->key;
}
//--delete tItem;
delete tItem;
}
}
numberOfElements = 0;
} //-- clear
/**
* Returns the object reference in this Map associated with the given key
* @return the object reference in this Map associated with the given key
**/
TxObject* Map::get(TxObject* key) {
BucketItem* item = getBucketItem(key);
if ( item ) return item->item;
return 0;
} //-- get
/**
* Returns true if there are no objects in this map.
* @return true if there are no objects in this map.
**/
MBool Map::isEmpty() {
return (numberOfElements == 0) ? MB_TRUE : MB_FALSE;
} //-- isEmpty
/**
* Returns a List of all the keys in this Map.
* Please delete this List when you are done with it
**/
List* Map::keys() {
List* list = new List();
for (int i = 0; i < numberOfBuckets; i++) {
BucketItem* item = elements[i];
while (item) {
list->add(item->key);
item = item->next;
}
}
return list;
} //-- keys
/**
* Adds the TxObject reference to the map and associates it with the given
* key
**/
void Map::put(TxObject* key, TxObject* obj) {
if ((!key) || (!obj)) return;
//-- compute hash for key
Int32 hashCode = key->hashCode();
//-- calculate index
int idx = hashCode % numberOfBuckets;
//-- fetch first item in bucket
BucketItem* bktItem = elements[idx];
//-- if bktItem is 0 then there are no items is this Bucket,
//-- add to front of list
if ( !bktItem ) {
elements[idx] = createBucketItem(key, obj);
++numberOfElements;
}
//-- find current item, or add to end of list
else {
BucketItem* prevItem = bktItem;
//-- advance to next spot
while ( bktItem ) {
//-- if current key equals desired key, break
if ( bktItem->key->equals(key) ) {
break;
}
prevItem = bktItem;
bktItem = bktItem->next;
}
//-- if we did not find a bucket Item create a new one
if ( !bktItem) {
bktItem = createBucketItem(key, obj);
prevItem->next = bktItem;
bktItem->prev = prevItem;
++numberOfElements;
}
//-- we found bucket item, just set value
else bktItem->item = obj;
}
} //-- put
/**
* Removes the the specified TxObject from the Map
* @param key the TxObject which is used to calculate the hashCode of
* the TxObject to remove from the Map
* @return the TxObject removed from the Map
**/
TxObject* Map::remove(TxObject* key) {
if (!key) return 0;
// compute hash for key
Int32 hashCode = key->hashCode();
int idx = hashCode % numberOfBuckets;
BucketItem* bktItem = elements[idx];
while ( bktItem ) {
if ( bktItem->key->equals(key) ) break;
bktItem = bktItem->next;
}
if ( bktItem ) {
if (bktItem == elements[idx]) elements[idx] = bktItem->next;
else bktItem->prev->next = bktItem->next;
numberOfElements--;
TxObject* txObject = bktItem->item;
bktItem->item = 0;
delete bktItem;
return txObject;
}
return 0;
} //-- remove
/**
* Sets the object deletion flag. If set to true, objects, including
* keys, in the Map will be deleted upon calling the clear() method, or
* upon destruction. By default this is false.
**/
void Map::setObjectDeletion(MBool deleteObjects) {
doObjectDeletion = deleteObjects;
} //-- setObjectDeletion
/**
* Returns the number of key-object pairs in the Map
* @return the number of key-object pairs in the Map
**/
int Map::size() {
return numberOfElements;
} //-- size
//-------------------/
//- Private Methods -/
//-------------------/
Map::BucketItem* Map::createBucketItem(TxObject* key, TxObject* obj)
{
BucketItem* bktItem = new BucketItem;
bktItem->next = 0;
bktItem->prev = 0;
bktItem->key = key;
bktItem->item = obj;
return bktItem;
} //-- createBucketItem
Map::BucketItem* Map::getBucketItem(TxObject* key) {
// compute hash for key
Int32 hashCode = key->hashCode();
int idx = hashCode % numberOfBuckets;
BucketItem* bktItem = elements[idx];
while ( bktItem ) {
if ( bktItem->key->equals(key) ) return bktItem;
bktItem = bktItem->next;
}
return bktItem;
} //-- getBucketItem