REMOVED USER_STD macros, code formating, csv changes, few file functions

This commit is contained in:
VaclavT 2021-02-15 23:20:20 +01:00
parent 125c73ac33
commit c1532e78b1
15 changed files with 10550 additions and 2101 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ build
/cmake-build-debug/ /cmake-build-debug/
.idea .idea
ml ml
.DS_Store

View File

@ -20,6 +20,7 @@ set(PROJECT_NAME ml)
set(SOURCE set(SOURCE
ml.cpp ml.cpp
ml_io.cpp
clib/csvparser.cpp clib/csvparser.cpp
clib/sslclient.cpp clib/sslclient.cpp
clib/json11.cpp) clib/json11.cpp)

View File

@ -1,13 +1,13 @@
### TODO ### TODO
- support for strings with " included - move system_cmd into ml_io
- logical operators - logical operators
- documentation - documentation
- add url of source/inspiration to clib/*.cpp - add url of source/inspiration to clib/*.cpp
- load std lib when starting - load std lib when starting
- add more command line args - add more command line args
- split into more files - add stdtest
- prejmenovat ivaluize - rename ivaluize
- add benchmark - add benchmark
- add some debug support?? - add some debug support??
- add instrumentation (time, nr of evals, debug info, debug environment etc) - add instrumentation (time, nr of evals, debug info, debug environment etc)

View File

@ -12,11 +12,13 @@ CsvParser::CsvParser(bool skip_hdr, char field_sep, char quote_ch, char line_sep
header_skiped = false; header_skiped = false;
} }
void CsvParser::parseCSV(const std::string &csvSource, std::vector< std::vector<std::string> > &lines) { MlValue CsvParser::parseCSV(const std::string &csvSource) {
bool inQuote(false); bool inQuote(false);
bool newLine(false); bool newLine(false);
std::string field; std::string field;
lines.clear();
// PERF optimize it for memory usage and performance
std::vector<std::vector<std::string>> parsed_data; // TODO some default size here
std::vector<std::string> line; std::vector<std::string> line;
std::string::const_iterator aChar = csvSource.begin(); std::string::const_iterator aChar = csvSource.begin();
@ -38,7 +40,7 @@ void CsvParser::parseCSV(const std::string &csvSource, std::vector< std::vector<
} else { } else {
if (newLine == false) { if (newLine == false) {
line.push_back(field); line.push_back(field);
addLine(line, lines); addLine(line, parsed_data);
field.clear(); field.clear();
line.clear(); line.clear();
newLine = true; newLine = true;
@ -55,37 +57,39 @@ void CsvParser::parseCSV(const std::string &csvSource, std::vector< std::vector<
if (field.size()) if (field.size())
line.push_back(field); line.push_back(field);
addLine(line, lines); addLine(line, parsed_data);
return ivalualize(parsed_data);
} }
MlValue CsvParser::ivalualize(std::vector< std::vector<std::string> > &parsed_data) const { MlValue CsvParser::ivalualize(std::vector<std::vector<std::string> > &parsed_data) const {
int rows = parsed_data.size(); int rows = parsed_data.size();
int cols = rows > 0 ? parsed_data[0].size() : 0; int cols = rows > 0 ? parsed_data[0].size() : 0;
std::vector<MlValue> result; std::vector<MlValue> result;
if (rows > 0 && cols > 0) { if (rows > 0 && cols > 0) {
for (int r = 0; r < rows; r++) { for (int r = 0; r < rows; r++) {
std::vector<MlValue> row; std::vector<MlValue> row;
for (int c = 0; c < cols; c++) { for (int c = 0; c < cols; c++) {
std::string value = parsed_data[r][c]; std::string value = parsed_data[r][c];
if (is_string_int(value)) { if (is_string_int(value)) {
row.push_back(MlValue(stoi(value))); row.push_back(MlValue(stoi(value)));
} }
if (is_string_float(value)) { if (is_string_float(value)) {
row.push_back(MlValue(std::stod(value))); row.push_back(MlValue(std::stod(value)));
} else { } else {
row.push_back(MlValue::string(value)); row.push_back(MlValue::string(value));
} }
} }
result.push_back(row); result.push_back(row);
} }
} }
return result; return result;
} }
void CsvParser::addLine(const std::vector<std::string> &line, std::vector< std::vector<std::string> > &lines) { void CsvParser::addLine(const std::vector<std::string> &line, std::vector<std::vector<std::string> > &lines) {
if (skip_header && !header_skiped) { if (skip_header && !header_skiped) {
header_skiped = true; header_skiped = true;
} else { } else {
@ -101,10 +105,10 @@ std::regex double_regex("[0-9]+\\.[0-9]+");
// Is string representing int value // Is string representing int value
bool CsvParser::is_string_int(const std::string &str) const { bool CsvParser::is_string_int(const std::string &str) const {
return std::regex_match(str, int_regex); return std::regex_match(str, int_regex);
} }
// Is string representing float value // Is string representing float value
bool CsvParser::is_string_float(const std::string &str) const { bool CsvParser::is_string_float(const std::string &str) const {
return std::regex_match(str, double_regex); return std::regex_match(str, double_regex);
} }

View File

@ -8,23 +8,26 @@
class CsvParser { class CsvParser {
private: private:
char field_separator; char field_separator;
char line_separator; char line_separator;
char line_separator2; char line_separator2;
char quote_character; char quote_character;
bool skip_header; bool skip_header;
bool header_skiped; bool header_skiped;
public: public:
CsvParser(bool skip_hdr = false, char field_sep = ',', char quote_ch = '"', char line_sep = '\r', char line_sep2 = '\n'); CsvParser(bool skip_hdr = false, char field_sep = ',', char quote_ch = '"', char line_sep = '\r',
char line_sep2 = '\n');
void parseCSV(const std::string &csvSource, std::vector< std::vector<std::string> > &lines); MlValue parseCSV(const std::string &csvSource);
MlValue ivalualize(std::vector< std::vector<std::string> > &parsed_data) const;
private: private:
void addLine(const std::vector<std::string> &line, std::vector< std::vector<std::string> > &lines); void addLine(const std::vector<std::string> &line, std::vector<std::vector<std::string> > &lines);
MlValue ivalualize(std::vector<std::vector<std::string> > &parsed_data) const;
bool is_string_int(const std::string &str) const; bool is_string_int(const std::string &str) const;
bool is_string_float(const std::string &str) const; bool is_string_float(const std::string &str) const;
}; };

8319
clib/date.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,165 +11,200 @@
namespace json11 { namespace json11 {
enum JsonParse { enum JsonParse {
STANDARD, COMMENTS STANDARD, COMMENTS
}; };
class JsonValue; class JsonValue;
class Json final { class Json final {
public: public:
// Types // Types
enum Type { enum Type {
NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
}; };
// Array and object typedefs // Array and object typedefs
typedef std::vector<Json> array; typedef std::vector<Json> array;
typedef std::map<std::string, Json> object; typedef std::map<std::string, Json> object;
// Constructors for the various types of JSON value. // Constructors for the various types of JSON value.
Json() noexcept; // NUL Json() noexcept; // NUL
Json(std::nullptr_t) noexcept; // NUL Json(std::nullptr_t) noexcept; // NUL
Json(double value); // NUMBER Json(double value); // NUMBER
Json(int value); // NUMBER Json(int value); // NUMBER
Json(bool value); // BOOL Json(bool value); // BOOL
Json(const std::string &value); // STRING Json(const std::string &value); // STRING
Json(std::string &&value); // STRING Json(std::string &&value); // STRING
Json(const char * value); // STRING Json(const char *value); // STRING
Json(const array &values); // ARRAY Json(const array &values); // ARRAY
Json(array &&values); // ARRAY Json(array &&values); // ARRAY
Json(const object &values); // OBJECT Json(const object &values); // OBJECT
Json(object &&values); // OBJECT Json(object &&values); // OBJECT
// Implicit constructor: anything with a to_json() function. // Implicit constructor: anything with a to_json() function.
template <class T, class = decltype(&T::to_json)> template<class T, class = decltype(&T::to_json)>
Json(const T & t) : Json(t.to_json()) {} Json(const T &t) : Json(t.to_json()) {}
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc) // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
template <class M, typename std::enable_if< template<class M, typename std::enable_if<
std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value
&& std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value, && std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
int>::type = 0> int>::type = 0>
Json(const M & m) : Json(object(m.begin(), m.end())) {} Json(const M &m) : Json(object(m.begin(), m.end())) {}
// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
template <class V, typename std::enable_if< template<class V, typename std::enable_if<
std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value, std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
int>::type = 0> int>::type = 0>
Json(const V & v) : Json(array(v.begin(), v.end())) {} Json(const V &v) : Json(array(v.begin(), v.end())) {}
// This prevents Json(some_pointer) from accidentally producing a bool. Use // This prevents Json(some_pointer) from accidentally producing a bool. Use
// Json(bool(some_pointer)) if that behavior is desired. // Json(bool(some_pointer)) if that behavior is desired.
Json(void *) = delete; Json(void *) = delete;
// Accessors // Accessors
Type type() const; Type type() const;
bool is_null() const { return type() == NUL; } bool is_null() const { return type() == NUL; }
bool is_number() const { return type() == NUMBER; }
bool is_bool() const { return type() == BOOL; }
bool is_string() const { return type() == STRING; }
bool is_array() const { return type() == ARRAY; }
bool is_object() const { return type() == OBJECT; }
// Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not bool is_number() const { return type() == NUMBER; }
// distinguish between integer and non-integer numbers - number_value() and int_value()
// can both be applied to a NUMBER-typed object.
double number_value() const;
int int_value() const;
// Return the enclosed value if this is a boolean, false otherwise. bool is_bool() const { return type() == BOOL; }
bool bool_value() const;
// Return the enclosed string if this is a string, "" otherwise.
const std::string &string_value() const;
// Return the enclosed std::vector if this is an array, or an empty vector otherwise.
const array &array_items() const;
// Return the enclosed std::map if this is an object, or an empty map otherwise.
const object &object_items() const;
// Return a reference to arr[i] if this is an array, Json() otherwise. bool is_string() const { return type() == STRING; }
const Json & operator[](size_t i) const;
// Return a reference to obj[key] if this is an object, Json() otherwise.
const Json & operator[](const std::string &key) const;
// Serialize. bool is_array() const { return type() == ARRAY; }
void dump(std::string &out) const;
std::string dump() const {
std::string out;
dump(out);
return out;
}
MlValue ivalualize() const; bool is_object() const { return type() == OBJECT; }
// Parse. If parse fails, return Json() and assign an error message to err. // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
static Json parse(const std::string & in, // distinguish between integer and non-integer numbers - number_value() and int_value()
std::string & err, // can both be applied to a NUMBER-typed object.
JsonParse strategy = JsonParse::STANDARD); double number_value() const;
static Json parse(const char * in,
std::string & err,
JsonParse strategy = JsonParse::STANDARD) {
if (in) {
return parse(std::string(in), err, strategy);
} else {
err = "null input";
return nullptr;
}
}
// Parse multiple objects, concatenated or separated by whitespace
static std::vector<Json> parse_multi(
const std::string & in,
std::string::size_type & parser_stop_pos,
std::string & err,
JsonParse strategy = JsonParse::STANDARD);
static inline std::vector<Json> parse_multi( int int_value() const;
const std::string & in,
std::string & err,
JsonParse strategy = JsonParse::STANDARD) {
std::string::size_type parser_stop_pos;
return parse_multi(in, parser_stop_pos, err, strategy);
}
bool operator== (const Json &rhs) const; // Return the enclosed value if this is a boolean, false otherwise.
bool operator< (const Json &rhs) const; bool bool_value() const;
bool operator!= (const Json &rhs) const { return !(*this == rhs); }
bool operator<= (const Json &rhs) const { return !(rhs < *this); }
bool operator> (const Json &rhs) const { return (rhs < *this); }
bool operator>= (const Json &rhs) const { return !(*this < rhs); }
/* has_shape(types, err) // Return the enclosed string if this is a string, "" otherwise.
* const std::string &string_value() const;
* Return true if this is a JSON object and, for each item in types, has a field of
* the given type. If not, return false and set err to a descriptive message. // Return the enclosed std::vector if this is an array, or an empty vector otherwise.
*/ const array &array_items() const;
typedef std::initializer_list<std::pair<std::string, Type>> shape;
bool has_shape(const shape & types, std::string & err) const; // Return the enclosed std::map if this is an object, or an empty map otherwise.
const object &object_items() const;
// Return a reference to arr[i] if this is an array, Json() otherwise.
const Json &operator[](size_t i) const;
// Return a reference to obj[key] if this is an object, Json() otherwise.
const Json &operator[](const std::string &key) const;
// Serialize.
void dump(std::string &out) const;
std::string dump() const {
std::string out;
dump(out);
return out;
}
MlValue ivalualize() const;
// Parse. If parse fails, return Json() and assign an error message to err.
static Json parse(const std::string &in,
std::string &err,
JsonParse strategy = JsonParse::STANDARD);
static Json parse(const char *in,
std::string &err,
JsonParse strategy = JsonParse::STANDARD) {
if (in) {
return parse(std::string(in), err, strategy);
} else {
err = "null input";
return nullptr;
}
}
// Parse multiple objects, concatenated or separated by whitespace
static std::vector<Json> parse_multi(
const std::string &in,
std::string::size_type &parser_stop_pos,
std::string &err,
JsonParse strategy = JsonParse::STANDARD);
static inline std::vector<Json> parse_multi(
const std::string &in,
std::string &err,
JsonParse strategy = JsonParse::STANDARD) {
std::string::size_type parser_stop_pos;
return parse_multi(in, parser_stop_pos, err, strategy);
}
bool operator==(const Json &rhs) const;
bool operator<(const Json &rhs) const;
bool operator!=(const Json &rhs) const { return !(*this == rhs); }
bool operator<=(const Json &rhs) const { return !(rhs < *this); }
bool operator>(const Json &rhs) const { return (rhs < *this); }
bool operator>=(const Json &rhs) const { return !(*this < rhs); }
/* has_shape(types, err)
*
* Return true if this is a JSON object and, for each item in types, has a field of
* the given type. If not, return false and set err to a descriptive message.
*/
typedef std::initializer_list<std::pair<std::string, Type>> shape;
bool has_shape(const shape &types, std::string &err) const;
private: private:
std::shared_ptr<JsonValue> m_ptr; std::shared_ptr<JsonValue> m_ptr;
}; };
// Internal class hierarchy - JsonValue objects are not exposed to users of this API. // Internal class hierarchy - JsonValue objects are not exposed to users of this API.
class JsonValue { class JsonValue {
protected: protected:
friend class Json; friend class Json;
friend class JsonInt;
friend class JsonDouble; friend class JsonInt;
virtual Json::Type type() const = 0;
virtual bool equals(const JsonValue * other) const = 0; friend class JsonDouble;
virtual bool less(const JsonValue * other) const = 0;
virtual void dump(std::string &out) const = 0; virtual Json::Type type() const = 0;
virtual MlValue ivalualize() const = 0;
virtual double number_value() const; virtual bool equals(const JsonValue *other) const = 0;
virtual int int_value() const;
virtual bool bool_value() const; virtual bool less(const JsonValue *other) const = 0;
virtual const std::string &string_value() const;
virtual const Json::array &array_items() const; virtual void dump(std::string &out) const = 0;
virtual const Json &operator[](size_t i) const;
virtual const Json::object &object_items() const; virtual MlValue ivalualize() const = 0;
virtual const Json &operator[](const std::string &key) const;
virtual ~JsonValue() {} virtual double number_value() const;
virtual int int_value() const;
virtual bool bool_value() const;
virtual const std::string &string_value() const;
virtual const Json::array &array_items() const;
virtual const Json &operator[](size_t i) const;
virtual const Json::object &object_items() const;
virtual const Json &operator[](const std::string &key) const;
virtual ~JsonValue() {}
}; };
} // namespace json11 } // namespace json11

