summaryrefslogtreecommitdiff
path: root/utils/writer.h
blob: d21b74d6566be6b86a3297777c27cd294145ebb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef WRITER_H
#define WRITER_H

#include <iostream>

struct Writer
{
  template <class Ch, class Tr,class value_type>
  std::basic_ostream<Ch,Tr>&
  operator()(std::basic_ostream<Ch,Tr>& o,const value_type &l) const {
    return o << l;
  }
};

struct LineWriter
{
  template <class Ch, class Tr,class Label>
  std::basic_ostream<Ch,Tr>&
  operator()(std::basic_ostream<Ch,Tr>& o,const Label &l) const {
    return o << l << std::endl;
  }
};

template <class O, class T,class W> inline
std::ios_base::iostate write_range_iostate(O& o,T begin, T end,W writer,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')',char space=' ')
{
  static const char *const MULTILINE_SEP="\n";
  if (parens) {
    o << open_paren;
    if (multiline)
      o << MULTILINE_SEP;
  }
  if (multiline) {
    for (;begin!=end;++begin) {
      o << space;
      writer(o,*begin);
      o << MULTILINE_SEP;
    }
  } else {
    for (T i=begin;i!=end;++i) {
      if (i!=begin) o<<space;
      writer(o,*i);
    }
  }
  if (parens) {
    o << close_paren;
    if (multiline)
      o << MULTILINE_SEP;
  }
  return std::ios_base::goodbit;
}


template <class Ib,class Ie,class W=Writer>
struct range_formatter {
  Ib i;
  Ie e;
  W w;
  bool multiline;
  bool parens;
  range_formatter(Ib i,Ie e,W w=W(),bool multiline=false,bool parens=true) :
    i(i),e(e),w(w),multiline(multiline),parens(parens) {}

  template <class Ch, class Tr>
  std::basic_ostream<Ch,Tr> &
  operator()(std::basic_ostream<Ch,Tr> &o) const {
    write_range_iostate(o,i,e,w,multiline,parens);
    return o;
  }

  template <class Ch, class Tr>
  friend inline
  std::basic_ostream<Ch,Tr> &
  operator<<(std::basic_ostream<Ch,Tr> &o,range_formatter<Ib,Ie,W> const& w) {
    return w(o);
  }
};

template <class Ib,class Ie,class W>
range_formatter<Ib,Ie,W>
wrange(Ib i,Ie e,W const& w,bool multiline=false,bool parens=true)
{
  return range_formatter<Ib,Ie,W>(i,e,w,multiline,parens);
}

template <class Ib,class Ie>
range_formatter<Ib,Ie>
prange(Ib i,Ie e,bool multiline=false,bool parens=true)
{
  return range_formatter<Ib,Ie,Writer>(i,e,Writer(),multiline,parens);
}


template <class Ch, class Tr, class T,class W> inline
std::basic_ostream<Ch,Tr> & write_range(std::basic_ostream<Ch,Tr>& o,T begin, T end,W writer,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')')
{
  write_range_iostate(o,begin,end,writer,multiline,parens,open_paren,close_paren);
  return o;
}

template <class O, class T>
inline std::ios_base::iostate print_range(O& o,T begin,T end,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')') {
  return  write_range_iostate(o,begin,end,Writer(),multiline,parens,open_paren,close_paren);
}

template <class O, class C>
inline std::ios_base::iostate print_range_i(O& o,C const&c,unsigned from,unsigned to,bool multiline=false,bool parens=true,char open_paren='(',char close_paren=')') {
  return  write_range_iostate(o,c.begin()+from,c.begin()+to,Writer(),multiline,parens,open_paren,close_paren);
}


template <class O>
struct bound_printer
{
    O *po;
    template <class T>
    void operator()(T const& t) const
    {
        *po << t;
    }
};

template <class O>
bound_printer<O>
make_bound_printer(O &o)
{
    bound_printer<O> ret;
    ret.po=&o;
    return ret;
}

template <class W>
struct bound_writer
{
    W const& w;
    bound_writer(W const& w) : w(w) {}
    bound_writer(bound_writer const& o) :w(o.w) {}
    template <class O,class V>
    void operator()(O &o,V const& v) const
    {
        v.print(o,w);
    }
};


template <class W>
bound_writer<W>
make_bound_writer(W const& w)
{
    return bound_writer<W>(w);
}



#endif