LCOV - code coverage report
Current view: top level - src - hfilter.h (source / functions) Hit Total Coverage
Test: test_coverage.info Lines: 40 40 100.0 %
Date: 2017-06-21 14:32:49 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             : # Copyright (C) 2016 Fulvio Benini
       3             : 
       4             : * This file is part of Scid (Shane's Chess Information Database).
       5             : *
       6             : * Scid is free software: you can redistribute it and/or modify
       7             : * it under the terms of the GNU General Public License as published by
       8             : * the Free Software Foundation.
       9             : *
      10             : * Scid is distributed in the hope that it will be useful,
      11             : * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      13             : * GNU General Public License for more details.
      14             : *
      15             : * You should have received a copy of the GNU General Public License
      16             : * along with Scid. If not, see <http://www.gnu.org/licenses/>.
      17             : */
      18             : 
      19             : #ifndef SCID_HFILTER_H
      20             : #define SCID_HFILTER_H
      21             : 
      22             : #include "filter.h"
      23             : #include <iterator>
      24             : 
      25             : /*
      26             :  * A database can be searched according to different criteria and the list of
      27             :  * matching games is stored into a Filter object.
      28             :  * This class abstracts its internal representation providing an interface
      29             :  * equivalent to a pointer to a std::map<gamenumT, uint8_t> object, where the
      30             :  * keys are the gamenumT of matching games and the mapped_types are the number
      31             :  * of half-moves necessary to reach the matching position.
      32             :  * Searches that use only header informations (player names, dates, ...) match
      33             :  * at the starting position (0 half-moves).
      34             :  *
      35             :  * It is also possible to combine two filters in an efficient and transparent
      36             :  * way. If a secondary "mask" filter is supplied, the functions get(), size()
      37             :  * and the const_iterator consider only the games included in both filters.
      38             :  * Their behavior is equal to:
      39             :  * using Filter = std::map<gamenumT, uint8_t>;
      40             :  * Filter tmp_combined;
      41             :  * std::set_intersection(mask->begin(), mask->end(), main->begin(), main->end(),
      42             :  *     std::inserter(tmp_combined, tmp_combined.end()),
      43             :  *     [](auto& a, auto& b) { return a.first < b.first; });
      44             :  * return HFilter(&tmp_combined).begin/get/size();
      45             : */
      46             : class HFilter {
      47             :         Filter* main_;
      48             :         const Filter* mask_;
      49             : 
      50             : public:
      51             :         /**
      52             :          * class const_iterator - iterator for HFilter objects
      53             :          *
      54             :          * This class and the relative functions begin() and end() allow to use
      55             :          * HFilter objects with STL algorithms and c++11 for-ranged loops.
      56             :          * For example:
      57             :          * for (auto& gnum : *hfilter_obj) {}
      58             :          * is equal to:
      59             :          * for (gamenumT gnum = 0, gnum < scidBaseT::numGames(); gnum++) {
      60             :          *     if (hfilter_obj->get(gnum) == 0) continue;
      61             :          * }
      62             :          */
      63             :         class const_iterator {
      64             :                 gamenumT gnum_;
      65             :                 gamenumT end_;
      66             :                 const HFilter* hfilter_;
      67             :                 bool inFilter_;
      68             : 
      69             :         public:
      70             :                 typedef std::forward_iterator_tag iterator_category;
      71             :                 typedef std::ptrdiff_t difference_type;
      72             :                 typedef gamenumT value_type;
      73             :                 typedef const gamenumT* pointer;
      74             :                 typedef const gamenumT& reference;
      75             : 
      76        1918 :                 const_iterator(gamenumT gnum, gamenumT end, const HFilter* hfilter,
      77             :                                bool inFilter = true)
      78        1918 :                     : gnum_(gnum), end_(end), hfilter_(hfilter), inFilter_(inFilter) {
      79        1918 :                         ASSERT(hfilter != 0);
      80        1918 :                         if (gnum_ != end_) {
      81         895 :                                 bool included = (hfilter_->get(gnum_) != 0);
      82         895 :                                 if (included != inFilter_) operator++();
      83             :                         }
      84        1918 :                 }
      85             : 
      86             :                 reference operator*() const { return gnum_; }
      87             : 
      88       54781 :                 const_iterator& operator++() {
      89      110677 :                         while (++gnum_ != end_) {
      90      109782 :                                 bool included = (hfilter_->get(gnum_) != 0);
      91      109782 :                                 if (included == inFilter_) break;
      92             :                         }
      93       54781 :                         return *this;
      94             :                 }
      95             : 
      96             :                 bool operator!=(const const_iterator& b) const {
      97       55185 :                         return gnum_ != b.gnum_ || hfilter_ != b.hfilter_;
      98             :                 }
      99             :                 bool operator==(const const_iterator& b) const {
     100         438 :                         return ! operator!=(b);
     101             :                 }
     102             :         };
     103             : 
     104             :         const_iterator begin() const {
     105         857 :                 return const_iterator(0, main_->Size(), this);
     106             :         }
     107             :         const_iterator end() const {
     108         953 :                 return const_iterator(main_->Size(), main_->Size(), this);
     109             :         }
     110             :         const_iterator beginInverted() const {
     111          54 :                 return const_iterator(0, main_->Size(), this, false);
     112             :         }
     113             :         const_iterator endInverted() const {
     114          54 :                 return const_iterator(main_->Size(), main_->Size(), this, false);
     115             :         }
     116             :         size_t sizeInverted() const {
     117          18 :                 return main_->Size() - size();
     118             :         }
     119             : 
     120             : public: // Pointer interface
     121             :         bool operator==(const Filter* b) const { return main_ == b; }
     122       19442 :         bool operator!=(const Filter* b) const { return main_ != b; }
     123             :         HFilter* operator->() { return this; }
     124             :         const HFilter* operator->() const { return this; }
     125             :         HFilter& operator*() { return *this; }
     126             :         const HFilter& operator*() const { return *this; }
     127             : 
     128             : public:
     129             :         explicit HFilter(Filter* main = 0, const Filter* mask = 0)
     130         162 :             : main_(main), mask_(mask) {}
     131             : 
     132          19 :         void clear() { return main_->Fill(0); }
     133         206 :         void erase(gamenumT gnum) { return main_->Set(gnum, 0); }
     134             :         void insert_or_assign(gamenumT gnum, uint8_t ply) {
     135         179 :                 return main_->Set(gnum, ply + 1);
     136             :         }
     137             :         size_t size() const;
     138             : 
     139             :         /* Convenience function, behave like:
     140             :          * for (gamenumT gnum = 0; gnum < scidBaseT::numGames(); gnum++)
     141             :          *              std:map::insert_or_assign(gnum, 0);
     142             :          */
     143          18 :         void includeAll() { return main_->Fill(1); }
     144             : 
     145             :         /* Convenience function, behave like:
     146             :          * auto it = std::map::find(gnum);
     147             :          * if (it == std::map::end()) return 0;
     148             :          * return 1 + it->second;
     149             :         */
     150             :         byte get(gamenumT gnum) const;
     151             : 
     152             :         /* Convenience function, behave like:
     153             :          * if (value == 0)
     154             :          *     erase(gnum);
     155             :          * else
     156             :          *     insert_or_assign(gnum, value - 1);
     157             :          */
     158        1531 :         void set(gamenumT gnum, byte value) { return main_->Set(gnum, value); }
     159             : };
     160             : 
     161       16658 : inline size_t HFilter::size() const {
     162       16658 :         if (mask_ == 0) return main_->Count();
     163         353 :         if (main_->isWhole()) return mask_->Count();
     164         536 :         const_iterator::difference_type res = std::distance(begin(), end());
     165         268 :         return static_cast<size_t>(res);
     166             : }
     167             : 
     168     4029929 : inline byte HFilter::get(gamenumT gnum) const {
     169     8059858 :         byte res = main_->Get(gnum);
     170     4029929 :         if (res != 0 && mask_ != 0)
     171        2489 :                 res = mask_->Get(gnum);
     172             : 
     173     4029929 :         return res;
     174             : }
     175             : 
     176             : /**
     177             :  * class HFilterInverted - iterate through games excluded from a filter
     178             :  *
     179             :  * This class allow to iterate through games not included in HFilter objects
     180             :  * using STL algorithms and c++11 for-ranged loops.
     181             :  * For example:
     182             :  * for (auto& gnum : HFilterInverted(hfilter_obj)) {}
     183             :  * is equal to:
     184             :  * for (gamenumT gnum = 0, gnum < scidBaseT::numGames(); gnum++) {
     185             :  *     if (hfilter_obj->get(gnum) != 0) continue;
     186             :  * }
     187             :  */
     188             : class HFilterInverted {
     189             :         const HFilter& hfilter_;
     190             : 
     191             : public:
     192          18 :         explicit HFilterInverted(const HFilter& hfilter) : hfilter_(hfilter) {
     193          36 :                 ASSERT(hfilter != 0);
     194             :         }
     195          72 :         HFilter::const_iterator begin() const { return hfilter_.beginInverted(); }
     196          72 :         HFilter::const_iterator end() const { return hfilter_.endInverted(); }
     197             :         size_t size() const { return hfilter_.sizeInverted(); }
     198             : };
     199             : 
     200             : #endif

Generated by: LCOV version 1.12