View File

@ -17,59 +17,60 @@
#include <string> #include <string>
HttpClient::HttpClient(){}; HttpClient::HttpClient() {};
std::pair<int, std::string> HttpClient::doGetRequest(const std::string &url, const std::unordered_map<std::string, std::string> &headers) { std::pair<int, std::string>
HttpClient::doGetRequest(const std::string &url, const std::unordered_map<std::string, std::string> &headers) {
// https://stackoverflow.com/questions/25896916/parse-http-headers-in-c // https://stackoverflow.com/questions/25896916/parse-http-headers-in-c
std::regex rgx{R"(^(?:((?:https?|s?ftp):)//)([^:/\s]+)(?::(\d*))?(?:/([^\s?#]+)?([?][^?#]*)?(#.*)?)?)"}; std::regex rgx{R"(^(?:((?:https?|s?ftp):)//)([^:/\s]+)(?::(\d*))?(?:/([^\s?#]+)?([?][^?#]*)?(#.*)?)?)"};
std::smatch matches; std::smatch matches;
if (std::regex_search(url, matches, rgx)) { if (std::regex_search(url, matches, rgx)) {
for (size_t i = 0; i < matches.size(); ++i) { for (size_t i = 0; i < matches.size(); ++i) {
switch (i) { switch (i) {
case 0: case 0:
full_url = matches[i].str(); full_url = matches[i].str();
break; break;
case 1: case 1:
proto = matches[i].str(); proto = matches[i].str();
break; break;
case 2: case 2:
server = matches[i].str(); server = matches[i].str();
break; break;
case 3: case 3:
port = matches[i].str(); port = matches[i].str();
break; break;
case 4: case 4:
uri = matches[i].str(); uri = matches[i].str();
break; break;
case 5: case 5:
params = matches[i].str(); params = matches[i].str();
break; break;
case 6: case 6:
href = matches[i].str(); href = matches[i].str();
break; break;
} }
// std::cout << i << ": '" << matches[i].str() << "'\n"; // std::cout << i << ": '" << matches[i].str() << "'\n";
} }
} else { } else {
std::cerr << "Match not found" << std::endl; // TODO better message std::cerr << "Match not found" << std::endl; // TODO better message
} }
std::string headers_string = ""; std::string headers_string = "";
for (auto it = headers.begin(); it != headers.end(); ++it) { for (auto it = headers.begin(); it != headers.end(); ++it) {
headers_string.append("\r\n" + it->first + ": " + it->second); headers_string.append("\r\n" + it->first + ": " + it->second);
// std::cerr << "KEY: `" << it->first << "`, VALUE: `" << it->second << '`' << std::endl; // std::cerr << "KEY: `" << it->first << "`, VALUE: `" << it->second << '`' << std::endl;
} }
std::string request = "GET " + full_url + " HTTP/1.0\r\nHost: " + server + headers_string + "\r\n\r\n"; std::string request = "GET " + full_url + " HTTP/1.0\r\nHost: " + server + headers_string + "\r\n\r\n";
// TODO memory leaks ??? // TODO memory leaks ???
int bytes_read = sslRequest(server, request); int bytes_read = sslRequest(server, request);
if (bytes_read <= 0) { if (bytes_read <= 0) {
std::cerr << "no data read" << std::endl; std::cerr << "no data read" << std::endl;
return std::make_pair(403, ""); return std::make_pair(403, "");
} }
std::string::size_type position = ssl_read_packet.find("\r\n\r\n"); std::string::size_type position = ssl_read_packet.find("\r\n\r\n");
@ -88,8 +89,8 @@ std::pair<int, std::string> HttpClient::doGetRequest(const std::string &url, con
std::smatch status_matches; std::smatch status_matches;
if (std::regex_search(status_str, status_matches, status_rgx)) { if (std::regex_search(status_str, status_matches, status_rgx)) {
if (status_matches.size() > 1) { if (status_matches.size() > 1) {
auto sta = status_matches[1].str(); // string "200" auto sta = status_matches[1].str(); // string "200"
// std::cout << "status: " << sta << std::endl; // std::cout << "status: " << sta << std::endl;
} }
} }
@ -116,7 +117,7 @@ std::string HttpClient::inetAddress(std::string hostname) {
std::cerr << hostname << " is unavailable" << std::endl; std::cerr << hostname << " is unavailable" << std::endl;
exit(1); exit(1);
} }
in_addr *address = (in_addr *)record->h_addr; in_addr *address = (in_addr *) record->h_addr;
std::string ip_address = inet_ntoa(*address); std::string ip_address = inet_ntoa(*address);
return ip_address; return ip_address;
@ -131,8 +132,8 @@ int HttpClient::sslRecvPacket() {
do { do {
len = SSL_read(ssl, buf, len); len = SSL_read(ssl, buf, len);
if (len >= 0) { if (len >= 0) {
buf[len] = 0; buf[len] = 0;
ssl_read_packet.append((const char *)buf); ssl_read_packet.append((const char *) buf);
} }
} while (len > 0); } while (len > 0);
@ -154,15 +155,15 @@ int HttpClient::sslSendPacket(std::string buf) {
if (len < 0) { if (len < 0) {
int err = SSL_get_error(ssl, len); int err = SSL_get_error(ssl, len);
switch (err) { switch (err) {
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
return 0; return 0;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
return 0; return 0;
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL: case SSL_ERROR_SSL:
default: default:
return -1; return -1;
} }
} }
@ -188,7 +189,7 @@ int HttpClient::sslRequest(const std::string &server_name, const std::string &re
socklen_t socklen = sizeof(sa); socklen_t socklen = sizeof(sa);
// connect to server // connect to server
if (connect(s, (struct sockaddr *)&sa, socklen)) { if (connect(s, (struct sockaddr *) &sa, socklen)) {
printf("MlError connecting to server.\n"); printf("MlError connecting to server.\n");
return -1; return -1;
} }
@ -206,8 +207,8 @@ int HttpClient::sslRequest(const std::string &server_name, const std::string &re
} }
sock = SSL_get_fd(ssl); sock = SSL_get_fd(ssl);
SSL_set_fd(ssl, s); SSL_set_fd(ssl, s);
SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)server.c_str()); SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void *) server.c_str());
int err = SSL_connect(ssl); int err = SSL_connect(ssl);
if (err <= 0) { if (err <= 0) {
@ -221,7 +222,7 @@ int HttpClient::sslRequest(const std::string &server_name, const std::string &re
// printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); // printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
// send request // send request
//std::err << request << std::endl; //std::err << request << std::endl;
sslSendPacket(request); sslSendPacket(request);
// read response and return its length // read response and return its length

View File

@ -7,26 +7,30 @@
class HttpClient { class HttpClient {
// TODO at this moment only https is implemented // TODO at this moment only https is implemented
private: private:
SSL *ssl; SSL *ssl;
int sock; int sock;
std::string full_url, proto, server, port, uri, params, href; std::string full_url, proto, server, port, uri, params, href;
std::basic_string<char> ssl_read_packet; std::basic_string<char> ssl_read_packet;
std::unordered_map<std::string, std::string> headers_map; std::unordered_map<std::string, std::string> headers_map;
public: public:
HttpClient(); HttpClient();
std::pair<int, std::string> doGetRequest(const std::string &url, const std::unordered_map<std::string, std::string> &headers); std::pair<int, std::string>
doGetRequest(const std::string &url, const std::unordered_map<std::string, std::string> &headers);
private: private:
std::string inetAddress(std::string hostname); std::string inetAddress(std::string hostname);
int sslRecvPacket(); int sslRecvPacket();
int sslSendPacket(std::string buf);
int sslRequest(const std::string &server_name, const std::string &request); int sslSendPacket(std::string buf);
void log_ssl();
int sslRequest(const std::string &server_name, const std::string &request);
void log_ssl();
}; };

View File

@ -61,8 +61,15 @@
(define pdate (second (first (filter (lambda (x) (= (first x) "payment_Date")) e)))) (define pdate (second (first (filter (lambda (x) (= (first x) "payment_Date")) e))))
(define rdate (second (first (filter (lambda (x) (= (first x) "record_Date")) e)))) (define rdate (second (first (filter (lambda (x) (= (first x) "record_Date")) e))))
(print symbol edate pdate divrate) ;(print symbol edate pdate divrate)
'(symbol edate pdate divrate)
) )
(print (ls-dir "/tmp"))
(print (is-file? "/tmp/file"))
(print (is-file? "/tmp/hovinko"))
(print (is-dir? "/tmp/powerlog"))
(print "Debug ends") (print "Debug ends")

2304
ml.cpp

File diff suppressed because it is too large Load Diff

204
ml.h
View File

@ -1,11 +1,5 @@
#pragma once #pragma once
// Comment this define out to drop support for standard library functions.
// This allows the program to run without a runtime.
#define USE_STD
// Comment this define out to drop support for libm functions
#define HAS_LIBM
#include <map> #include <map>
#include <string> #include <string>
@ -14,7 +8,7 @@
#include <exception> #include <exception>
// // Forward declaration for MlEnvironment class definition // Forward declaration for MlEnvironment class definition
class MlValue; class MlValue;
@ -29,19 +23,22 @@ public:
// This is only used to determine which atoms to capture when // This is only used to determine which atoms to capture when
// creating a lambda function. // creating a lambda function.
bool has(std::string name) const; bool has(std::string name) const;
// Get the value associated with this name in this scope // Get the value associated with this name in this scope
MlValue get(const std::string& name) const; MlValue get(const std::string &name) const;
// Set the value associated with this name in this scope // Set the value associated with this name in this scope
void set(std::string name, MlValue value); void set(std::string name, MlValue value);
void combine(MlEnvironment const &other); void combine(MlEnvironment const &other);
void set_parent_scope(MlEnvironment *parent) { void set_parent_scope(MlEnvironment *parent) {
parent_scope = parent; parent_scope = parent;
} }
// Output this scope in readable form to a stream. // Output this scope in readable form to a stream.
friend std::ostream &operator<<(std::ostream &os, MlEnvironment const &v); friend std::ostream &operator<<(std::ostream &os, MlEnvironment const &v);
private: private:
// The definitions in the scope. // The definitions in the scope.
@ -50,20 +47,21 @@ private:
}; };
// An exception thrown by the lisp // An exception thrown by the lisp
class MlError { class MlError {
public: public:
// Create an error with the value that caused the error, // Create an error with the value that caused the error,
// the scope where the error was found, and the message. // the scope where the error was found, and the message.
MlError(const MlValue &v, MlEnvironment const &env, const char *msg); MlError(const MlValue &v, MlEnvironment const &env, const char *msg);
// Copy constructor is needed to prevent double frees // Copy constructor is needed to prevent double frees
MlError(MlError const &other); MlError(MlError const &other);
~MlError(); ~MlError();
// Get the printable error description. // Get the printable error description.
std::string description(); std::string description();
private: private:
MlValue *cause; MlValue *cause;
MlEnvironment env; MlEnvironment env;
@ -71,142 +69,144 @@ private:
}; };
// The type for a builtin function, which takes a list of values, // The type for a builtin function, which takes a list of values,
// and the environment to run the function in. // and the environment to run the function in.
typedef MlValue (*Builtin)(std::vector<MlValue>, MlEnvironment &); typedef MlValue (*Builtin)(std::vector<MlValue>, MlEnvironment &);
class MlValue { class MlValue {
public: public:
// Constructs a unit value // Constructs a unit value
MlValue(); MlValue();
// Constructs an integer // Constructs an integer
MlValue(int i); MlValue(int i);
// Constructs a floating point value
MlValue(double f);
// Constructs a list
MlValue(const std::vector<MlValue> &list);
// Construct a quoted value // Constructs a floating point value
static MlValue quote(const MlValue& quoted); MlValue(double f);
// Construct an atom // Constructs a list
static MlValue atom(const std::string &s); MlValue(const std::vector<MlValue> &list);
// Construct a string // Construct a quoted value
static MlValue string(const std::string &s); static MlValue quote(const MlValue &quoted);
// Construct a lambda function // Construct an atom
MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env); static MlValue atom(const std::string &s);
// Construct a builtin function // Construct a string
MlValue(const std::string &name, Builtin b); static MlValue string(const std::string &s);
std::vector<std::string> get_used_atoms(); // Construct a lambda function
MlValue(const std::vector<MlValue> &params, MlValue ret, MlEnvironment const &env);
// Is this a builtin function? // Construct a builtin function
bool is_builtin(); MlValue(const std::string &name, Builtin b);
// Apply this as a function to a list of arguments in a given environment. std::vector<std::string> get_used_atoms();
MlValue apply(std::vector<MlValue> args, MlEnvironment &env);
// Evaluate this value as lisp code.
MlValue eval(MlEnvironment &env);
bool is_number() const; // Is this a builtin function?
bool is_builtin();
// Get the "truthy" boolean value of this value. // Apply this as a function to a list of arguments in a given environment.
bool as_bool() const; MlValue apply(std::vector<MlValue> args, MlEnvironment &env);
// Get this item's integer value // Evaluate this value as lisp code.
int as_int() const; MlValue eval(MlEnvironment &env);
// Get this item's floating point value bool is_number() const;
double as_float() const;
// Get this item's string value // Get the "truthy" boolean value of this value.
std::string as_string() const; bool as_bool() const;
// Get this item's atom value // Get this item's integer value
std::string as_atom() const; int as_int() const;
// Get this item's list value // Get this item's floating point value
std::vector<MlValue> as_list() const; double as_float() const;
// Push an item to the end of this list // Get this item's string value
void push(MlValue val); std::string as_string() const;
// Push an item from the end of this list // Get this item's atom value
MlValue pop(); std::string as_atom() const;
// Get this item's list value
std::vector<MlValue> as_list() const;
// Push an item to the end of this list
void push(MlValue val);
// Push an item from the end of this list
MlValue pop();
// Cast this to an integer value // Cast this to an integer value
MlValue cast_to_int() const; MlValue cast_to_int() const;
// Cast this to a floating point value // Cast this to a floating point value
MlValue cast_to_float() const; MlValue cast_to_float() const;
bool operator==(MlValue other) const; bool operator==(MlValue other) const;
bool operator!=(const MlValue &other) const; bool operator!=(const MlValue &other) const;
bool operator>=(const MlValue &other) const; bool operator>=(const MlValue &other) const;
bool operator<=(const MlValue &other) const; bool operator<=(const MlValue &other) const;
bool operator>(const MlValue &other) const; bool operator>(const MlValue &other) const;
bool operator<(const MlValue &other) const; bool operator<(const MlValue &other) const;
// This function adds two lisp values, and returns the lisp value result. // This function adds two lisp values, and returns the lisp value result.
MlValue operator+(const MlValue &other) const; MlValue operator+(const MlValue &other) const;
// This function subtracts two lisp values, and returns the lisp value result. // This function subtracts two lisp values, and returns the lisp value result.
MlValue operator-(const MlValue &other) const; MlValue operator-(const MlValue &other) const;
// This function multiplies two lisp values, and returns the lisp value result. // This function multiplies two lisp values, and returns the lisp value result.
MlValue operator*(const MlValue &other) const; MlValue operator*(const MlValue &other) const;
// This function divides two lisp values, and returns the lisp value result. // This function divides two lisp values, and returns the lisp value result.
MlValue operator/(const MlValue &other) const; MlValue operator/(const MlValue &other) const;
// This function finds the remainder of two lisp values, and returns the lisp value result. // This function finds the remainder of two lisp values, and returns the lisp value result.
MlValue operator%(const MlValue &other) const; MlValue operator%(const MlValue &other) const;
// Get the name of the type of this value // Get the name of the type of this value
std::string get_type_name(); std::string get_type_name();
std::string display() const; std::string display() const;
std::string debug() const; std::string debug() const;
friend std::ostream &operator<<(std::ostream &os, MlValue const &v); friend std::ostream &operator<<(std::ostream &os, MlValue const &v);
private: private:
enum { enum {
QUOTE, QUOTE,
ATOM, ATOM,
INT, INT,
FLOAT, FLOAT,
LIST, LIST,
STRING, STRING,
LAMBDA, LAMBDA,
BUILTIN, BUILTIN,
UNIT UNIT
} type; } type;
union { union {
int i; int i;
double f; double f;
Builtin b; Builtin b;
} stack_data; } stack_data;
std::string str; std::string str;
std::vector<MlValue> list; std::vector<MlValue> list;
MlEnvironment lambda_scope; MlEnvironment lambda_scope;
}; };

