// -*- coding: utf-8 -*- // Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // // Spot is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // Spot is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "tgbamask.hh" #include namespace spot { namespace { struct transition { const state* dest; bdd cond; bdd acc; }; typedef std::vector transitions; struct succ_iter_filtered: public tgba_succ_iterator { ~succ_iter_filtered() { for (auto& t: trans_) t.dest->destroy(); } bool first() { it_ = trans_.begin(); return it_ != trans_.end(); } bool next() { ++it_; return it_ != trans_.end(); } bool done() const { return it_ == trans_.end(); } state* current_state() const { return it_->dest->clone(); } bdd current_condition() const { return it_->cond; } bdd current_acceptance_conditions() const { return it_->acc; } transitions trans_; transitions::const_iterator it_; }; class tgba_mask_keep: public tgba_mask { const state_set& mask_; public: tgba_mask_keep(const tgba* masked, const state_set& mask, const state* init) : tgba_mask(masked, init), mask_(mask) { } bool wanted(const state* s) const { state_set::const_iterator i = mask_.find(s); return i != mask_.end(); } }; class tgba_mask_ignore: public tgba_mask { const state_set& mask_; public: tgba_mask_ignore(const tgba* masked, const state_set& mask, const state* init) : tgba_mask(masked, init), mask_(mask) { } bool wanted(const state* s) const { state_set::const_iterator i = mask_.find(s); return i == mask_.end(); } }; } tgba_mask::tgba_mask(const tgba* masked, const state* init) : tgba_proxy(masked), init_(init) { if (!init) init_ = masked->get_init_state(); } tgba_mask::~tgba_mask() { init_->destroy(); } state* tgba_mask::get_init_state() const { return init_->clone(); } tgba_succ_iterator* tgba_mask::succ_iter(const state* state) const { succ_iter_filtered* res; if (iter_cache_) { res = down_cast(iter_cache_); res->trans_.clear(); iter_cache_ = nullptr; } else { res = new succ_iter_filtered; } for (auto it: original_->succ(state)) { const spot::state* s = it->current_state(); if (!wanted(s)) { s->destroy(); continue; } transition t = { s, it->current_condition(), it->current_acceptance_conditions() }; res->trans_.push_back(t); } return res; } const tgba* build_tgba_mask_keep(const tgba* to_mask, const state_set& to_keep, const state* init) { return new tgba_mask_keep(to_mask, to_keep, init); } const tgba* build_tgba_mask_ignore(const tgba* to_mask, const state_set& to_ignore, const state* init) { return new tgba_mask_ignore(to_mask, to_ignore, init); } }