1 /* 2 This file is part of LilyPond, the GNU music typesetter. 3 4 Copyright (C) 2005--2021 Han-Wen Nienhuys <hanwen@xs4all.nl> 5 6 LilyPond 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, either version 3 of the License, or 9 (at your option) any later version. 10 11 LilyPond is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef GROB_ARRAY_HH 21 #define GROB_ARRAY_HH 22 23 #include "lily-proto.hh" 24 #include "smobs.hh" 25 26 #include <vector> 27 28 class Grob_array : public Simple_smob<Grob_array> 29 { 30 public: 31 int print_smob (SCM, scm_print_state *) const; 32 SCM mark_smob () const; 33 static const char *const type_p_name_; 34 private: 35 std::vector<Grob *> grobs_; 36 bool ordered_; 37 38 Grob_array (); 39 public: ordered() const40 bool ordered () const { return ordered_; } set_ordered(bool b)41 void set_ordered (bool b) { ordered_ = b; } grob(vsize i) const42 Grob *grob (vsize i) const { return grobs_.at (i); } size() const43 vsize size () const { return grobs_.size (); } empty() const44 bool empty () const { return grobs_.empty (); } 45 void remove_duplicates (); clear()46 void clear () { grobs_.clear (); } add(Grob * x)47 void add (Grob *x) { grobs_.push_back (x); } set_array(std::vector<Grob * > const & src)48 void set_array (std::vector<Grob *> const &src) { grobs_ = src; } array_reference()49 std::vector<Grob *> &array_reference () { return grobs_; } array_reference() const50 const std::vector<Grob *> &array_reference () const { return grobs_; } array() const51 std::vector<Grob *> const &array () const { return grobs_; } 52 static SCM make_array (); 53 54 // Remove grobs that do not satisfy the predicate, leaving the order 55 // unchanged. 56 void filter (bool (*predicate) (const Grob *)); 57 58 // Run a function on all grobs in this array. If the function returns null, 59 // remove the original grob, reducing the size of the array. If the function 60 // returns a Grob, replace the original grob with the returned Grob. 61 // 62 // Optional extra arguments to filter_map are passed to the provided mapping 63 // function ahead of the Grob. 64 template <class Fn, class... Args> filter_map(Fn && fn,Args &&...args)65 void filter_map (Fn &&fn, Args &&... args) 66 { 67 vsize new_size = 0; 68 for (auto *og : grobs_) 69 if (auto *g = std::forward<Fn> (fn) (std::forward<Args> (args)..., og)) 70 grobs_[new_size++] = g; 71 grobs_.resize (new_size); 72 grobs_.shrink_to_fit (); 73 } 74 75 // Like src.filter_map (f), but store the result in this array instead of 76 // mutating the input. 77 template <class Fn, class... Args> filter_map_assign(const Grob_array & src,Fn && fn,Args &&...args)78 void filter_map_assign (const Grob_array &src, Fn &&fn, Args &&... args) 79 { 80 if (&src != this) 81 { 82 grobs_.clear (); 83 grobs_.reserve (src.grobs_.size ()); 84 for (auto *og : src.grobs_) 85 if (auto *g = std::forward<Fn> (fn) (std::forward<Args> (args)..., og)) 86 grobs_.push_back (g); 87 grobs_.shrink_to_fit (); 88 } 89 else 90 filter_map (std::forward<Fn> (fn), std::forward<Args> (args)...); 91 } 92 }; 93 94 std::vector<Grob *> const &ly_scm2link_array (SCM x); 95 SCM grob_list_to_grob_array (SCM lst); 96 SCM grob_array_to_list (Grob_array *array); 97 98 #endif /* GROB_ARRAY_HH */ 99