Skip to content

Commit 6fbc24f

Browse files
authored
Term:cout clog cerr cin (#271)
Term::cout Term::clog Term::cin Term::clog
1 parent ee8ebc1 commit 6fbc24f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+870
-446
lines changed

cpp-terminal/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ configure_file(version.cpp.in version.cpp)
44
add_subdirectory(platforms)
55

66
# create and configure library target
7-
add_library(cpp-terminal prompt.cpp window.cpp input.cpp terminal.cpp color.cpp key.cpp event.cpp screen.cpp options.cpp cursor.cpp style.cpp io.cpp "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
7+
add_library(cpp-terminal buffer.cpp iostream.cpp stream.cpp prompt.cpp window.cpp input.cpp terminal.cpp color.cpp key.cpp event.cpp screen.cpp options.cpp cursor.cpp style.cpp "${CMAKE_CURRENT_BINARY_DIR}/version.cpp")
88
target_link_libraries(cpp-terminal PRIVATE Warnings::Warnings cpp-terminal::cpp-terminal-platforms)
99
target_compile_options(cpp-terminal PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/utf-8>)
1010
target_include_directories(cpp-terminal PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}> $<INSTALL_INTERFACE:include>)

cpp-terminal/buffer.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#include "cpp-terminal/buffer.hpp"
2+
3+
#include "cpp-terminal/options.hpp"
4+
#include "cpp-terminal/platforms/file.hpp"
5+
#include "cpp-terminal/terminal.hpp"
6+
7+
static std::string remplace(const Term::Buffer::int_type& c)
8+
{
9+
#if defined(_WIN32)
10+
std::string ret;
11+
if(static_cast<char>(c) == '\n') ret = "\r\n";
12+
else
13+
ret.push_back(static_cast<char>(c));
14+
return ret;
15+
#else
16+
std::string ret;
17+
ret.push_back(static_cast<char>(c));
18+
return ret;
19+
#endif
20+
}
21+
22+
static bool newline_sequence(const std::string& str) //https://en.wikipedia.org/wiki/Newline
23+
{
24+
if(str.back() == '\n' || str.back() == '\r' || str.back() == '\036' || str.back() == '\036' || str.back() == '\025') return true;
25+
else
26+
return false;
27+
}
28+
29+
int Term::Buffer::sync()
30+
{
31+
int ret = Term::Private::out.write(m_buffer);
32+
m_buffer.clear();
33+
return ret;
34+
}
35+
36+
Term::Buffer::Buffer(const Term::Buffer::Type& type, const std::streamsize& size)
37+
{
38+
setType(type);
39+
switch(m_type)
40+
{
41+
case Type::Unbuffered: setbuf(nullptr, 0); break;
42+
case Type::LineBuffered:
43+
case Type::FullBuffered: setbuf(&m_buffer[0], size); break;
44+
}
45+
}
46+
47+
void Term::Buffer::setType(const Term::Buffer::Type& type) { m_type = type; }
48+
49+
std::streambuf* Term::Buffer::setbuf(char* s, std::streamsize n)
50+
{
51+
if(s != nullptr) m_buffer.reserve(n);
52+
return this;
53+
}
54+
55+
Term::Buffer::int_type Term::Buffer::underflow()
56+
{
57+
try
58+
{
59+
//TODO Maybe use input function ?
60+
m_buffer.clear();
61+
if(terminal.getOptions().has(Option::Raw))
62+
{
63+
do {
64+
std::string ret{Term::Private::in.read()};
65+
if(!ret.empty())
66+
{
67+
if(ret[0] == '\x7f' || ret[0] == '\b')
68+
{
69+
Term::Private::out.write("\b \b"); //Backspace is DEL, CTRL+Backspace is Backspace '\b'
70+
if(!m_buffer.empty()) m_buffer.erase(m_buffer.size() - 1);
71+
}
72+
else if(ret[0] == '\033')
73+
{
74+
continue; // For now if it's escape sequence do nothing
75+
}
76+
else if(ret[0] <= 31 && ret[0] != '\t' && ret[0] != '\b' && ret[0] != 127 && ret[0] != ' ' && ret[0] != '\n' && ret[0] != '\r') { continue; }
77+
else
78+
{
79+
Term::Private::out.write(ret);
80+
m_buffer += ret;
81+
}
82+
}
83+
} while(m_buffer.empty() || !newline_sequence(m_buffer));
84+
Term::Private::out.write('\n');
85+
}
86+
else
87+
{
88+
do {
89+
std::string ret{Term::Private::in.read()};
90+
m_buffer += ret;
91+
} while(m_buffer.empty());
92+
}
93+
setg(&m_buffer[0], &m_buffer[0], &m_buffer[0] + m_buffer.size());
94+
return traits_type::to_int_type(m_buffer.at(0));
95+
}
96+
catch(...)
97+
{
98+
return traits_type::eof();
99+
}
100+
}
101+
102+
Term::Buffer::int_type Term::Buffer::overflow(int c)
103+
{
104+
if(c != std::char_traits<Term::Buffer::char_type>::eof())
105+
{
106+
switch(m_type)
107+
{
108+
case Type::Unbuffered:
109+
{
110+
Term::Private::out.write(remplace(c));
111+
break;
112+
}
113+
case Type::LineBuffered:
114+
{
115+
m_buffer += remplace(c);
116+
if(static_cast<char>(c) == '\n')
117+
{
118+
Term::Private::out.write(m_buffer);
119+
m_buffer.clear();
120+
}
121+
break;
122+
}
123+
case Type::FullBuffered:
124+
{
125+
if(m_buffer.size() >= m_buffer.capacity())
126+
{
127+
Term::Private::out.write(m_buffer);
128+
m_buffer.clear();
129+
}
130+
m_buffer += remplace(c);
131+
break;
132+
}
133+
}
134+
}
135+
return c;
136+
}

cpp-terminal/buffer.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include <cstdint>
5+
#include <streambuf>
6+
7+
namespace Term
8+
{
9+
10+
class Buffer : public std::streambuf
11+
{
12+
public:
13+
enum class Type : std::uint8_t
14+
{
15+
Unbuffered,
16+
LineBuffered,
17+
FullBuffered,
18+
};
19+
explicit Buffer(const Term::Buffer::Type& type = Term::Buffer::Type::LineBuffered, const std::streamsize& size = BUFSIZ);
20+
virtual ~Buffer() = default;
21+
22+
protected:
23+
virtual Term::Buffer::int_type underflow() final;
24+
virtual Term::Buffer::int_type overflow(int c = std::char_traits<Term::Buffer::char_type>::eof());
25+
virtual int sync() final;
26+
27+
private:
28+
void setType(const Term::Buffer::Type& type);
29+
std::streambuf* setbuf(char* s, std::streamsize n) final;
30+
std::string m_buffer;
31+
Term::Buffer::Type m_type{Term::Buffer::Type::LineBuffered};
32+
};
33+
34+
} // namespace Term

cpp-terminal/io.cpp

Lines changed: 0 additions & 23 deletions
This file was deleted.

cpp-terminal/io.hpp

Lines changed: 0 additions & 21 deletions
This file was deleted.

cpp-terminal/iostream.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "cpp-terminal/iostream.hpp"
2+
3+
#include <iostream>
4+
#include <new>
5+
6+
namespace Term
7+
{
8+
// Output
9+
static char coutBuf[sizeof(Term::TOstream)];
10+
TOstream& cout = reinterpret_cast<Term::TOstream&>(coutBuf);
11+
static char cerrBuf[sizeof(Term::TOstream)];
12+
TOstream& cerr = reinterpret_cast<Term::TOstream&>(cerrBuf);
13+
static char clogBuf[sizeof(Term::TOstream)];
14+
TOstream& clog = reinterpret_cast<Term::TOstream&>(clogBuf);
15+
// Input
16+
static char cinBuf[sizeof(Term::TIstream)];
17+
TIstream& cin = reinterpret_cast<Term::TIstream&>(cinBuf);
18+
} // namespace Term */
19+
20+
int Term::StreamInitializer::m_counter{0};
21+
22+
void Term::StreamInitializer::init()
23+
{
24+
if(m_counter++ == 0)
25+
{
26+
std::ios_base::Init();
27+
new(&Term::cout) TOstream(Term::Buffer::Type::FullBuffered, BUFSIZ);
28+
new(&Term::clog) TOstream(Term::Buffer::Type::LineBuffered, BUFSIZ);
29+
new(&Term::cerr) TOstream(Term::Buffer::Type::Unbuffered, 0);
30+
new(&Term::cin) TIstream(Term::Buffer::Type::FullBuffered, BUFSIZ);
31+
std::cin.rdbuf(Term::cin.rdbuf());
32+
}
33+
}
34+
35+
Term::StreamInitializer::StreamInitializer() { init(); }
36+
37+
Term::StreamInitializer::~StreamInitializer()
38+
{
39+
if(--m_counter == 0)
40+
{
41+
(&Term::cout)->~TOstream();
42+
(&Term::cerr)->~TOstream();
43+
(&Term::clog)->~TOstream();
44+
(&Term::cin)->~TIstream();
45+
}
46+
}

cpp-terminal/iostream.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
3+
#include "cpp-terminal/stream.hpp"
4+
5+
namespace Term
6+
{
7+
8+
extern TIstream& cin;
9+
extern TOstream& cout;
10+
extern TOstream& cerr;
11+
extern TOstream& clog;
12+
13+
class StreamInitializer
14+
{
15+
public:
16+
StreamInitializer();
17+
static void init();
18+
~StreamInitializer();
19+
StreamInitializer(const StreamInitializer&) = delete;
20+
StreamInitializer& operator=(const StreamInitializer&) = delete;
21+
StreamInitializer(StreamInitializer&&) = delete;
22+
StreamInitializer& operator=(StreamInitializer&&) = delete;
23+
24+
private:
25+
static int m_counter;
26+
};
27+
28+
static StreamInitializer m_streams;
29+
30+
} // namespace Term

cpp-terminal/platforms/cursor.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
#include "cpp-terminal/cursor.hpp"
22

33
#if defined(_WIN32)
4-
#include "cpp-terminal/platforms/file.hpp"
54
#include "windows.h"
65
#else
76
#include "cpp-terminal/input.hpp"
8-
#include "cpp-terminal/terminal.hpp"
97
#endif
108

9+
#include "cpp-terminal/platforms/file.hpp"
10+
1111
Term::Cursor Term::cursor_position()
1212
{
1313
#if defined(_WIN32)
1414
CONSOLE_SCREEN_BUFFER_INFO inf;
15-
if(GetConsoleScreenBufferInfo(Private::std_cout.getHandler(), &inf)) return Term::Cursor(inf.dwCursorPosition.Y + 1, inf.dwCursorPosition.X + 1);
15+
if(GetConsoleScreenBufferInfo(Private::out.handle(), &inf)) return Term::Cursor(inf.dwCursorPosition.Y + 1, inf.dwCursorPosition.X + 1);
1616
else
1717
return Term::Cursor(0, 0);
1818
#else
19-
Term::terminal << Term::cursor_position_report();
19+
Term::Private::out.write(Term::cursor_position_report());
2020
Term::Cursor c;
2121
while((c = Platform::read_raw()).empty()) continue;
2222
return c;

0 commit comments

Comments
 (0)