/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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. */ #pragma once #include #include #include namespace apache { namespace thrift { template struct BaseDistinctTablePolicy { template using Index = std::unordered_set; using Hash = std::hash; using Equal = std::equal_to; using Store = std::vector; }; /** * Accumulates only distinct values in an externally owned store. */ template class Policy = BaseDistinctTablePolicy> class DistinctTable { public: typedef typename Policy::Store Store; typedef typename Policy::Hash Hash; typedef typename Policy::Equal Equal; explicit DistinctTable( Store* store, Equal equal = Equal(), Hash hash = Hash()) : store_(store), indexes_(0, HashIndirect(hash, store), EqualIndirect(equal, store)) { assert(store->empty()); } /** * Construct a T given the arguments, return the index at which such a value * can now be found, either newly or previously constructed. */ template size_t add(Args&&... args) { auto index = store_->size(); store_->push_back(std::forward(args)...); auto insertion = indexes_.insert(index); if (insertion.second) { return index; } else { store_->pop_back(); return *insertion.first; } } private: class HashIndirect : public Hash { public: HashIndirect(Hash _hash, Store* store) : Hash(std::move(_hash)), store_(store) {} size_t operator()(size_t i) const { return Hash::operator()((*store_)[i]); } private: Store* store_; }; class EqualIndirect : public Equal { public: EqualIndirect(Equal equal, Store* store) : Equal(std::move(equal)), store_(store) {} bool operator()(size_t a, size_t b) const { return a == b || Equal::operator()((*store_)[a], (*store_)[b]); } private: Store* store_; }; typedef typename Policy::template Index Index; Store* store_; Index indexes_; }; } // namespace thrift } // namespace apache