SGL
consolestreambuf.h
1 /*
2  * File: consolestreambuf.h
3  * ------------------------
4  * This file defines the <code>ConsoleStreambuf</code> class, which
5  * represents a stream buffer that reads/writes to the graphical console
6  * using a process pipe to a Java back-end process.
7  *
8  * @version 2021/04/03
9  * - removed dependency on error function
10  * @version 2016/10/04
11  * - initial version
12  */
13 
14 #ifndef _consolestreambuf_h
15 #define _consolestreambuf_h
16 
17 #include <exception>
18 #include <iostream>
19 #include <stdexcept>
20 #include <streambuf>
21 
22 namespace sgl {
23 
24 class ConsoleStreambuf : public std::streambuf {
25 protected:
26  /* Constants */
27  static const int BUFFER_SIZE = 4096;
28 
29  /* Instance variables */
30  char inBuffer[BUFFER_SIZE];
31  char outBuffer[BUFFER_SIZE];
32  int blocked;
33 
34  // to be overridden in subclasses
35  virtual void myEndLineConsole(bool isStderr) = 0;
36 
37  virtual string myGetLineConsole() = 0;
38 
39  virtual void myPutConsole(const string& str, bool isStderr) = 0;
40 
41 public:
42  ConsoleStreambuf() {
43  setg(inBuffer, inBuffer, inBuffer);
44  setp(outBuffer, outBuffer + BUFFER_SIZE);
45  blocked = 0;
46  }
47 
48  ~ConsoleStreambuf() {
49  /* Empty */
50  }
51 
52  virtual bool isBlocked() {
53  return blocked > 0;
54  }
55 
56  virtual int overflow(int ch = EOF) {
57  return overflow(ch, /* isStderr */ false);
58  }
59 
60  virtual int overflow(int ch, bool isStderr) {
61  string line = "";
62  for (char *cp = pbase(); cp < pptr(); cp++) {
63  if (*cp == '\n') {
64  myPutConsole(line, isStderr);
65  myEndLineConsole(isStderr);
66  line = "";
67  } else {
68  line += *cp;
69  }
70  }
71  if (line != "") {
72  myPutConsole(line, isStderr);
73  }
74  setp(outBuffer, outBuffer + BUFFER_SIZE);
75  if (ch != EOF) {
76  outBuffer[0] = ch;
77  pbump(1);
78  }
79  return ch != EOF;
80  }
81 
82  virtual int sync() {
83  return overflow();
84  }
85 
86  virtual int sync(bool isStderr) {
87  return overflow(EOF, isStderr);
88  }
89 
90  virtual int underflow() {
91  // Allow long strings at some point
92  blocked++;
93  string line = myGetLineConsole();
94  blocked--;
95 
96  bool eof = std::cin.eof();
97  fflush(stdout);
98 
99  if (eof) {
100  return EOF;
101  }
102 
103  int n = line.length();
104  if (n + 1 >= BUFFER_SIZE) {
105  throw std::runtime_error("ConsoleStreambuf::underflow: String too long");
106  }
107  for (int i = 0; i < n; i++) {
108  inBuffer[i] = line[i];
109  }
110  inBuffer[n++] = '\n';
111  inBuffer[n] = '\0';
112  setg(inBuffer, inBuffer, inBuffer + n);
113  return inBuffer[0];
114  }
115 };
116 
117 extern void endLineConsoleQt(bool isStderr);
118 extern string getLineConsoleQt();
119 extern void putConsoleQt(const string& str, bool isStderr);
120 
121 /*
122  * The following class is an exact copy of the ConsoleStreambuf class above,
123  * except using different Qt-related functions for output.
124  */
125 class ConsoleStreambufQt : public ::sgl::ConsoleStreambuf {
126 public:
127  ConsoleStreambufQt(bool isStderr = false)
128  : ConsoleStreambuf(),
129  _isStderr(isStderr) {
130  // empty
131  }
132 
133  ~ConsoleStreambufQt() {
134  /* Empty */
135  }
136 
137 protected:
138  virtual void myEndLineConsole(bool /* isStderr */) {
139  endLineConsoleQt(_isStderr);
140  }
141 
142  virtual string myGetLineConsole() {
143  return getLineConsoleQt();
144  }
145 
146  virtual void myPutConsole(const string& str, bool /* isStderr */) {
147  return putConsoleQt(str, _isStderr);
148  }
149 
150 private:
151  bool _isStderr;
152 };
153 
154 } // namespace sgl
155 
156 #endif // _consolestreambuf_h
void endLineConsoleQt(bool isStderr)
Definition: gconsolewindow.cpp:1441
string getLineConsoleQt()
Definition: gconsolewindow.cpp:1445
Definition: console.h:45
void putConsoleQt(string str, bool isStderr)
Definition: gconsolewindow.cpp:1449