REMOVED USER_STD macros, code formating, csv changes, few file functions
This commit is contained in:
parent
125c73ac33
commit
c1532e78b1
|
|
@ -2,3 +2,4 @@ build
|
||||||
/cmake-build-debug/
|
/cmake-build-debug/
|
||||||
.idea
|
.idea
|
||||||
ml
|
ml
|
||||||
|
.DS_Store
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,10 +57,12 @@ 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;
|
||||||
|
|
||||||
|
|
@ -85,7 +89,7 @@ MlValue CsvParser::ivalualize(std::vector< std::vector<std::string> > &parsed_da
|
||||||
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 {
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,17 @@ private:
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
187
clib/json11.cpp
187
clib/json11.cpp
|
|
@ -23,6 +23,7 @@ namespace json11 {
|
||||||
*/
|
*/
|
||||||
struct NullStruct {
|
struct NullStruct {
|
||||||
bool operator==(NullStruct) const { return true; }
|
bool operator==(NullStruct) const { return true; }
|
||||||
|
|
||||||
bool operator<(NullStruct) const { return false; }
|
bool operator<(NullStruct) const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -76,12 +77,12 @@ namespace json11 {
|
||||||
char buf[8];
|
char buf[8];
|
||||||
snprintf(buf, sizeof buf, "\\u%04x", ch);
|
snprintf(buf, sizeof buf, "\\u%04x", ch);
|
||||||
out += buf;
|
out += buf;
|
||||||
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
|
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i + 1]) == 0x80
|
||||||
&& static_cast<uint8_t>(value[i+2]) == 0xa8) {
|
&& static_cast<uint8_t>(value[i + 2]) == 0xa8) {
|
||||||
out += "\\u2028";
|
out += "\\u2028";
|
||||||
i += 2;
|
i += 2;
|
||||||
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
|
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i + 1]) == 0x80
|
||||||
&& static_cast<uint8_t>(value[i+2]) == 0xa9) {
|
&& static_cast<uint8_t>(value[i + 2]) == 0xa9) {
|
||||||
out += "\\u2029";
|
out += "\\u2029";
|
||||||
i += 2;
|
i += 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -144,7 +145,7 @@ namespace json11 {
|
||||||
return MlValue(value);
|
return MlValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MlValue ivalualize(const string& value) {
|
static MlValue ivalualize(const string &value) {
|
||||||
return MlValue::string(value);
|
return MlValue::string(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,44 +178,17 @@ namespace json11 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
* Value wrappers
|
* Value wrappers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <Json::Type tag, typename T>
|
template<Json::Type tag, typename T>
|
||||||
class Value : public JsonValue {
|
class Value : public JsonValue {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
explicit Value(const T &value) : m_value(value) {}
|
explicit Value(const T &value) : m_value(value) {}
|
||||||
|
|
||||||
explicit Value(T &&value) : m_value(move(value)) {}
|
explicit Value(T &&value) : m_value(move(value)) {}
|
||||||
|
|
||||||
// Get type tag
|
// Get type tag
|
||||||
|
|
@ -223,14 +197,16 @@ namespace json11 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparisons
|
// Comparisons
|
||||||
bool equals(const JsonValue * other) const override {
|
bool equals(const JsonValue *other) const override {
|
||||||
return m_value == static_cast<const Value<tag, T> *>(other)->m_value;
|
return m_value == static_cast<const Value<tag, T> *>(other)->m_value;
|
||||||
}
|
}
|
||||||
bool less(const JsonValue * other) const override {
|
|
||||||
|
bool less(const JsonValue *other) const override {
|
||||||
return m_value < static_cast<const Value<tag, T> *>(other)->m_value;
|
return m_value < static_cast<const Value<tag, T> *>(other)->m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T m_value;
|
const T m_value;
|
||||||
|
|
||||||
void dump(string &out) const override { json11::dump(m_value, out); }
|
void dump(string &out) const override { json11::dump(m_value, out); }
|
||||||
|
|
||||||
MlValue ivalualize() const override { return json11::ivalualize(m_value); }
|
MlValue ivalualize() const override { return json11::ivalualize(m_value); }
|
||||||
|
|
@ -238,48 +214,65 @@ namespace json11 {
|
||||||
|
|
||||||
class JsonDouble final : public Value<Json::NUMBER, double> {
|
class JsonDouble final : public Value<Json::NUMBER, double> {
|
||||||
double number_value() const override { return m_value; }
|
double number_value() const override { return m_value; }
|
||||||
|
|
||||||
int int_value() const override { return static_cast<int>(m_value); }
|
int int_value() const override { return static_cast<int>(m_value); }
|
||||||
bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
|
|
||||||
bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
|
bool equals(const JsonValue *other) const override { return m_value == other->number_value(); }
|
||||||
|
|
||||||
|
bool less(const JsonValue *other) const override { return m_value < other->number_value(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonDouble(double value) : Value(value) {}
|
explicit JsonDouble(double value) : Value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonInt final : public Value<Json::NUMBER, int> {
|
class JsonInt final : public Value<Json::NUMBER, int> {
|
||||||
double number_value() const override { return m_value; }
|
double number_value() const override { return m_value; }
|
||||||
|
|
||||||
int int_value() const override { return m_value; }
|
int int_value() const override { return m_value; }
|
||||||
bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
|
|
||||||
bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
|
bool equals(const JsonValue *other) const override { return m_value == other->number_value(); }
|
||||||
|
|
||||||
|
bool less(const JsonValue *other) const override { return m_value < other->number_value(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonInt(int value) : Value(value) {}
|
explicit JsonInt(int value) : Value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonBoolean final : public Value<Json::BOOL, bool> {
|
class JsonBoolean final : public Value<Json::BOOL, bool> {
|
||||||
bool bool_value() const override { return m_value; }
|
bool bool_value() const override { return m_value; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonBoolean(bool value) : Value(value) {}
|
explicit JsonBoolean(bool value) : Value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonString final : public Value<Json::STRING, string> {
|
class JsonString final : public Value<Json::STRING, string> {
|
||||||
const string &string_value() const override { return m_value; }
|
const string &string_value() const override { return m_value; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonString(const string &value) : Value(value) {}
|
explicit JsonString(const string &value) : Value(value) {}
|
||||||
|
|
||||||
explicit JsonString(string &&value) : Value(move(value)) {}
|
explicit JsonString(string &&value) : Value(move(value)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArray final : public Value<Json::ARRAY, Json::array> {
|
class JsonArray final : public Value<Json::ARRAY, Json::array> {
|
||||||
const Json::array &array_items() const override { return m_value; }
|
const Json::array &array_items() const override { return m_value; }
|
||||||
const Json & operator[](size_t i) const override;
|
|
||||||
|
const Json &operator[](size_t i) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonArray(const Json::array &value) : Value(value) {}
|
explicit JsonArray(const Json::array &value) : Value(value) {}
|
||||||
|
|
||||||
explicit JsonArray(Json::array &&value) : Value(move(value)) {}
|
explicit JsonArray(Json::array &&value) : Value(move(value)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonObject final : public Value<Json::OBJECT, Json::object> {
|
class JsonObject final : public Value<Json::OBJECT, Json::object> {
|
||||||
const Json::object &object_items() const override { return m_value; }
|
const Json::object &object_items() const override { return m_value; }
|
||||||
const Json & operator[](const string &key) const override;
|
|
||||||
|
const Json &operator[](const string &key) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JsonObject(const Json::object &value) : Value(value) {}
|
explicit JsonObject(const Json::object &value) : Value(value) {}
|
||||||
|
|
||||||
explicit JsonObject(Json::object &&value) : Value(move(value)) {}
|
explicit JsonObject(Json::object &&value) : Value(move(value)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -298,15 +291,16 @@ namespace json11 {
|
||||||
const string empty_string;
|
const string empty_string;
|
||||||
const vector<Json> empty_vector;
|
const vector<Json> empty_vector;
|
||||||
const map<string, Json> empty_map;
|
const map<string, Json> empty_map;
|
||||||
|
|
||||||
Statics() {}
|
Statics() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Statics & statics() {
|
static const Statics &statics() {
|
||||||
static const Statics s {};
|
static const Statics s{};
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Json & static_null() {
|
static const Json &static_null() {
|
||||||
// This has to be separate, not in Statics, because Json() accesses statics().null.
|
// This has to be separate, not in Statics, because Json() accesses statics().null.
|
||||||
static const Json json_null;
|
static const Json json_null;
|
||||||
return json_null;
|
return json_null;
|
||||||
|
|
@ -316,17 +310,28 @@ namespace json11 {
|
||||||
* Constructors
|
* Constructors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Json::Json() noexcept : m_ptr(statics().null) {}
|
Json::Json() noexcept: m_ptr(statics().null) {}
|
||||||
Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {}
|
|
||||||
|
Json::Json(std::nullptr_t) noexcept: m_ptr(statics().null) {}
|
||||||
|
|
||||||
Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {}
|
Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {}
|
||||||
|
|
||||||
Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {}
|
Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {}
|
||||||
|
|
||||||
Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
|
Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
|
||||||
|
|
||||||
Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {}
|
Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {}
|
||||||
|
|
||||||
Json::Json(string &&value) : m_ptr(make_shared<JsonString>(move(value))) {}
|
Json::Json(string &&value) : m_ptr(make_shared<JsonString>(move(value))) {}
|
||||||
Json::Json(const char * value) : m_ptr(make_shared<JsonString>(value)) {}
|
|
||||||
|
Json::Json(const char *value) : m_ptr(make_shared<JsonString>(value)) {}
|
||||||
|
|
||||||
Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {}
|
Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {}
|
||||||
|
|
||||||
Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {}
|
Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {}
|
||||||
|
|
||||||
Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {}
|
Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {}
|
||||||
|
|
||||||
Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {}
|
Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
|
@ -334,29 +339,45 @@ namespace json11 {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Json::Type Json::type() const { return m_ptr->type(); }
|
Json::Type Json::type() const { return m_ptr->type(); }
|
||||||
|
|
||||||
double Json::number_value() const { return m_ptr->number_value(); }
|
double Json::number_value() const { return m_ptr->number_value(); }
|
||||||
|
|
||||||
int Json::int_value() const { return m_ptr->int_value(); }
|
int Json::int_value() const { return m_ptr->int_value(); }
|
||||||
|
|
||||||
bool Json::bool_value() const { return m_ptr->bool_value(); }
|
bool Json::bool_value() const { return m_ptr->bool_value(); }
|
||||||
const string & Json::string_value() const { return m_ptr->string_value(); }
|
|
||||||
const vector<Json> & Json::array_items() const { return m_ptr->array_items(); }
|
const string &Json::string_value() const { return m_ptr->string_value(); }
|
||||||
const map<string, Json> & Json::object_items() const { return m_ptr->object_items(); }
|
|
||||||
const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; }
|
const vector<Json> &Json::array_items() const { return m_ptr->array_items(); }
|
||||||
const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; }
|
|
||||||
|
const map<string, Json> &Json::object_items() const { return m_ptr->object_items(); }
|
||||||
|
|
||||||
|
const Json &Json::operator[](size_t i) const { return (*m_ptr)[i]; }
|
||||||
|
|
||||||
|
const Json &Json::operator[](const string &key) const { return (*m_ptr)[key]; }
|
||||||
|
|
||||||
double JsonValue::number_value() const { return 0; }
|
double JsonValue::number_value() const { return 0; }
|
||||||
int JsonValue::int_value() const { return 0; }
|
|
||||||
bool JsonValue::bool_value() const { return false; }
|
|
||||||
const string & JsonValue::string_value() const { return statics().empty_string; }
|
|
||||||
const vector<Json> & JsonValue::array_items() const { return statics().empty_vector; }
|
|
||||||
const map<string, Json> & JsonValue::object_items() const { return statics().empty_map; }
|
|
||||||
const Json & JsonValue::operator[] (size_t) const { return static_null(); }
|
|
||||||
const Json & JsonValue::operator[] (const string &) const { return static_null(); }
|
|
||||||
|
|
||||||
const Json & JsonObject::operator[] (const string &key) const {
|
int JsonValue::int_value() const { return 0; }
|
||||||
|
|
||||||
|
bool JsonValue::bool_value() const { return false; }
|
||||||
|
|
||||||
|
const string &JsonValue::string_value() const { return statics().empty_string; }
|
||||||
|
|
||||||
|
const vector<Json> &JsonValue::array_items() const { return statics().empty_vector; }
|
||||||
|
|
||||||
|
const map<string, Json> &JsonValue::object_items() const { return statics().empty_map; }
|
||||||
|
|
||||||
|
const Json &JsonValue::operator[](size_t) const { return static_null(); }
|
||||||
|
|
||||||
|
const Json &JsonValue::operator[](const string &) const { return static_null(); }
|
||||||
|
|
||||||
|
const Json &JsonObject::operator[](const string &key) const {
|
||||||
auto iter = m_value.find(key);
|
auto iter = m_value.find(key);
|
||||||
return (iter == m_value.end()) ? static_null() : iter->second;
|
return (iter == m_value.end()) ? static_null() : iter->second;
|
||||||
}
|
}
|
||||||
const Json & JsonArray::operator[] (size_t i) const {
|
|
||||||
|
const Json &JsonArray::operator[](size_t i) const {
|
||||||
if (i >= m_value.size()) return static_null();
|
if (i >= m_value.size()) return static_null();
|
||||||
else return m_value[i];
|
else return m_value[i];
|
||||||
}
|
}
|
||||||
|
|
@ -365,7 +386,7 @@ namespace json11 {
|
||||||
* Comparison
|
* Comparison
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Json::operator== (const Json &other) const {
|
bool Json::operator==(const Json &other) const {
|
||||||
if (m_ptr == other.m_ptr)
|
if (m_ptr == other.m_ptr)
|
||||||
return true;
|
return true;
|
||||||
if (m_ptr->type() != other.m_ptr->type())
|
if (m_ptr->type() != other.m_ptr->type())
|
||||||
|
|
@ -374,7 +395,7 @@ namespace json11 {
|
||||||
return m_ptr->equals(other.m_ptr.get());
|
return m_ptr->equals(other.m_ptr.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Json::operator< (const Json &other) const {
|
bool Json::operator<(const Json &other) const {
|
||||||
if (m_ptr == other.m_ptr)
|
if (m_ptr == other.m_ptr)
|
||||||
return false;
|
return false;
|
||||||
if (m_ptr->type() != other.m_ptr->type())
|
if (m_ptr->type() != other.m_ptr->type())
|
||||||
|
|
@ -428,7 +449,7 @@ namespace json11 {
|
||||||
return fail(move(msg), Json());
|
return fail(move(msg), Json());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
T fail(string &&msg, const T err_ret) {
|
T fail(string &&msg, const T err_ret) {
|
||||||
if (!failed)
|
if (!failed)
|
||||||
err = std::move(msg);
|
err = std::move(msg);
|
||||||
|
|
@ -462,22 +483,20 @@ namespace json11 {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
comment_found = true;
|
comment_found = true;
|
||||||
}
|
} else if (str[i] == '*') { // multiline comment
|
||||||
else if (str[i] == '*') { // multiline comment
|
|
||||||
i++;
|
i++;
|
||||||
if (i > str.size()-2)
|
if (i > str.size() - 2)
|
||||||
return fail("unexpected end of input inside multi-line comment", false);
|
return fail("unexpected end of input inside multi-line comment", false);
|
||||||
// advance until closing tokens
|
// advance until closing tokens
|
||||||
while (!(str[i] == '*' && str[i+1] == '/')) {
|
while (!(str[i] == '*' && str[i + 1] == '/')) {
|
||||||
i++;
|
i++;
|
||||||
if (i > str.size()-2)
|
if (i > str.size() - 2)
|
||||||
return fail(
|
return fail(
|
||||||
"unexpected end of input inside multi-line comment", false);
|
"unexpected end of input inside multi-line comment", false);
|
||||||
}
|
}
|
||||||
i += 2;
|
i += 2;
|
||||||
comment_found = true;
|
comment_found = true;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return fail("malformed comment", false);
|
return fail("malformed comment", false);
|
||||||
}
|
}
|
||||||
return comment_found;
|
return comment_found;
|
||||||
|
|
@ -489,14 +508,13 @@ namespace json11 {
|
||||||
*/
|
*/
|
||||||
void consume_garbage() {
|
void consume_garbage() {
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
if(strategy == JsonParse::COMMENTS) {
|
if (strategy == JsonParse::COMMENTS) {
|
||||||
bool comment_found = false;
|
bool comment_found = false;
|
||||||
do {
|
do {
|
||||||
comment_found = consume_comment();
|
comment_found = consume_comment();
|
||||||
if (failed) return;
|
if (failed) return;
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
}
|
} while (comment_found);
|
||||||
while(comment_found);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,9 +525,9 @@ namespace json11 {
|
||||||
*/
|
*/
|
||||||
char get_next_token() {
|
char get_next_token() {
|
||||||
consume_garbage();
|
consume_garbage();
|
||||||
if (failed) return (char)0;
|
if (failed) return (char) 0;
|
||||||
if (i == str.size())
|
if (i == str.size())
|
||||||
return fail("unexpected end of input", (char)0);
|
return fail("unexpected end of input", (char) 0);
|
||||||
|
|
||||||
return str[i++];
|
return str[i++];
|
||||||
}
|
}
|
||||||
|
|
@ -518,7 +536,7 @@ namespace json11 {
|
||||||
*
|
*
|
||||||
* Encode pt as UTF-8 and add it to out.
|
* Encode pt as UTF-8 and add it to out.
|
||||||
*/
|
*/
|
||||||
void encode_utf8(long pt, string & out) {
|
void encode_utf8(long pt, string &out) {
|
||||||
if (pt < 0)
|
if (pt < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -699,7 +717,8 @@ namespace json11 {
|
||||||
i += expected.length();
|
i += expected.length();
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length()));
|
return fail(
|
||||||
|
"parse error: expected " + expected + ", got " + str.substr(i, expected.length()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -785,7 +804,7 @@ namespace json11 {
|
||||||
return fail("expected ',' in list, got " + esc(ch));
|
return fail("expected ',' in list, got " + esc(ch));
|
||||||
|
|
||||||
ch = get_next_token();
|
ch = get_next_token();
|
||||||
(void)ch;
|
(void) ch;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
@ -796,7 +815,7 @@ namespace json11 {
|
||||||
}//namespace {
|
}//namespace {
|
||||||
|
|
||||||
Json Json::parse(const string &in, string &err, JsonParse strategy) {
|
Json Json::parse(const string &in, string &err, JsonParse strategy) {
|
||||||
JsonParser parser { in, 0, err, false, strategy };
|
JsonParser parser{in, 0, err, false, strategy};
|
||||||
Json result = parser.parse_json(0);
|
Json result = parser.parse_json(0);
|
||||||
|
|
||||||
// Check for any trailing garbage
|
// Check for any trailing garbage
|
||||||
|
|
@ -814,7 +833,7 @@ namespace json11 {
|
||||||
std::string::size_type &parser_stop_pos,
|
std::string::size_type &parser_stop_pos,
|
||||||
string &err,
|
string &err,
|
||||||
JsonParse strategy) {
|
JsonParse strategy) {
|
||||||
JsonParser parser { in, 0, err, false, strategy };
|
JsonParser parser{in, 0, err, false, strategy};
|
||||||
parser_stop_pos = 0;
|
parser_stop_pos = 0;
|
||||||
vector<Json> json_vec;
|
vector<Json> json_vec;
|
||||||
while (parser.i != in.size() && !parser.failed) {
|
while (parser.i != in.size() && !parser.failed) {
|
||||||
|
|
@ -835,13 +854,13 @@ namespace json11 {
|
||||||
* Shape-checking
|
* Shape-checking
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Json::has_shape(const shape & types, string & err) const {
|
bool Json::has_shape(const shape &types, string &err) const {
|
||||||
if (!is_object()) {
|
if (!is_object()) {
|
||||||
err = "expected JSON object, got " + dump();
|
err = "expected JSON object, got " + dump();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & item : types) {
|
for (auto &item : types) {
|
||||||
if ((*this)[item.first].type() != item.second) {
|
if ((*this)[item.first].type() != item.second) {
|
||||||
err = "bad type for " + item.first + " in " + dump();
|
err = "bad type for " + item.first + " in " + dump();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -35,28 +35,28 @@ namespace json11 {
|
||||||
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.
|
||||||
|
|
@ -66,34 +66,45 @@ namespace json11 {
|
||||||
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_number() const { return type() == NUMBER; }
|
||||||
|
|
||||||
bool is_bool() const { return type() == BOOL; }
|
bool is_bool() const { return type() == BOOL; }
|
||||||
|
|
||||||
bool is_string() const { return type() == STRING; }
|
bool is_string() const { return type() == STRING; }
|
||||||
|
|
||||||
bool is_array() const { return type() == ARRAY; }
|
bool is_array() const { return type() == ARRAY; }
|
||||||
|
|
||||||
bool is_object() const { return type() == OBJECT; }
|
bool is_object() const { return type() == OBJECT; }
|
||||||
|
|
||||||
// Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
|
// Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
|
||||||
// distinguish between integer and non-integer numbers - number_value() and int_value()
|
// distinguish between integer and non-integer numbers - number_value() and int_value()
|
||||||
// can both be applied to a NUMBER-typed object.
|
// can both be applied to a NUMBER-typed object.
|
||||||
double number_value() const;
|
double number_value() const;
|
||||||
|
|
||||||
int int_value() const;
|
int int_value() const;
|
||||||
|
|
||||||
// Return the enclosed value if this is a boolean, false otherwise.
|
// Return the enclosed value if this is a boolean, false otherwise.
|
||||||
bool bool_value() const;
|
bool bool_value() const;
|
||||||
|
|
||||||
// Return the enclosed string if this is a string, "" otherwise.
|
// Return the enclosed string if this is a string, "" otherwise.
|
||||||
const std::string &string_value() const;
|
const std::string &string_value() const;
|
||||||
|
|
||||||
// Return the enclosed std::vector if this is an array, or an empty vector otherwise.
|
// Return the enclosed std::vector if this is an array, or an empty vector otherwise.
|
||||||
const array &array_items() const;
|
const array &array_items() const;
|
||||||
|
|
||||||
// Return the enclosed std::map if this is an object, or an empty map otherwise.
|
// Return the enclosed std::map if this is an object, or an empty map otherwise.
|
||||||
const object &object_items() const;
|
const object &object_items() const;
|
||||||
|
|
||||||
// Return a reference to arr[i] if this is an array, Json() otherwise.
|
// Return a reference to arr[i] if this is an array, Json() otherwise.
|
||||||
const Json & operator[](size_t i) const;
|
const Json &operator[](size_t i) const;
|
||||||
|
|
||||||
// Return a reference to obj[key] if this is an object, Json() otherwise.
|
// Return a reference to obj[key] if this is an object, Json() otherwise.
|
||||||
const Json & operator[](const std::string &key) const;
|
const Json &operator[](const std::string &key) const;
|
||||||
|
|
||||||
// Serialize.
|
// Serialize.
|
||||||
void dump(std::string &out) const;
|
void dump(std::string &out) const;
|
||||||
|
|
||||||
std::string dump() const {
|
std::string dump() const {
|
||||||
std::string out;
|
std::string out;
|
||||||
dump(out);
|
dump(out);
|
||||||
|
|
@ -103,11 +114,12 @@ namespace json11 {
|
||||||
MlValue ivalualize() const;
|
MlValue ivalualize() const;
|
||||||
|
|
||||||
// Parse. If parse fails, return Json() and assign an error message to err.
|
// Parse. If parse fails, return Json() and assign an error message to err.
|
||||||
static Json parse(const std::string & in,
|
static Json parse(const std::string &in,
|
||||||
std::string & err,
|
std::string &err,
|
||||||
JsonParse strategy = JsonParse::STANDARD);
|
JsonParse strategy = JsonParse::STANDARD);
|
||||||
static Json parse(const char * in,
|
|
||||||
std::string & err,
|
static Json parse(const char *in,
|
||||||
|
std::string &err,
|
||||||
JsonParse strategy = JsonParse::STANDARD) {
|
JsonParse strategy = JsonParse::STANDARD) {
|
||||||
if (in) {
|
if (in) {
|
||||||
return parse(std::string(in), err, strategy);
|
return parse(std::string(in), err, strategy);
|
||||||
|
|
@ -116,27 +128,33 @@ namespace json11 {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse multiple objects, concatenated or separated by whitespace
|
// Parse multiple objects, concatenated or separated by whitespace
|
||||||
static std::vector<Json> parse_multi(
|
static std::vector<Json> parse_multi(
|
||||||
const std::string & in,
|
const std::string &in,
|
||||||
std::string::size_type & parser_stop_pos,
|
std::string::size_type &parser_stop_pos,
|
||||||
std::string & err,
|
std::string &err,
|
||||||
JsonParse strategy = JsonParse::STANDARD);
|
JsonParse strategy = JsonParse::STANDARD);
|
||||||
|
|
||||||
static inline std::vector<Json> parse_multi(
|
static inline std::vector<Json> parse_multi(
|
||||||
const std::string & in,
|
const std::string &in,
|
||||||
std::string & err,
|
std::string &err,
|
||||||
JsonParse strategy = JsonParse::STANDARD) {
|
JsonParse strategy = JsonParse::STANDARD) {
|
||||||
std::string::size_type parser_stop_pos;
|
std::string::size_type parser_stop_pos;
|
||||||
return parse_multi(in, parser_stop_pos, err, strategy);
|
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;
|
|
||||||
bool operator!= (const Json &rhs) const { return !(*this == rhs); }
|
bool operator<(const Json &rhs) const;
|
||||||
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); }
|
||||||
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)
|
/* has_shape(types, err)
|
||||||
*
|
*
|
||||||
|
|
@ -144,7 +162,8 @@ namespace json11 {
|
||||||
* the given type. If not, return false and set err to a descriptive message.
|
* the given type. If not, return false and set err to a descriptive message.
|
||||||
*/
|
*/
|
||||||
typedef std::initializer_list<std::pair<std::string, Type>> shape;
|
typedef std::initializer_list<std::pair<std::string, Type>> shape;
|
||||||
bool has_shape(const shape & types, std::string & err) const;
|
|
||||||
|
bool has_shape(const shape &types, std::string &err) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<JsonValue> m_ptr;
|
std::shared_ptr<JsonValue> m_ptr;
|
||||||
|
|
@ -154,21 +173,37 @@ namespace json11 {
|
||||||
class JsonValue {
|
class JsonValue {
|
||||||
protected:
|
protected:
|
||||||
friend class Json;
|
friend class Json;
|
||||||
|
|
||||||
friend class JsonInt;
|
friend class JsonInt;
|
||||||
|
|
||||||
friend class JsonDouble;
|
friend class JsonDouble;
|
||||||
|
|
||||||
virtual Json::Type type() const = 0;
|
virtual Json::Type type() const = 0;
|
||||||
virtual bool equals(const JsonValue * other) const = 0;
|
|
||||||
virtual bool less(const JsonValue * other) const = 0;
|
virtual bool equals(const JsonValue *other) const = 0;
|
||||||
|
|
||||||
|
virtual bool less(const JsonValue *other) const = 0;
|
||||||
|
|
||||||
virtual void dump(std::string &out) const = 0;
|
virtual void dump(std::string &out) const = 0;
|
||||||
|
|
||||||
virtual MlValue ivalualize() const = 0;
|
virtual MlValue ivalualize() const = 0;
|
||||||
|
|
||||||
virtual double number_value() const;
|
virtual double number_value() const;
|
||||||
|
|
||||||
virtual int int_value() const;
|
virtual int int_value() const;
|
||||||
|
|
||||||
virtual bool bool_value() const;
|
virtual bool bool_value() const;
|
||||||
|
|
||||||
virtual const std::string &string_value() const;
|
virtual const std::string &string_value() const;
|
||||||
|
|
||||||
virtual const Json::array &array_items() const;
|
virtual const Json::array &array_items() const;
|
||||||
|
|
||||||
virtual const Json &operator[](size_t i) const;
|
virtual const Json &operator[](size_t i) const;
|
||||||
|
|
||||||
virtual const Json::object &object_items() const;
|
virtual const Json::object &object_items() const;
|
||||||
|
|
||||||
virtual const Json &operator[](const std::string &key) const;
|
virtual const Json &operator[](const std::string &key) const;
|
||||||
|
|
||||||
virtual ~JsonValue() {}
|
virtual ~JsonValue() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@
|
||||||
#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?#]+)?([?][^?#]*)?(#.*)?)?)"};
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -132,7 +133,7 @@ int HttpClient::sslRecvPacket() {
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +208,7 @@ 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) {
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,17 @@ private:
|
||||||
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 sslSendPacket(std::string buf);
|
||||||
|
|
||||||
int sslRequest(const std::string &server_name, const std::string &request);
|
int sslRequest(const std::string &server_name, const std::string &request);
|
||||||
|
|
||||||
void log_ssl();
|
void log_ssl();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
148
ml.cpp
148
ml.cpp
|
|
@ -1,39 +1,23 @@
|
||||||
// Comment this define out to drop support for standard library functions.
|
|
||||||
// This allows the program to run without a runtime.
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAS_LIBM
|
|
||||||
#include <cmath>
|
|
||||||
#else
|
|
||||||
#define NO_LIBM_SUPPORT "no libm support"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "ml.h"
|
#include "ml.h"
|
||||||
|
#include "ml_io.h"
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <sstream>
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_STD
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "csvparser.h"
|
#include "csvparser.h"
|
||||||
#include "sslclient.h"
|
#include "sslclient.h"
|
||||||
#include "json11.h"
|
#include "json11.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
|
||||||
#define TOO_FEW_ARGS "too few arguments to function"
|
#define TOO_FEW_ARGS "too few arguments to function"
|
||||||
#define TOO_MANY_ARGS "too many arguments to function"
|
#define TOO_MANY_ARGS "too many arguments to function"
|
||||||
#define INVALID_ARGUMENT "invalid argument"
|
#define INVALID_ARGUMENT "invalid argument"
|
||||||
|
|
@ -62,34 +46,11 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_STD
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define NO_STD "no standard library support"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Convert an object to a string using a stringstream conveniently
|
// Convert an object to a string using a stringstream conveniently
|
||||||
#define to_string(x) static_cast<std::ostringstream>((std::ostringstream() << std::dec << x )).str()
|
#define to_string(x) static_cast<std::ostringstream>((std::ostringstream() << std::dec << x )).str()
|
||||||
|
|
||||||
// Replace a substring with a replacement string in a source string
|
// Replace a substring with a replacement string in a source string
|
||||||
void replace_substring(std::string &src, const std::string& substr, const std::string &replacement) {
|
void replace_substring(std::string &src, const std::string &substr, const std::string &replacement) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = src.find(substr, i); i != std::string::npos; i = src.find(substr, i)) {
|
for (i = src.find(substr, i); i != std::string::npos; i = src.find(substr, i)) {
|
||||||
src.replace(i, substr.size(), replacement);
|
src.replace(i, substr.size(), replacement);
|
||||||
|
|
@ -103,8 +64,6 @@ bool is_symbol(char ch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MlValue::MlValue() : type(UNIT) {}
|
MlValue::MlValue() : type(UNIT) {}
|
||||||
|
|
||||||
MlValue::MlValue(int i) : type(INT) { stack_data.i = i; }
|
MlValue::MlValue(int i) : type(INT) { stack_data.i = i; }
|
||||||
|
|
@ -526,21 +485,12 @@ MlValue MlValue::operator%(const MlValue &other) const {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// If we support libm, we can find the remainder of floating point values.
|
// If we support libm, we can find the remainder of floating point values.
|
||||||
#ifdef HAS_LIBM
|
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
return MlValue(fmod(stack_data.f, other.cast_to_float().stack_data.f));
|
return MlValue(fmod(stack_data.f, other.cast_to_float().stack_data.f));
|
||||||
case INT:
|
case INT:
|
||||||
if (other.type == FLOAT)
|
if (other.type == FLOAT)
|
||||||
return MlValue(fmod(cast_to_float().stack_data.f, other.stack_data.f));
|
return MlValue(fmod(cast_to_float().stack_data.f, other.stack_data.f));
|
||||||
else return MlValue(stack_data.i % other.stack_data.i);
|
else return MlValue(stack_data.i % other.stack_data.i);
|
||||||
#else
|
|
||||||
case INT:
|
|
||||||
// If we do not support libm, we have to throw errors for floating point values.
|
|
||||||
if (other.type != INT)
|
|
||||||
throw MlError(other, MlEnvironment(), NO_LIBM_SUPPORT);
|
|
||||||
return MlValue(stack_data.i % other.stack_data.i);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case UNIT:
|
case UNIT:
|
||||||
// Unit types consume all arithmetic operations.
|
// Unit types consume all arithmetic operations.
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -1004,7 +954,7 @@ namespace builtin {
|
||||||
// Evaluate a block of expressions in the current environment (SPECIAL FORM)
|
// Evaluate a block of expressions in the current environment (SPECIAL FORM)
|
||||||
MlValue do_block(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue do_block(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
MlValue acc;
|
MlValue acc;
|
||||||
for (auto & arg : args)
|
for (auto &arg : args)
|
||||||
acc = arg.eval(env);
|
acc = arg.eval(env);
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
@ -1013,7 +963,7 @@ namespace builtin {
|
||||||
MlValue scope(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue scope(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
MlEnvironment e = env;
|
MlEnvironment e = env;
|
||||||
MlValue acc;
|
MlValue acc;
|
||||||
for (auto & arg : args)
|
for (auto &arg : args)
|
||||||
acc = arg.eval(e);
|
acc = arg.eval(e);
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
@ -1021,12 +971,11 @@ namespace builtin {
|
||||||
// Quote an expression (SPECIAL FORM)
|
// Quote an expression (SPECIAL FORM)
|
||||||
MlValue quote(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue quote(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
std::vector<MlValue> v;
|
std::vector<MlValue> v;
|
||||||
for (const auto & arg : args)
|
for (const auto &arg : args)
|
||||||
v.push_back(arg);
|
v.push_back(arg);
|
||||||
return MlValue(v);
|
return MlValue(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_STD
|
|
||||||
|
|
||||||
// Exit the program with an integer code
|
// Exit the program with an integer code
|
||||||
MlValue exit(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue exit(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
|
|
@ -1089,12 +1038,8 @@ namespace builtin {
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw MlError(MlValue("parse-csv", parse_csv), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
throw MlError(MlValue("parse-csv", parse_csv), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
// PERF optimize it for memory usage and performance
|
|
||||||
CsvParser csv(true);
|
CsvParser csv(true);
|
||||||
std::vector<std::vector<std::string> > parsed_data; // TODO some default size here
|
return csv.parseCSV(args[0].as_string());
|
||||||
csv.parseCSV(args[0].as_string(), parsed_data);
|
|
||||||
|
|
||||||
return csv.ivalualize(parsed_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the contents of a file
|
// Get the contents of a file
|
||||||
|
|
@ -1112,7 +1057,8 @@ namespace builtin {
|
||||||
eval_args(args, env);
|
eval_args(args, env);
|
||||||
|
|
||||||
if (args.size() != 2)
|
if (args.size() != 2)
|
||||||
throw MlError(MlValue("write-file", write_file), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
throw MlError(MlValue("write-file", write_file), env,
|
||||||
|
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
std::ofstream f;
|
std::ofstream f;
|
||||||
// The first argument is the file name
|
// The first argument is the file name
|
||||||
|
|
@ -1135,9 +1081,9 @@ namespace builtin {
|
||||||
HttpClient client;
|
HttpClient client;
|
||||||
|
|
||||||
if (args.size() == 2) {
|
if (args.size() == 2) {
|
||||||
for(const auto& pair_list: args[1].as_list()[0].as_list()) {
|
for (const auto &pair_list: args[1].as_list()[0].as_list()) {
|
||||||
// TODO check its 2 string elements list
|
// TODO check its 2 string elements list
|
||||||
const auto& pair = pair_list.as_list();
|
const auto &pair = pair_list.as_list();
|
||||||
headers[pair[0].as_string()] = pair[1].as_string();
|
headers[pair[0].as_string()] = pair[1].as_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1177,7 +1123,8 @@ namespace builtin {
|
||||||
// TODO add support for more params constructing options as one string
|
// TODO add support for more params constructing options as one string
|
||||||
// TODO add support for stderr
|
// TODO add support for stderr
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw MlError(MlValue("system-cmd", system_cmd), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
throw MlError(MlValue("system-cmd", system_cmd), env,
|
||||||
|
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
std::string cmd = args[0].as_string();
|
std::string cmd = args[0].as_string();
|
||||||
|
|
||||||
|
|
@ -1211,6 +1158,37 @@ namespace builtin {
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// list directory
|
||||||
|
MlValue ls_dir(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
|
eval_args(args, env);
|
||||||
|
|
||||||
|
if (args.size() != 1)
|
||||||
|
throw MlError(MlValue("ls-dir", ls_dir), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
|
return list_dir(args[0].as_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// is_path file
|
||||||
|
MlValue is_file(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
|
eval_args(args, env);
|
||||||
|
|
||||||
|
// TODO add suppor for more params and list params
|
||||||
|
if (args.size() != 1)
|
||||||
|
throw MlError(MlValue("is-file?", is_file), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
|
return MlValue(is_path_file(args[0].as_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// is_path directory
|
||||||
|
MlValue is_dir(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
|
eval_args(args, env);
|
||||||
|
|
||||||
|
// TODO add suppor for more params and list params
|
||||||
|
if (args.size() != 1)
|
||||||
|
throw MlError(MlValue("is-dir?", is_dir), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
|
|
||||||
|
return MlValue(is_path_dir(args[0].as_string()));
|
||||||
|
}
|
||||||
|
|
||||||
// Read a file and execute its code
|
// Read a file and execute its code
|
||||||
MlValue include(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue include(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
|
|
@ -1227,7 +1205,6 @@ namespace builtin {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Evaluate a value as code
|
// Evaluate a value as code
|
||||||
MlValue eval(std::vector<MlValue> args, MlEnvironment &env) {
|
MlValue eval(std::vector<MlValue> args, MlEnvironment &env) {
|
||||||
|
|
@ -1367,7 +1344,8 @@ namespace builtin {
|
||||||
eval_args(args, env);
|
eval_args(args, env);
|
||||||
|
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw MlError(MlValue(FLOAT_TYPE, cast_to_float), env, args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
throw MlError(MlValue(FLOAT_TYPE, cast_to_float), env,
|
||||||
|
args.size() > 1 ? TOO_MANY_ARGS : TOO_FEW_ARGS);
|
||||||
return args[0].cast_to_float();
|
return args[0].cast_to_float();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1590,7 +1568,6 @@ namespace builtin {
|
||||||
}
|
}
|
||||||
|
|
||||||
void repl(MlEnvironment &env) {
|
void repl(MlEnvironment &env) {
|
||||||
#ifdef USE_STD
|
|
||||||
std::string code;
|
std::string code;
|
||||||
std::string input;
|
std::string input;
|
||||||
MlValue tmp;
|
MlValue tmp;
|
||||||
|
|
@ -1622,7 +1599,6 @@ void repl(MlEnvironment &env) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does this environment, or its parent environment, have a variable?
|
// Does this environment, or its parent environment, have a variable?
|
||||||
|
|
@ -1640,7 +1616,7 @@ bool MlEnvironment::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 MlEnvironment::get(const std::string& name) const {
|
MlValue MlEnvironment::get(const std::string &name) const {
|
||||||
// Meta operations
|
// Meta operations
|
||||||
if (name == "eval") return MlValue("eval", builtin::eval);
|
if (name == "eval") return MlValue("eval", builtin::eval);
|
||||||
if (name == "type") return MlValue("type", builtin::get_type_name);
|
if (name == "type") return MlValue("type", builtin::get_type_name);
|
||||||
|
|
@ -1694,7 +1670,6 @@ MlValue MlEnvironment::get(const std::string& name) const {
|
||||||
if (name == "reduce") return MlValue("reduce", builtin::reduce_list);
|
if (name == "reduce") return MlValue("reduce", builtin::reduce_list);
|
||||||
|
|
||||||
// IO operations
|
// IO operations
|
||||||
#ifdef USE_STD
|
|
||||||
if (name == "exit") return MlValue("exit", builtin::exit);
|
if (name == "exit") return MlValue("exit", builtin::exit);
|
||||||
if (name == "quit") return MlValue("quit", builtin::exit);
|
if (name == "quit") return MlValue("quit", builtin::exit);
|
||||||
if (name == "print") return MlValue("print", builtin::print);
|
if (name == "print") return MlValue("print", builtin::print);
|
||||||
|
|
@ -1707,7 +1682,9 @@ MlValue MlEnvironment::get(const std::string& name) const {
|
||||||
if (name == "read-url") return MlValue("read-url", builtin::read_url);
|
if (name == "read-url") return MlValue("read-url", builtin::read_url);
|
||||||
if (name == "read-json") return MlValue("read-json", builtin::read_json);
|
if (name == "read-json") return MlValue("read-json", builtin::read_json);
|
||||||
if (name == "system-cmd") return MlValue("system-cmd", builtin::system_cmd);
|
if (name == "system-cmd") return MlValue("system-cmd", builtin::system_cmd);
|
||||||
#endif
|
if (name == "ls-dir") return MlValue("ls-dir", builtin::ls_dir);
|
||||||
|
if (name == "is-file?") return MlValue("is-file?", builtin::is_file);
|
||||||
|
if (name == "is-dir?") return MlValue("is-der?", builtin::is_dir);
|
||||||
|
|
||||||
// String operations
|
// String operations
|
||||||
if (name == "debug") return MlValue("debug", builtin::debug);
|
if (name == "debug") return MlValue("debug", builtin::debug);
|
||||||
|
|
@ -1749,7 +1726,6 @@ int main(int argc, const char **argv) {
|
||||||
args.push_back(MlValue::string(argv[i]));
|
args.push_back(MlValue::string(argv[i]));
|
||||||
env.set("cmd-args", MlValue(args));
|
env.set("cmd-args", MlValue(args));
|
||||||
|
|
||||||
#ifdef USE_STD
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
try {
|
try {
|
||||||
// Load std library
|
// Load std library
|
||||||
|
|
@ -1767,10 +1743,6 @@ int main(int argc, const char **argv) {
|
||||||
} catch (std::runtime_error &e) {
|
} catch (std::runtime_error &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (argc == 3 && std::string(argv[1]) == "-c")
|
|
||||||
run(argv[2], env);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
ml.h
32
ml.h
|
|
@ -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,8 +23,10 @@ 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);
|
||||||
|
|
||||||
|
|
@ -42,6 +38,7 @@ public:
|
||||||
|
|
||||||
// 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,27 +69,28 @@ 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
|
// Constructs a floating point value
|
||||||
MlValue(double f);
|
MlValue(double f);
|
||||||
|
|
||||||
// Constructs a list
|
// Constructs a list
|
||||||
MlValue(const std::vector<MlValue> &list);
|
MlValue(const std::vector<MlValue> &list);
|
||||||
|
|
||||||
// Construct a quoted value
|
// Construct a quoted value
|
||||||
static MlValue quote(const MlValue& quoted);
|
static MlValue quote(const MlValue "ed);
|
||||||
|
|
||||||
// Construct an atom
|
// Construct an atom
|
||||||
static MlValue atom(const std::string &s);
|
static MlValue atom(const std::string &s);
|
||||||
|
|
@ -112,6 +111,7 @@ typedef MlValue (*Builtin)(std::vector<MlValue>, MlEnvironment &);
|
||||||
|
|
||||||
// Apply this as a function to a list of arguments in a given environment.
|
// Apply this as a function to a list of arguments in a given environment.
|
||||||
MlValue apply(std::vector<MlValue> args, MlEnvironment &env);
|
MlValue apply(std::vector<MlValue> args, MlEnvironment &env);
|
||||||
|
|
||||||
// Evaluate this value as lisp code.
|
// Evaluate this value as lisp code.
|
||||||
MlValue eval(MlEnvironment &env);
|
MlValue eval(MlEnvironment &env);
|
||||||
|
|
||||||
|
|
@ -187,7 +187,7 @@ typedef MlValue (*Builtin)(std::vector<MlValue>, MlEnvironment &);
|
||||||
|
|
||||||
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,
|
||||||
|
|
@ -209,4 +209,4 @@ typedef MlValue (*Builtin)(std::vector<MlValue>, MlEnvironment &);
|
||||||
std::string str;
|
std::string str;
|
||||||
std::vector<MlValue> list;
|
std::vector<MlValue> list;
|
||||||
MlEnvironment lambda_scope;
|
MlEnvironment lambda_scope;
|
||||||
};
|
};
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
Loading…
Reference in New Issue