summaryrefslogtreecommitdiff
path: root/Source/Core/OOLongUtil.cs
blob: 767b64a1ef91231505bb41d733e9299a93f5b6a1 (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics.Contracts;

namespace Boogie.Util {
  public class TeeWriter : TextWriter {
    readonly TextWriter/*!*/ a;
    readonly TextWriter/*!*/ b;
    [ContractInvariantMethod]
    void ObjectInvariant() {
      Contract.Invariant(a != null);
      Contract.Invariant(b != null);
    }


    public TeeWriter(TextWriter a, TextWriter b) {
      Contract.Requires(b != null);
      Contract.Requires(a != null);
      this.a = a;
      this.b = b;
    }

    public override System.Text.Encoding Encoding {
      get {
        return a.Encoding;
      }
    }

    public override void Close() {
      a.Close();
      b.Close();
    }

    public override void Flush() {
      a.Flush();
      b.Flush();
    }

    [Pure]
    public override string ToString() {
      Contract.Ensures(Contract.Result<string>() != null);
      return "<TeeWriter: " + a.ToString() + ", " + b.ToString() + ">";
    }

    public override void Write(char ch) {
      a.Write(ch);
      b.Write(ch);
    }

    public override void Write(string s) {
      a.Write(s);
      b.Write(s);
    }
  }

  /// <summary>
  /// A LineReader is a class that allows further subclasses to just override the ReadLine() method.
  /// It simply reads from the given "reader".
  /// </summary>
  public class LineReader : TextReader {
    [Rep]
    readonly TextReader/*!*/ reader;
    [ContractInvariantMethod]
    void ObjectInvariant() {
      Contract.Invariant(reader != null);
      Contract.Invariant(readAhead == null || (0 <= readAheadConsumed && readAheadConsumed < readAhead.Length));
    }

    string readAhead;
    int readAheadConsumed;


    public LineReader([Captured] TextReader reader) {
      Contract.Requires(reader != null);
      this.reader = reader;
    }
    public override void Close() {
      cce.BeginExpose(this);
      {
        reader.Close();
      }
      cce.EndExpose();
    }
    public override int Read() {
      cce.BeginExpose(this);
      try {
        while (readAhead == null) {
          readAhead = reader.ReadLine();
          if (readAhead == null) {
            // we're at EOF
            return -1;
          } else if (readAhead.Length > 0) {
            readAheadConsumed = 0;
            break;
          }
        }
        int res = readAhead[readAheadConsumed++];
        if (readAheadConsumed == readAhead.Length) {
          readAhead = null;
        }
        return res;
      } finally {
        cce.EndExpose();
      }
    }
    public override int Read(char[] buffer, int index, int count) {
      
      int n = 0;
      for (; n < count; n++) {
        int ch = Read();
        if (ch == -1) {
          break;
        }
        buffer[index + n] = (char)ch;
      }
      return n;
    }
    public override string ReadLine() {
      string res;
      if (readAhead != null) {
        cce.BeginExpose(this);
        {
          res = readAhead.Substring(readAheadConsumed);
          readAhead = null;
        }
        cce.EndExpose();
      } else {
        res = reader.ReadLine();
      }
      return res;
    }
  }

  public class IfdefReader : LineReader {
    [Rep]
    readonly List<string/*!*/>/*!*/ defines;
    [Rep]
    readonly List<bool>/*!*/ readState = new List<bool>();
    int ignoreCutoff = 0;  // 0 means we're not ignoring
    [ContractInvariantMethod]
    void ObjectInvariant() {
      Contract.Invariant(readState != null);
      Contract.Invariant(cce.NonNullElements(defines));
      Contract.Invariant(0 <= ignoreCutoff && ignoreCutoff <= readState.Count);
    }



    public IfdefReader([Captured] TextReader reader, [Captured] List<string/*!*/>/*!*/ defines)
      : base(reader) {
      Contract.Requires(reader != null);
      Contract.Requires(cce.NonNullElements(defines));
      this.defines = defines;
    }

    public override string ReadLine() {
      while (true) {
        string s = base.ReadLine();
        if (s == null) {
          return s;
        }
        string t = s.Trim();
        if (t.StartsWith("#if")) {
          string arg = t.Substring(3).TrimStart();
          bool sense = true;
          while (t.StartsWith("!")) {
            sense = !sense;
            t = t.Substring(1).TrimStart();
          }
          // push "true", since we're in a "then" branch
          readState.Add(true);
          if (ignoreCutoff == 0 && defines.Contains(arg) != sense) {
            ignoreCutoff = readState.Count;  // start ignoring
          }
        } else if (t == "#else") {
          if (readState.Count == 0 || !readState[readState.Count - 1]) {
            return s;  // malformed input; return the read line as if it were not special
          }
          // change the "true" to a "false" on top of the state, since we're now going into the "else" branch
          readState[readState.Count - 1] = false;
          if (ignoreCutoff == 0) {
            // the "then" branch had been included, so we'll ignore the "else" branch
            ignoreCutoff = readState.Count;
          } else if (ignoreCutoff == readState.Count) {
            // we had ignored the "then" branch, so we'll include the "else" branch
            ignoreCutoff = 0;
          }
        } else if (t == "#endif") {
          if (readState.Count == 0) {
            return s;  // malformed input; return the read line as if it were not special
          }
          if (ignoreCutoff == readState.Count) {
            // we had ignored the branch that ends here; so, now we start including again
            ignoreCutoff = 0;
          }
          // pop
          readState.RemoveAt(readState.Count - 1);
        } else if (ignoreCutoff == 0) {
          return s;
        }
      }
    }
  }
}