70 lines
2.1 KiB
C++
70 lines
2.1 KiB
C++
|
#include "utils.h"
|
||
|
|
||
|
namespace humanus {
|
||
|
|
||
|
const std::filesystem::path PROJECT_ROOT = get_project_root();
|
||
|
|
||
|
size_t validate_utf8(const std::string& text) {
|
||
|
size_t len = text.size();
|
||
|
if (len == 0) return 0;
|
||
|
|
||
|
// Check the last few bytes to see if a multi-byte character is cut off
|
||
|
for (size_t i = 1; i <= 4 && i <= len; ++i) {
|
||
|
unsigned char c = text[len - i];
|
||
|
// Check for start of a multi-byte sequence from the end
|
||
|
if ((c & 0xE0) == 0xC0) {
|
||
|
// 2-byte character start: 110xxxxx
|
||
|
// Needs at least 2 bytes
|
||
|
if (i < 2) return len - i;
|
||
|
} else if ((c & 0xF0) == 0xE0) {
|
||
|
// 3-byte character start: 1110xxxx
|
||
|
// Needs at least 3 bytes
|
||
|
if (i < 3) return len - i;
|
||
|
} else if ((c & 0xF8) == 0xF0) {
|
||
|
// 4-byte character start: 11110xxx
|
||
|
// Needs at least 4 bytes
|
||
|
if (i < 4) return len - i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If no cut-off multi-byte character is found, return full length
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
bool readline_utf8(std::string & line, bool multiline_input) {
|
||
|
#if defined(_WIN32)
|
||
|
std::wstring wline;
|
||
|
if (!std::getline(std::wcin, wline)) {
|
||
|
// Input stream is bad or EOF received
|
||
|
line.clear();
|
||
|
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), NULL, 0, NULL, NULL);
|
||
|
line.resize(size_needed);
|
||
|
WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), &line[0], size_needed, NULL, NULL);
|
||
|
#else
|
||
|
if (!std::getline(std::cin, line)) {
|
||
|
// Input stream is bad or EOF received
|
||
|
line.clear();
|
||
|
return false;
|
||
|
}
|
||
|
#endif
|
||
|
if (!line.empty()) {
|
||
|
char last = line.back();
|
||
|
if (last == '/') { // Always return control on '/' symbol
|
||
|
line.pop_back();
|
||
|
return false;
|
||
|
}
|
||
|
if (last == '\\') { // '\\' changes the default action
|
||
|
line.pop_back();
|
||
|
multiline_input = !multiline_input;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// By default, continue input if multiline_input is set
|
||
|
return multiline_input;
|
||
|
}
|
||
|
|
||
|
} // namespace humanus
|