box.hh

Go to the documentation of this file.
00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #ifndef __BOX_HH
00019 # define __BOX_HH
00020 
00021 # include <iostream>
00022 # include <string>
00023 # include <memory>
00024 
00029 namespace aurelia {
00030 
00033   struct virtual_box {
00036     virtual ~virtual_box() {}
00037 
00044     virtual unsigned to_text(std::ostream& s, unsigned pos) const = 0;
00045   };
00046 
00049   template <typename ExactType>
00050   struct box: public virtual_box {
00052     operator ExactType&() {
00053       return *static_cast<ExactType*>(this);
00054     }
00055 
00057     operator const ExactType&() const {
00058       return *static_cast<const ExactType*>(this);
00059     }
00060   };
00061 
00064   struct string_box: public box<string_box> {
00065   private:
00066     std::string s;
00067 
00068   public:
00071     string_box(const std::string& s): s(s) {}
00072 
00075     string_box(const string_box& other): s(other.s) {}
00076 
00079     operator std::string() const {
00080       return s;
00081     }
00082 
00085     string_box& operator=(string_box other) {
00086       this->swap(other);
00087       return *this;
00088     }
00089 
00092     void swap(string_box& other) {
00093       std::swap(this->s, other.s);
00094     }
00095 
00098     virtual unsigned to_text(std::ostream& s, unsigned pos) const;
00099   };
00100 
00102   typedef string_box S;
00103 
00106   enum Dir : unsigned {
00107     HDir, VDir, HVDir
00108   };
00109 
00111   struct h_box {
00112     enum { dir = HDir };
00113   };
00115   struct v_box {
00116     enum { dir = VDir };
00117   };
00119   struct hv_box {
00120     enum { dir = HVDir };
00121   };
00122 
00123   struct virtual_boxList {
00126     virtual ~virtual_boxList() {}
00127 
00130     virtual unsigned to_text(std::ostream& s, unsigned pos,
00131                              unsigned VS, unsigned HS, unsigned IS,
00132                              Dir direction, bool first) const = 0;
00133   };
00134 
00137   template <typename ExactType>
00138   struct box_list: public virtual_boxList {
00140     operator ExactType&() {
00141       return *static_cast<ExactType*>(this);
00142     }
00143 
00145     operator const ExactType&() const {
00146       return *static_cast<const ExactType*>(this);
00147     }
00148   };
00149 
00150 
00153   struct box_list_end:
00154     public box_list<box_list_end> {
00155     virtual unsigned to_text(std::ostream&, unsigned pos,
00156                              unsigned, unsigned, unsigned,
00157                              Dir, bool) const {
00158       return pos;
00159     }
00160   };
00161 
00164   template <typename Head, typename Tail>
00165   struct box_list_cons: public box_list<box_list_cons<Head, Tail> > {
00166   private:
00167     Head _head;
00168     Tail _tail;
00169 
00170   public:
00173     box_list_cons(const Head& _head, const Tail& _tail):
00174       _head(_head), _tail(_tail) {}
00175 
00178     const Head& head() const {
00179       return _head;
00180     }
00181 
00184     const Tail& tail() const {
00185       return _tail;
00186     }
00187 
00190     virtual unsigned to_text(std::ostream& s, unsigned pos,
00191                              unsigned HS, unsigned VS, unsigned IS,
00192                              Dir direction, bool first)
00193       const {
00194       if (direction == HDir) {
00195         pos = box_to_text(s, pos, head());
00196         for (unsigned i = 0; i < HS; ++i)
00197           s << " ";
00198         pos += HS;
00199         return tail().to_text(s, pos, HS, VS, IS, direction, false);
00200       } else if (direction == VDir) {
00201         if (!first) {
00202           for (unsigned i = 0; i <= VS; ++i)
00203             s << "\n";
00204           for (unsigned i = 0; i < pos; ++i)
00205             s << " ";
00206         }
00207         box_to_text(s, pos, head());
00208         if (first)
00209           pos += IS;
00210         return tail().to_text(s, pos, HS, VS, IS, direction, false);
00211       }
00212 
00213       return pos;
00214     }
00215   };
00216 
00217 
00220   struct any_box_list: public box_list<any_box_list> {
00221   private:
00222     std::shared_ptr<virtual_boxList> list;
00223 
00224   public:
00227     template <typename ExactType>
00228     any_box_list(const box_list<ExactType>& l): list(new ExactType(l)) {}
00229 
00232     any_box_list(const any_box_list& other): list(other.list) {}
00233 
00236     any_box_list& operator=(any_box_list other) {
00237       this->swap(other);
00238       return *this;
00239     }
00240 
00243     void swap(any_box_list& other) {
00244       std::swap(this->list, other.list);
00245     }
00246 
00249     virtual unsigned to_text(std::ostream& s, unsigned pos,
00250                              unsigned VS, unsigned HS, unsigned IS,
00251                              Dir direction, bool first) const {
00252       return list->to_text(s, pos, VS, HS, IS, direction, first);
00253     }
00254   };
00255 
00264   template <typename Direction, unsigned VS, unsigned HS, unsigned IS,
00265             typename List>
00266   struct container_box:
00267     public box<container_box<Direction, VS, HS, IS, List> > {
00268   private:
00269     List list;
00270   public:
00272     container_box(const List& list): list(list) {}
00273 
00275     container_box(const container_box& other): list(other.list) {}
00276 
00278     const List* operator->() const {
00279       return &list;
00280     }
00281 
00283     const List& operator*() const {
00284       return list;
00285     }
00286 
00288     container_box& operator=(container_box other) {
00289       this->swap(other);
00290       return *this;
00291     }
00292 
00294     void swap(container_box& other) {
00295       this->list.swap(other.list);
00296     }
00297 
00299     virtual unsigned to_text(std::ostream& s, unsigned pos) const {
00300       return box_to_text(s, pos, *this);
00301     }
00302   };
00303 
00306   struct any_box: public box<any_box> {
00307   private:
00308     std::shared_ptr<virtual_box> _box;
00309 
00310   public:
00313     template <typename RealType>
00314     explicit any_box(const box<RealType>& b): _box(new RealType(b)) {}
00315 
00318     any_box(const any_box& other): _box(other._box) {}
00319 
00322     any_box& operator=(any_box other) {
00323       this->swap(other);
00324       return (*this);
00325     }
00326 
00329     void swap(any_box& other) {
00330       std::swap(this->_box, other._box);
00331     }
00332 
00335     virtual unsigned to_text(std::ostream&s, unsigned pos) const;
00336   };
00337 
00340   template <typename ExactBox>
00341   box_list_cons<ExactBox, box_list_end>
00342   append(const box_list_end&, const box<ExactBox>& b) {
00343     return box_list_cons<ExactBox, box_list_end>(b, box_list_end());
00344   }
00345 
00348   template <typename B, typename Tail, typename ExactBox>
00349   box_list_cons<B,decltype(append(std::declval<Tail>(),
00350                                 std::declval<ExactBox>()))>
00351   append(const box_list_cons<B, Tail>& l, const box<ExactBox>& b) {
00352     return box_list_cons<B,decltype(append(std::declval<Tail>(),
00353                                          std::declval<ExactBox>()))>
00354     (l.head(), append(l.tail(), b));
00355   }
00356 
00359   template <typename ExactBox, typename ExactList>
00360   decltype(append(std::declval<ExactList>(), std::declval<ExactBox>()))
00361   operator,(const box_list<ExactList>& l, const box<ExactBox>& s) {
00362     return append(ExactList(l), s);
00363   }
00364 
00367   template <typename ExactBox, typename ExactBox2>
00368   box_list_cons<ExactBox, box_list_cons<ExactBox2, box_list_end> >
00369   operator,(const box<ExactBox>& s, const box<ExactBox2>& t) {
00370     return box_list_cons<ExactBox, box_list_cons<ExactBox2, box_list_end> >
00371       (s, box_list_cons<ExactBox2, box_list_end>(t, box_list_end()));
00372   }
00373 
00376   template <unsigned VS, unsigned HS, unsigned IS>
00377   struct space_conf {};
00378 
00380   template <unsigned VS>
00381   space_conf<VS, 0, 0> Vs() {
00382     return space_conf<VS, 0, 0>();
00383   }
00384 
00386   template <unsigned HS>
00387   space_conf<0, HS, 0> Hs() {
00388     return space_conf<0, HS, 0>();
00389   }
00390 
00392   template <unsigned IS>
00393   space_conf<0, 0, IS> Is() {
00394     return space_conf<0, 0, IS>();
00395   }
00396 
00398   template <unsigned a, unsigned b>
00399   struct max {
00400     enum : unsigned { ret = (a>b)?a:b };
00401   };
00402 
00403 
00405   template <unsigned VS1, unsigned HS1, unsigned IS1,
00406             unsigned VS2, unsigned HS2, unsigned IS2>
00407   space_conf<max<VS1, VS2>::ret,
00408             max<HS1, HS2>::ret,
00409             max<IS1, IS2>::ret>
00410   operator,(const space_conf<VS1, HS1, IS1>&,
00411             const space_conf<VS2, HS2, IS2>&) {
00412     return space_conf<max<VS1, VS2>::ret,
00413       max<HS1, HS2>::ret,
00414       max<IS1, IS2>::ret>();
00415   }
00416 
00418   template <typename Direction, unsigned VS, unsigned HS, unsigned IS>
00419   struct box_artifact {
00421     template <typename ExactList>
00422     container_box<Direction, VS, HS, IS, ExactList>
00423     operator[](const box_list<ExactList>& l) const {
00424       return container_box<Direction, VS, HS, IS, ExactList>(l);
00425     }
00426 
00428     template <typename ExactBox>
00429     container_box<Direction, VS, HS, IS, box_list_cons<ExactBox, box_list_end> >
00430     operator[](const box<ExactBox>& l) const {
00431       return
00432         container_box<Direction, VS, HS, IS, box_list_cons<ExactBox, box_list_end> >
00433         (box_list_cons<ExactBox, box_list_end>(l, box_list_end()));
00434     }
00435   };
00436 
00438   template <unsigned VS, unsigned HS, unsigned IS>
00439   box_artifact<h_box, VS, HS, IS> H(const space_conf<VS, HS, IS>&) {
00440     return box_artifact<h_box, VS, HS, IS>();
00441   }
00442 
00444   box_artifact<h_box, 0, 1, 0> H() {
00445     return box_artifact<h_box, 0, 1, 0>();
00446   }
00447 
00449   template <unsigned VS, unsigned HS, unsigned IS>
00450   box_artifact<v_box, VS, HS, IS> V(const space_conf<VS, HS, IS>&) {
00451     return box_artifact<v_box, VS, HS, IS>();
00452   }
00453 
00455   box_artifact<v_box, 0, 0, 0> V() {
00456     return box_artifact<v_box, 0, 0, 0>();
00457   }
00458 
00460   template <unsigned VS, unsigned HS, unsigned IS>
00461   box_artifact<hv_box, VS, HS, IS> HV(const space_conf<VS, HS, IS>&) {
00462     return box_artifact<hv_box, VS, HS, IS>();
00463   }
00464 
00466   box_artifact<hv_box, 0, 1, 0> HV() {
00467     return box_artifact<hv_box, 0, 1, 0>();
00468   }
00469 
00477   template <typename Stream, unsigned VS, unsigned HS, unsigned IS,
00478             typename Head, typename Head2, typename Tail>
00479   unsigned box_to_text(Stream& s, unsigned pos, const v_box&,
00480                        const space_conf<VS, HS, IS>&,
00481                        const box_list_cons<Head,
00482                        box_list_cons<Head2, Tail> >& bl) {
00483     box_to_text(s, pos, bl.head());
00484     for (unsigned i = 0; i < (VS + 1); ++i)
00485       s << std::endl;
00486     for (unsigned i = 0; i < pos; ++i)
00487       s << " ";
00488     return box_to_text(s, pos, v_box(), space_conf<VS, HS, IS>(), bl.tail());
00489   }
00490 
00498   template <typename Stream, unsigned VS, unsigned HS, unsigned IS,
00499             typename Head>
00500   unsigned box_to_text(Stream& s, unsigned pos, const v_box&,
00501                        const space_conf<VS, HS, IS>&,
00502                        const box_list_cons<Head, box_list_end>& bl) {
00503     return box_to_text(s, pos, bl.head());
00504   }
00505 
00512   template <typename Stream, unsigned VS, unsigned HS, unsigned IS>
00513   unsigned box_to_text(Stream&, unsigned pos, const v_box&,
00514                        const space_conf<VS, HS, IS>&,
00515                        const box_list_end&) {
00516     return pos;
00517   }
00518 
00524   template <unsigned HS>
00525   struct print_space {
00526     template <typename Stream>
00527     static void doit(Stream& s) {
00528       for (unsigned i = 0; i < HS; ++i)
00529         s << " ";
00530     }
00531   };
00532 
00538   template <>
00539   struct print_space<0U> {
00540     template <typename Stream>
00541     static void doit(Stream&) {}
00542   };
00543 
00551   template <typename Stream, unsigned VS, unsigned HS, unsigned IS,
00552             typename Head, typename Head2, typename Tail>
00553   unsigned box_to_text(Stream& s, unsigned pos, const h_box&,
00554                        const space_conf<VS, HS, IS>&,
00555                        const box_list_cons<Head,
00556                        box_list_cons<Head2, Tail> >& bl) {
00557     pos = box_to_text(s, pos, bl.head());
00558     print_space<HS>::doit(s);
00559     pos += HS;
00560     return box_to_text(s, pos, h_box(), space_conf<VS, HS, IS>(), bl.tail());
00561   }
00562 
00570   template <typename Stream, unsigned VS, unsigned HS, unsigned IS,
00571             typename Head>
00572   unsigned box_to_text(Stream& s, unsigned pos, const h_box&,
00573                        const space_conf<VS, HS, IS>&,
00574                        const box_list_cons<Head, box_list_end>& bl) {
00575     return box_to_text(s, pos, bl.head());
00576   }
00577 
00578 
00585   template <typename Stream, unsigned VS, unsigned HS, unsigned IS>
00586   unsigned box_to_text(Stream&, unsigned pos, const h_box&,
00587                        const space_conf<VS, HS, IS>&,
00588                        const box_list_end&) {
00589     return pos;
00590   }
00591 
00599   template <typename Stream>
00600   unsigned box_to_text(Stream& s, unsigned pos, const string_box& str) {
00601     s << std::string(str);
00602     return pos + std::string(str).size();
00603   }
00604 
00612   template <typename Stream>
00613   unsigned box_to_text(Stream& s, unsigned pos, const any_box& b) {
00614     return b.to_text(s, pos);
00615   }
00616 
00624   template <typename Stream, unsigned VS, unsigned HS, unsigned IS,
00625             typename Head, typename Tail>
00626   unsigned box_to_text(Stream& s, unsigned pos,
00627                        const container_box<v_box, VS, HS, IS,
00628                        box_list_cons<Head, Tail> >& b) {
00629     box_to_text(s, pos, b->head());
00630     for (unsigned i = 0; i < (VS + 1); ++i)
00631       s << std::endl;
00632     pos+=IS;
00633     for (unsigned i = 0; i < pos; ++i)
00634       s << " ";
00635     return box_to_text(s, pos, v_box(), (Vs<VS>(), Is<IS>()), b->tail());
00636   }
00637 
00644   template <typename Stream, unsigned VS, unsigned HS, unsigned IS>
00645   unsigned box_to_text(Stream& s, unsigned pos,
00646                        const container_box<v_box, VS, HS, IS, box_list_end>&) {
00647     return pos;
00648   }
00649 
00657   template <typename Stream, unsigned VS, unsigned HS, unsigned IS,
00658             typename Head, typename Tail>
00659   unsigned box_to_text(Stream& s, unsigned pos,
00660                        const container_box<h_box, VS, HS, IS,
00661                        box_list_cons<Head, Tail> >& b) {
00662     return box_to_text(s, pos, h_box(), (Hs<HS>()), *b);
00663   }
00664 
00672   template <typename Stream, unsigned VS, unsigned HS, unsigned IS>
00673   unsigned box_to_text(Stream& s, unsigned pos,
00674                        const container_box<h_box, VS, HS, IS,
00675                        any_box_list>& b) {
00676     return b->to_text(s, pos, VS, HS, IS, HDir, true);
00677   }
00678 
00686   template <typename Stream, unsigned VS, unsigned HS, unsigned IS>
00687   unsigned box_to_text(Stream& s, unsigned pos,
00688                        const container_box<v_box, VS, HS, IS,
00689                        any_box_list>& b) {
00690     return b->to_text(s, pos, VS, HS, IS, VDir, true);
00691   }
00692 
00699   template <typename Stream, unsigned VS, unsigned HS, unsigned IS>
00700   unsigned box_to_text(Stream& s, unsigned pos,
00701                        const container_box<h_box, VS, HS, IS, box_list_end>&) {
00702     return pos;
00703   }
00704 
00711   template <typename Stream, typename ExactBox>
00712   Stream& operator<<(Stream& s, const box<ExactBox>& b) {
00713     box_to_text(s, 0U, (const ExactBox&)(b));
00714     return s;
00715   }
00716 
00717   unsigned string_box::to_text(std::ostream& s, unsigned pos) const {
00718     return box_to_text(s, pos, *this);
00719   }
00720 
00721   unsigned any_box::to_text(std::ostream& s, unsigned pos) const {
00722     return this->_box->to_text(s, pos);
00723   }
00724 }
00725 
00726 #endif