SGL
echoinputstreambuf.h
1 /*
2  * File: echoinputstreambuf.h
3  * --------------------------
4  * This file defines the <code>EchoInputStreambuf</code> class, which
5  * represents a stream buffer that echoes to stdout any user input.
6  * We mostly use this to display console input when redirecting in from a file.
7  *
8  * @version 2016/10/30
9  * - added constructor that takes a string of input
10  * @version 2016/10/04
11  * - initial version
12  */
13 
14 #ifndef _echoinputstreambuf_h
15 #define _echoinputstreambuf_h
16 
17 #include <iostream>
18 #include <sstream>
19 #include <streambuf>
20 
21 namespace sgl {
22 
23 /*
24  * An input stream buffer that echoes characters as they are read.
25  * Used to echo cin console input for capturing for test case diffing
26  * when fixed input has been fed to cin by autograders.
27  *
28  * inspired by: http://gabisoft.free.fr/articles/fltrsbf1.html
29  */
30 class EchoInputStreambuf : public std::streambuf {
31 public:
32  EchoInputStreambuf(std::streambuf* source) : m_source(source), m_buffer('\0') {
33  // empty
34  }
35 
36  EchoInputStreambuf(const string& input) : m_buffer('\0') {
37  std::istringstream* istream = new std::istringstream(input);
38  m_source = istream->rdbuf();
39  }
40 
41  virtual ~EchoInputStreambuf() {
42  sync();
43  }
44 
45  virtual int overflow(int) {
46  return EOF;
47  }
48 
49  /*
50  * This is the crucial function; called to read a character from the
51  * underlying stream buffer (cin). We capture it in a one-char m_buffer
52  * so we can return it later.
53  */
54  virtual int underflow() {
55  int result(EOF);
56  if (gptr() < egptr()) {
57  result = *gptr();
58  } else {
59  result = m_source->sbumpc();
60  if (result != EOF) {
61  m_buffer = result;
62  setg(&m_buffer, &m_buffer, &m_buffer + 1);
63 
64  // echo the character to stdout
65  std::cout.put(result);
66  std::cout.flush();
67  }
68  }
69  return result;
70  }
71 
72  virtual int sync() {
73  int result(0);
74  if (gptr() < egptr()) {
75  result = m_source->sputbackc(*gptr());
76  setg(nullptr, nullptr, nullptr);
77  }
78  if (m_source->pubsync() == EOF) {
79  result = EOF;
80  }
81  return result;
82  }
83 
84  virtual std::streambuf* setbuf(char* p, std::streamsize len) {
85  return m_source->pubsetbuf(p, len);
86  }
87 
88 private:
89  std::streambuf* m_source;
90  char m_buffer;
91 };
92 
93 } // namespace sgl
94 
95 #endif // _echoinputstreambuf_h
Definition: console.h:293