]> pilppa.org Git - lib1wire.git/blob - src/W1Util.cc
001f9f63c293d5677f3aa9a9bfd67ba4e1d18329
[lib1wire.git] / src / W1Util.cc
1 /*
2  * W1Util.cc
3  *
4  *  Created on: Nov 14, 2010
5  *      Author: lamikr
6  */
7 #include <algorithm>
8 #include <string>
9 #include <iostream>
10 #include <fstream>
11 #include <sstream>
12
13 #include <errno.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <stdbool.h>
17
18 #include <plp/log.h>
19
20 #include "W1Util.hh"
21 #include "W1Configure.hh"
22
23 using namespace std;
24 using namespace w1;
25
26 template <class NumberDataType>
27 bool string_to_number(NumberDataType& result,
28                  const std::string& string_param,
29                  std::ios_base& (*format)(std::ios_base&))
30 {
31         std::istringstream iss(string_param);
32         return !(iss >> format >> result).fail();
33 }
34
35 W1Util::W1Util() {
36 }
37
38 W1Util::~W1Util() {
39 }
40
41 void W1Util::printout_date(struct tm *date_time) {
42         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;
43 }
44
45 void W1Util::printout_data(Data *data) {
46         int     ii;
47         if (data != NULL) {
48                 printout_date(data->date_time);
49                 for (ii = 0; ii < data->data_list.size(); ii++) {
50                         log_debug("  data[%d] = %f\n", ii, data->data_list.at(ii));
51                 }
52         }
53 }
54
55 char *W1Util::parse_directory_path(const char *file_path) {
56         char    *p;
57         size_t  b_count;
58         size_t  f_size;
59         char    *ret_val;
60
61         ret_val = NULL;
62         if (file_path != NULL) {
63                 f_size  = 0;
64                 b_count = strlen(file_path);
65                 for (p = &((char *)file_path)[b_count]; p != (char *)file_path; p--) {
66                         f_size++;
67                         if ((*p == '/') ||
68                             (*p == '\\')) {
69                                 b_count = (b_count - f_size) + 1;
70                                 ret_val = strndup(file_path, b_count);
71                                 log_debug("dir: %s\n", ret_val);
72                                 break;
73                         }
74                 }
75         }
76         return ret_val;
77 }
78
79 bool W1Util::mkdirs(char *path) {
80         bool    ret_val;
81         char    *p;
82         int     err_flg;
83
84         ret_val = true;
85         if (path != NULL) {
86                 // go through each directory one by and and create if not exist
87                 for (p = path; *p; p++) {
88                     if ((p != path) &&
89                         ((*p == '/') ||
90                          (*p == '\\'))) {
91                                 *p = '\0';
92                                 // test whether directory exist and is writable
93                                 if (access(path, F_OK)) {
94                                         log_debug("trying to create directory: %s\n", path);
95                                         err_flg = mkdir(path, S_IRWXU);
96                                         if (err_flg != 0) {
97                                                 ret_val = false;
98                                                 break;
99                                         }
100                                 }
101                                 *p = '/';
102                         }
103                 }
104                 if (ret_val == true) {
105                         // test also the existense of whole directory
106                         if (access(path, F_OK)) {
107                                 log_debug("trying to create directory: %s\n", path);
108                                 err_flg = mkdir(path, S_IRWXU);
109                                 if (err_flg != 0) {
110                                         ret_val = false;
111                                 }
112                         }
113                 }
114         }
115         else {
116                 ret_val = false;
117                 log_error("Could not create NULL directory\n");
118         }
119         return ret_val;
120 }
121
122 std::ofstream *W1Util::open_for_writing(const char *f_path) {
123         char            *d_path;
124         char            *p;
125         size_t          b_count;
126         int             ii;
127         ofstream        *ret_val;
128         bool            b_flg;
129
130         ret_val = NULL;
131         if (f_path != NULL) {
132                 b_count = strlen(f_path);
133                 if ((f_path[b_count - 1] != '/') &&
134                     (f_path[b_count - 1] != '\\')) {
135                         ret_val = new ofstream();
136                         ret_val->open(f_path, ios::app);
137                         if (ret_val->is_open() == false) {
138                                 d_path  = parse_directory_path(f_path);
139                                 if (d_path != NULL) {
140                                         b_flg   = mkdirs(d_path);
141                                         free(d_path);
142                                 }
143                                 if (b_flg == true) {
144                                         ret_val->open(f_path, ios::app);
145                                 }
146                         }
147                 }
148                 else {
149                         log_error("Could not open file, invalid file name. (%s)\n", f_path);
150                 }
151         }
152         else {
153                 log_error("Could not open file, invalid file name. (= NULL)\n");
154         }
155         return ret_val;
156 }
157
158 string W1Util::concat_paths(string path_start, string path_end) {
159         return concat_paths(path_start.c_str(), path_end.c_str());
160 }
161
162 string W1Util::concat_paths(const char *path_start, const char *path_end) {
163         string  ret_val;
164         string  end_str;
165         int     pos;
166         int     b_count;
167
168         if (path_start != NULL) {
169                 ret_val = path_start;
170                 if (path_end != NULL) {
171                         end_str = path_end;
172                         b_count = ret_val.length();
173                         pos     = ret_val.find_last_of("/");
174                         if (pos == (b_count -1)) {
175                                 ret_val.append(end_str);
176                         }
177                         else {
178                                 pos     = end_str.find_first_of("/");
179                                 if (pos == 0) {
180                                         ret_val.append(end_str);
181                                 }
182                                 else {
183                                         ret_val.append("/");
184                                         ret_val.append(end_str);
185                                 }
186                         }
187                 }
188         }
189         else {
190                 if (path_end != NULL) {
191                         ret_val = path_end;
192                 }
193         }
194         return ret_val;
195 }
196
197 bool W1Util::is_subdirectory(const char *path, dirent *direntry) {
198         bool            ret_val;
199         struct stat     stat_info;
200         string          fname;
201
202         ret_val = false;
203         if (direntry != NULL) {
204                 if ((strcmp(direntry->d_name, ".") == 0) ||
205                     (strcmp(direntry->d_name, "..") == 0)) {
206                         ret_val = false;
207                 }
208                 else {
209                         fname   = concat_paths(path, direntry->d_name);
210                         stat(fname.c_str(), &stat_info);
211                         ret_val = S_ISDIR(stat_info.st_mode);
212                         //log_debug("stat for: %s: %d\n", fname.c_str(), ret_val);
213                 }
214         }
215         return ret_val;
216 }
217
218 bool W1Util::is_datafile(const char *path, dirent *direntry) {
219         bool            ret_val;
220         struct stat     stat_info;
221         string          name;
222         int             pos;
223         string          fname;
224
225         ret_val = false;
226         if (direntry != NULL) {
227                 name    = direntry->d_name;
228                 pos     = name.find(DATAFILE_SUFFIX);
229                 if (pos > 0) {
230                         fname   = concat_paths(path, direntry->d_name);
231                         stat(fname.c_str(), &stat_info);
232                         ret_val = S_ISREG(stat_info.st_mode);
233                 }
234         }
235         return ret_val;
236 }
237
238 /**
239  * get sub-directories sorted in alphabetical order.
240  */
241 vector<string> W1Util::get_subdirectories(const string& path) {
242         dirent          *direntry;
243         DIR             *dir;
244         bool            bool_flg;
245         vector<string>  ret_val;
246
247         log_debug("scanning path: %s\n", path.c_str());
248         errno   = 0;
249         if (path.empty() == false) {
250                 dir     = opendir(path.c_str());
251                 if (dir) {
252                         while (true) {
253                                 errno           = 0;
254                                 direntry        = readdir(dir);
255                                 if (direntry != NULL) {
256                                         bool_flg        = is_subdirectory(path.c_str(), direntry);
257                                         if (bool_flg == true) {
258                                                 ret_val.push_back(string(direntry->d_name));
259                                                 //log_debug("added dir: %s\n", direntry->d_name);
260                                         }
261                                 }
262                                 else {
263                                         break;
264                                 }
265                         }
266                         closedir(dir);
267                         sort(ret_val.begin(), ret_val.end());
268                 }
269         }
270         return ret_val;
271 }
272
273 /**
274  * get sub-directories sorted in alphabetical order.
275  */
276 vector<string> W1Util::get_data_files(const string& path) {
277         dirent          *direntry;
278         DIR             *dir;
279         vector<string>  ret_val;
280
281         errno   = 0;
282         if (path.empty() == false) {
283                 dir     = opendir(path.c_str());
284                 if (dir) {
285                         while (true) {
286                                 errno           = 0;
287                                 direntry        = readdir(dir);
288                                 if (direntry != NULL) {
289                                         if (is_datafile(path.c_str(), direntry) == true) {
290                                                 ret_val.push_back(string(direntry->d_name));
291                                         }
292                                 }
293                                 else {
294                                         break;
295                                 }
296                         }
297                         closedir(dir);
298                         sort(ret_val.begin(), ret_val.end());
299                 }
300         }
301         return ret_val;
302 }
303
304 struct tm *W1Util::parse_date_str(string date_str) {
305         stringstream ss(date_str);
306         struct tm *ret_val = NULL;
307
308         //ss << "2007-07-19 17:18:01";
309         int year;
310         int month;
311         int day;
312         int hour;
313         int min;
314         int sec;
315         char c;
316
317         ret_val = (struct tm*)malloc(sizeof(struct tm));
318         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;
319         mktime(ret_val);
320         //printout_date(ret_val);
321         return ret_val;
322 }
323
324 Data *W1Util::parse_data_line(const string& dataline) {
325         stringstream    ss(dataline);
326         string          item;
327         double          dbl;
328         Data            *ret_val;
329         int             ii;
330         bool            suc_flg;
331
332         ret_val = new Data();
333         ii      = 0;
334         while(getline(ss, item, '|')) {
335                 if (ii == 0) {
336                         // parse date
337                         ret_val->date_time      = parse_date_str(item);
338                 }
339                 else if (ii == 1) {
340                         // skip the device type for now.Maybe better to store only once under the year dir...
341                 }
342                 else if (ii >= 2) {
343                         suc_flg = string_to_number<double>(dbl, item, dec);
344                         if (suc_flg) {
345                                 ret_val->data_list.push_back(dbl);
346                         }
347                 }
348                 ii++;
349         }
350         return ret_val;
351 }
352
353 Data *W1Util::load_first_data_row(const string& datafile_path) {
354         Data            *ret_val;
355         ifstream        in;
356         string          line;
357
358         ret_val = NULL;
359         in.open(datafile_path.c_str());
360         if (in.eof() == false) {
361                 getline(in, line);
362                 ret_val = parse_data_line(line);
363         }
364         return ret_val;
365 }
366
367 Data *W1Util::load_last_data_row(const string& datafile_path) {
368         Data            *ret_val;
369         ifstream        in;
370         string          line;
371         string          prev_line;
372
373         ret_val = NULL;
374         in.open(datafile_path.c_str());
375         while (in.eof() == false) {
376                 getline(in, line);
377                 if (line.empty() == false) {
378                         prev_line       = line;
379                 }
380         }
381         if (prev_line.empty() == false) {
382                 ret_val = parse_data_line(prev_line);
383         }
384         return ret_val;
385 }