]> pilppa.org Git - lib1wire.git/blob - src/W1Util.cc
started adding support for reading average and sum data...
[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 using namespace plp;
26
27 template <class NumberDataType>
28 bool string_to_number(NumberDataType& result,
29                  const std::string& string_param,
30                  std::ios_base& (*format)(std::ios_base&))
31 {
32         std::istringstream iss(string_param);
33         return !(iss >> format >> result).fail();
34 }
35
36 W1Util::W1Util() {
37 }
38
39 W1Util::~W1Util() {
40 }
41
42 char *W1Util::parse_directory_path(const char *file_path) {
43         char    *p;
44         size_t  b_count;
45         size_t  f_size;
46         char    *ret_val;
47
48         ret_val = NULL;
49         if (file_path != NULL) {
50                 f_size  = 0;
51                 b_count = strlen(file_path);
52                 for (p = &((char *)file_path)[b_count]; p != (char *)file_path; p--) {
53                         f_size++;
54                         if ((*p == '/') ||
55                             (*p == '\\')) {
56                                 b_count = (b_count - f_size) + 1;
57                                 ret_val = strndup(file_path, b_count);
58                                 log_debug("dir: %s\n", ret_val);
59                                 break;
60                         }
61                 }
62         }
63         return ret_val;
64 }
65
66 bool W1Util::mkdirs(char *path) {
67         bool    ret_val;
68         char    *p;
69         int     err_flg;
70
71         ret_val = true;
72         if (path != NULL) {
73                 // go through each directory one by and and create if not exist
74                 for (p = path; *p; p++) {
75                     if ((p != path) &&
76                         ((*p == '/') ||
77                          (*p == '\\'))) {
78                                 *p = '\0';
79                                 // test whether directory exist and is writable
80                                 if (access(path, F_OK)) {
81                                         log_debug("trying to create directory: %s\n", path);
82                                         err_flg = mkdir(path, S_IRWXU);
83                                         if (err_flg != 0) {
84                                                 ret_val = false;
85                                                 break;
86                                         }
87                                 }
88                                 *p = '/';
89                         }
90                 }
91                 if (ret_val == true) {
92                         // test also the existense of whole directory
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                                 }
99                         }
100                 }
101         }
102         else {
103                 ret_val = false;
104                 log_error("Could not create NULL directory\n");
105         }
106         return ret_val;
107 }
108
109 std::ofstream *W1Util::open_for_writing(const char *f_path) {
110         char            *d_path;
111         char            *p;
112         size_t          b_count;
113         int             ii;
114         ofstream        *ret_val;
115         bool            b_flg;
116
117         ret_val = NULL;
118         if (f_path != NULL) {
119                 b_count = strlen(f_path);
120                 if ((f_path[b_count - 1] != '/') &&
121                     (f_path[b_count - 1] != '\\')) {
122                         ret_val = new ofstream();
123                         ret_val->open(f_path, ios::app);
124                         if (ret_val->is_open() == false) {
125                                 d_path  = parse_directory_path(f_path);
126                                 if (d_path != NULL) {
127                                         b_flg   = mkdirs(d_path);
128                                         free(d_path);
129                                 }
130                                 if (b_flg == true) {
131                                         ret_val->open(f_path, ios::app);
132                                 }
133                         }
134                 }
135                 else {
136                         log_error("Could not open file, invalid file name. (%s)\n", f_path);
137                 }
138         }
139         else {
140                 log_error("Could not open file, invalid file name. (= NULL)\n");
141         }
142         return ret_val;
143 }
144
145 string W1Util::concat_paths(string path_start, string path_end) {
146         return concat_paths(path_start.c_str(), path_end.c_str());
147 }
148
149 string W1Util::concat_paths(const char *path_start, const char *path_end) {
150         string  ret_val;
151         string  end_str;
152         int     pos;
153         int     b_count;
154
155         if (path_start != NULL) {
156                 ret_val = path_start;
157                 if (path_end != NULL) {
158                         end_str = path_end;
159                         b_count = ret_val.length();
160                         pos     = ret_val.find_last_of("/");
161                         if (pos == (b_count -1)) {
162                                 ret_val.append(end_str);
163                         }
164                         else {
165                                 pos     = end_str.find_first_of("/");
166                                 if (pos == 0) {
167                                         ret_val.append(end_str);
168                                 }
169                                 else {
170                                         ret_val.append("/");
171                                         ret_val.append(end_str);
172                                 }
173                         }
174                 }
175         }
176         else {
177                 if (path_end != NULL) {
178                         ret_val = path_end;
179                 }
180         }
181         return ret_val;
182 }
183
184 bool W1Util::is_subdirectory(const char *path, dirent *direntry) {
185         bool            ret_val;
186         struct stat     stat_info;
187         string          fname;
188
189         ret_val = false;
190         if (direntry != NULL) {
191                 if ((strcmp(direntry->d_name, ".") == 0) ||
192                     (strcmp(direntry->d_name, "..") == 0)) {
193                         ret_val = false;
194                 }
195                 else {
196                         fname   = concat_paths(path, direntry->d_name);
197                         stat(fname.c_str(), &stat_info);
198                         ret_val = S_ISDIR(stat_info.st_mode);
199                         //log_debug("stat for: %s: %d\n", fname.c_str(), ret_val);
200                 }
201         }
202         return ret_val;
203 }
204
205 bool W1Util::is_datafile(const char *path, dirent *direntry) {
206         bool            ret_val;
207         struct stat     stat_info;
208         string          name;
209         int             pos;
210         string          fname;
211
212         ret_val = false;
213         if (direntry != NULL) {
214                 name    = direntry->d_name;
215                 pos     = name.find(DATAFILE_SUFFIX);
216                 if (pos > 0) {
217                         fname   = concat_paths(path, direntry->d_name);
218                         stat(fname.c_str(), &stat_info);
219                         ret_val = S_ISREG(stat_info.st_mode);
220                 }
221         }
222         return ret_val;
223 }
224
225 /**
226  * get sub-directories sorted in alphabetical order.
227  */
228 vector<string> W1Util::get_subdirectories(const string& path) {
229         dirent          *direntry;
230         DIR             *dir;
231         bool            bool_flg;
232         vector<string>  ret_val;
233
234         log_debug("scanning path: %s\n", path.c_str());
235         errno   = 0;
236         if (path.empty() == false) {
237                 dir     = opendir(path.c_str());
238                 if (dir) {
239                         while (true) {
240                                 errno           = 0;
241                                 direntry        = readdir(dir);
242                                 if (direntry != NULL) {
243                                         bool_flg        = is_subdirectory(path.c_str(), direntry);
244                                         if (bool_flg == true) {
245                                                 ret_val.push_back(string(direntry->d_name));
246                                                 //log_debug("added dir: %s\n", direntry->d_name);
247                                         }
248                                 }
249                                 else {
250                                         break;
251                                 }
252                         }
253                         closedir(dir);
254                         sort(ret_val.begin(), ret_val.end());
255                 }
256         }
257         return ret_val;
258 }
259
260 /**
261  * get sub-directories sorted in alphabetical order.
262  */
263 vector<string> W1Util::get_data_files(const string& path) {
264         dirent          *direntry;
265         DIR             *dir;
266         vector<string>  ret_val;
267
268         errno   = 0;
269         if (path.empty() == false) {
270                 dir     = opendir(path.c_str());
271                 if (dir) {
272                         while (true) {
273                                 errno           = 0;
274                                 direntry        = readdir(dir);
275                                 if (direntry != NULL) {
276                                         if (is_datafile(path.c_str(), direntry) == true) {
277                                                 ret_val.push_back(string(direntry->d_name));
278                                         }
279                                 }
280                                 else {
281                                         break;
282                                 }
283                         }
284                         closedir(dir);
285                         sort(ret_val.begin(), ret_val.end());
286                 }
287         }
288         return ret_val;
289 }
290
291 Date W1Util::parse_date_str(string date_str) {
292         char            c;
293         stringstream    ss(date_str);
294         Date            ret_val;
295
296         ss >>ret_val.year >>c >>ret_val.month >>c >>ret_val.day >>ret_val.hour >>c >>ret_val.min >>c >>ret_val.sec;
297         return ret_val;
298 }
299
300 Data *W1Util::parse_data_line(const string& dataline) {
301         stringstream    ss(dataline);
302         string          item;
303         double          val;
304         Data            *ret_val;
305         int             ii;
306         bool            suc_flg;
307         vector<double>  v;
308         Date            date;
309
310         ii      = 0;
311         while(getline(ss, item, '|')) {
312                 if (ii == 0) {
313                         // parse date
314                         date    = parse_date_str(item);
315                 }
316                 // skip the device type and device id fields
317                 // TODO: store device type and id to own file
318                 else if (ii >= 3) {
319                         suc_flg = string_to_number<double>(val, item, dec);
320                         if (suc_flg) {
321                                 //log_debug("adding number: %f\n", val);
322                                 v.push_back(val);
323                         }
324                 }
325                 ii++;
326         }
327         ret_val = new Data(v, &date);
328         return ret_val;
329 }