// 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__