summaryrefslogtreecommitdiff
path: root/TAO/CIAO/CCF/CCF/CodeGenerationKit/IndentationImplanter.hpp
blob: 8dfc4093bdbd3ed840eb408bde73fa0072a61edd (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
// file      : CCF/CodeGenerationKit/IndentationImplanter.hpp
// author    : Boris Kolpackov <boris@dre.vanderbilt.edu>
// cvs-id    : $Id$

#ifndef CCF_CODE_GENERATION_KIT_INDENTATION_IMPLANTER
#define CCF_CODE_GENERATION_KIT_INDENTATION_IMPLANTER

#include <ostream>

#include "CCF/CodeGenerationKit/IndentationBuffer.hpp"

namespace Indentation
{
  class ToStreamBufAdapter : public std::streambuf
  {
  public:
    ToStreamBufAdapter (Buffer& buffer)
        : buffer_ (buffer)
    {
    }

    virtual int_type
    overflow (int_type c)
    {
      return buffer_.put (Buffer::traits_type::to_char_type (c));
    }

    virtual int
    sync ()
    {
      return 0;
    }

  private:
    Buffer& buffer_;
  };

  class FromStreamBufAdapter : public Buffer
  {
  public:
    FromStreamBufAdapter (std::streambuf& buffer)
        : buffer_ (buffer)
    {
    }

    virtual int_type
    put (char_type c) throw (Exception, ExH::System::Exception)
    {
      return buffer_.sputc (traits_type::to_int_type (c));
    }

    virtual void
    unbuffer () throw (ExH::System::Exception)
    {
      try
      {
        if (buffer_.pubsync () == 0) return;
      }
      catch (std::ios_base::failure const&)
      {
      }

      throw Exception ("underlying std::streambuf::sync failed");
    }

  private:
    std::streambuf& buffer_;
  };

  template <typename Buffer>
  class Implanter
  {
  public:
    Implanter (std::ostream& os)
        : os_ (os),
          prev_ (os_.rdbuf ()),
          from_adapter_ (*prev_),
          buffer_ (from_adapter_),
          to_adapter_ (buffer_)
    {
      os_.rdbuf (&to_adapter_);
    }

    template <typename Arg0>
    Implanter (std::ostream& os, Arg0 a0)
        : os_ (os),
          prev_ (os_.rdbuf ()),
          from_adapter_ (*prev_),
          buffer_ (from_adapter_, a0),
          to_adapter_ (buffer_)
    {
      os_.rdbuf (&to_adapter_);
    }

    ~Implanter ()
    {
      try
      {
        buffer_.unbuffer ();
      }
      catch (...)
      {
        // there is nothing I can do...
      }

      os_.rdbuf (prev_);
    }

  private:
    std::ostream& os_;
    std::streambuf* prev_;

    FromStreamBufAdapter from_adapter_;

    Buffer buffer_;

    ToStreamBufAdapter to_adapter_;
  };
}

#endif // CCF_CODE_GENERATION_KIT_INDENTATION_IMPLANTER