diff --git a/src/sicccPersister.H b/src/sicccPersister.H new file mode 100644 index 0000000..647f962 --- /dev/null +++ b/src/sicccPersister.H @@ -0,0 +1,179 @@ +#ifndef __SICCCPERSISTER_H_ +#define __SICCCPERSISTER_H_ + +#include +#include +#include +#include +#include +#include + +#include "sicccobject.H" + +static json_t * load_json(const std::string &s) +{ + assert(!s.empty()); + std::cout << "[DEBUG] joad_json: " << s << std::endl; + json_t *root = nullptr; + json_error_t error; + root = json_load_file(s.c_str(), JSON_DECODE_ANY, &error); + if (!root) { + /* std::cerr << "[read_json] " << error << std::endl; */ + return nullptr; + } + return root; +} + +static std::string get_string_from_json(const json_t *j) +{ + assert(j); + assert(json_is_string(j)); + const char *tmp = json_string_value(j); + assert(tmp); + return std::string(tmp); +} + +static json_t *get_json_from_string(const std::string &s) +{ + json_t* ret = json_string(s.c_str()); + assert(ret); + return ret; +} + +static unsigned int get_integer_from_json(const json_t *j) +{ + assert(j); + assert(json_is_integer(j)); + return json_integer_value(j); +} + +static json_t *get_json_from_integer(const unsigned int value) +{ + assert(value); + json_t* ret = json_integer(value); + assert(ret); + return ret; +} + +static std::chrono::time_point +get_time_from_json(const json_t *j) +{ + assert(j); + auto tmp = get_string_from_json(j); + time_t t = stol(tmp); + return std::chrono::system_clock::from_time_t(t); +} + +static std::string time_to_string(const std::chrono::time_point& t) +{ + time_t time = std::chrono::system_clock::to_time_t(t); + std::string ret = std::to_string(time); + return ret; +} + +/** TODO + * implement bool operator to take advantages of the use of assert + */ +static json_t *get_json_from_sicccobject(const Sicccobject& so) +{ + json_t *root = json_object(); + json_object_set_new(root, "filename", get_json_from_string(so.get_filename())); + json_object_set_new(root, "filetype", get_json_from_string(so.get_filetype())); + json_object_set_new(root, "path", get_json_from_string(so.get_path())); + json_object_set_new(root, "size", get_json_from_integer(so.get_size())); + std::string tmp = time_to_string(so.get_uploadtime()); + json_object_set_new(root, "upload_time", get_json_from_string(tmp)); + assert(root); + return root; +} + +static std::string get_json_string_representation(const json_t *j) +{ + assert(j); + assert(json_is_object(j)); + const char *tmp = json_dumps(j, JSON_INDENT(4)); + assert(tmp); + std::string ret(tmp); + free((void*) tmp); + return ret; +} + +class SicccPersister +{ + public: + SicccPersister() + { + root = json_object(); + perists_path = "./"; + json_file_name = "foo.json"; // not the best default + }; + + SicccPersister(const Sicccobject& so) + { + root = get_json_from_sicccobject(so); + perists_path = "./"; + json_file_name = so.get_filename(); + } + + SicccPersister(json_t *j) + { + root = json_object(); + json_object_update(root, j); + } + + /*TODO + * clean up path handling + */ + SicccPersister(const std::string& jsonfilename, + const std::string& storepath + ) : perists_path(storepath), json_file_name(jsonfilename) + { + root = load_json(std::string(perists_path + json_file_name)); + assert(root); + } + + ~SicccPersister() + { + if (root) + json_decref(root); + } + + int write_sicccfile(const Sicccobject&); + int write_sicccfile(); + std::vector read_sicccdir(); + Sicccobject read_json(const std::string&); + Sicccobject read_json() { return read_json(json_file_name); } + void set_persist_path(std::string&); + void set_json_filename(std::string&); + + friend std::ostream& operator << (std::ostream& out, const SicccPersister &p) + { + out << get_json_string_representation(p.root); + return out; + } + + friend std::ostream& operator << (std::ostream& out, const json_t *j) + { + assert(j); + out << get_json_string_representation(j); + return out; + } + + private: + std::string perists_path; + std::string json_file_name; + json_t *root; + + std::string + inline beautify_filename() + { + std::string s; + if (json_file_name.empty()) return s; + size_t pos = json_file_name.find_last_of("."); + s = json_file_name.substr(0, pos + 1); + s.append("json"); + return s; + } +}; + +#endif /* __SICCCPERSISTER_H_ */ diff --git a/src/sicccPersister.cc b/src/sicccPersister.cc new file mode 100644 index 0000000..a81831a --- /dev/null +++ b/src/sicccPersister.cc @@ -0,0 +1,70 @@ +#include "sicccPersister.H" + +/*TODO + * check if path is valid + */ +void +SicccPersister::set_persist_path(std::string &s) +{ + assert(!s.empty()); + perists_path = s; +} + +void +SicccPersister::set_json_filename(std::string &s) +{ + assert(!s.empty()); + json_file_name = s; +} + +int +SicccPersister::write_sicccfile(const Sicccobject& so) +{ + json_t *new_json = get_json_from_sicccobject(so); + if (json_object_update(root, new_json) == 0) + std::cout << "[DEBUG] update root json successfully" << std::endl; + else + std::cerr << "Error update root failed" << std::endl; + assert(root); + int ret = write_sicccfile(); + return ret; +} + +int +SicccPersister::write_sicccfile() +{ + assert(!json_file_name.empty()); + std::string store_str = perists_path + "/" + beautify_filename(); + assert(root); + int ret = json_dump_file(root, store_str.c_str(), JSON_INDENT(4)); + return ret; +} + +Sicccobject +SicccPersister::read_json(const std::string &s) +{ + root = load_json(s); + return Sicccobject(root); +} + +std::vector +SicccPersister::read_sicccdir() +{ + DIR *dir = nullptr; + struct dirent *entry = nullptr; + std::vector v; + json_error_t *error = nullptr; + if ((dir = opendir(perists_path.c_str())) == NULL) { + std::cerr << "Error could not open directory" << std::endl; + return v; // should throw exception instea1d + } + while ((entry = readdir(dir)) != NULL) { + if (std::strstr(entry->d_name, ".json") == NULL) + continue; + json_t *tmp = json_load_file(entry->d_name, JSON_DECODE_ANY, error); + assert(tmp); + Sicccobject so(tmp); + v.push_back(so); + } + return v; +} diff --git a/src/sicccobject.H b/src/sicccobject.H index 07f10b4..9bcdc1c 100644 --- a/src/sicccobject.H +++ b/src/sicccobject.H @@ -5,6 +5,9 @@ #include #include +#include +#include + class Sicccobject { public: Sicccobject() {} // just for test cases @@ -43,6 +46,7 @@ class Sicccobject { size(sz), upload_date(date) { } + Sicccobject(const json_t*); Sicccobject(const Sicccobject&); ~Sicccobject() {} Sicccobject& operator = (const Sicccobject&); diff --git a/src/sicccobject.cc b/src/sicccobject.cc index 4289a42..531c2cf 100644 --- a/src/sicccobject.cc +++ b/src/sicccobject.cc @@ -1,4 +1,25 @@ #include "sicccobject.H" +#include "sicccPersister.H" + + +// FIXME: +// check for right reference counting of val +Sicccobject::Sicccobject(const json_t *j) +{ + assert(j); + json_t *val; + val = json_object_get(j, "filename"); + filename = get_string_from_json(val); + val = json_object_get(j, "filetype"); + filetype = get_string_from_json(val); + val = json_object_get(j, "path"); + path = get_string_from_json(val); + val = json_object_get(j, "size"); + size = get_integer_from_json(val); + val = json_object_get(j, "upload_time"); + upload_date = get_time_from_json(val); + json_decref(val); +} Sicccobject::Sicccobject(const Sicccobject& obj) { @@ -27,7 +48,7 @@ Sicccobject::operator = (const Sicccobject& obj) std::ostream& operator << (std::ostream& out, const Sicccobject& obj) { - std::time_t time = + std::time_t time = std::chrono::system_clock::to_time_t(obj.get_uploadtime()); out << "[Filename] " << obj.get_filename() << std::endl << "[Filetype] " << obj.get_filetype() << std::endl