Skip to content

Instantly share code, notes, and snippets.

@saper
Last active April 18, 2020 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saper/be135ce816ceb594893479989ed83843 to your computer and use it in GitHub Desktop.
Save saper/be135ce816ceb594893479989ed83843 to your computer and use it in GitHub Desktop.
#include <sstream>
#include <math.h>
#include <iostream>
#include <fstream>
#include <string>
#include <limits>
#include <limits.h>
#include <unordered_map>
#include <stdlib.h>
#include <chrono>
#include <thread>
#include <time.h>
#include <vector>
#define NVM_FLOAT_EPSILON 0.00000001
#define CRLF "\n"
#define ldpl_number double
#define ldpl_vector ldpl_map
#define ldpl_text chText
using namespace std;
// -------------------------------------------------------
#ifndef CHTEXT
#define CHTEXT
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <string.h>
class chText {
private:
vector<string> buffer;
string stringRep;
size_t chText_get_str_utf8length(const string cstr);
void createFromString(const string & cstr);
void createFromChar(const char * cstr);
public:
size_t size();
bool empty();
size_t length();
string str_rep();
chText();
chText (const string& x);
chText (const double& f);
chText& operator= (const string& x);
chText (const char * x);
chText& operator= (const char * x);
chText (char x);
chText& operator= (char x);
chText operator [](size_t i) const;
string & operator [](int i);
friend ostream & operator << (ostream &out, const chText &c);
friend chText operator+(const chText &c1, const chText &c2);
friend chText operator+(const string &c1, const chText &c2);
friend chText operator+(const chText &c1, const string &c2);
friend chText operator+(const char * c1, const chText &c2);
friend chText operator+(const chText &c1, const char * c2);
friend bool operator<(const chText &c1, const chText &c2);
friend bool operator>(const chText &c1, const chText &c2);
friend bool operator==(const chText& ch1, const chText& ch2);
friend bool operator==(const chText& ch1, const string& ch2);
friend bool operator==(const chText& ch1, const char * ch2);
friend bool operator==(const string& ch2, const chText& ch1);
friend bool operator==(const char * ch2, const chText& ch1);
friend bool operator==(const chText& ch1, const char ch2);
friend bool operator==(const char ch2, const chText& ch1);
friend bool operator!=(const chText& ch1, const chText& ch2);
bool loadFile(const string &fileName);
chText & operator += (const chText & txt);
chText & operator += (const string & txt);
chText & operator += (const char * txt);
bool isAlphanumeric();
bool isAlphanumeric(size_t from);
bool isNumber();
double getNumber();
chText substr(size_t from, size_t count);
chText & erase(size_t from, size_t count);
chText substr(size_t from);
int compare(size_t from, size_t count, chText other);
int compare(chText other);
};
ostream & operator << (ostream &out, const chText &c);
chText operator+(const chText &c1, const chText &c2);
chText operator+(const string &c1, const chText &c2);
chText operator+(const chText &c1, const string &str);
chText operator+(const char * c1, const chText &c2);
chText operator+(const chText &c1, const char * str);
bool operator==(const chText& ch1, const chText& ch2);
bool operator==(const string& c1, const chText& ch2);
bool operator==(const chText& ch1, const string& c2);
bool operator==(const char * c1, const chText& ch2);
bool operator==(const chText& ch1, const char * c2);
bool operator==(const char c1, const chText& ch2);
bool operator==(const chText& ch1, const char c2);
bool operator<(const chText &c1, const chText &c2);
bool operator>(const chText &c1, const chText &c2);
bool operator!=(const chText& ch1, const chText& ch2);
chText to_ldpl_string(double x);
#endif
// Gets length of utf8-encoded c++ string
size_t chText::chText_get_str_utf8length(const string cstr){
size_t len = cstr.size();
size_t utf8len = 0;
unsigned int c;
for (size_t i = 0; i < len; i++)
{
size_t l = 0;
c = (unsigned char) cstr[i];
if (c >= 0 && c <= 127) l = 0;
else if ((c & 0xE0) == 0xC0) l = 1;
else if ((c & 0xF0) == 0xE0) l = 2;
else if ((c & 0xF8) == 0xF0) l = 3;
else if (c>=248 && c<=255) return 0; //invalid utf8
i += l;
utf8len++;
}
return utf8len;
}
// Fills buffer with utf8-encoded c++ string
void chText::createFromString(const string & cstr){
buffer.clear();
size_t cstrlen = cstr.size();
size_t chPos = 0;
for(size_t i = 0; i < cstrlen; ++i){
string ch = "";
char c = cstr[i];
if (c >= 0 && c <= 127){
ch += c;
}
else if ((c & 0xE0) == 0xC0){
ch += c;
ch += cstr[++i];
}
else if ((c & 0xF0) == 0xE0){
ch += c;
ch += cstr[++i];
ch += cstr[++i];
}
else if ((c & 0xF8) == 0xF0){
ch += c;
ch += cstr[++i];
ch += cstr[++i];
ch += cstr[++i];
}
buffer.push_back(ch);
chPos++;
}
}
// Fills buffer with utf8-encoded c++ string
void chText::createFromChar(const char * cstr){
buffer.clear();
size_t cstrlen = strlen(cstr);
size_t chPos = 0;
for(size_t i = 0; i < cstrlen; ++i){
string ch = "";
char c = cstr[i];
if (c >= 0 && c <= 127){
ch += c;
}
else if ((c & 0xE0) == 0xC0){
ch += c;
ch += cstr[++i];
}
else if ((c & 0xF0) == 0xE0){
ch += c;
ch += cstr[++i];
ch += cstr[++i];
}
else if ((c & 0xF8) == 0xF0){
ch += c;
ch += cstr[++i];
ch += cstr[++i];
ch += cstr[++i];
}
buffer.push_back(ch);
chPos++;
}
}
size_t chText::size(){
return buffer.size();
}
bool chText::empty(){
return buffer.empty();
}
size_t chText::length(){
return size();
}
string chText::str_rep(){
stringRep = "";
for(size_t i = 0; i < size(); ++i){
stringRep += buffer[i];
}
return stringRep;
}
// default constructor
chText::chText(){}
// conversion from string (constructor):
chText::chText (const string& x) {
createFromString(x);
}
// conversion from double (constructor):
chText::chText (const double& f) {
std::string str = to_string (f);
str.erase(str.find_last_not_of('0') + 1, std::string::npos);
str.erase ( str.find_last_not_of('.') + 1, std::string::npos );
createFromString(str);
}
// conversion from string (assignment):
chText& chText::operator= (const string& x) {
createFromString(x);
return *this;
}
// conversion from char * (constructor):
chText::chText (const char * x) {
createFromChar(x);
}
// conversion from char * (assignment):
chText& chText::operator= (const char * x) {
createFromChar(x);
return *this;
}
// conversion from char (constructor):
chText::chText (char x) {
string a = "";
a += x;
createFromString(a);
}
// conversion from char (assignment):
chText& chText::operator= (char x) {
string a = "";
a += x;
createFromString(a);
return *this;
}
// [] for reading
chText chText::operator [](size_t i) const {
if(i >= buffer.size()){
cout << "Out-of-bounds index access." << endl;
exit(1);
}
chText c = buffer[i];
return c;
}
// [] for setting
string & chText::operator [](int i) {
if(i >= buffer.size()){
cout << "Out-of-bounds index access." << endl;
exit(1);
}
return buffer[i];
}
bool chText::loadFile(const string &fileName){
string line;
string fileContents = "";
ifstream myfile (fileName);
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
fileContents += line + "\n";
}
myfile.close();
}
else return false;
createFromString(fileContents);
return true;
}
// += operator
chText & chText::operator += (const chText & txt){
for(const string & s : txt.buffer){
buffer.push_back(s);
}
return *this;
}
// += operator
chText & chText::operator += (const string & txt){
chText c2 = txt;
for(const string & s : c2.buffer){
buffer.push_back(s);
}
return *this;
}
// += operator
chText & chText::operator += (const char * txt){
chText c2 = txt;
for(const string & s : c2.buffer){
buffer.push_back(s);
}
return *this;
}
bool chText::isAlphanumeric(){
for(const string & s : buffer){
for(const char & c : s)
if(!isalnum(c)) return false;
}
return true;
}
bool chText::isAlphanumeric(size_t from){
for(size_t i = from; i < size(); ++i){
for(const char & c : buffer[i])
if(!isalnum(c)) return false;
}
return true;
}
bool chText::isNumber(){
string number = "";
for(size_t i = 0; i < size(); ++i){
number += buffer[i];
}
unsigned int firstchar = 0;
if(number[0] == '-') firstchar = 1;
if(number[firstchar] == '.') return false; //.12 is not a valid decimal in LDPL, 0.12 is.
if(number[firstchar] == '+') return false; //+5 is not a valid decimal in LDPL, 5 is.
istringstream iss(number);
double f;
iss >> f;
bool isNumber = iss.eof() && !iss.fail();
//If it is a number, it might be an octal literal (e.g. 025, 067, 003 etc)
//so we proceed to fix the original number to make it decimal.
if(isNumber){
string f_number = "";
unsigned int i;
for(i = 1; i < number.length(); ++i){
//If prev char not 0
if(number[i - 1] != '0'){
//if prev char is -, continue check
if(number[i - 1] == '-') f_number += '-';
//if prev char is number, break
else break;
}
//If prev number is 0
else if(number[i] == '.') {
f_number += '0';
}
}
f_number += number.substr(i - 1);
number = f_number;
return true;
}else{
return false;
}
}
double chText::getNumber(){
string number = "";
for(size_t i = 0; i < size(); ++i){
number += buffer[i];
}
return stod(number);
}
chText chText::substr(size_t from, size_t count){
chText newText;
for(size_t i = from; i < from + count; ++i){
if(i >= buffer.size()) break;
newText.buffer.push_back(buffer[i]);
}
return newText;
}
chText & chText::erase(size_t from, size_t count){
for(size_t i = 0; i < count; ++i)
buffer.erase(buffer.begin() + from);
return *this;
}
chText chText::substr(size_t from){
chText newText;
for(size_t i = from; i < from + buffer.size(); ++i){
if(i >= buffer.size()) break;
newText.buffer.push_back(buffer[i]);
}
return newText;
}
int chText::compare(size_t from, size_t count, chText other){
chText newText;
for(size_t i = from; i < from + count; ++i){
if(i >= buffer.size()) break;
newText.buffer.push_back(buffer[i]);
}
if (newText == other) return 0;
if (newText.size() < other.size()) return -1;
else return 1;
}
int chText::compare(chText other){
if (*this == other) return 0;
if (this->size() < other.size()) return -1;
else return 1;
}
ostream & operator << (ostream &out, const chText &c){
for(const string & s : c.buffer){
out << s;
}
return out;
}
chText operator+(const chText &c1, const chText &c2){
chText res = c1;
for(const string & s : c2.buffer){
res.buffer.push_back(s);
}
return res;
}
chText operator+(const string &c1, const chText &c2){
chText res = c1;
for(const string & s : c2.buffer){
res.buffer.push_back(s);
}
return res;
}
chText operator+(const chText &c1, const string &str){
chText res = c1;
chText c2 = str;
for(const string & s : c2.buffer){
res.buffer.push_back(s);
}
return res;
}
chText operator+(const char * c1, const chText &c2){
chText res = c1;
for(const string & s : c2.buffer){
res.buffer.push_back(s);
}
return res;
}
chText operator+(const chText &c1, const char * str){
chText res = c1;
chText c2 = str;
for(const string & s : c2.buffer){
res.buffer.push_back(s);
}
return res;
}
bool operator==(const chText& ch1, const chText& ch2){
return ch1.buffer == ch2.buffer;
}
bool operator==(const string& c1, const chText& ch2){
const chText ch1 = c1;
return ch1 == ch2;
}
bool operator==(const chText& ch1, const string& c2){
const chText ch2 = c2;
return ch1 == ch2;
}
bool operator==(const char * c1, const chText& ch2){
const chText ch1 = c1;
return ch1 == ch2;
}
bool operator==(const chText& ch1, const char * c2){
const chText ch2 = c2;
return ch1 == ch2;
}
bool operator==(const char c1, const chText& ch2){
const chText ch1 = c1;
return ch1 == ch2;
}
bool operator==(const chText& ch1, const char c2){
const chText ch2 = c2;
return ch1 == ch2;
}
bool operator<(const chText &c1, const chText &c2){
size_t max = c1.buffer.size() > c2.buffer.size() ? c2.buffer.size() : c1.buffer.size();
for(size_t i = 0; i < max; ++i){
if(c1.buffer[i] < c2.buffer[i]) return true;
else if (c1.buffer[i] > c2.buffer[i]) return false;
}
return false;
}
bool operator>(const chText &c1, const chText &c2){
size_t max = c1.buffer.size() > c2.buffer.size() ? c2.buffer.size() : c1.buffer.size();
for(size_t i = 0; i < max; ++i){
if(c1.buffer[i] > c2.buffer[i]) return true;
else if (c1.buffer[i] < c2.buffer[i]) return false;
}
return false;
}
bool operator!=(const chText& ch1, const chText& ch2){
return ch1.buffer != ch2.buffer;
}
// ---------------------------------------------------------------------------------------------------
//Global variables
ifstream file_loading_stream;
ofstream file_writing_stream;
string file_loading_line;
chText joinvar; //Generic temporary use text variable (used by join but can be used by any other statement as well)
ldpl_number VAR_ERRORCODE = 0;
chText VAR_ERRORTEXT = "";
//Forward declarations
chText to_ldpl_string(ldpl_number x);
chText trimCopy(chText _line);
#ifndef LDPLMAP
#define LDPLMAP
template<typename T>
struct ldpl_map {
unordered_map<string, T> inner_collection;
T& operator [] (chText i);
T& operator [] (ldpl_number i);
};
#endif
template<typename T>
T& ldpl_map<T>::operator [] (chText i) {
return inner_collection[i.str_rep()];
}
template<typename T>
T& ldpl_map<T>::operator [] (ldpl_number i) {
return inner_collection[to_ldpl_string(i).str_rep()];
}
#ifndef LDPLLIST
#define LDPLLIST
template<typename T>
struct ldpl_list {
vector<T> inner_collection;
T& operator [] (ldpl_number i);
};
#endif LDPLMAP
template<typename T>
T& ldpl_list<T>::operator [] (ldpl_number i) {
i = floor(i);
if (i < 0 || i >= inner_collection.size()) {
cerr << "Runtime Error: LIST index " << i << " out of range [0, "
<< inner_collection.size() << ")" << endl;
exit(1);
}
return inner_collection[i];
}
template<typename T>
void get_indices(ldpl_list<chText> & dest, ldpl_vector<T> & source){
dest.inner_collection.clear();
int i = 0;
for (const auto &keyPair : source.inner_collection) {
dest.inner_collection.push_back(keyPair.first);
++i;
}
}
ldpl_number input_number(){
string s = "";
while(true){
getline(cin, s);
try {
ldpl_number num = stod(s);
return num;
}
catch (const invalid_argument& ia) {
cout << "Redo from start: " << flush;
}
}
}
ldpl_number to_number(chText & textNumber){
string a = textNumber.str_rep();
try {
//This is used to disallow the use of hexadecimal and binary literals.
for(char i : a){
if(i != '0' && i != '1' && i != '2' &&
i != '3' && i != '4' && i != '5' &&
i != '6' && i != '7' && i != '8' &&
i != '9' && i != '-' && i != '.') return 0;
}
ldpl_number num = stod(a);
return num;
}
catch (const invalid_argument& ia) {
return 0;
}
}
string input_string(){
string s = "";
getline(cin, s);
return s;
}
string input_until_eof(){
stringstream full;
string s = "";
bool firstLine = true;
while (getline(cin, s)) {
if(!firstLine) s = "\n" + s;
firstLine = false;
full << s;
}
return full.str();
}
bool num_equal(ldpl_number a, ldpl_number b){
return fabs(a - b) < NVM_FLOAT_EPSILON;
}
int str_cmp(chText a, chText b) {
return a.compare(b);
}
ldpl_number modulo(ldpl_number a, ldpl_number b){
long f_a = floor(a);
long f_b = floor(b);
return ( f_a % f_b + f_b ) % f_b;
}
void join(const chText & a, const chText & b, chText & c){
c = a + b;
}
//https://stackoverflow.com/a/27658515
chText str_replace(string s, string find, string replace){
string result;
size_t find_len = find.size();
size_t pos, from=0;
while (string::npos != (pos=s.find(find,from))){
result.append(s, from, pos-from);
result.append(replace);
from = pos + find_len;
}
result.append(s, from , string::npos);
return result;
}
ldpl_number get_char_num(chText chr){
int length = chr.str_rep().size();
if (length != 1) {
VAR_ERRORTEXT = "Multibyte character received (probably UTF-8). Can't be parsed into a single number.";
VAR_ERRORCODE = 1;
return -1;
}
VAR_ERRORTEXT = "";
VAR_ERRORCODE = 0;
ldpl_number ord = (unsigned char) chr.str_rep()[0];
return ord;
}
chText charat(const chText & s, ldpl_number pos){
unsigned int _pos = floor(pos);
return s[pos];
}
//Convert ldpl_number to LDPL string, killing trailing 0's
//https://stackoverflow.com/questions/16605967/ & https://stackoverflow.com/questions/13686482/
chText to_ldpl_string(ldpl_number x){
ostringstream out;
out.precision(10);
out << fixed << x;
string str = out.str();
str.erase(str.find_last_not_of('0') + 1, string::npos);
str.erase(str.find_last_not_of('.') + 1, string::npos);
return str;
}
#include <cstdio>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>
chText exec(const char* cmd) {
array<char, 128> buffer;
string result;
unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
throw runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
#include <random>
ldpl_number get_random(){
random_device rd;
mt19937 mt(rd());
uniform_real_distribution<double> dist(0.0, 1.0);
ldpl_number r = (ldpl_number) dist(mt);
return r;
}
string expandHomeDirectory(string filename){
#if defined(_WIN32)
return filename;
#else
string homeDir = exec("echo $HOME").str_rep();
homeDir = trimCopy(homeDir).str_rep();
string newPath = "";
for(size_t i = 0; i < filename.length(); ++i){
if(filename[i] == '~'){
newPath += homeDir;
}else{
newPath += filename[i];
}
}
//cout << "newPath:" << newPath << endl;
return newPath;
#endif
}
//getLineSafe by https://gist.github.com/josephwb/df09e3a71679461fc104
std::istream& getlineSafe(std::istream& is, std::string& t) {
t.clear();
std::istream::sentry se(is, true);
std::streambuf* sb = is.rdbuf();
for (;;) {
int c = sb->sbumpc();
switch (c) {
case '\n':
t += (char)c;
return is;
case '\r':
t += (char)c;
if (sb->sgetc() == '\n') {
t += sb->sbumpc();
}
return is;
case EOF:
if (t.empty()) {
is.setstate(std::ios::eofbit);
}
return is;
default:
t += (char)c;
}
}
}
void load_file(chText filename, chText & destination)
{
//Load file
ifstream file(expandHomeDirectory(filename.str_rep()));
//Fail if the file couldn't be loaded
if(!file.is_open()){
destination = "";
VAR_ERRORTEXT = "The file '" + filename + "' couldn't be opened.";
VAR_ERRORCODE = 1;
return;
}
//Get file contents
destination = "";
string line = "";
while(getlineSafe(file, line))
{
destination += line;
}
VAR_ERRORTEXT = "";
VAR_ERRORCODE = 0;
file.close();
}
// Used by append_ and write_.
void save_to_file(chText filename, chText content, ios_base::openmode mode){
file_writing_stream.open(expandHomeDirectory(filename.str_rep()), mode);
if(!file_writing_stream.is_open()){
VAR_ERRORTEXT = "Could not open " + filename;
VAR_ERRORCODE = 1;
return;
}
file_writing_stream << content;
if(file_writing_stream.bad()){
VAR_ERRORTEXT = "Could not write to " + filename;
VAR_ERRORCODE = 2;
return;
}
VAR_ERRORTEXT = "";
VAR_ERRORCODE = 0;
file_writing_stream.close();
}
void append_to_file(chText filename, chText content){
save_to_file(filename, content, ios_base::app);
}
void write_file(chText filename, chText content){
save_to_file(filename, content, ios_base::out);
}
ldpl_number utf8GetIndexOf(chText haystack, chText needle){
int lenHaystack = haystack.size();
int lenNeedle = needle.size();
if(lenHaystack < lenNeedle) return -1;
int i = 0;
while(i + lenNeedle <= lenHaystack){
if(haystack.substr(i, lenNeedle) == needle) return i;
++i;
}
return -1;
}
ldpl_number utf8Count(chText haystack, chText needle){
int lenHaystack = haystack.size();
int lenNeedle = needle.size();
if(lenHaystack < lenNeedle) return 0;
int i = 0;
int count = 0;
while(i + lenNeedle <= lenHaystack){
if(haystack.substr(i, lenNeedle) == needle) ++count;
++i;
}
return count;
}
//Removes all trailing and ending whitespace from a string
chText trimCopy(chText _line){
string line = _line.str_rep();
//If the string is empty
if(line.size() == 0) return line;
//If the string has only one character
if(line.size() == 1 && !isspace(line[0])) return line;
//Left trim
int first = 0;
for(unsigned int i = 0; i < line.size(); ++i){
if (!isspace(line[i])){
first = i;
break;
}
}
//Right trim
int last = 0;
for(unsigned int i = line.size()-1; i >= 0; --i){
if (!isspace(line[i])){
last = i+1;
break;
}
//--i will break with unsigned int when reaching 0, so we check
//if i == 0 and, if it is and it's not a space, we break
if(i == 0){
last = 0;
break;
}
}
//Trim the string
line = line.substr(first, last-first);
return line;
}
ldpl_list<chText> utf8_split_list(chText haystack, chText needle){
ldpl_list<chText> result;
int lenHaystack = haystack.size();
int lenNeedle = needle.size();
if (lenNeedle > 0) {
int i = 0;
int last_start = 0;
while (i + lenNeedle <= lenHaystack) {
if (haystack.substr(i, lenNeedle) == needle) {
result.inner_collection.push_back(haystack.substr(last_start, i - last_start));
i += lenNeedle;
last_start = i;
} else {
++i;
}
}
// Grab everything after the last needle
result.inner_collection.push_back(haystack.substr(last_start, lenHaystack - last_start));
} else {
// Split into individual characters
for (int i = 0; i < lenHaystack; i++)
result.inner_collection.push_back(charat(haystack, i));
}
return result;
}
ldpl_list<chText> VAR_ARGV;
extern chText MY_NAME;
void HELLO();
void GREET();
int main(int argc, char *argv[]){
cout.precision(numeric_limits<ldpl_number>::digits10);
for(int i = 1; i < argc; ++i)
VAR_ARGV.inner_collection.push_back(argv[i]);
#line 6 "hello.ldpl"
HELLO();
#line 7 "hello.ldpl"
cout << "What's your name, friend? " << flush;
#line 8 "hello.ldpl"
MY_NAME = input_string();
#line 9 "hello.ldpl"
GREET();
return 0;
}
#include "hello.cpp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment