зеркало из https://github.com/mozilla/pjs.git
270 строки
6.3 KiB
C++
270 строки
6.3 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.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* A Hashtable for TxObjects
|
|
*/
|
|
|
|
|
|
#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(PRInt32 size) {
|
|
|
|
//-- by default the Map will not delete it's
|
|
//-- object references
|
|
mOwnership = eOwnsNone;
|
|
|
|
//-- create a new array of bucket pointers
|
|
elements = new BucketItem*[size];
|
|
|
|
//-- initialize all elements to 0;
|
|
for ( PRInt32 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. Deletes objects according
|
|
* to the mOwnership attribute
|
|
**/
|
|
void Map::clear() {
|
|
|
|
for (int i = 0; i < numberOfBuckets; i++) {
|
|
|
|
BucketItem* bktItem = elements[i];
|
|
while (bktItem) {
|
|
BucketItem* tItem = bktItem;
|
|
bktItem = bktItem->next;
|
|
if (mOwnership & eOwnsItems)
|
|
delete tItem->item;
|
|
if (mOwnership & eOwnsKeys)
|
|
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
|
|
PRUint32 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
|
|
PRUint32 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 ownership flag.
|
|
**/
|
|
void Map::setOwnership(txMapOwnership aOwnership) {
|
|
mOwnership = aOwnership;
|
|
} //-- setOwnership
|
|
|
|
/**
|
|
* 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
|
|
PRUint32 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
|