Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
util/array.hh
1 // Copyright (C) 2008, 2009, 2011 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena 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 GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_UTIL_ARRAY_HH
28 # define MLN_UTIL_ARRAY_HH
29 
36 
37 # include <vector>
38 # include <iostream>
39 # include <algorithm>
40 
41 # include <mln/core/concept/function.hh>
42 # include <mln/core/concept/proxy.hh>
43 # include <mln/core/concept/iterator.hh>
44 
45 # include <mln/fun/internal/selector.hh>
46 
47 
48 namespace mln
49 {
50 
51  namespace util
52  {
53 
55  template <typename T>
56  class array;
57 
58  } // end of namespace mln::util
59 
60 
61  namespace convert
62  {
63 
64  namespace over_load
65  {
66 
67  template <typename T1, typename T2>
68  void
69  from_to_(const util::array<T1>& from, util::array<T2>& to);
70 
71  template <typename T1, typename T2>
72  void
73  from_to_(const fun::i2v::array<T1>& from, util::array<T2>& to);
74 
75  } // end of namespace mln::convert::over_load
76 
77  } // end of namespace mln::convert
78 
79 
80 
81  namespace util
82  {
83 
84  // Forward declarations.
85  template <typename T> class array_fwd_iter;
86  template <typename T> class array_bkd_iter;
87 
88 
97  //
98  template <typename T>
99  class array
100  : public fun::internal::selector_from_result_<T, array<T> >::ret
101 
102  // public Function_v2v< mln::util::array<T> >
103  {
104  public:
105 
107  typedef T element;
108 
112  typedef T result;
113  typedef typename std::vector<T>::const_reference ro_result;
114  typedef typename std::vector<T>::reference mutable_result;
116 
117 
121  typedef array_fwd_iter<T> fwd_eiter;
122 
124  typedef array_bkd_iter<T> bkd_eiter;
125 
127  typedef fwd_eiter eiter;
129 
130 
134  array();
135 
137  array(unsigned n);
138 
141  array(unsigned n, const T& value);
143 
145  void reserve(unsigned n);
146 
148  void resize(unsigned n);
149 
151  void resize(unsigned n, const T& value);
152 
153 
155  array<T>& append(const T& elt);
156 
158  template <typename U>
159  array<T>& append(const array<U>& other);
160 
161 
163  unsigned nelements() const;
164 
168  unsigned size() const;
169 
171  bool is_empty() const;
172 
173 
176  ro_result operator()(unsigned i) const;
177 
180  mutable_result operator()(unsigned i);
181 
184  ro_result operator[](unsigned i) const;
185 
188  mutable_result operator[](unsigned i);
189 
191  ro_result last() const;
192 
194  mutable_result last();
195 
198  void clear();
199 
201  void fill(const T& value);
202 
204  const std::vector<T>& std_vector() const;
205 
207  std::vector<T>& hook_std_vector_();
208 
210  std::size_t memory_size() const;
211 
212  private:
213  std::vector<T> v_;
214  };
215 
216 
218  template <typename T>
219  std::ostream& operator<<(std::ostream& ostr,
220  const array<T>& a);
221 
223  template <typename T>
224  bool operator==(const array<T>& lhs,
225  const array<T>& rhs);
226 
227 
228  // array_fwd_iter<T>
229 
230  template <typename T>
231  class array_fwd_iter : public Proxy< array_fwd_iter<T> >,
232  public mln::internal::proxy_impl< const T&,
233  array_fwd_iter<T> >
234  {
235  public:
236  typedef typename array<T>::ro_result subj_t;
237 
241  array_fwd_iter();
242 
244  array_fwd_iter(const array<T>& a);
246 
248  void change_target(const array<T>& a);
249 
251  void start();
252 
254  void next();
255 
257  bool is_valid() const;
258 
260  void invalidate();
261 
263  T element() const;
264 
265  // As a Proxy.
266  subj_t subj_();
267 
269  unsigned index_() const;
270 
271  protected:
272  unsigned i_;
273  const array<T>* a_;
274  };
275 
276 
277 
278 
279  // array_bkd_iter<T>
280 
281  template <typename T>
282  class array_bkd_iter : public Proxy< array_bkd_iter<T> >,
283  public mln::internal::proxy_impl< const T&,
284  array_bkd_iter<T> >
285  {
286  public:
287  typedef typename array<T>::ro_result subj_t;
288 
292  array_bkd_iter();
293 
295  array_bkd_iter(const array<T>& a);
297 
299  void change_target(const array<T>& a);
300 
302  void start();
303 
305  void next();
306 
308  bool is_valid() const;
309 
311  void invalidate();
312 
314  T element() const;
315 
316  // As a Proxy.
317  subj_t subj_();
318 
320  unsigned index_() const;
321 
322  protected:
323  unsigned i_;
324  const array<T>* a_;
325  };
326 
327  } // end of namespace mln::util
328 
329 
330  namespace internal
331  {
332 
333  template <typename T, typename E>
334  struct subject_impl<const util::array<T>&, E>
335  {
336  typedef typename util::array<T>::ro_result ro_result;
337 
338  unsigned nelements() const;
339  unsigned size() const;
340  bool is_empty() const;
341  ro_result operator()(unsigned i) const;
342  ro_result operator[](unsigned i) const;
343  const std::vector<T>& std_vector() const;
344 
345  private:
346  const E& exact_() const;
347  };
348 
349 
350  template <typename T, typename E>
351  struct subject_impl<util::array<T>&, E>
352  : subject_impl<const util::array<T>&, E>
353  {
354  typedef typename util::array<T>::mutable_result mutable_result;
355 
356  void reserve(unsigned n);
357  void resize(unsigned n);
358  void resize(unsigned n, const T& value);
359 
360  util::array<T>& append(const T& elt);
361 
362  template <typename U>
363  util::array<T>& append(const util::array<U>& other);
364 
365  mutable_result operator()(unsigned i);
366  mutable_result operator[](unsigned i);
367 
368  void clear();
369 
370  void fill(const T& value);
371 
372  std::vector<T>& hook_std_vector_();
373 
374  private:
375  E& exact_();
376  };
377 
378 
379  } // end of namespace mln::internal
380 
381 
382 # ifndef MLN_INCLUDE_ONLY
383 
384 
385  // convert::from_to_
386 
387  namespace convert
388  {
389 
390  namespace over_load
391  {
392 
393  template <typename T1, typename T2>
394  void
395  from_to_(const util::array<T1>& from, util::array<T2>& to)
396  {
397  to.resize(from.nelements());
398 
399  for (unsigned i = 0; i < from.nelements(); ++i)
400  to[i] = convert::to<T2>(from[i]);
401  }
402 
403  template <typename T1, typename T2>
404  void
405  from_to_(const fun::i2v::array<T1>& from, util::array<T2>& to)
406  {
407  to.resize(from.size());
408 
409  for (unsigned i = 0; i < from.size(); ++i)
410  to[i] = convert::to<T2>(from(i));
411  }
412 
413 
414  } // end of namespace mln::convert::over_load
415 
416  } // end of namespace mln::convert
417 
418 
419  namespace util
420  {
421 
422  // util::array<T>
423 
424 
425  template <typename T>
426  inline
428  {
429  }
430 
431  template <typename T>
432  inline
433  array<T>::array(unsigned n)
434  : v_(n)
435  {
436  }
437 
438  template <typename T>
439  inline
440  array<T>::array(unsigned n, const T& value)
441  : v_(n, value)
442  {
443  }
444 
445  template <typename T>
446  inline
447  void
448  array<T>::reserve(unsigned n)
449  {
450  v_.reserve(n);
451  }
452 
453  template <typename T>
454  inline
455  void
456  array<T>::resize(unsigned n)
457  {
458  v_.resize(n);
459  }
460 
461  template <typename T>
462  inline
463  void
464  array<T>::resize(unsigned n, const T& value)
465  {
466  v_.resize(n, value);
467  }
468 
469  template <typename T>
470  inline
471  array<T>&
472  array<T>::append(const T& elt)
473  {
474  v_.push_back(elt);
475  return *this;
476  }
477 
478  template <typename T>
479  template <typename U>
480  inline
481  array<T>&
483  {
484  if (other.is_empty())
485  // No-op.
486  return *this;
487  v_.insert(v_.end(),
488  other.std_vector().begin(), other.std_vector().end());
489  return *this;
490  }
491 
492  template <typename T>
493  inline
494  void
496  {
497  v_.clear();
498  mln_postcondition(is_empty());
499  }
500 
501  template <typename T>
502  inline
503  void
504  array<T>::fill(const T& value)
505  {
506  std::fill(v_.begin(), v_.end(), value);
507  }
508 
509  template <typename T>
510  inline
511  unsigned
513  {
514  return nelements();
515  }
516 
517  template <typename T>
518  inline
519  unsigned
521  {
522  return v_.size();
523  }
524 
525  template <typename T>
526  inline
527  typename array<T>::ro_result
528  array<T>::operator()(unsigned i) const
529  {
530  return (*this)[i];
531  }
532 
533  template <typename T>
534  inline
535  typename array<T>::mutable_result
537  {
538  return (*this)[i];
539  }
540 
541  template <typename T>
542  inline
543  typename array<T>::ro_result
544  array<T>::operator[](unsigned i) const
545  {
546  mln_precondition(i < nelements());
547  return v_[i];
548  }
549 
550  template <typename T>
551  inline
552  typename array<T>::mutable_result
554  {
555  mln_precondition(i < nelements());
556  return v_[i];
557  }
558 
559  template <typename T>
560  inline
561  typename array<T>::ro_result
563  {
564  return v_[nelements() - 1];
565  }
566 
567  template <typename T>
568  inline
569  typename array<T>::mutable_result
571  {
572  return v_[nelements() - 1];
573  }
574 
575  template <typename T>
576  inline
577  bool
579  {
580  return nelements() == 0;
581  }
582 
583  template <typename T>
584  inline
585  const std::vector<T>&
587  {
588  return v_;
589  }
590 
591  template <typename T>
592  inline
593  std::vector<T>&
595  {
596  return v_;
597  }
598 
599  template <typename T>
600  inline
601  std::size_t
603  {
604  return sizeof(*this) + nelements() * sizeof(T);
605  }
606 
607 
608 
609  // util::array_fwd_iter<T>
610 
611 
612  template <typename T>
613  inline
614  array_fwd_iter<T>::array_fwd_iter()
615  {
616  a_ = 0;
617  }
618 
619  template <typename T>
620  inline
621  array_fwd_iter<T>::array_fwd_iter(const array<T>& a)
622  {
623  change_target(a);
624  }
625 
626  template <typename T>
627  inline
628  void
629  array_fwd_iter<T>::change_target(const array<T>& a)
630  {
631  a_ = &a;
632  invalidate();
633  }
634 
635  template <typename T>
636  inline
637  void
638  array_fwd_iter<T>::start()
639  {
640  mln_precondition(a_ != 0);
641  i_ = 0;
642  }
643 
644  template <typename T>
645  inline
646  void
647  array_fwd_iter<T>::next()
648  {
649  mln_precondition(is_valid());
650  ++i_;
651  }
652 
653  template <typename T>
654  inline
655  bool
656  array_fwd_iter<T>::is_valid() const
657  {
658  return a_ != 0 && i_ != a_->nelements();
659  }
660 
661  template <typename T>
662  inline
663  void
664  array_fwd_iter<T>::invalidate()
665  {
666  if (a_ != 0)
667  i_ = a_->nelements();
668  mln_postcondition(! is_valid());
669  }
670 
671  template <typename T>
672  inline
673  T
674  array_fwd_iter<T>::element() const
675  {
676  mln_precondition(is_valid());
677  return a_->operator[](i_);
678  }
679 
680  template <typename T>
681  inline
682  typename array_fwd_iter<T>::subj_t
683  array_fwd_iter<T>::subj_()
684  {
685  mln_precondition(is_valid());
686  return a_->operator[](i_);
687  }
688 
689  template <typename T>
690  inline
691  unsigned
692  array_fwd_iter<T>::index_() const
693  {
694  return i_;
695  }
696 
697 
698 
699  // util::array_bkd_iter<T>
700 
701 
702  template <typename T>
703  inline
704  array_bkd_iter<T>::array_bkd_iter()
705  {
706  a_ = 0;
707  }
708 
709  template <typename T>
710  inline
711  array_bkd_iter<T>::array_bkd_iter(const array<T>& a)
712  {
713  change_target(a);
714  }
715 
716  template <typename T>
717  inline
718  void
719  array_bkd_iter<T>::change_target(const array<T>& a)
720  {
721  a_ = &a;
722  invalidate();
723  }
724 
725  template <typename T>
726  inline
727  void
728  array_bkd_iter<T>::start()
729  {
730  mln_precondition(a_ != 0);
731  if (! a_->is_empty())
732  i_ = a_->nelements() - 1;
733  }
734 
735  template <typename T>
736  inline
737  void
738  array_bkd_iter<T>::next()
739  {
740  mln_precondition(is_valid());
741  if (i_ == 0)
742  invalidate();
743  else
744  --i_;
745  }
746 
747  template <typename T>
748  inline
749  bool
750  array_bkd_iter<T>::is_valid() const
751  {
752  return a_ != 0 && i_ != a_->nelements();
753  }
754 
755  template <typename T>
756  inline
757  void
758  array_bkd_iter<T>::invalidate()
759  {
760  if (a_ != 0)
761  i_ = a_->nelements();
762  mln_postcondition(! is_valid());
763  }
764 
765  template <typename T>
766  inline
767  T
768  array_bkd_iter<T>::element() const
769  {
770  mln_precondition(is_valid());
771  return a_->operator[](i_);
772  }
773 
774  template <typename T>
775  inline
776  typename array_bkd_iter<T>::subj_t
777  array_bkd_iter<T>::subj_()
778  {
779  mln_precondition(is_valid());
780  return a_->operator[](i_);
781  }
782 
783  template <typename T>
784  inline
785  unsigned
786  array_bkd_iter<T>::index_() const
787  {
788  return i_;
789  }
790 
791 
792 
793  // Operator <<.
794 
795  template <typename T>
796  std::ostream& operator<<(std::ostream& ostr,
797  const array<T>& a)
798  {
799  ostr << '[';
800  const unsigned n = a.nelements();
801  for (unsigned i = 0; i < n; ++i)
802  {
803  ostr << a[i];
804  if (i != n - 1)
805  ostr << ", ";
806  }
807  ostr << ']';
808  return ostr;
809  }
810 
811 
812  // Operator <<.
813 
814  template <typename T>
815  bool operator==(const array<T>& lhs,
816  const array<T>& rhs)
817  {
818  return lhs.std_vector() == rhs.std_vector();
819  }
820 
821  } // end of namespace mln::util
822 
823 
824  namespace internal
825  {
826 
827  template <typename T, typename E>
828  inline
829  void
830  subject_impl<util::array<T>&, E>::reserve(unsigned n)
831  {
832  exact_().get_subject().reserve(n);
833  }
834 
835  template <typename T, typename E>
836  inline
837  void
838  subject_impl<util::array<T>&, E>::resize(unsigned n)
839  {
840  exact_().get_subject().resize(n);
841  }
842 
843  template <typename T, typename E>
844  inline
845  void
846  subject_impl<util::array<T>&, E>::resize(unsigned n, const T& value)
847  {
848  exact_().get_subject().resize(n, value);
849  }
850 
851  template <typename T, typename E>
852  inline
853  util::array<T>&
854  subject_impl<util::array<T>&, E>::append(const T& elt)
855  {
856  return exact_().get_subject().append(elt);
857  }
858 
859  template <typename T, typename E>
860  template <typename U>
861  inline
862  util::array<T>&
863  subject_impl<util::array<T>&, E>::append(const util::array<U>& other)
864  {
865  return exact_().get_subject().append(other);
866  }
867 
868  template <typename T, typename E>
869  inline
870  typename subject_impl<util::array<T>&, E>::mutable_result
871  subject_impl<util::array<T>&, E>::operator()(unsigned i)
872  {
873  return exact_().get_subject()(i);
874  }
875 
876  template <typename T, typename E>
877  inline
878  typename subject_impl<util::array<T>&, E>::mutable_result
879  subject_impl<util::array<T>&, E>::operator[](unsigned i)
880  {
881  return exact_().get_subject()[i];
882  }
883 
884  template <typename T, typename E>
885  inline
886  void
887  subject_impl<util::array<T>&, E>::clear()
888  {
889  exact_().get_subject().clear();
890  }
891 
892  template <typename T, typename E>
893  inline
894  void
895  subject_impl<util::array<T>&, E>::fill(const T& value)
896  {
897  exact_().get_subject().fill(value);
898  }
899 
900  template <typename T, typename E>
901  inline
902  std::vector<T>&
903  subject_impl<util::array<T>&, E>::hook_std_vector_()
904  {
905  return exact_().get_subject().hook_std_vector_();
906  }
907 
908  template <typename T, typename E>
909  inline
910  E&
911  subject_impl<util::array<T>&, E >::exact_()
912  {
913  return internal::force_exact<E>(*this);
914  }
915 
916 
917  template <typename T, typename E>
918  inline
919  unsigned
920  subject_impl<const util::array<T>&, E>::size() const
921  {
922  return exact_().get_subject().size();
923  }
924 
925  template <typename T, typename E>
926  inline
927  unsigned
928  subject_impl<const util::array<T>&, E>::nelements() const
929  {
930  return exact_().get_subject().nelements();
931  }
932 
933  template <typename T, typename E>
934  inline
935  bool
936  subject_impl<const util::array<T>&, E>::is_empty() const
937  {
938  return exact_().get_subject().is_empty();
939  }
940 
941  template <typename T, typename E>
942  inline
943  typename subject_impl<const util::array<T>&, E>::ro_result
944  subject_impl<const util::array<T>&, E>::operator()(unsigned i) const
945  {
946  return exact_().get_subject()(i);
947  }
948 
949  template <typename T, typename E>
950  inline
951  typename subject_impl<const util::array<T>&, E>::ro_result
952  subject_impl<const util::array<T>&, E>::operator[](unsigned i) const
953  {
954  return exact_().get_subject()[i];
955  }
956 
957  template <typename T, typename E>
958  inline
959  const std::vector<T>&
960  subject_impl<const util::array<T>&, E>::std_vector() const
961  {
962  return exact_().get_subject().std_vector();
963  }
964 
965  template <typename T, typename E>
966  inline
967  const E&
968  subject_impl<const util::array<T>&, E >::exact_() const
969  {
970  return internal::force_exact<const E>(*this);
971  }
972 
973 
974  } // end of namespace mln::internal
975 
976 # endif // ! MLN_INCLUDE_ONLY
977 
978 
979 } // end of namespace mln
980 
981 #endif // ! MLN_UTIL_ARRAY_HH