+/*
+ * W1Util.cc
+ *
+ * Created on: Nov 14, 2010
+ * Author: lamikr
+ */
+#include <algorithm>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+
+#include <plp/log.h>
+
+#include "W1Util.hh"
+#include "W1Configure.hh"
+
+using namespace std;
+using namespace w1;
+
+template <class NumberDataType>
+bool string_to_number(NumberDataType& result,
+ const std::string& string_param,
+ std::ios_base& (*format)(std::ios_base&))
+{
+ std::istringstream iss(string_param);
+ return !(iss >> format >> result).fail();
+}
+
+W1Util::W1Util() {
+}
+
+W1Util::~W1Util() {
+}
+
+void W1Util::printout_date(struct tm *date_time) {
+ cout << "date: " << date_time->tm_year << " " << date_time->tm_mon << " " << date_time->tm_mday << " " << date_time->tm_hour << " " << date_time->tm_min << " " << date_time->tm_sec << endl;
+}
+
+void W1Util::printout_data(Data *data) {
+ int ii;
+ if (data != NULL) {
+ printout_date(data->date_time);
+ for (ii = 0; ii < data->data_list.size(); ii++) {
+ log_debug(" data[%d] = %f\n", ii, data->data_list.at(ii));
+ }
+ }
+}
+
+char *W1Util::parse_directory_path(const char *file_path) {
+ char *p;
+ size_t b_count;
+ size_t f_size;
+ char *ret_val;
+
+ ret_val = NULL;
+ if (file_path != NULL) {
+ f_size = 0;
+ b_count = strlen(file_path);
+ for (p = &((char *)file_path)[b_count]; p != (char *)file_path; p--) {
+ f_size++;
+ if ((*p == '/') ||
+ (*p == '\\')) {
+ b_count = (b_count - f_size) + 1;
+ ret_val = strndup(file_path, b_count);
+ log_debug("dir: %s\n", ret_val);
+ break;
+ }
+ }
+ }
+ return ret_val;
+}
+
+bool W1Util::mkdirs(char *path) {
+ bool ret_val;
+ char *p;
+ int err_flg;
+
+ ret_val = true;
+ if (path != NULL) {
+ // go through each directory one by and and create if not exist
+ for (p = path; *p; p++) {
+ if ((p != path) &&
+ ((*p == '/') ||
+ (*p == '\\'))) {
+ *p = '\0';
+ // test whether directory exist and is writable
+ if (access(path, F_OK)) {
+ log_debug("trying to create directory: %s\n", path);
+ err_flg = mkdir(path, S_IRWXU);
+ if (err_flg != 0) {
+ ret_val = false;
+ break;
+ }
+ }
+ *p = '/';
+ }
+ }
+ if (ret_val == true) {
+ // test also the existense of whole directory
+ if (access(path, F_OK)) {
+ log_debug("trying to create directory: %s\n", path);
+ err_flg = mkdir(path, S_IRWXU);
+ if (err_flg != 0) {
+ ret_val = false;
+ }
+ }
+ }
+ }
+ else {
+ ret_val = false;
+ log_error("Could not create NULL directory\n");
+ }
+ return ret_val;
+}
+
+std::ofstream *W1Util::open_for_writing(const char *f_path) {
+ char *d_path;
+ char *p;
+ size_t b_count;
+ int ii;
+ ofstream *ret_val;
+ bool b_flg;
+
+ ret_val = NULL;
+ if (f_path != NULL) {
+ b_count = strlen(f_path);
+ if ((f_path[b_count - 1] != '/') &&
+ (f_path[b_count - 1] != '\\')) {
+ ret_val = new ofstream();
+ ret_val->open(f_path, ios::app);
+ if (ret_val->is_open() == false) {
+ d_path = parse_directory_path(f_path);
+ if (d_path != NULL) {
+ b_flg = mkdirs(d_path);
+ free(d_path);
+ }
+ if (b_flg == true) {
+ ret_val->open(f_path, ios::app);
+ }
+ }
+ }
+ else {
+ log_error("Could not open file, invalid file name. (%s)\n", f_path);
+ }
+ }
+ else {
+ log_error("Could not open file, invalid file name. (= NULL)\n");
+ }
+ return ret_val;
+}
+
+string W1Util::concat_paths(string path_start, string path_end) {
+ return concat_paths(path_start.c_str(), path_end.c_str());
+}
+
+string W1Util::concat_paths(const char *path_start, const char *path_end) {
+ string ret_val;
+ string end_str;
+ int pos;
+ int b_count;
+
+ if (path_start != NULL) {
+ ret_val = path_start;
+ if (path_end != NULL) {
+ end_str = path_end;
+ b_count = ret_val.length();
+ pos = ret_val.find_last_of("/");
+ if (pos == (b_count -1)) {
+ ret_val.append(end_str);
+ }
+ else {
+ pos = end_str.find_first_of("/");
+ if (pos == 0) {
+ ret_val.append(end_str);
+ }
+ else {
+ ret_val.append("/");
+ ret_val.append(end_str);
+ }
+ }
+ }
+ }
+ else {
+ if (path_end != NULL) {
+ ret_val = path_end;
+ }
+ }
+ return ret_val;
+}
+
+bool W1Util::is_subdirectory(const char *path, dirent *direntry) {
+ bool ret_val;
+ struct stat stat_info;
+ string fname;
+
+ ret_val = false;
+ if (direntry != NULL) {
+ if ((strcmp(direntry->d_name, ".") == 0) ||
+ (strcmp(direntry->d_name, "..") == 0)) {
+ ret_val = false;
+ }
+ else {
+ fname = concat_paths(path, direntry->d_name);
+ stat(fname.c_str(), &stat_info);
+ ret_val = S_ISDIR(stat_info.st_mode);
+ //log_debug("stat for: %s: %d\n", fname.c_str(), ret_val);
+ }
+ }
+ return ret_val;
+}
+
+bool W1Util::is_datafile(const char *path, dirent *direntry) {
+ bool ret_val;
+ struct stat stat_info;
+ string name;
+ int pos;
+ string fname;
+
+ ret_val = false;
+ if (direntry != NULL) {
+ name = direntry->d_name;
+ pos = name.find(DATAFILE_SUFFIX);
+ if (pos > 0) {
+ fname = concat_paths(path, direntry->d_name);
+ stat(fname.c_str(), &stat_info);
+ ret_val = S_ISREG(stat_info.st_mode);
+ }
+ }
+ return ret_val;
+}
+
+/**
+ * get sub-directories sorted in alphabetical order.
+ */
+vector<string> W1Util::get_subdirectories(const string& path) {
+ dirent *direntry;
+ DIR *dir;
+ bool bool_flg;
+ vector<string> ret_val;
+
+ log_debug("scanning path: %s\n", path.c_str());
+ errno = 0;
+ if (path.empty() == false) {
+ dir = opendir(path.c_str());
+ if (dir) {
+ while (true) {
+ errno = 0;
+ direntry = readdir(dir);
+ if (direntry != NULL) {
+ bool_flg = is_subdirectory(path.c_str(), direntry);
+ if (bool_flg == true) {
+ ret_val.push_back(string(direntry->d_name));
+ //log_debug("added dir: %s\n", direntry->d_name);
+ }
+ }
+ else {
+ break;
+ }
+ }
+ closedir(dir);
+ sort(ret_val.begin(), ret_val.end());
+ }
+ }
+ return ret_val;
+}
+
+/**
+ * get sub-directories sorted in alphabetical order.
+ */
+vector<string> W1Util::get_data_files(const string& path) {
+ dirent *direntry;
+ DIR *dir;
+ vector<string> ret_val;
+
+ errno = 0;
+ if (path.empty() == false) {
+ dir = opendir(path.c_str());
+ if (dir) {
+ while (true) {
+ errno = 0;
+ direntry = readdir(dir);
+ if (direntry != NULL) {
+ if (is_datafile(path.c_str(), direntry) == true) {
+ ret_val.push_back(string(direntry->d_name));
+ }
+ }
+ else {
+ break;
+ }
+ }
+ closedir(dir);
+ sort(ret_val.begin(), ret_val.end());
+ }
+ }
+ return ret_val;
+}
+
+struct tm *W1Util::parse_date_str(string date_str) {
+ stringstream ss(date_str);
+ struct tm *ret_val = NULL;
+
+ //ss << "2007-07-19 17:18:01";
+ int year;
+ int month;
+ int day;
+ int hour;
+ int min;
+ int sec;
+ char c;
+
+ ret_val = (struct tm*)malloc(sizeof(struct tm));
+ ss >>ret_val->tm_year >>c >>ret_val->tm_mon >>c >>ret_val->tm_mday >>ret_val->tm_hour >>c >>ret_val->tm_min >>c >>ret_val->tm_sec;
+ mktime(ret_val);
+ //printout_date(ret_val);
+ return ret_val;
+}
+
+Data *W1Util::parse_data_line(const string& dataline) {
+ stringstream ss(dataline);
+ string item;
+ double dbl;
+ Data *ret_val;
+ int ii;
+ bool suc_flg;
+
+ ret_val = new Data();
+ ii = 0;
+ while(getline(ss, item, '|')) {
+ if (ii == 0) {
+ // parse date
+ ret_val->date_time = parse_date_str(item);
+ }
+ else if (ii == 1) {
+ // skip the device type for now.Maybe better to store only once under the year dir...
+ }
+ else if (ii >= 2) {
+ suc_flg = string_to_number<double>(dbl, item, dec);
+ if (suc_flg) {
+ ret_val->data_list.push_back(dbl);
+ }
+ }
+ ii++;
+ }
+ return ret_val;
+}
+
+Data *W1Util::load_first_data_row(const string& datafile_path) {
+ Data *ret_val;
+ ifstream in;
+ string line;
+
+ ret_val = NULL;
+ in.open(datafile_path.c_str());
+ if (in.eof() == false) {
+ getline(in, line);
+ ret_val = parse_data_line(line);
+ }
+ return ret_val;
+}
+
+Data *W1Util::load_last_data_row(const string& datafile_path) {
+ Data *ret_val;
+ ifstream in;
+ string line;
+ string prev_line;
+
+ ret_val = NULL;
+ in.open(datafile_path.c_str());
+ while (in.eof() == false) {
+ getline(in, line);
+ if (line.empty() == false) {
+ prev_line = line;
+ }
+ }
+ if (prev_line.empty() == false) {
+ ret_val = parse_data_line(prev_line);
+ }
+ return ret_val;
+}