62
ml_io.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "ml_io.h"
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
std::string read_file_contents(const std::string &filename) {
std::ifstream f;
f.open(filename.c_str());
if (!f)
throw std::runtime_error("could not open file");
f.seekg(0, std::ios::end);
std::string contents;
contents.reserve(f.tellg());
f.seekg(0, std::ios::beg);
contents.assign(std::istreambuf_iterator<char>(f),
std::istreambuf_iterator<char>());
f.close();
return contents;
}
MlValue list_dir(const std::string &path) {
std::vector<MlValue> entries;
DIR *dirp = opendir(path.c_str());
if (dirp == NULL) {
// handle error - probably not a dir or non existing path
}
struct dirent *dp;
while ((dp = readdir(dirp)) != NULL) {
entries.push_back(MlValue::string(dp->d_name));
}
closedir(dirp);
return MlValue(entries);
}
bool is_path_file(const std::string &path) {
std::ifstream ifile(path.c_str());
return (bool) ifile;
}
bool is_path_dir(const std::string &path) {
struct stat buf;
stat(path.c_str(), &buf);
return (bool) S_ISDIR(buf.st_mode);
}
int mk_dir(const std::string &path) {
int r = ::mkdir(path.c_str(), 0755);
return r;
}
int rm_dir(const std::string &path) {
int r = ::rmdir(path.c_str());
return r;
}

21
ml_io.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "../ml.h"
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
std::string read_file_contents(const std::string &filename);
MlValue list_dir(const std::string &path);
bool is_path_file(const std::string &path);
bool is_path_dir(const std::string &path);
int mk_dir(const std::string &path);
int rm_dir(const std::string &path);