1 /*
2  * Utils.h
3  *
4  * Created on: Jul 30, 2015
5  *     Author: dpayne
6  */
7 
8 #ifndef _VIS_UTILS_H
9 #define _VIS_UTILS_H
10 
11 #include "Domain/VisConstants.h"
12 #include "Domain/VisTypes.h"
13 
14 #include <algorithm>
15 #include <cctype>
16 #include <cstdlib>
17 #include <iostream>
18 #include <locale>
19 #include <sstream>
20 #include <string>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include <pwd.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 
28 namespace vis
29 {
30 
31 class Utils
32 {
33 
34   public:
35     /**
36      * Returns true if the given string is an integer. Supports signed and
37      * unsigned numbers between MIN_LONG and MAX_LONG
38      */
is_numeric(const std::string & s)39     static inline bool is_numeric(const std::string &s)
40     {
41         char *p = nullptr;
42         auto cstr = s.c_str();
43 
44         std::strtol(cstr, &p, 10);
45 
46         return p != cstr;
47     }
48 
49     /**
50      * lowercase and ascii string.
51      *  Note: this will not work on multi-byte unicode strings
52      */
lowercase(const std::string & str)53     static inline std::string lowercase(const std::string &str)
54     {
55         std::string result = str;
56         std::transform(result.begin(), result.end(), result.begin(), ::tolower);
57         return result;
58     }
59 
60     /**
61      *
62      * Converts strings to bool's. "1" and "true" are true where "true" can be
63      * mixed case, otherwise false is returned.
64      *
65      */
to_bool(const std::string & s)66     static inline bool to_bool(const std::string &s)
67     {
68         return (s == "1" || lowercase(s) == VisConstants::k_true);
69     }
70 
wstring_to_string(const std::wstring & s)71     static inline const std::string wstring_to_string(const std::wstring &s)
72     {
73         return std::string(s.begin(), s.end());
74     }
75 
76     /**
77      * Helper method for getting a value from a unordered map with a default.
78      */
79     template <class E, class V>
get(const std::unordered_map<E,V> & map,const E & key,const V & default_value)80     static inline const V &get(const std::unordered_map<E, V> &map,
81                                const E &key, const V &default_value)
82     {
83         auto iter = map.find(key);
84         if (iter != map.end())
85         {
86             return iter->second;
87         }
88 
89         return default_value;
90     }
91 
92     /**
93      * Helper method for getting a value from a unordered map with a default.
94      */
95     template <class E>
96     static inline const std::string
get(const std::unordered_map<E,std::wstring> & map,const E & key,const std::string & default_value)97     get(const std::unordered_map<E, std::wstring> &map, const E &key,
98         const std::string &default_value)
99     {
100         auto iter = map.find(key);
101         if (iter != map.end())
102         {
103             return wstring_to_string(iter->second);
104         }
105 
106         return default_value;
107     }
108 
109     /**
110      * Helper method for getting a wchar_t value from a unordered map with a
111      * default.
112      */
113     template <class E>
get(const std::unordered_map<E,std::wstring> & map,const E & key,const wchar_t default_value)114     static inline wchar_t get(const std::unordered_map<E, std::wstring> &map,
115                               const E &key, const wchar_t default_value)
116     {
117         auto iter = map.find(key);
118         if (iter != map.end())
119         {
120             if (iter->second.empty())
121             {
122                 return '\0';
123             }
124 
125             return iter->second.at(0);
126         }
127 
128         return default_value;
129     }
130 
131     /**
132      * Helper method for getting a bool value from a unordered map with a
133      * default.
134      */
135     template <class E>
get(const std::unordered_map<E,std::wstring> & map,const E & key,const bool default_value)136     static inline bool get(const std::unordered_map<E, std::wstring> &map,
137                            const E &key, const bool default_value)
138     {
139         auto iter = map.find(key);
140         if (iter != map.end())
141         {
142             return to_bool(wstring_to_string(iter->second));
143         }
144 
145         return default_value;
146     }
147 
148     /**
149      * Helper method for getting a double value from a unordered map with a
150      * default.
151      */
152     template <class E>
get(const std::unordered_map<E,std::wstring> & map,const E & key,const double default_value)153     static inline double get(const std::unordered_map<E, std::wstring> &map,
154                              const E &key, const double default_value)
155     {
156         auto iter = map.find(key);
157         if (iter != map.end())
158         {
159             return std::stod(wstring_to_string(iter->second));
160         }
161 
162         return default_value;
163     }
164 
165     /**
166      * Helper method for getting a uint32_t from a unordered map with a default.
167      */
168     template <class E>
get(const std::unordered_map<E,std::wstring> & map,const E & key,const uint32_t default_value)169     static inline uint32_t get(const std::unordered_map<E, std::wstring> &map,
170                                const E &key, const uint32_t default_value)
171     {
172         auto iter = map.find(key);
173         if (iter != map.end())
174         {
175             const auto num = to_int(wstring_to_string(iter->second));
176             if (num < 0)
177             {
178                 return default_value;
179             }
180             return static_cast<uint32_t>(num);
181         }
182 
183         return default_value;
184     }
185 
186     /**
187      * Helper method for getting a int32_t from a unordered map with a default.
188      */
189     template <class E>
get(const std::unordered_map<E,std::wstring> & map,const E & key,const int32_t default_value)190     static inline int32_t get(const std::unordered_map<E, std::wstring> &map,
191                               const E &key, const int32_t default_value)
192     {
193         auto iter = map.find(key);
194         if (iter != map.end())
195         {
196             return to_int(wstring_to_string(iter->second));
197         }
198 
199         return default_value;
200     }
201 
202     /**
203      * Helper method for getting a int64_t from a unordered map with a default.
204      */
205     template <class E>
get(const std::unordered_map<E,std::wstring> & map,const E & key,const int64_t default_value)206     static inline int64_t get(const std::unordered_map<E, std::wstring> &map,
207                               const E &key, const int64_t default_value)
208     {
209         auto iter = map.find(key);
210         if (iter != map.end())
211         {
212             return to_long(wstring_to_string(iter->second));
213         }
214 
215         return default_value;
216     }
217 
218     /**
219      * Split a string by the first delimiter. Note, the delimiter will not be
220      * included in either the first or second string in the pair.
221      */
split_first(const std::string & s,char delim,std::pair<std::string,std::string> * elems)222     static inline void split_first(const std::string &s, char delim,
223                                    std::pair<std::string, std::string> *elems)
224     {
225         auto index_of_first_elem = s.find_first_of(delim);
226 
227         // delimiter not found
228         if (index_of_first_elem == std::string::npos)
229         {
230             elems->first = s;
231             elems->second.clear();
232             return;
233         }
234 
235         elems->first = s.substr(0, index_of_first_elem);
236 
237         // nothing after the delimiter
238         if (index_of_first_elem == (s.size() - 1))
239         {
240             elems->second.clear();
241         }
242         else
243         {
244             elems->second =
245                 s.substr(index_of_first_elem + 1, std::string::npos);
246         }
247     }
248 
249     /**
250      * Split a string by the first delimiter. Note, the delimiter will not be
251      * included in either the first or second string in the pair.
252      */
split_first(const std::wstring & s,char delim,std::pair<std::wstring,std::wstring> * elems)253     static inline void split_first(const std::wstring &s, char delim,
254                                    std::pair<std::wstring, std::wstring> *elems)
255     {
256         auto index_of_first_elem = s.find_first_of(delim);
257 
258         // delimiter not found
259         if (index_of_first_elem == std::wstring::npos)
260         {
261             elems->first = s;
262             elems->second.clear();
263             return;
264         }
265 
266         elems->first = s.substr(0, index_of_first_elem);
267 
268         // nothing after the delimiter
269         if (index_of_first_elem == (s.size() - 1))
270         {
271             elems->second.clear();
272         }
273         else
274         {
275             elems->second =
276                 s.substr(index_of_first_elem + 1, std::wstring::npos);
277         }
278     }
279 
280     /**
281      * Helper method to convert string to long. If string is empty, 0 is
282      * returned.
283      */
to_long(const std::string & str)284     static inline int64_t to_long(const std::string &str)
285     {
286         if (str.empty())
287         {
288             return 0L;
289         }
290 
291         return std::atoi(str.c_str());
292     }
293 
294     /**
295      * Helper method to convert string to int. If string is empty, 0 is
296      * returned.
297      */
to_int(const std::string & str)298     static inline int32_t to_int(const std::string &str)
299     {
300         if (str.empty())
301         {
302             return 0;
303         }
304 
305         return std::atoi(str.c_str());
306     }
307 
308     /**
309      * Helper method to split a string by the delimiter "delim"
310      */
split(const std::string & s,char delim)311     static inline std::vector<std::string> split(const std::string &s,
312                                                  char delim)
313     {
314         std::vector<std::string> result;
315         split(s, delim, &result);
316         return result;
317     }
318 
319     /**
320      * Helper method to split a string by the delimiter "delim", contents are
321      * put input the vector "elems"
322      */
split(const std::string & s,char delim,std::vector<std::string> * elems)323     static inline void split(const std::string &s, char delim,
324                              std::vector<std::string> *elems)
325     {
326         std::stringstream ss(s);
327         std::string item;
328 
329         elems->clear();
330 
331         while (std::getline(ss, item, delim))
332         {
333             elems->push_back(item);
334         }
335     }
336 
337     /**
338      * Helper method to split a wstring by the delimiter "delim"
339      */
split(const std::wstring & s,wchar_t delim)340     static inline std::vector<std::wstring> split(const std::wstring &s,
341                                                   wchar_t delim)
342     {
343         std::vector<std::wstring> result;
344         split(s, delim, &result);
345         return result;
346     }
347 
348     /**
349      * Helper method to split a wstring by the delimiter "delim", contents are
350      * put input the vector "elems"
351      */
split(const std::wstring & s,wchar_t delim,std::vector<std::wstring> * elems)352     static inline void split(const std::wstring &s, wchar_t delim,
353                              std::vector<std::wstring> *elems)
354     {
355         std::wstringstream ss(s);
356         std::wstring item;
357 
358         elems->clear();
359 
360         while (std::getline(ss, item, delim))
361         {
362             elems->push_back(item);
363         }
364     }
365 
366     /**
367      * Helper method to convert a single hex character to the equivalent integer
368      * representation.
369      */
hex_to_int(char c)370     static inline int64_t hex_to_int(char c)
371     {
372         int64_t hex_number;
373         if (c >= '0' && c <= '9')
374         {
375             hex_number = static_cast<int64_t>(c - '0');
376         }
377         else
378         {
379             if (c >= 'a' && c <= 'z')
380             {
381                 c -= 32;
382             }
383 
384             if (c >= 'A' && c <= 'F')
385             {
386                 hex_number = 10 + static_cast<int64_t>(c - 'A');
387             }
388             else
389             {
390                 hex_number = 0;
391             }
392         }
393 
394         return hex_number;
395     }
396 
397     /**
398      * Helper method to convert a hex string to the equivalent integer
399      * representation.
400      */
hex_to_int(const std::string & hex)401     static inline int64_t hex_to_int(const std::string &hex)
402     {
403         auto decimalValue = 0l;
404         for (const auto &elem : hex)
405         {
406             decimalValue = decimalValue * 16 + hex_to_int(elem);
407         }
408 
409         return decimalValue;
410     }
411 };
412 } // namespace vis
413 
414 #endif
415