std::vector::data().
Replace most code that reached into into Grob_array and modified its
internal vector with calls to new member functions such as filter().
Move the definitions of some trivial methods into grob-array.hh.
#define VPOS ((vsize) -1)
#endif
-#if HAVE_STL_DATA_METHOD
#include <vector>
-#else /* !HAVE_STL_DATA_METHOD */
-#define vector __flower_vector
-#include <vector>
-#undef vector
-
-namespace std
-{
-
-/* Interface without pointer arithmetic (iterator) semantics. */
-template<typename T, typename A = std::allocator<T> >
-class vector : public __flower_vector<T, A>
-{
-public:
- typedef typename __flower_vector<T>::iterator iterator;
- typedef typename __flower_vector<T>::const_iterator const_iterator;
-
- vector<T, A> () : __flower_vector<T, A> ()
- {
- }
-
- vector<T, A> (size_t n) : __flower_vector<T, A> (n)
- {
- }
-
- vector<T, A> (vector<T, A> const &v) : __flower_vector<T, A> (v)
- {
- }
-
- vector<T, A> (const_iterator b, const_iterator e) : __flower_vector<T, A> (b, e)
- {
- }
-
- T *
- data ()
- {
- return &(*this)[0];
- }
-
- T const *
- data () const
- {
- return &(*this)[0];
- }
-};
-
-} /* namespace std */
-
-#endif /* !HAVE_STL_DATA_METHOD */
template<typename T>
T const &
return src;
}
-/*
- Perform substitution on GROB_LIST using a constant amount of stack.
-*/
-vector<Grob *> temporary_substition_array;
-void
-substitute_grob_array (Grob_array *grob_arr, Grob_array *new_arr)
-{
- vector<Grob *> &old_grobs (grob_arr->array_reference ());
- vector<Grob *> *new_grobs (new_arr == grob_arr
- ? & temporary_substition_array
- : &new_arr->array_reference ());
-
- new_grobs->resize (old_grobs.size ());
- Grob **array = (Grob **) new_grobs->data ();
- Grob **ptr = array;
- for (vsize i = 0; i < old_grobs.size (); i++)
- {
- Grob *orig = old_grobs[i];
- Grob *new_grob = substitute_grob (orig);
- if (new_grob)
- *ptr++ = new_grob;
- }
-
- new_grobs->resize (ptr - array);
- if (new_arr == grob_arr)
- new_arr->set_array (*new_grobs);
-}
-
/*
We don't do
: Grob_array::make_array ();
Grob_array *new_arr = unsmob<Grob_array> (newval);
-
- substitute_grob_array (orig, new_arr);
+ // TODO: What if new_arr is null?
+ new_arr->filter_map_assign (*orig, substitute_grob);
val = newval;
}
else
newval = Grob_array::make_array ();
sc->set_object (sym, newval);
}
- substitute_grob_array (grob_array, unsmob<Grob_array> (newval));
+ Grob_array *new_arr = unsmob<Grob_array> (newval);
+ new_arr->filter_map_assign (*grob_array, substitute_grob);
}
else
{
ordered_ = true;
}
-vector<Grob *> &
-Grob_array::array_reference ()
-{
- return grobs_;
-}
-
-vector<Grob *> const &
-Grob_array::array () const
-{
- return grobs_;
-}
-
SCM
Grob_array::mark_smob () const
{
return ga.smobbed_copy ();
}
-void
-Grob_array::clear ()
-{
- grobs_.clear ();
-}
-
void
Grob_array::remove_duplicates ()
{
uniquify (grobs_);
}
-bool
-Grob_array::empty () const
+void
+Grob_array::filter (bool (*predicate) (const Grob *))
+{
+ vsize new_size = 0;
+ for (vsize i = 0; i < grobs_.size (); ++i)
+ if (predicate (grobs_[i]))
+ grobs_[new_size++] = grobs_[i];
+ grobs_.resize (new_size);
+ // could call grobs_.shrink_to_fit () with C++11
+}
+
+void
+Grob_array::filter_map (Grob * (*map_fun) (Grob *))
{
- return grobs_.empty ();
+ vsize new_size = 0;
+ for (vsize i = 0; i < grobs_.size (); ++i)
+ if (Grob *grob = map_fun (grobs_[i]))
+ grobs_[new_size++] = grob;
+ grobs_.resize (new_size);
+ // could call grobs_.shrink_to_fit () with C++11
}
void
-Grob_array::set_array (vector<Grob *> const &src)
+Grob_array::filter_map_assign (const Grob_array &src,
+ Grob * (*map_fun) (Grob *))
{
- grobs_ = src;
+ if (&src != this)
+ {
+ grobs_.resize (0);
+ grobs_.reserve (src.grobs_.size ());
+ for (vsize i = 0; i < src.grobs_.size (); i++)
+ if (Grob *grob = map_fun (src.grobs_[i]))
+ grobs_.push_back (grob);
+ // could call grobs_.shrink_to_fit () with C++11
+ }
+ else
+ filter_map (map_fun);
}
const char Grob_array::type_p_name_[] = "ly:grob-array?";
Spanner *spanner (vsize i);
Grob *grob (vsize i) const { return grobs_.at (i); }
vsize size () const { return grobs_.size (); }
- bool empty () const;
+ bool empty () const { return grobs_.empty (); }
void remove_duplicates ();
- void clear ();
+ void clear () { grobs_.clear (); }
void add (Grob *x) { grobs_.push_back (x); }
- void set_array (vector<Grob *> const &src);
- vector<Grob *> &array_reference ();
- vector<Grob *> const &array () const;
+ void set_array (vector<Grob *> const &src) { grobs_ = src; }
+ vector<Grob *> &array_reference () { return grobs_; }
+ vector<Grob *> const &array () const { return grobs_; }
static SCM make_array ();
+
+ // Remove grobs that do not satisfy the predicate, leaving the order
+ // unchanged.
+ void filter (bool (*predicate) (const Grob *));
+
+ // Run a function on all grobs in this array. If the function returns null,
+ // remove the original grob, reducing the size of the array. If the function
+ // returns a Grob, replace the original grob with the returned Grob.
+ void filter_map (Grob * (*map_fun) (Grob *));
+
+ // Like src.filter_map (f), but store the result in this array instead of
+ // mutating the input.
+ void filter_map_assign (const Grob_array &src, Grob * (*map_fun) (Grob *));
};
return t.smobbed_copy ();
}
+static bool grob_is_live (const Grob *g)
+{
+ return g && g->is_live ();
+}
+
/*
This is all too hairy. We use bounded-by-me to make sure that some
columns are kept "alive". Unfortunately, when spanners are suicided,
{
Grob *me = unsmob<Grob> (grob);
- SCM bbm = me->get_object ("bounded-by-me");
- Grob_array *ga = unsmob<Grob_array> (bbm);
- if (!ga)
- return SCM_UNSPECIFIED;
-
- vector<Grob *> &array (ga->array_reference ());
-
- for (vsize i = array.size (); i--;)
- {
- Grob *g = array[i];
-
- if (!g || !g->is_live ())
- /* UGH . potentially quadratic. */
- array.erase (array.begin () + i);
- }
+ if (Grob_array *ga = unsmob<Grob_array> (me->get_object ("bounded-by-me")))
+ ga->filter (grob_is_live);
return SCM_UNSPECIFIED;
}
vector<Grob *> new_elts;
new_elts.insert (new_elts.end (), elts.begin (), elts.end ());
- SCM neighbors_scm = me->get_object ("neighbors");
- if (unsmob<Grob_array> (neighbors_scm))
- {
- vector<Grob *> &arr
- = unsmob<Grob_array> (neighbors_scm)->array_reference ();
- arr = new_elts;
- }
+ if (Grob_array *a = unsmob<Grob_array> (me->get_object ("neighbors")))
+ a->set_array (new_elts);
return Axis_group_interface::internal_calc_pure_relevant_grobs (me, "neighbors");
}
new_encompasses.push_back (g);
}
- SCM encompass_scm = me->get_object ("encompass-objects");
- if (unsmob<Grob_array> (encompass_scm))
- {
- vector<Grob *> &arr
- = unsmob<Grob_array> (encompass_scm)->array_reference ();
- arr = new_encompasses;
- }
+ if (Grob_array *a = unsmob<Grob_array> (me->get_object ("encompass-objects")))
+ a->set_array (new_encompasses);
}
Bezier
void
System::derived_mark () const
{
- if (!all_elements_->empty ())
- {
- Grob **ptr = &all_elements_->array_reference ()[0];
- Grob **end = ptr + all_elements_->size ();
- while (ptr < end)
- {
- scm_gc_mark ((*ptr)->self_scm ());
- ptr++;
- }
- }
+ const vector <Grob *> &arr = all_elements_->array ();
+ for (vsize i = arr.size (); i--;)
+ scm_gc_mark (arr[i]->self_scm ());
if (pscore_)
scm_gc_mark (pscore_->self_scm ());