1// vi:set ft=cpp: -*- Mode: C++ -*-
2/**
3 * \file
4 * \brief Basic IO stream
5 */
6/*
7 * (c) 2009 Alexander Warg <warg@os.inf.tu-dresden.de>
8 *     economic rights: Technische Universität Dresden (Germany)
9 *
10 * This file is part of TUD:OS and distributed under the terms of the
11 * GNU General Public License 2.
12 * Please see the COPYING-GPL-2 file for details.
13 *
14 * As a special exception, you may use this file as part of a free software
15 * library without restriction.  Specifically, if other files instantiate
16 * templates or use macros or inline functions from this file, or you compile
17 * this file and link it with other files to produce an executable, this
18 * file does not by itself cause the resulting executable to be covered by
19 * the GNU General Public License.  This exception does not however
20 * invalidate any other reasons why the executable file might be covered by
21 * the GNU General Public License.
22 */
23#pragma once
24
25namespace L4 {
26
27  /**
28   * \brief Modifier class for the IO stream.
29   *
30   * An IO Modifier can be used to change properties of an IO stream
31   * for example the number format.
32   */
33  class IOModifier
34  {
35  public:
36    IOModifier(int x) : mod(x) {}
37    bool operator == (IOModifier o) { return mod == o.mod; }
38    bool operator != (IOModifier o) { return mod != o.mod; }
39    int mod;
40  };
41
42  /**
43   * \internal
44   * \brief Backend to write or read stream data.
45   */
46  class IOBackend
47  {
48  public:
49    typedef int Mode;
50
51  protected:
52    friend class BasicOStream;
53
54    IOBackend()
55    : int_mode(10)
56    {}
57
58    virtual ~IOBackend() {}
59
60    virtual void write(char const *str, unsigned len) = 0;
61
62  private:
63    void write(IOModifier m);
64    void write(long long int c, int len);
65    void write(long long unsigned c, int len);
66    void write(long long unsigned c, unsigned char base = 10,
67               unsigned char len = 0, char pad = ' ');
68
69    Mode mode() const
70    { return int_mode; }
71
72    void mode(Mode m)
73    { int_mode = m; }
74
75    int int_mode;
76  };
77
78  /**
79   * \internal
80   * \brief Write-only backend for stream data.
81   */
82  class BasicOStream
83  {
84  public:
85    BasicOStream(IOBackend *b)
86    : iob(b)
87    {}
88
89    void write(char const *str, unsigned len)
90    {
91      if (iob)
92        iob->write(str, len);
93    }
94
95    void write(long long int c, int len)
96    {
97      if (iob)
98        iob->write(c, len);
99    }
100
101    void write(long long unsigned c, unsigned char base = 10,
102               unsigned char len = 0, char pad = ' ')
103    {
104      if (iob)
105        iob->write(c, base, len, pad);
106    }
107
108    void write(long long unsigned c, int len)
109    {
110      if (iob)
111        iob->write(c, len);
112    }
113
114    void write(IOModifier m)
115    {
116      if (iob)
117        iob->write(m);
118    }
119
120    IOBackend::Mode be_mode() const
121    {
122      if (iob)
123        return iob->mode();
124      return 0;
125    }
126
127    void be_mode(IOBackend::Mode m)
128    {
129      if (iob)
130        iob->mode(m);
131    }
132
133  private:
134    IOBackend *iob;
135  };
136
137  /**
138   * \internal
139   * \brief Container class describing a the number format.
140   */
141  class IONumFmt
142  {
143  public:
144    IONumFmt(unsigned long long n, unsigned char base = 10,
145             unsigned char len = 0, char pad = ' ')
146      : n(n), base(base), len(len), pad(pad)
147    {}
148
149  BasicOStream &print(BasicOStream &o) const;
150
151  private:
152    unsigned long long n;
153    unsigned char base, len;
154    char pad;
155  };
156
157  inline IONumFmt n_hex(unsigned long long n) { return IONumFmt(n, 16); }
158
159  /**
160   * \brief Modifies the stream to print numbers as hexadecimal values.
161   */
162  extern IOModifier const hex;
163
164  /**
165   * \brief Modifies the stream to print numbers as decimal values.
166   */
167  extern IOModifier const dec;
168
169  inline
170  BasicOStream &IONumFmt::print(BasicOStream &o) const
171  {
172    o.write(n, base, len, pad);
173    return o;
174  }
175}
176
177
178// Implementation
179
180inline
181L4::BasicOStream &
182operator << (L4::BasicOStream &s, char const * const str)
183{
184  if (!str)
185    {
186      s.write("(NULL)", 6);
187      return s;
188    }
189
190  unsigned l = 0;
191  for (; str[l] != 0; l++)
192    ;
193  s.write(str, l);
194  return s;
195}
196
197inline
198L4::BasicOStream &
199operator << (L4::BasicOStream &s, signed short u)
200{
201  s.write((long long signed)u, -1);
202  return s;
203}
204
205inline
206L4::BasicOStream &
207operator << (L4::BasicOStream &s, signed u)
208{
209  s.write((long long signed)u, -1);
210  return s;
211}
212
213inline
214L4::BasicOStream &
215operator << (L4::BasicOStream &s, signed long u)
216{
217  s.write((long long signed)u, -1);
218  return s;
219}
220
221inline
222L4::BasicOStream &
223operator << (L4::BasicOStream &s, signed long long u)
224{
225  s.write(u, -1);
226  return s;
227}
228
229inline
230L4::BasicOStream &
231operator << (L4::BasicOStream &s, unsigned short u)
232{
233  s.write((long long unsigned)u, -1);
234  return s;
235}
236
237inline
238L4::BasicOStream &
239operator << (L4::BasicOStream &s, unsigned u)
240{
241  s.write((long long unsigned)u, -1);
242  return s;
243}
244
245inline
246L4::BasicOStream &
247operator << (L4::BasicOStream &s, unsigned long u)
248{
249  s.write((long long unsigned)u, -1);
250  return s;
251}
252
253inline
254L4::BasicOStream &
255operator << (L4::BasicOStream &s, unsigned long long u)
256{
257  s.write(u, -1);
258  return s;
259}
260
261inline
262L4::BasicOStream &
263operator << (L4::BasicOStream &s, void const *u)
264{
265  long unsigned x = (long unsigned)u;
266  L4::IOBackend::Mode mode = s.be_mode();
267  s.write(L4::hex);
268  s.write((long long unsigned)x, -1);
269  s.be_mode(mode);
270  return s;
271}
272
273inline
274L4::BasicOStream &
275operator << (L4::BasicOStream &s, L4::IOModifier m)
276{
277  s.write(m);
278  return s;
279}
280
281inline
282L4::BasicOStream &
283operator << (L4::BasicOStream &s, char c)
284{
285  s.write(&c, 1);
286  return s;
287}
288
289inline
290L4::BasicOStream &
291operator << (L4::BasicOStream &o, L4::IONumFmt const &n)
292{ return n.print(o); }
293