aboutsummaryrefslogtreecommitdiff
path: root/odb/relational/schema-source.hxx
blob: 74fdd00d68953b98c8e682caa7922ff2159fad15 (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
// file      : odb/relational/schema-source.hxx
// copyright : Copyright (c) 2009-2017 Code Synthesis Tools CC
// license   : GNU GPL v3; see accompanying LICENSE file

#ifndef ODB_RELATIONAL_SCHEMA_SOURCE_HXX
#define ODB_RELATIONAL_SCHEMA_SOURCE_HXX

#include <odb/diagnostics.hxx>

#include <odb/emitter.hxx>
#include <odb/relational/context.hxx>
#include <odb/relational/schema.hxx>

namespace relational
{
  namespace schema
  {
    struct cxx_emitter: emitter, virtual context
    {
      typedef cxx_emitter base;

      void
      pass (unsigned short p)
      {
        empty_ = true;
        pass_ = p;
        new_pass_ = true;

        if (pass_ == 1)
          empty_passes_ = 0; // New set of passes.

        // Assume this pass is empty.
        //
        empty_passes_++;
      }

      // Did this pass produce anything?
      //
      bool
      empty () const
      {
        return empty_;
      }

      virtual void
      pre ()
      {
        first_ = true;
      }

      virtual void
      line (const string& l)
      {
        if (l.empty ())
          return; // Ignore empty lines.

        if (first_)
        {
          first_ = false;

          // If this line starts a new pass, then output the switch/case
          // blocks.
          //
          if (new_pass_)
          {
            new_pass_ = false;
            empty_ = false;
            empty_passes_--; // This pass is not empty.

            // Output case statements for empty preceeding passes, if any.
            //
            if (empty_passes_ != 0)
            {
              unsigned short s (pass_ - empty_passes_);

              if (s == 1)
                os << "switch (pass)"
                   << "{";
              else
                os << "return true;" // One more pass.
                   << "}";

              for (; s != pass_; ++s)
                os << "case " << s << ":" << endl;

              os << "{";
              empty_passes_ = 0;
            }

            if (pass_ == 1)
              os << "switch (pass)"
                 << "{";
            else
              os << "return true;" // One more pass.
                 << "}";

            os << "case " << pass_ << ":" << endl
               << "{";
          }

          os << "db.execute (";
        }
        else
          os << strlit (line_ + '\n') << endl;

        line_ = l;
      }

      virtual void
      post ()
      {
        if (!first_) // Ignore empty statements.
          os << strlit (line_) << ");";
      }

    private:
      std::string line_;
      bool first_;
      bool empty_;
      bool new_pass_;
      unsigned short pass_;
      unsigned short empty_passes_; // Number of preceding empty passes.
    };
  }
}

#endif // ODB_RELATIONAL_SCHEMA_SOURCE_HXX