blob: 26be50481c2f943298451f692028db3ac16249c7 [file] [log] [blame]
// collection.h
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright 2005-2010 Google, Inc.
// Author: riley@google.com (Michael Riley)
//
// \file
// Class to store a collection of sets with elements of type T.
#ifndef FST_EXTENSIONS_PDT_COLLECTION_H__
#define FST_EXTENSIONS_PDT_COLLECTION_H__
#include <algorithm>
#include <vector>
using std::vector;
#include <fst/bi-table.h>
namespace fst {
// Stores a collection of non-empty sets with elements of type T. A
// default constructor, equality ==, a total order <, and an STL-style
// hash class must be defined on the elements. Provides signed
// integer ID (of type I) of each unique set. The IDs are allocated
// starting from 0 in order.
template <class I, class T>
class Collection {
public:
struct Node { // Trie node
I node_id; // Root is kNoNodeId;
T element;
Node() : node_id(kNoNodeId), element(T()) {}
Node(I i, const T &t) : node_id(i), element(t) {}
bool operator==(const Node& n) const {
return n.node_id == node_id && n.element == element;
}
};
struct NodeHash {
size_t operator()(const Node &n) const {
return n.node_id + hash_(n.element) * kPrime;
}
};
typedef CompactHashBiTable<I, Node, NodeHash> NodeTable;
class SetIterator {
public:
SetIterator(I id, Node node, NodeTable *node_table)
:id_(id), node_(node), node_table_(node_table) {}
bool Done() const { return id_ == kNoNodeId; }
const T &Element() const { return node_.element; }
void Next() {
id_ = node_.node_id;
if (id_ != kNoNodeId)
node_ = node_table_->FindEntry(id_);
}
private:
I id_; // Iterator set node id
Node node_; // Iterator set node
NodeTable *node_table_;
};
Collection() {}
// Lookups integer ID from set. If it doesn't exist, then adds it.
// Set elements should be in strict order (and therefore unique).
I FindId(const vector<T> &set) {
I node_id = kNoNodeId;
for (ssize_t i = set.size() - 1; i >= 0; --i) {
Node node(node_id, set[i]);
node_id = node_table_.FindId(node);
}
return node_id;
}
// Finds set given integer ID. Returns true if ID corresponds
// to set. Use iterators below to traverse result.
SetIterator FindSet(I id) {
if (id < 0 && id >= node_table_.Size()) {
return SetIterator(kNoNodeId, Node(kNoNodeId, T()), &node_table_);
} else {
return SetIterator(id, node_table_.FindEntry(id), &node_table_);
}
}
private:
static const I kNoNodeId;
static const size_t kPrime;
static std::tr1::hash<T> hash_;
NodeTable node_table_;
DISALLOW_COPY_AND_ASSIGN(Collection);
};
template<class I, class T> const I Collection<I, T>::kNoNodeId = -1;
template <class I, class T> const size_t Collection<I, T>::kPrime = 7853;
template <class I, class T> std::tr1::hash<T> Collection<I, T>::hash_;
} // namespace fst
#endif // FST_EXTENSIONS_PDT_COLLECTION_H__