glean/rts/substitution.cpp (112 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #include "glean/rts/substitution.h" namespace facebook { namespace glean { namespace rts { Substitution::Substitution(Id first, size_t size) : base(first) , items(size, Id::invalid()) {} Substitution::Substitution(Id first, std::vector<Id> ids) : base(first) , items(std::move(ids)) {} Id Substitution::firstFreeId() const { const auto i = std::max_element(items.begin(), items.end()); return i != items.end() ? std::max(*i+1, finish()) : finish(); } std::vector<Id> Substitution::substIntervals(const std::vector<Id>& intervals) const { CHECK_EQ(intervals.size() % 2, 0); boost::icl::interval_set<Id> is; auto i = intervals.begin(); const auto e = intervals.end(); while (i != e) { const auto start = i[0]; const auto finish = i[1]; CHECK(start <= finish); if (finish < base) { is.add({start,finish}); } else { for (Id id = start; id <= finish; ++id) { is.add(subst(id)); } } i += 2; } std::vector<Id> results; results.reserve(is.iterative_size()*2); for (auto p : is) { results.push_back(p.lower()); results.push_back(p.upper()); } return results; } boost::icl::interval_set<Id> Substitution::substIntervals(const boost::icl::interval_set<Id>& intervals) const { boost::icl::interval_set<Id> result; for (auto ival : intervals) { if (ival.upper() < base) { result.add(ival); } else { for (Id id = ival.lower(); id <= ival.upper(); ++id) { result.add(subst(id)); } } } return result; } Substitution Substitution::compose( const Substitution& first, const Substitution& second) { std::vector<Id> ids; ids.reserve(first.items.size()); for (auto id : first.items) { ids.push_back(id < second.finish() ? second.subst(id) : id); } return Substitution(first.base, std::move(ids)); } thrift::Subst Substitution::serialize() const { std::vector<thrift::Id> ids; ids.reserve(items.size()); std::transform( items.begin(), items.end(), std::back_inserter(ids), [](auto x) { return x.toThrift(); } ); thrift::Subst s; s.firstId() = base.toThrift(); s.ids() = std::move(ids); return s; } Substitution Substitution::deserialize(const thrift::Subst& subst) { Substitution s(Id::fromThrift(subst.get_firstId()), subst.get_ids().size()); std::transform( subst.get_ids().begin(), subst.get_ids().end(), s.items.begin(), Id::fromThrift ); return s; } bool Substitution::sanityCheck(bool incomplete) const { if (base == Id::invalid()) { if (!items.empty()) { LOG(ERROR) << "substitution with base 0 and size " << items.size(); return false; } } else { if (base < Id::lowest()) { LOG(ERROR) << "substitution with base " << base.toThrift(); return false; } for (auto id : items) { if (id < Id::lowest() && !(incomplete && !id)) { LOG(ERROR) << "substitution with invalid id " << id.toThrift(); return false; } } } return true; } } } }