source: nscp/include/strEx.h @ 465866c

0.4.10.4.2
Last change on this file since 465866c was 465866c, checked in by Michael Medin <michael@…>, 13 months ago

2012-06-05 MickeM

  • Tweaked all servers to use the new internals and added first testcase for NSCP socket

2012-05-24 MickeM

  • Reworked real time event log support to be a lot more flexible You can now specify all options on a "filter" level.
  • WARNING* Old syntax NOT supported (and will not upgrade) but hopefully not to many will be affected.
  • Added support for ipv6 allowed hosts validation

2012-05-21 MickeM

  • Sofia Born (My second daughter)
  • Property mode set to 100644
File size: 33.2 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#pragma once
22#include <unicode_char.hpp>
23#include <types.hpp>
24
25#include <string>
26#include <sstream>
27#include <iomanip>
28#include <utility>
29#include <list>
30#include <functional>
31#include <time.h>
32#include <algorithm>
33#include <locale>
34#include <iostream>
35
36#include <cctype>
37
38#ifdef __GNUC__
39#include <iconv.h>
40#include <errno.h>
41#endif
42
43#include <boost/lexical_cast.hpp>
44#include <boost/date_time.hpp>
45#include <boost/algorithm/string.hpp>
46#include <boost/foreach.hpp>
47//#include <boost/date_time/local_time/local_date_time.hpp>
48//#include <boost/date_time/gregorian/conversion.hpp>
49//boost::local_time::local_date_time
50
51
52#ifdef _DEBUG
53#include <iostream>
54#endif
55
56
57
58
59#include <string>
60#include <locale>
61
62
63namespace utf8 {
64        /** Converts a std::wstring into a std::string with UTF-8 encoding. */
65        template<typename StringT>
66        StringT cvt(std::wstring const & string);
67
68        /** Converts a std::String with UTF-8 encoding into a std::wstring.     */
69        template<typename StringT>
70        StringT cvt(std::string const & string );
71
72        /** Nop specialization for std::string. */
73        template <>
74        inline std::string cvt(std::string const & string) {
75                return string;
76        }
77
78        /** Nop specialization for std::wstring. */
79        template<>
80        inline std::wstring cvt(std::wstring const & rc_string) {
81                return rc_string;
82        }
83
84        inline std::wstring to_unicode(std::string const & str) {
85#ifdef WIN32
86                int len = static_cast<int>(str.length());
87                int nChars = MultiByteToWideChar(CP_ACP, 0, str.c_str(), len, NULL, 0);
88                if (nChars == 0)
89                        return L"";
90                wchar_t *buffer = new wchar_t[nChars+1];
91                if (buffer == NULL)
92                        return L"";
93                MultiByteToWideChar(CP_ACP, 0, str.c_str(), len, buffer, nChars);
94                buffer[nChars] = 0;
95                std::wstring buf(buffer, nChars);
96                delete [] buffer;
97                return buf;
98#else
99                size_t utf8Length = str.length();
100                size_t outbytesLeft = utf8Length*sizeof(wchar_t);
101
102                //Copy the instring
103                char *inString = new char[str.length()+1];
104                strcpy(inString, str.c_str());
105
106                //Create buffer for output
107                char *outString = (char*)new wchar_t[utf8Length+1];
108                memset(outString, 0, sizeof(wchar_t)*(utf8Length+1));
109
110                char *inPointer = inString;
111                char *outPointer = outString;
112
113                iconv_t convDesc = iconv_open("WCHAR_T", "");
114                iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft);
115                iconv_close(convDesc);
116
117                std::wstring retval( (wchar_t *)outString );
118
119                //Cleanup
120                delete[] inString;
121                delete[] outString;
122
123                return retval;
124#endif 
125        }
126        /*
127        inline std::wstring to_unicode(std::wstring const & str) {
128#ifdef WIN32
129                // figure out how many narrow characters we are going to get
130                int nChars = WideCharToMultiByte(CP_OEMCP, 0, str.c_str(), static_cast<int>(str.length()), NULL, 0, NULL, NULL);
131                if (nChars == 0)
132                        return "";
133
134                // convert the wide string to a narrow string
135                // nb: slightly naughty to write directly into the string like this
136                std::string buf;
137                buf.resize(nChars);
138                WideCharToMultiByte(CP_OEMCP, 0, str.c_str(), static_cast<int>(str.length()), const_cast<char*>(buf.c_str()), nChars, NULL, NULL);
139                return buf;
140#else
141                return str;
142#endif
143        }
144*/
145
146        template<>
147        inline std::string cvt(std::wstring const & str) {
148#ifdef WIN32
149                // figure out how many narrow characters we are going to get
150                int nChars = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), static_cast<int>(str.length()), NULL, 0, NULL, NULL);
151                if (nChars == 0)
152                        return "";
153
154                // convert the wide string to a narrow string
155                // nb: slightly naughty to write directly into the string like this
156                std::string buf;
157                buf.resize(nChars);
158                WideCharToMultiByte(CP_UTF8, 0, str.c_str(), static_cast<int>(str.length()), const_cast<char*>(buf.c_str()), nChars, NULL, NULL);
159                return buf;
160#else
161                size_t wideSize = sizeof(wchar_t)*str.length();
162                size_t outbytesLeft = wideSize+sizeof(char); //We cannot know how many wide character there is yet
163
164                //Copy the instring
165                char *inString = (char*)new wchar_t[str.length()+1];
166                memcpy(inString, str.c_str(), wideSize+sizeof(wchar_t));
167
168                //Create buffer for output
169                char *outString = new char[outbytesLeft];
170                memset(outString, 0, sizeof(char)*(outbytesLeft));
171
172                char *inPointer = inString;
173                char *outPointer = outString;
174
175                iconv_t convDesc = iconv_open("UTF-8", "WCHAR_T");
176                iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft);
177                iconv_close(convDesc);
178
179                std::string retval(outString);
180
181                //Cleanup
182                delete[] inString;
183                delete[] outString;
184
185                return retval;
186#endif
187        }
188
189        template<>
190        inline std::wstring cvt(std::string const & str) {
191#ifdef WIN32
192                int len = static_cast<int>(str.length());
193                int nChars = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), len, NULL, 0);
194                if (nChars == 0)
195                        return L"";
196                wchar_t *buffer = new wchar_t[nChars+1];
197                if (buffer == NULL)
198                        return L"";
199                MultiByteToWideChar(CP_UTF8, 0, str.c_str(), len, buffer, nChars);
200                buffer[nChars] = 0;
201                std::wstring buf(buffer, nChars);
202                delete [] buffer;
203                return buf;
204#else
205                size_t utf8Length = str.length();
206                size_t outbytesLeft = utf8Length*sizeof(wchar_t);
207
208                //Copy the instring
209                char *inString = new char[str.length()+1];
210                strcpy(inString, str.c_str());
211
212                //Create buffer for output
213                char *outString = (char*)new wchar_t[utf8Length+1];
214                memset(outString, 0, sizeof(wchar_t)*(utf8Length+1));
215
216                char *inPointer = inString;
217                char *outPointer = outString;
218
219                iconv_t convDesc = iconv_open("WCHAR_T", "UTF-8");
220                iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft);
221                iconv_close(convDesc);
222
223                std::wstring retval( (wchar_t *)outString );
224
225                //Cleanup
226                delete[] inString;
227                delete[] outString;
228
229                return retval;
230#endif
231        }
232}
233
234namespace boost
235{
236        template<>
237        inline std::wstring lexical_cast<std::wstring, std::string>(const std::string& arg) {
238                return utf8::cvt<std::wstring>(arg);
239        }
240
241        template<>
242        inline std::string lexical_cast<std::string, std::wstring>(const std::wstring& arg) {
243                return utf8::cvt<std::string>(arg);
244        }
245}
246
247namespace strEx {
248        class string_exception : public std::exception {
249                std::wstring _what;
250        public:
251                string_exception(std::wstring what) : _what(what) {}
252                std::wstring what() {
253                        return _what;
254                }
255                virtual ~string_exception() throw();
256        };
257        namespace s {
258                /*
259                inline std::string itos(float i) {
260                        std::stringstream ss;
261                        ss << i;
262                        return ss.str();
263                }
264                inline std::string itos(double i) {
265                        std::stringstream ss;
266                        ss << i;
267                        return ss.str();
268                }
269                inline std::string itos(int i) {
270                        std::stringstream ss;
271                        ss << i;
272                        return ss.str();
273                }
274                */
275                template<typename T>
276                inline std::string itos(T i) {
277                        std::stringstream ss;
278                        ss << i;
279                        return ss.str();
280                }
281                inline std::string itos_non_sci(double i) {
282                        std::stringstream ss;
283                        if (i < 10)
284                                ss.precision(20);
285                        ss << std::noshowpoint << std::fixed << i;
286                        std::string s = ss.str();
287                        std::string::size_type pos = s.find_last_not_of('0');
288                        if (pos == std::wstring::npos)
289                                return s;
290                        if (s[pos] != '.')
291                                pos++;
292                        return s.substr(0, pos);
293                }
294        }
295
296        inline std::wstring strip_hex(std::wstring str) {
297                std::wstring ret; ret.reserve(str.size());
298                BOOST_FOREACH(wchar_t c, str)
299                {
300                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
301                                ret.push_back(L'?');
302                        else
303                                ret.push_back(c);
304                }
305                return ret;
306        }
307        inline std::string strip_hex(std::string str) {
308                std::string ret; ret.reserve(str.size());
309                BOOST_FOREACH(char c, str)
310                {
311                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
312                                ret.push_back('?');
313                        else
314                                ret.push_back(c);
315                }
316                return ret;
317        }
318
319        inline std::string strip_hex(std::vector<char> str) {
320                std::string ret; ret.reserve(str.size());
321                BOOST_FOREACH(char c, str)
322                {
323                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
324                                ret.push_back('?');
325                        else
326                                ret.push_back(c);
327                }
328                return ret;
329        }
330
331        inline void append_list(std::wstring &lst, std::wstring &append, std::wstring sep = _T(", ")) {
332                if (append.empty())
333                        return;
334                if (!lst.empty())
335                        lst += sep;
336                lst += append;
337        }
338        inline void append_list_ex(std::wstring &lst, std::wstring append, std::wstring sep = _T(", ")) {
339                if (append.empty())
340                        return;
341                if (!lst.empty())
342                        lst += sep;
343                lst += append;
344        }
345        inline std::string wstring_to_string( const std::wstring& str ) {
346                return utf8::cvt<std::string>(str);
347        }
348        inline std::wstring string_to_wstring( const std::string& str ) {
349                return utf8::cvt<std::wstring>(str);
350        }
351
352        inline std::wstring format_buffer(const wchar_t* buf, unsigned int len) {
353                std::wstringstream ss;
354                std::wstring chars;
355                for (unsigned int i=0;i<len;i++) {
356                        ss << std::hex << buf[i];
357                        ss << _T(", ");
358                        if (buf[i] >= ' ' && buf[i] <= 'z')
359                                chars += buf[i];
360                        else
361                                chars += '?';
362                        if (i%32==0) {
363                                ss << chars;
364                                ss << _T("\n");
365                                chars = _T("");
366                        }
367                }
368                ss << chars;
369                return ss.str();
370        }
371        inline std::string format_buffer(const char* buf, std::string::size_type len) {
372                std::stringstream ss;
373                std::string chars;
374                for (std::string::size_type i=0;i<len;i++) {
375                        if (i%32==0) {
376                                if (i > 0) {
377                                        ss << chars;
378                                        ss << "\n";
379                                }
380                                chars = "";
381                                ss << std::hex << std::setw(8) << std::setfill('0') << i;
382                                ss << ": ";
383                        }
384                        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(buf[i]));
385                        ss << ", ";
386                        if (buf[i] < 30 || buf[i] == 127)
387                                chars += '?';
388                        else
389                                chars += buf[i];
390                }
391                ss << chars;
392                return ss.str();
393        }
394        inline std::string format_buffer(const std::string &buf) {
395                return format_buffer(buf.c_str(), buf.size());
396        }
397        inline std::string format_buffer(const std::vector<char> &buf) {
398                std::stringstream ss;
399                std::string chars;
400                for (unsigned int i=0;i<buf.size();i++) {
401                        if (i%32==0) {
402                                if (i > 0) {
403                                        ss << chars;
404                                        ss << "\n";
405                                }
406                                chars = "";
407                                ss << std::hex << std::setw(8) << std::setfill('0') << i;
408                                ss << ": ";
409                        }
410                        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(buf[i]));
411                        ss << ", ";
412                        if (buf[i] < 30 || buf[i] == 127)
413                                chars += '?';
414                        else
415                                chars += buf[i];
416                }
417                ss << chars;
418                return ss.str();
419        }
420        inline std::wstring format_date(boost::posix_time::ptime date, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
421                std::locale locale_local ("");
422
423                boost::gregorian::wdate_facet *date_output = new boost::gregorian::wdate_facet();
424                std::locale locale_adjusted (locale_local, date_output);
425
426                std::wstringstream date_ss;
427                date_ss.imbue(locale_adjusted);
428
429                date_output->format(format.c_str());
430                date_ss << date;
431
432                std::wstring ss = date_ss.str();
433                return ss;
434        }
435#ifdef WIN32
436        inline std::wstring format_date(const SYSTEMTIME &time, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
437                TCHAR buf[51];
438
439                struct tm tmTime;
440                memset(&tmTime, 0, sizeof(tmTime));
441
442                tmTime.tm_sec = time.wSecond; // seconds after the minute - [0,59]
443                tmTime.tm_min = time.wMinute; // minutes after the hour - [0,59]
444                tmTime.tm_hour = time.wHour;  // hours since midnight - [0,23]
445                tmTime.tm_mday = time.wDay;  // day of the month - [1,31]
446                tmTime.tm_mon = time.wMonth-1; // months since January - [0,11]
447                tmTime.tm_year = time.wYear-1900; // years since 1900
448                tmTime.tm_wday = time.wDayOfWeek; // days since Sunday - [0,6]
449
450                size_t l = wcsftime(buf, 50, format.c_str(), &tmTime);
451                if (l <= 0 || l >= 50)
452                        return _T("");
453                buf[l] = 0;
454                return buf;
455        }
456#endif
457
458
459        inline std::wstring format_date(std::time_t time, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
460                return format_date(boost::posix_time::from_time_t(time), format);
461        }
462
463       
464        static const long long SECS_BETWEEN_EPOCHS = 11644473600;
465        static const long long SECS_TO_100NS = 10000000;
466        inline unsigned long long filetime_to_time(unsigned long long filetime) {
467                return (filetime - (SECS_BETWEEN_EPOCHS * SECS_TO_100NS)) / SECS_TO_100NS;
468        }
469        inline std::wstring format_filetime(unsigned long long filetime, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
470                if (filetime == 0)
471                        return _T("ZERO");
472                return format_date(static_cast<time_t>(filetime_to_time(filetime)), format);
473        }
474
475        inline void replace(std::wstring &string, const std::wstring replace, const std::wstring with) {
476                std::wstring::size_type pos = string.find(replace);
477                std::wstring::size_type len = replace.length();
478                while (pos != std::wstring::npos) {
479                        string = string.substr(0,pos)+with+string.substr(pos+len);
480                        if (with.find(replace) != std::wstring::npos) // If the replace containes the key look after the replace!
481                                pos = string.find(replace, pos+with.length());
482                        else
483                                pos = string.find(replace, pos+1);
484                }
485        }
486        inline void replace(std::string &string, const std::string replace, const std::string with) {
487                std::string::size_type pos = string.find(replace);
488                std::string::size_type len = replace.length();
489                while (pos != std::string::npos) {
490                        string = string.substr(0,pos)+with+string.substr(pos+len);
491                        if (with.find(replace) != std::string::npos) // If the replace containes the key look after the replace!
492                                pos = string.find(replace, pos+with.length());
493                        else
494                                pos = string.find(replace, pos+1);
495                }
496        }
497        inline std::wstring ctos(wchar_t c) {
498                return std::wstring(1, c);
499        }
500        inline wchar_t stoc(std::wstring str) {
501                if (str.length() == 0)
502                        return L' ';
503                return str[0];
504        }
505        inline std::wstring itos(unsigned int i) {
506                std::wstringstream ss;
507                ss << i;
508                return ss.str();
509        }
510        inline std::wstring itos(int i) {
511                std::wstringstream ss;
512                ss << i;
513                return ss.str();
514        }
515        inline std::wstring itos(unsigned long long i) {
516                std::wstringstream ss;
517                ss << i;
518                return ss.str();
519        }
520        inline std::wstring itos(long long i) {
521                std::wstringstream ss;
522                ss << i;
523                return ss.str();
524        }
525        /*
526        inline std::wstring itos(__int64 i) {
527                std::wstringstream ss;
528                ss << i;
529                return ss.str();
530        }
531        */
532        inline std::wstring itos(unsigned long i) {
533                std::wstringstream ss;
534                ss << i;
535                return ss.str();
536        }
537        inline std::wstring itos(double i) {
538                std::wstringstream ss;
539                ss << i;
540                return ss.str();
541        }
542        inline std::wstring itos_non_sci(double i) {
543                std::wstringstream ss;
544                if (i < 10)
545                        ss.precision(20);
546                ss << std::noshowpoint << std::fixed << i;
547                std::wstring s = ss.str();
548                std::wstring::size_type pos = s.find_last_not_of('0');
549                if (pos == std::wstring::npos)
550                        return s;
551                if (s[pos] != '.')
552                        pos++;
553                return s.substr(0, pos);
554        }
555        inline std::wstring itos(float i) {
556                std::wstringstream ss;
557                ss << i;
558                return ss.str();
559        }
560        inline std::wstring ihextos(unsigned int i) {
561                std::wstringstream ss;
562                ss << std::hex << i;
563                return ss.str();
564        }
565        inline int stoi(std::wstring s) {
566                return boost::lexical_cast<int>(s.c_str());
567        }
568        inline int stoi(std::string s) {
569                return boost::lexical_cast<int>(s.c_str());
570        }
571        template<class T>
572        inline double stod(T s) {
573                return boost::lexical_cast<double>(s.c_str());
574        }
575        inline long long stoi64(std::wstring s) {
576                return boost::lexical_cast<long long>(s.c_str());
577        }
578        inline unsigned stoui_as_time(std::wstring time, unsigned int smallest_unit = 1000) {
579                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
580                std::wstring::size_type pend = time.find_first_not_of(_T("0123456789"));
581                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::wstring::npos?time:time.substr(0,pend).c_str());
582                if (p == std::wstring::npos)
583                        return value * smallest_unit;
584                else if ( (time[p] == 's') || (time[p] == 'S') )
585                        return value * 1000;
586                else if ( (time[p] == 'm') || (time[p] == 'M') )
587                        return value * 60 * 1000;
588                else if ( (time[p] == 'h') || (time[p] == 'H') )
589                        return value * 60 * 60 * 1000;
590                else if ( (time[p] == 'd') || (time[p] == 'D') )
591                        return value * 24 * 60 * 60 * 1000;
592                else if ( (time[p] == 'w') || (time[p] == 'W') )
593                        return value * 7 * 24 * 60 * 60 * 1000;
594                return value * smallest_unit;
595        }
596        inline unsigned stoui_as_time_sec(std::wstring time, unsigned int smallest_unit = 1) {
597                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
598                std::wstring::size_type pend = time.find_first_not_of(_T("0123456789"));
599                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::wstring::npos?time:time.substr(0,pend).c_str());
600                if (p == std::wstring::npos)
601                        return value * smallest_unit;
602                else if ( (time[p] == L's') || (time[p] == L'S') )
603                        return value;
604                else if ( (time[p] == L'm') || (time[p] == L'M') )
605                        return value * 60;
606                else if ( (time[p] == L'h') || (time[p] == L'H') )
607                        return value * 60 * 60;
608                else if ( (time[p] == L'd') || (time[p] == L'D') )
609                        return value * 24 * 60 * 60;
610                else if ( (time[p] == L'w') || (time[p] == L'W') )
611                        return value * 7 * 24 * 60 * 60;
612                return value * smallest_unit;
613        }
614        inline unsigned stoui_as_time_sec(std::string time, unsigned int smallest_unit = 1) {
615                std::string::size_type p = time.find_first_of("sSmMhHdDwW");
616                std::string::size_type pend = time.find_first_not_of("0123456789");
617                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::string::npos?time:time.substr(0,pend).c_str());
618                if (p == std::string::npos)
619                        return value * smallest_unit;
620                else if ( (time[p] == 's') || (time[p] == 'S') )
621                        return value;
622                else if ( (time[p] == 'm') || (time[p] == 'M') )
623                        return value * 60;
624                else if ( (time[p] == 'h') || (time[p] == 'H') )
625                        return value * 60 * 60;
626                else if ( (time[p] == 'd') || (time[p] == 'D') )
627                        return value * 24 * 60 * 60;
628                else if ( (time[p] == 'w') || (time[p] == 'W') )
629                        return value * 7 * 24 * 60 * 60;
630                return value * smallest_unit;
631        }
632        inline long stol_as_time_sec(std::wstring time, unsigned int smallest_unit = 1) {
633                long neg = 1;
634                if (time.length() > 1 && time[0] == L'-')
635                        return -(long)stoui_as_time_sec(time.substr(1), smallest_unit);
636                return stoui_as_time_sec(time, smallest_unit);
637        }
638        inline long stol_as_time_sec(std::string time, unsigned int smallest_unit = 1) {
639                long neg = 1;
640                if (time.length() > 1 && time[0] == '-')
641                        return -(long)stoui_as_time_sec(time.substr(1), smallest_unit);
642                return stoui_as_time_sec(time, smallest_unit);
643        }
644
645        inline unsigned long long stoi64_as_time(std::wstring time, unsigned int smallest_unit = 1000) {
646                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
647                if (p == std::wstring::npos)
648                        return boost::lexical_cast<long long>(time) * smallest_unit;
649                unsigned long long value = boost::lexical_cast<long long>(time.substr(0, p));
650                if ( (time[p] == 's') || (time[p] == 'S') )
651                        return value * 1000;
652                else if ( (time[p] == 'm') || (time[p] == 'M') )
653                        return value * 60 * 1000;
654                else if ( (time[p] == 'h') || (time[p] == 'H') )
655                        return value * 60 * 60 * 1000;
656                else if ( (time[p] == 'd') || (time[p] == 'D') )
657                        return value * 24 * 60 * 60 * 1000;
658                else if ( (time[p] == 'w') || (time[p] == 'W') )
659                        return value * 7 * 24 * 60 * 60 * 1000;
660                return value * smallest_unit;
661        }
662
663
664#define WEEK    (7 * 24 * 60 * 60 * 1000)
665#define DAY             (24 * 60 * 60 * 1000)
666#define HOUR    (60 * 60 * 1000)
667#define MIN             (60 * 1000)
668#define SEC             (1000)
669        inline std::wstring itos_as_time(unsigned long long time) {
670                if (time > WEEK) {
671                        unsigned int w = static_cast<unsigned int>(time/WEEK);
672                        unsigned int d = static_cast<unsigned int>((time-(w*WEEK))/DAY);
673                        unsigned int h = static_cast<unsigned int>((time-(w*WEEK)-(d*DAY))/HOUR);
674                        unsigned int m = static_cast<unsigned int>((time-(w*WEEK)-(d*DAY)-(h*HOUR))/MIN);
675                        return itos(w) + _T("w ") + itos(d) + _T("d ") + itos(h) + _T(":") + itos(m);
676                }
677                else if (time > DAY) {
678                        unsigned int d = static_cast<unsigned int>((time)/DAY);
679                        unsigned int h = static_cast<unsigned int>((time-(d*DAY))/HOUR);
680                        unsigned int m = static_cast<unsigned int>((time-(d*DAY)-(h*HOUR))/MIN);
681                        return itos(d) + _T("d ") + itos(h) + _T(":") + itos(m);
682                }
683                else if (time > HOUR) {
684                        unsigned int h = static_cast<unsigned int>((time)/HOUR);
685                        unsigned int m = static_cast<unsigned int>((time-(h*HOUR))/MIN);
686                        return itos(h) + _T(":") + itos(m);
687                } else if (time > MIN) {
688                        return _T("0:") + itos(static_cast<unsigned int>(time/(60 * 1000)));
689                } else if (time > SEC)
690                        return itos(static_cast<unsigned int>(time/(1000))) + _T("s");
691                return itos(static_cast<unsigned int>(time));
692        }
693
694        inline long long stoi64_as_BKMG(const std::wstring &s) {
695                std::wstring::size_type p = s.find_first_not_of(_T("0123456789"));
696                if (p == std::wstring::npos || p == 0)
697                        return boost::lexical_cast<long long>(s);
698                std::wstring numbers = s.substr(0, p);
699                if (s[p] == 'B')
700                        return boost::lexical_cast<long long>(numbers);
701                else if (s[p] == 'K')
702                        return boost::lexical_cast<long long>(numbers)*1024;
703                else if (s[p] == 'M')
704                        return boost::lexical_cast<long long>(numbers)*1024*1024;
705                else if (s[p] == 'G')
706                        return boost::lexical_cast<long long>(numbers)*1024*1024*1024;
707                else if (s[p] == 'T')
708                        return boost::lexical_cast<long long>(numbers)*1024*1024*1024*1024;
709                else
710                        return boost::lexical_cast<long long>(numbers);
711        }
712#define BKMG_RANGE _T("BKMGTP")
713#define BKMG_SIZE 5
714
715        inline std::wstring itos_as_BKMG(unsigned long long i) {
716                double cpy = static_cast<double>(i);
717                wchar_t postfix[] = BKMG_RANGE;
718                int idx = 0;
719                while ((cpy > 999)&&(idx<BKMG_SIZE)) {
720                        cpy/=1024;
721                        idx++;
722                }
723                std::wstringstream ss;
724                ss << std::setprecision(3);
725                ss << cpy;
726                std::wstring ret = ss.str(); // itos(cpy);
727                ret += postfix[idx];
728                return ret;
729        }
730        inline std::wstring format_BKMG(unsigned long long i, std::wstring unit) {
731                double cpy = static_cast<double>(i);
732                wchar_t postfix[] = BKMG_RANGE;
733                if (unit.length() != 1)
734                        return itos(cpy);
735                for (int i=0;i<BKMG_SIZE;i++) {
736                        if (unit[0] == postfix[i]) {
737                                std::wstringstream ss;
738                                ss << std::setiosflags(std::ios::fixed) << std::setprecision(3) << cpy;
739                                std::wstring s = ss.str();
740                                std::wstring::size_type pos = s.find_last_not_of(_T("0"));
741                                if (pos != std::string::npos) {
742                                        s = s.substr(0,pos);
743                                }
744                                return s;
745                        }
746                        cpy/=1024;
747                }
748                return itos(cpy);
749        }
750        inline std::wstring find_proper_unit_BKMG(unsigned long long i) {
751                double cpy = static_cast<double>(i);
752                wchar_t postfix[] = BKMG_RANGE;
753                int idx = 0;
754                while ((cpy > 999)&&(idx<BKMG_SIZE)) {
755                        cpy/=1024;
756                        idx++;
757                }
758                return std::wstring(1, postfix[idx]);
759        }
760
761        typedef std::list<std::wstring> splitList;
762        inline splitList splitEx(const std::wstring str, const std::wstring key) {
763                splitList ret;
764                std::wstring::size_type pos = 0, lpos = 0;
765                while ((pos = str.find(key, pos)) !=  std::wstring::npos) {
766                        ret.push_back(str.substr(lpos, pos-lpos));
767                        lpos = ++pos;
768                }
769                if (lpos < str.size())
770                        ret.push_back(str.substr(lpos));
771                return ret;
772        }
773        typedef std::vector<std::wstring> splitVector;
774        template<class T>
775        inline std::vector<T> splitV(const T str, const T key) {
776                std::vector<T> ret;
777                typename T::size_type pos = 0, lpos = 0;
778                while ((pos = str.find(key, pos)) !=  T::npos) {
779                        ret.push_back(str.substr(lpos, pos-lpos));
780                        lpos = ++pos;
781                }
782                if (lpos < str.size())
783                        ret.push_back(str.substr(lpos));
784                return ret;
785        }
786        inline std::wstring joinEx(splitList lst, std::wstring key) {
787                std::wstring ret;
788                for (splitList::const_iterator it = lst.begin(); it != lst.end(); ++it) {
789                        if (!ret.empty())
790                                ret += key;
791                        ret += *it;
792                }
793                return ret;
794        }
795
796
797
798        inline std::wstring trim_right(const std::wstring &source , const std::wstring& t = _T(" "))
799        {
800                std::wstring str = source;
801                return str.erase( str.find_last_not_of(t) + 1);
802        }
803
804        inline std::wstring trim_left( const std::wstring& source, const std::wstring& t = _T(" "))
805        {
806                std::wstring str = source;
807                return str.erase(0 , source.find_first_not_of(t) );
808        }
809
810        inline std::wstring trim(const std::wstring& source, const std::wstring& t = _T(" "))
811        {
812                std::wstring str = source;
813                return trim_left( trim_right( str , t) , t );
814        }
815        template<class T>
816        inline std::pair<T,T> split(T str, T key) {
817                typename T::size_type pos = str.find(key);
818                if (pos == T::npos)
819                        return std::pair<T,T>(str, T());
820                return std::pair<T,T>(str.substr(0, pos), str.substr(pos+key.length()));
821        }
822        typedef std::pair<std::wstring,std::wstring> token;
823        // foo bar "foo \" bar" foo -> foo, bar "foo \" bar" foo -> bar, "foo \" bar" foo ->
824        //
825        inline token getToken(std::wstring buffer, char split, bool escape = false) {
826                std::wstring::size_type pos = std::wstring::npos;
827                if ((escape) && (buffer[0] == '\"')) {
828                        do {
829                                pos = buffer.find('\"');
830                        }
831                        while (((pos != std::wstring::npos)&&(pos > 1))&&(buffer[pos-1] == '\\'));
832                } else
833                        pos = buffer.find(split);
834                if (pos == std::wstring::npos)
835                        return token(buffer, _T(""));
836                if (pos == buffer.length()-1)
837                        return token(buffer.substr(0, pos), _T(""));
838                return token(buffer.substr(0, pos-1), buffer.substr(++pos));
839        }
840
841
842
843        template<class char_type>
844        struct ci_char_traits : public std::char_traits<char_type> {
845                static bool eq( char_type c1, char_type c2 ) {
846                        return toupper(c1) == toupper(c2);
847                }
848
849                static bool ne( char_type c1, char_type c2 ) {
850                        return toupper(c1) != toupper(c2);
851                }
852
853                static bool lt( char_type c1, char_type c2 ) {
854                        return toupper(c1) <  toupper(c2);
855                }
856
857                static int compare( const char_type* s1, const char_type* s2, size_t n ) {
858#ifdef WIN32
859                        return memicmp( s1, s2, n );
860#else
861                        while (n-- && eq(*s1, *s2))
862                                ++s1, ++s2;
863                        return lt(*s2, *s1) - lt(*s1, *s2);
864#endif
865                }
866
867                static const char* find( const char_type* s, int n, char_type a ) {
868                        while( n-- > 0 && toupper(*s) != toupper(a) ) {
869                                ++s;
870                        }
871                        return s;
872                }
873        };
874        typedef std::basic_string<wchar_t, ci_char_traits<wchar_t> > wci_string;
875
876        template<class _E>
877        struct blind_traits : public std::char_traits<_E>
878        {
879               
880                static bool eq(const _E& x, const _E& y) {
881                        return boost::algorithm::iequals(x,y);
882                }
883                static bool lt(const _E& x, const _E& y) {
884                        return ilexicographical_compare(x, y);
885                }
886/*
887                static int compare(const _E *x, const _E *y, size_t n) {
888                        return ilexicographical_compare(x, y);
889                        return _wcsnicmp( x, y, n );
890                }
891
892                //  There's no memichr(), so we roll our own.  It ain't rocket science.
893                static const _E * / *__cdecl* / find(const _E *buf, size_t len, const _E& ch) {
894                        //  Jerry says that x86s have special mojo for memchr(), so the
895                        //  memchr() calls end up being reasonably efficient in practice.
896                        const _E *pu = (const _E *)memchr(buf, ch, len);
897                        const _E *pl = (const _E *)memchr(buf, tolower( ch ), len);
898                        if ( ! pu )
899                                return pl;  //  Might be NULL; if so, NULL's the word.
900                        else if ( ! pl )
901                                return pu;
902                        else
903                                //  If either one was NULL, we return the other; if neither is
904                                //  NULL, we return the lesser of the two.
905                                return ( pu < pl ) ? pu : pl;
906                }
907
908                //  I'm reasonably sure that this is eq() for wide characters.  Maybe.
909                static bool eq_int_type(const long& ch1, const long& ch2) {
910                        return std::char_traits<_E>::eq_int_type( tolower( ch1 ), tolower( ch2 ) );
911                }
912                */
913        };
914
915        //  And here's our case-blind string class.
916        //typedef std::basic_string<char, blind_traits<char>, std::allocator<char> >  blindstr;
917        typedef std::basic_string<wchar_t, blind_traits<wchar_t>, std::allocator<wchar_t> >  blindstr;
918
919
920
921
922        class StrICmp
923        {
924        public:
925                StrICmp(const std::string &Lang = "english") : m_locE(Lang.c_str())
926                {
927                }
928                class CharLessI
929                {
930                public:
931                        CharLessI(std::locale &locE) : m_locE(locE)
932                        {
933                        }
934                        template<typename T>
935                        bool operator()(T c1, T c2)
936                        {
937                                return std::tolower(c1, m_locE) < std::tolower(c2, m_locE);
938                        }
939                private:
940                        std::locale &m_locE;
941                };
942                template<typename T>
943                int operator()(const T &s1, const T &s2) const
944                {
945                        if (std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), CharLessI(m_locE)))
946                                return -1;
947                        if (std::lexicographical_compare(s2.begin(), s2.end(), s1.begin(), s1.end(), CharLessI(m_locE)))
948                                return 1;
949                        return 0;
950                }
951        private:
952                std::locale m_locE;
953        };
954
955        template<typename T>
956        int StrCmpI(const T &s1, const T &s2, const std::string &Lang = "english")
957        {
958                return StrICmp(Lang)(s1, s2);
959        }
960
961#define MK_FORMAT_FTD(min, key, val) \
962        if (mtm->tm_year > min) \
963        strEx::replace(format, key, strEx::itos(val));  \
964        else  \
965        strEx::replace(format, key, _T("0"));
966#ifdef WIN32
967        inline std::wstring format_time_delta(struct tm *mtm, std::wstring format = _T("%Y years %m months %d days %H hours %M minutes")) {
968                // "Date: %Y-%m-%d %H:%M:%S"
969                MK_FORMAT_FTD(70, _T("%Y"), mtm->tm_year);
970                MK_FORMAT_FTD(0, _T("%m"), mtm->tm_mon);
971                MK_FORMAT_FTD(0, _T("%d"), mtm->tm_mday-1);
972                MK_FORMAT_FTD(0, _T("%H"), mtm->tm_hour);
973                MK_FORMAT_FTD(0, _T("%M"), mtm->tm_min);
974                MK_FORMAT_FTD(0, _T("%S"), mtm->tm_sec);
975                return format;
976        }
977        inline std::wstring format_time_delta(time_t time, std::wstring format = _T("%Y years %m months %d days %H hours %M minutes")) {
978                struct tm nt; // = new struct tm;
979#if (_MSC_VER > 1300)  // 1300 == VC++ 7.0
980                if (gmtime_s(&nt, &time) != 0)
981                        return _T("");
982#else
983                nt = gmtime(&time);
984                if (nt == NULL)
985                        return "";
986#endif
987                return format_time_delta(&nt, format);
988        }
989        inline std::wstring format_filetime_delta(unsigned long long filetime, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
990                if (filetime == 0)
991                        return _T("ZERO");
992                //filetime -= (SECS_BETWEEN_EPOCHS * SECS_TO_100NS);
993                filetime /= SECS_TO_100NS;
994                return format_time_delta(static_cast<time_t>(filetime), format);
995        }
996#endif
997
998#ifdef _DEBUG
999        inline void test_getToken(std::wstring in1, char in2, std::wstring out1, std::wstring out2) {
1000                token t = getToken(in1, in2);
1001                std::wcout << _T("strEx::test_getToken(") << in1 << _T(", ") << in2 << _T(") : ");
1002                if ((t.first == out1) && (t.second == out2))
1003                        std::wcout << _T("Succeeded") << std::endl;
1004                else
1005                        std::wcout << _T("Failed [") << out1 << _T("=") << t.first << _T(", ") << out2 << _T("=") << t.second << _T("]") << std::endl;
1006        }
1007        inline void run_test_getToken() {
1008                test_getToken(_T(""), '&', _T(""), _T(""));
1009                test_getToken(_T("&"), '&', _T(""), _T(""));
1010                test_getToken(_T("&&"), '&', _T(""), _T("&"));
1011                test_getToken(_T("foo"), '&', _T("foo"), _T(""));
1012                test_getToken(_T("foo&"), '&', _T("foo"), _T(""));
1013                test_getToken(_T("foo&bar"), '&', _T("foo"), _T("bar"));
1014                test_getToken(_T("foo&bar&test"), '&', _T("foo"), _T("bar&test"));
1015        }
1016
1017        inline void test_replace(std::wstring source, std::wstring replace, std::wstring with, std::wstring out) {
1018                std::wcout << _T("strEx::test_replace(") << source << _T(", ") << replace << _T(", ") << with << _T(") : ");
1019                std::wstring s = source;
1020                strEx::replace(s, replace, with);
1021                if (s == out)
1022                        std::wcout << _T("Succeeded") << std::endl;
1023                else
1024                        std::wcout << _T("Failed [") << s << _T("=") << out << _T("]") << std::endl;
1025        }
1026        inline void run_test_replace() {
1027                test_replace(_T(""), _T(""), _T(""), _T(""));
1028                test_replace(_T("foo"), _T(""), _T(""), _T("foo"));
1029                test_replace(_T("foobar"), _T("foo"), _T(""), _T("bar"));
1030                test_replace(_T("foobar"), _T("foo"), _T("bar"), _T("barbar"));
1031        }
1032
1033#endif
1034
1035        template<typename T>
1036        inline void parse_command(T &cmd_line, std::list<T> &args) {
1037                boost::tokenizer<boost::escaped_list_separator<wchar_t>, typename T::const_iterator, T > tok(cmd_line, boost::escaped_list_separator<wchar_t>(L'\\', L' ', L'\"'));
1038                BOOST_FOREACH(T s, tok)
1039                        args.push_back(s);
1040        }
1041        template<typename T>
1042        inline void parse_command(T cmd_line, T &cmd, std::list<T> &args) {
1043                boost::tokenizer<boost::escaped_list_separator<wchar_t>, typename T::const_iterator, T > tok(cmd_line, boost::escaped_list_separator<wchar_t>(L'\\', L' ', L'\"'));
1044                bool first = true;
1045                BOOST_FOREACH(T s, tok)
1046                {
1047                        if (first) {
1048                                cmd = s;
1049                                first = false;
1050                        } else {
1051                                args.push_back(s);
1052                        }
1053
1054                }
1055        }
1056        /*
1057        template<typename T = std::string>
1058        inline void parse_command(T &string, std::list<T> &list) {
1059                boost::tokenizer<boost::escaped_list_separator<char>, T::const_iterator, T > tok(string, boost::escaped_list_separator<char>('\\', ' ', '\"'));
1060                BOOST_FOREACH(T s, tok)
1061                        list.push_back(s);
1062        }
1063        */
1064
1065}
1066
1067namespace nscp {
1068        namespace helpers {
1069                template <typename T> std::string to_string(const T& arg) {
1070                        try {
1071                                return boost::lexical_cast<std::string>(arg) ;
1072                        }
1073                        catch(...) {
1074                                return "";
1075                        }
1076                }
1077                template <typename T> std::string to_string(const std::string& arg) {
1078                        return arg;
1079                }
1080                template <typename T> std::string to_string(const std::wstring& arg) {
1081                        return utf8::cvt<std::string>(arg);
1082                }
1083                template <typename T> std::string to_string(const wchar_t* arg) {
1084                        return utf8::cvt<std::string>(std::wstring(arg));
1085                }
1086                template <typename T> std::wstring to_wstring(const T& arg) {
1087                        try {
1088                                return boost::lexical_cast<std::wstring>(arg) ;
1089                        }
1090                        catch(...) {
1091                                return _T("");
1092                        }
1093                }
1094                template <typename T> std::wstring to_wstring(const std::wstring& arg) {
1095                        return arg;
1096                }
1097                template <typename T> std::wstring to_wstring(const std::string& arg) {
1098                        return utf8::cvt<std::wstring>(arg);
1099                }
1100        }
1101}
1102
Note: See TracBrowser for help on using the repository browser.