-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
392 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "cpp-terminal/args.hpp" | ||
namespace Term | ||
{ | ||
|
||
Term::Argc::Argc() {} | ||
|
||
Term::Argc::operator long unsigned int() { return static_cast<int>(Term::Arguments::argc()); } | ||
|
||
Term::Argc::operator long unsigned int() const { return static_cast<int>(Term::Arguments::argc()); } | ||
|
||
Term::Arguments::Arguments() {} | ||
|
||
std::string Term::Arguments::operator[](const std::size_t& i) const { return m_args[i]; } | ||
|
||
} // namespace Term |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
namespace Term | ||
{ | ||
|
||
class Arguments | ||
{ | ||
public: | ||
Arguments(); | ||
static std::size_t argc(); | ||
static std::vector<std::string> argv(); | ||
std::string operator[](const std::size_t&) const; | ||
|
||
private: | ||
static void parse(); | ||
static std::vector<std::string> m_args; | ||
static bool m_parsed; | ||
}; | ||
|
||
class Argc | ||
{ | ||
public: | ||
Argc(); | ||
operator long unsigned int(); | ||
operator long unsigned int() const; | ||
}; | ||
|
||
static const Arguments argv; | ||
static const Argc argc; | ||
|
||
} // namespace Term |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ class Color | |
Bit3, | ||
Bit4, | ||
Bit8, | ||
Bit24, | ||
Bit24 | ||
}; | ||
/* | ||
* The 3bit/4bit colors for the terminal | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#include "cpp-terminal/args.hpp" | ||
|
||
#include "cpp-terminal/platforms/conversion.hpp" | ||
|
||
#if defined(_WIN32) | ||
#include <memory> | ||
// clang-format off | ||
#include <windows.h> | ||
#include <processenv.h> | ||
// clang-format on | ||
#elif defined(__APPLE__) | ||
#include <crt_externs.h> | ||
#else | ||
#include <algorithm> | ||
#include <fstream> | ||
#include <limits> | ||
#endif | ||
|
||
void Term::Arguments::parse() | ||
{ | ||
if(m_parsed == true) return; | ||
#if defined(_WIN32) | ||
int argc{0}; | ||
std::unique_ptr<LPWSTR[], void (*)(wchar_t**)> wargv = std::unique_ptr<LPWSTR[], void (*)(wchar_t**)>(CommandLineToArgvW(GetCommandLineW(), &argc), [](wchar_t** ptr) { LocalFree(ptr); }); | ||
if(wargv == nullptr) | ||
{ | ||
m_parsed = false; | ||
return; | ||
} | ||
else | ||
{ | ||
m_args.reserve(static_cast<std::size_t>(argc)); | ||
for(std::size_t i = 0; i != static_cast<std::size_t>(argc); ++i) { m_args.push_back(Term::Private::to_utf8(&wargv.get()[i][0])); } | ||
m_parsed = true; | ||
} | ||
#elif defined(__APPLE__) | ||
int argc{*_NSGetArgc()}; | ||
m_args.reserve(argc); | ||
char** argv{*_NSGetArgv()}; | ||
for(std::size_t i = 0; i != argc; ++i) { m_args.push_back(argv[i]); } | ||
m_parsed = true; | ||
#else | ||
std::string cmdline; | ||
std::fstream fs; | ||
std::fstream::iostate old_iostate{fs.exceptions()}; | ||
try | ||
{ | ||
fs.exceptions(std::ifstream::failbit | std::ifstream::badbit); | ||
fs.open("/proc/self/cmdline", std::fstream::in | std::fstream::binary); | ||
fs.ignore(std::numeric_limits<std::streamsize>::max()); | ||
cmdline.resize(fs.gcount()); | ||
fs.seekg(0, std::ios_base::beg); | ||
fs.get(&cmdline[0], cmdline.size()); | ||
fs.exceptions(old_iostate); | ||
if(fs.is_open()) fs.close(); | ||
const std::size_t argc = static_cast<std::size_t>(std::count(cmdline.begin(), cmdline.end(), '\0')); | ||
m_args.reserve(argc); | ||
for(std::string::iterator it = cmdline.begin(); it != cmdline.end(); it = std::find(it, cmdline.end(), '\0') + 1) { m_args.push_back(cmdline.data() + (it - cmdline.begin())); } | ||
m_parsed = true; | ||
} | ||
catch(...) | ||
{ | ||
fs.exceptions(old_iostate); | ||
if(fs.is_open()) fs.close(); | ||
m_parsed = false; | ||
m_args.clear(); | ||
m_parsed = false; | ||
} | ||
#endif | ||
} | ||
|
||
std::size_t Term::Arguments::argc() | ||
{ | ||
parse(); | ||
return m_args.size(); | ||
} | ||
|
||
std::vector<std::string> Term::Arguments::argv() | ||
{ | ||
parse(); | ||
return m_args; | ||
} | ||
|
||
bool Term::Arguments::m_parsed = false; | ||
|
||
std::vector<std::string> Term::Arguments::m_args = std::vector<std::string>(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#include "cpp-terminal/platforms/conversion.hpp" | ||
|
||
#include "cpp-terminal/exception.hpp" | ||
|
||
#if defined(_WIN32) | ||
#include <windows.h> | ||
#endif | ||
|
||
namespace Term | ||
{ | ||
namespace Private | ||
{ | ||
|
||
#if defined(_WIN32) | ||
std::string to_utf8(LPCWCH utf16Str) | ||
{ | ||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, utf16Str, -1, nullptr, 0, nullptr, nullptr); | ||
std::string ret(size_needed, '\0'); | ||
WideCharToMultiByte(CP_UTF8, 0, utf16Str, wcslen(utf16Str), &ret[0], size_needed, nullptr, nullptr); | ||
return ret.c_str(); | ||
} | ||
#endif | ||
|
||
static constexpr std::uint8_t UTF8_ACCEPT = 0; | ||
static constexpr std::uint8_t UTF8_REJECT = 0xf; | ||
|
||
std::uint8_t utf8_decode_step(std::uint8_t state, std::uint8_t octet, std::uint32_t* cpp) | ||
{ | ||
static const std::uint32_t utf8ClassTab[0x10] = { | ||
0x88888888UL, 0x88888888UL, 0x99999999UL, 0x99999999UL, 0xaaaaaaaaUL, 0xaaaaaaaaUL, 0xaaaaaaaaUL, 0xaaaaaaaaUL, 0x222222ffUL, 0x22222222UL, 0x22222222UL, 0x22222222UL, 0x3333333bUL, 0x33433333UL, 0xfff5666cUL, 0xffffffffUL, | ||
}; | ||
|
||
static const std::uint32_t utf8StateTab[0x10] = { | ||
0xfffffff0UL, 0xffffffffUL, 0xfffffff1UL, 0xfffffff3UL, 0xfffffff4UL, 0xfffffff7UL, 0xfffffff6UL, 0xffffffffUL, 0x33f11f0fUL, 0xf3311f0fUL, 0xf33f110fUL, 0xfffffff2UL, 0xfffffff5UL, 0xffffffffUL, 0xffffffffUL, 0xffffffffUL, | ||
}; | ||
|
||
const std::uint8_t reject = (state >> 3), nonAscii = (octet >> 7); | ||
const std::uint8_t class_ = (!nonAscii ? 0 : (0xf & (utf8ClassTab[(octet >> 3) & 0xf] >> (4 * (octet & 7))))); | ||
|
||
*cpp = (state == UTF8_ACCEPT ? (octet & (0xffU >> class_)) : ((octet & 0x3fU) | (*cpp << 6))); | ||
|
||
return (reject ? 0xf : (0xf & (utf8StateTab[class_] >> (4 * (state & 7))))); | ||
} | ||
|
||
void codepoint_to_utf8(std::string& s, char32_t c) | ||
{ | ||
if(c > 0x0010FFFF) { throw Term::Exception("Invalid UTF32 codepoint."); } | ||
char bytes[4]; | ||
int nbytes = 1; | ||
char32_t d = c; | ||
if(c >= 0x10000) | ||
{ | ||
nbytes++; | ||
bytes[3] = ((d | 0x80) & 0xBF); | ||
d >>= 6; | ||
} | ||
if(c >= 0x800) | ||
{ | ||
nbytes++; | ||
bytes[2] = ((d | 0x80) & 0xBF); | ||
d >>= 6; | ||
} | ||
if(c >= 0x80) | ||
{ | ||
nbytes++; | ||
bytes[1] = ((d | 0x80) & 0xBF); | ||
d >>= 6; | ||
} | ||
static const unsigned char mask[4] = {0x00, 0xC0, 0xE0, 0xF0}; | ||
bytes[0] = static_cast<char>(d | mask[nbytes - 1]); | ||
s.append(bytes, nbytes); | ||
} | ||
|
||
std::u32string utf8_to_utf32(const std::string& s) | ||
{ | ||
std::uint32_t codepoint{}; | ||
std::uint8_t state = UTF8_ACCEPT; | ||
std::u32string r{}; | ||
for(char i: s) | ||
{ | ||
state = utf8_decode_step(state, i, &codepoint); | ||
if(state == UTF8_ACCEPT) { r.push_back(codepoint); } | ||
else if(state == UTF8_REJECT) { throw Term::Exception("Invalid byte in UTF8 encoded string"); } | ||
} | ||
if(state != UTF8_ACCEPT) { throw Term::Exception("Expected more bytes in UTF8 encoded string"); } | ||
return r; | ||
} | ||
|
||
std::string utf32_to_utf8(const std::u32string& s) | ||
{ | ||
std::string r{}; | ||
for(char32_t i: s) { codepoint_to_utf8(r, i); } | ||
return r; | ||
} | ||
|
||
std::string vector_to_string(const std::vector<char>& vector) | ||
{ | ||
std::string string; | ||
for(char i: vector) { string.push_back(i); } | ||
return string; | ||
} | ||
|
||
} // namespace Private | ||
} // namespace Term |
Oops, something went wrong.