00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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