Last active
April 18, 2020 11:50
-
-
Save saper/be135ce816ceb594893479989ed83843 to your computer and use it in GitHub Desktop.
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
#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