source: nscp/include/strEx.h @ fa11893

0.4.00.4.10.4.2
Last change on this file since fa11893 was fa11893, checked in by Michael Medin <michael@…>, 13 months ago
  • Fixed issue with parsing size-type (usch as MinCritFree?=10G)
  • 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                inline std::string itos(float i) {
259                        std::stringstream ss;
260                        ss << i;
261                        return ss.str();
262                }
263                inline std::string itos(double i) {
264                        std::stringstream ss;
265                        ss << i;
266                        return ss.str();
267                }
268                inline std::string itos(int i) {
269                        std::stringstream ss;
270                        ss << i;
271                        return ss.str();
272                }
273                inline std::string itos(unsigned int i) {
274                        std::stringstream ss;
275                        ss << i;
276                        return ss.str();
277                }
278                inline std::string itos_non_sci(double i) {
279                        std::stringstream ss;
280                        if (i < 10)
281                                ss.precision(20);
282                        ss << std::noshowpoint << std::fixed << i;
283                        std::string s = ss.str();
284                        std::string::size_type pos = s.find_last_not_of('0');
285                        if (pos == std::wstring::npos)
286                                return s;
287                        if (s[pos] != '.')
288                                pos++;
289                        return s.substr(0, pos);
290                }
291        }
292
293        inline std::wstring strip_hex(std::wstring str) {
294                std::wstring ret; ret.reserve(str.size());
295                BOOST_FOREACH(wchar_t c, str)
296                {
297                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
298                                ret.push_back(L'?');
299                        else
300                                ret.push_back(c);
301                }
302                return ret;
303        }
304        inline std::string strip_hex(std::string str) {
305                std::string ret; ret.reserve(str.size());
306                BOOST_FOREACH(char c, str)
307                {
308                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
309                                ret.push_back('?');
310                        else
311                                ret.push_back(c);
312                }
313                return ret;
314        }
315
316        inline std::string strip_hex(std::vector<char> str) {
317                std::string ret; ret.reserve(str.size());
318                BOOST_FOREACH(char c, str)
319                {
320                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
321                                ret.push_back('?');
322                        else
323                                ret.push_back(c);
324                }
325                return ret;
326        }
327
328        inline void append_list(std::wstring &lst, std::wstring &append, std::wstring sep = _T(", ")) {
329                if (append.empty())
330                        return;
331                if (!lst.empty())
332                        lst += sep;
333                lst += append;
334        }
335        inline void append_list_ex(std::wstring &lst, std::wstring append, std::wstring sep = _T(", ")) {
336                if (append.empty())
337                        return;
338                if (!lst.empty())
339                        lst += sep;
340                lst += append;
341        }
342        inline std::string wstring_to_string( const std::wstring& str ) {
343                return utf8::cvt<std::string>(str);
344        }
345        inline std::wstring string_to_wstring( const std::string& str ) {
346                return utf8::cvt<std::wstring>(str);
347        }
348
349        inline std::wstring format_buffer(const wchar_t* buf, unsigned int len) {
350                std::wstringstream ss;
351                std::wstring chars;
352                for (unsigned int i=0;i<len;i++) {
353                        ss << std::hex << buf[i];
354                        ss << _T(", ");
355                        if (buf[i] >= ' ' && buf[i] <= 'z')
356                                chars += buf[i];
357                        else
358                                chars += '?';
359                        if (i%32==0) {
360                                ss << chars;
361                                ss << _T("\n");
362                                chars = _T("");
363                        }
364                }
365                ss << chars;
366                return ss.str();
367        }
368        inline std::string format_buffer(const char* buf, std::string::size_type len) {
369                std::stringstream ss;
370                std::string chars;
371                for (std::string::size_type i=0;i<len;i++) {
372                        if (i%32==0) {
373                                if (i > 0) {
374                                        ss << chars;
375                                        ss << "\n";
376                                }
377                                chars = "";
378                                ss << std::hex << std::setw(8) << std::setfill('0') << i;
379                                ss << ": ";
380                        }
381                        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(buf[i]));
382                        ss << ", ";
383                        if (buf[i] < 30 || buf[i] == 127)
384                                chars += '?';
385                        else
386                                chars += buf[i];
387                }
388                ss << chars;
389                return ss.str();
390        }
391        inline std::string format_buffer(const std::string &buf) {
392                return format_buffer(buf.c_str(), buf.size());
393        }
394        inline std::string format_buffer(const std::vector<char> &buf) {
395                std::stringstream ss;
396                std::string chars;
397                for (unsigned int i=0;i<buf.size();i++) {
398                        if (i%32==0) {
399                                if (i > 0) {
400                                        ss << chars;
401                                        ss << "\n";
402                                }
403                                chars = "";
404                                ss << std::hex << std::setw(8) << std::setfill('0') << i;
405                                ss << ": ";
406                        }
407                        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(buf[i]));
408                        ss << ", ";
409                        if (buf[i] < 30 || buf[i] == 127)
410                                chars += '?';
411                        else
412                                chars += buf[i];
413                }
414                ss << chars;
415                return ss.str();
416        }
417        inline std::wstring format_date(boost::posix_time::ptime date, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
418                std::locale locale_local ("");
419
420                boost::gregorian::wdate_facet *date_output = new boost::gregorian::wdate_facet();
421                std::locale locale_adjusted (locale_local, date_output);
422
423                std::wstringstream date_ss;
424                date_ss.imbue(locale_adjusted);
425
426                date_output->format(format.c_str());
427                date_ss << date;
428
429                std::wstring ss = date_ss.str();
430                return ss;
431        }
432#ifdef WIN32
433        inline std::wstring format_date(const SYSTEMTIME &time, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
434                TCHAR buf[51];
435
436                struct tm tmTime;
437                memset(&tmTime, 0, sizeof(tmTime));
438
439                tmTime.tm_sec = time.wSecond; // seconds after the minute - [0,59]
440                tmTime.tm_min = time.wMinute; // minutes after the hour - [0,59]
441                tmTime.tm_hour = time.wHour;  // hours since midnight - [0,23]
442                tmTime.tm_mday = time.wDay;  // day of the month - [1,31]
443                tmTime.tm_mon = time.wMonth-1; // months since January - [0,11]
444                tmTime.tm_year = time.wYear-1900; // years since 1900
445                tmTime.tm_wday = time.wDayOfWeek; // days since Sunday - [0,6]
446
447                size_t l = wcsftime(buf, 50, format.c_str(), &tmTime);
448                if (l <= 0 || l >= 50)
449                        return _T("");
450                buf[l] = 0;
451                return buf;
452        }
453#endif
454
455
456        inline std::wstring format_date(std::time_t time, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
457                return format_date(boost::posix_time::from_time_t(time), format);
458        }
459
460       
461        static const long long SECS_BETWEEN_EPOCHS = 11644473600;
462        static const long long SECS_TO_100NS = 10000000;
463        inline unsigned long long filetime_to_time(unsigned long long filetime) {
464                return (filetime - (SECS_BETWEEN_EPOCHS * SECS_TO_100NS)) / SECS_TO_100NS;
465        }
466        inline std::wstring format_filetime(unsigned long long filetime, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
467                if (filetime == 0)
468                        return _T("ZERO");
469                return format_date(static_cast<time_t>(filetime_to_time(filetime)), format);
470        }
471
472        inline void replace(std::wstring &string, const std::wstring replace, const std::wstring with) {
473                std::wstring::size_type pos = string.find(replace);
474                std::wstring::size_type len = replace.length();
475                while (pos != std::wstring::npos) {
476                        string = string.substr(0,pos)+with+string.substr(pos+len);
477                        if (with.find(replace) != std::wstring::npos) // If the replace containes the key look after the replace!
478                                pos = string.find(replace, pos+with.length());
479                        else
480                                pos = string.find(replace, pos+1);
481                }
482        }
483        inline void replace(std::string &string, const std::string replace, const std::string with) {
484                std::string::size_type pos = string.find(replace);
485                std::string::size_type len = replace.length();
486                while (pos != std::string::npos) {
487                        string = string.substr(0,pos)+with+string.substr(pos+len);
488                        if (with.find(replace) != std::string::npos) // If the replace containes the key look after the replace!
489                                pos = string.find(replace, pos+with.length());
490                        else
491                                pos = string.find(replace, pos+1);
492                }
493        }
494        inline std::wstring ctos(wchar_t c) {
495                return std::wstring(1, c);
496        }
497        inline wchar_t stoc(std::wstring str) {
498                if (str.length() == 0)
499                        return L' ';
500                return str[0];
501        }
502        inline std::wstring itos(unsigned int i) {
503                std::wstringstream ss;
504                ss << i;
505                return ss.str();
506        }
507        inline std::wstring itos(int i) {
508                std::wstringstream ss;
509                ss << i;
510                return ss.str();
511        }
512        inline std::wstring itos(unsigned long long i) {
513                std::wstringstream ss;
514                ss << i;
515                return ss.str();
516        }
517        inline std::wstring itos(long long i) {
518                std::wstringstream ss;
519                ss << i;
520                return ss.str();
521        }
522        /*
523        inline std::wstring itos(__int64 i) {
524                std::wstringstream ss;
525                ss << i;
526                return ss.str();
527        }
528        */
529        inline std::wstring itos(unsigned long i) {
530                std::wstringstream ss;
531                ss << i;
532                return ss.str();
533        }
534        inline std::wstring itos(double i) {
535                std::wstringstream ss;
536                ss << i;
537                return ss.str();
538        }
539        inline std::wstring itos_non_sci(double i) {
540                std::wstringstream ss;
541                if (i < 10)
542                        ss.precision(20);
543                ss << std::noshowpoint << std::fixed << i;
544                std::wstring s = ss.str();
545                std::wstring::size_type pos = s.find_last_not_of('0');
546                if (pos == std::wstring::npos)
547                        return s;
548                if (s[pos] != '.')
549                        pos++;
550                return s.substr(0, pos);
551        }
552        inline std::wstring itos(float i) {
553                std::wstringstream ss;
554                ss << i;
555                return ss.str();
556        }
557        inline std::wstring ihextos(unsigned int i) {
558                std::wstringstream ss;
559                ss << std::hex << i;
560                return ss.str();
561        }
562        inline int stoi(std::wstring s) {
563                return boost::lexical_cast<int>(s.c_str());
564        }
565        inline int stoi(std::string s) {
566                return boost::lexical_cast<int>(s.c_str());
567        }
568        template<class T>
569        inline double stod(T s) {
570                return boost::lexical_cast<double>(s.c_str());
571        }
572        inline long long stoi64(std::wstring s) {
573                return boost::lexical_cast<long long>(s.c_str());
574        }
575        inline unsigned stoui_as_time(std::wstring time, unsigned int smallest_unit = 1000) {
576                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
577                std::wstring::size_type pend = time.find_first_not_of(_T("0123456789"));
578                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::wstring::npos?time:time.substr(0,pend).c_str());
579                if (p == std::wstring::npos)
580                        return value * smallest_unit;
581                else if ( (time[p] == 's') || (time[p] == 'S') )
582                        return value * 1000;
583                else if ( (time[p] == 'm') || (time[p] == 'M') )
584                        return value * 60 * 1000;
585                else if ( (time[p] == 'h') || (time[p] == 'H') )
586                        return value * 60 * 60 * 1000;
587                else if ( (time[p] == 'd') || (time[p] == 'D') )
588                        return value * 24 * 60 * 60 * 1000;
589                else if ( (time[p] == 'w') || (time[p] == 'W') )
590                        return value * 7 * 24 * 60 * 60 * 1000;
591                return value * smallest_unit;
592        }
593        inline unsigned stoui_as_time_sec(std::wstring time, unsigned int smallest_unit = 1) {
594                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
595                std::wstring::size_type pend = time.find_first_not_of(_T("0123456789"));
596                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::wstring::npos?time:time.substr(0,pend).c_str());
597                if (p == std::wstring::npos)
598                        return value * smallest_unit;
599                else if ( (time[p] == L's') || (time[p] == L'S') )
600                        return value;
601                else if ( (time[p] == L'm') || (time[p] == L'M') )
602                        return value * 60;
603                else if ( (time[p] == L'h') || (time[p] == L'H') )
604                        return value * 60 * 60;
605                else if ( (time[p] == L'd') || (time[p] == L'D') )
606                        return value * 24 * 60 * 60;
607                else if ( (time[p] == L'w') || (time[p] == L'W') )
608                        return value * 7 * 24 * 60 * 60;
609                return value * smallest_unit;
610        }
611        inline unsigned stoui_as_time_sec(std::string time, unsigned int smallest_unit = 1) {
612                std::string::size_type p = time.find_first_of("sSmMhHdDwW");
613                std::string::size_type pend = time.find_first_not_of("0123456789");
614                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::string::npos?time:time.substr(0,pend).c_str());
615                if (p == std::string::npos)
616                        return value * smallest_unit;
617                else if ( (time[p] == 's') || (time[p] == 'S') )
618                        return value;
619                else if ( (time[p] == 'm') || (time[p] == 'M') )
620                        return value * 60;
621                else if ( (time[p] == 'h') || (time[p] == 'H') )
622                        return value * 60 * 60;
623                else if ( (time[p] == 'd') || (time[p] == 'D') )
624                        return value * 24 * 60 * 60;
625                else if ( (time[p] == 'w') || (time[p] == 'W') )
626                        return value * 7 * 24 * 60 * 60;
627                return value * smallest_unit;
628        }
629        inline long stol_as_time_sec(std::wstring time, unsigned int smallest_unit = 1) {
630                long neg = 1;
631                if (time.length() > 1 && time[0] == L'-')
632                        return -(long)stoui_as_time_sec(time.substr(1), smallest_unit);
633                return stoui_as_time_sec(time, smallest_unit);
634        }
635        inline long stol_as_time_sec(std::string time, unsigned int smallest_unit = 1) {
636                long neg = 1;
637                if (time.length() > 1 && time[0] == '-')
638                        return -(long)stoui_as_time_sec(time.substr(1), smallest_unit);
639                return stoui_as_time_sec(time, smallest_unit);
640        }
641
642        inline unsigned long long stoi64_as_time(std::wstring time, unsigned int smallest_unit = 1000) {
643                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
644                if (p == std::wstring::npos)
645                        return boost::lexical_cast<long long>(time) * smallest_unit;
646                unsigned long long value = boost::lexical_cast<long long>(time.substr(0, p));
647                if ( (time[p] == 's') || (time[p] == 'S') )
648                        return value * 1000;
649                else if ( (time[p] == 'm') || (time[p] == 'M') )
650                        return value * 60 * 1000;
651                else if ( (time[p] == 'h') || (time[p] == 'H') )
652                        return value * 60 * 60 * 1000;
653                else if ( (time[p] == 'd') || (time[p] == 'D') )
654                        return value * 24 * 60 * 60 * 1000;
655                else if ( (time[p] == 'w') || (time[p] == 'W') )
656                        return value * 7 * 24 * 60 * 60 * 1000;
657                return value * smallest_unit;
658        }
659
660
661#define WEEK    (7 * 24 * 60 * 60 * 1000)
662#define DAY             (24 * 60 * 60 * 1000)
663#define HOUR    (60 * 60 * 1000)
664#define MIN             (60 * 1000)
665#define SEC             (1000)
666        inline std::wstring itos_as_time(unsigned long long time) {
667                if (time > WEEK) {
668                        unsigned int w = static_cast<unsigned int>(time/WEEK);
669                        unsigned int d = static_cast<unsigned int>((time-(w*WEEK))/DAY);
670                        unsigned int h = static_cast<unsigned int>((time-(w*WEEK)-(d*DAY))/HOUR);
671                        unsigned int m = static_cast<unsigned int>((time-(w*WEEK)-(d*DAY)-(h*HOUR))/MIN);
672                        return itos(w) + _T("w ") + itos(d) + _T("d ") + itos(h) + _T(":") + itos(m);
673                }
674                else if (time > DAY) {
675                        unsigned int d = static_cast<unsigned int>((time)/DAY);
676                        unsigned int h = static_cast<unsigned int>((time-(d*DAY))/HOUR);
677                        unsigned int m = static_cast<unsigned int>((time-(d*DAY)-(h*HOUR))/MIN);
678                        return itos(d) + _T("d ") + itos(h) + _T(":") + itos(m);
679                }
680                else if (time > HOUR) {
681                        unsigned int h = static_cast<unsigned int>((time)/HOUR);
682                        unsigned int m = static_cast<unsigned int>((time-(h*HOUR))/MIN);
683                        return itos(h) + _T(":") + itos(m);
684                } else if (time > MIN) {
685                        return _T("0:") + itos(static_cast<unsigned int>(time/(60 * 1000)));
686                } else if (time > SEC)
687                        return itos(static_cast<unsigned int>(time/(1000))) + _T("s");
688                return itos(static_cast<unsigned int>(time));
689        }
690
691        inline long long stoi64_as_BKMG(const std::wstring &s) {
692                std::wstring::size_type p = s.find_first_not_of(_T("0123456789"));
693                if (p == std::wstring::npos || p == 0)
694                        return boost::lexical_cast<long long>(s);
695                std::wstring numbers = s.substr(0, p);
696                if (s[p] == 'B')
697                        return boost::lexical_cast<long long>(numbers);
698                else if (s[p] == 'K')
699                        return boost::lexical_cast<long long>(numbers)*1024;
700                else if (s[p] == 'M')
701                        return boost::lexical_cast<long long>(numbers)*1024*1024;
702                else if (s[p] == 'G')
703                        return boost::lexical_cast<long long>(numbers)*1024*1024*1024;
704                else if (s[p] == 'T')
705                        return boost::lexical_cast<long long>(numbers)*1024*1024*1024*1024;
706                else
707                        return boost::lexical_cast<long long>(numbers);
708        }
709#define BKMG_RANGE _T("BKMGTP")
710#define BKMG_SIZE 5
711
712        inline std::wstring itos_as_BKMG(unsigned long long i) {
713                double cpy = static_cast<double>(i);
714                wchar_t postfix[] = BKMG_RANGE;
715                int idx = 0;
716                while ((cpy > 999)&&(idx<BKMG_SIZE)) {
717                        cpy/=1024;
718                        idx++;
719                }
720                std::wstringstream ss;
721                ss << std::setprecision(3);
722                ss << cpy;
723                std::wstring ret = ss.str(); // itos(cpy);
724                ret += postfix[idx];
725                return ret;
726        }
727        inline std::wstring format_BKMG(unsigned long long i, std::wstring unit) {
728                double cpy = static_cast<double>(i);
729                wchar_t postfix[] = BKMG_RANGE;
730                if (unit.length() != 1)
731                        return itos(cpy);
732                for (int i=0;i<BKMG_SIZE;i++) {
733                        if (unit[0] == postfix[i]) {
734                                std::wstringstream ss;
735                                ss << std::setiosflags(std::ios::fixed) << std::setprecision(3) << cpy;
736                                std::wstring s = ss.str();
737                                std::wstring::size_type pos = s.find_last_not_of(_T("0"));
738                                if (pos != std::string::npos) {
739                                        s = s.substr(0,pos);
740                                }
741                                return s;
742                        }
743                        cpy/=1024;
744                }
745                return itos(cpy);
746        }
747        inline std::wstring find_proper_unit_BKMG(unsigned long long i) {
748                double cpy = static_cast<double>(i);
749                wchar_t postfix[] = BKMG_RANGE;
750                int idx = 0;
751                while ((cpy > 999)&&(idx<BKMG_SIZE)) {
752                        cpy/=1024;
753                        idx++;
754                }
755                return std::wstring(1, postfix[idx]);
756        }
757
758        typedef std::list<std::wstring> splitList;
759        inline splitList splitEx(const std::wstring str, const std::wstring key) {
760                splitList ret;
761                std::wstring::size_type pos = 0, lpos = 0;
762                while ((pos = str.find(key, pos)) !=  std::wstring::npos) {
763                        ret.push_back(str.substr(lpos, pos-lpos));
764                        lpos = ++pos;
765                }
766                if (lpos < str.size())
767                        ret.push_back(str.substr(lpos));
768                return ret;
769        }
770        typedef std::vector<std::wstring> splitVector;
771        template<class T>
772        inline std::vector<T> splitV(const T str, const T key) {
773                std::vector<T> ret;
774                typename T::size_type pos = 0, lpos = 0;
775                while ((pos = str.find(key, pos)) !=  T::npos) {
776                        ret.push_back(str.substr(lpos, pos-lpos));
777                        lpos = ++pos;
778                }
779                if (lpos < str.size())
780                        ret.push_back(str.substr(lpos));
781                return ret;
782        }
783        inline std::wstring joinEx(splitList lst, std::wstring key) {
784                std::wstring ret;
785                for (splitList::const_iterator it = lst.begin(); it != lst.end(); ++it) {
786                        if (!ret.empty())
787                                ret += key;
788                        ret += *it;
789                }
790                return ret;
791        }
792
793
794
795        inline std::wstring trim_right(const std::wstring &source , const std::wstring& t = _T(" "))
796        {
797                std::wstring str = source;
798                return str.erase( str.find_last_not_of(t) + 1);
799        }
800
801        inline std::wstring trim_left( const std::wstring& source, const std::wstring& t = _T(" "))
802        {
803                std::wstring str = source;
804                return str.erase(0 , source.find_first_not_of(t) );
805        }
806
807        inline std::wstring trim(const std::wstring& source, const std::wstring& t = _T(" "))
808        {
809                std::wstring str = source;
810                return trim_left( trim_right( str , t) , t );
811        }
812        template<class T>
813        inline std::pair<T,T> split(T str, T key) {
814                typename T::size_type pos = str.find(key);
815                if (pos == T::npos)
816                        return std::pair<T,T>(str, T());
817                return std::pair<T,T>(str.substr(0, pos), str.substr(pos+key.length()));
818        }
819        typedef std::pair<std::wstring,std::wstring> token;
820        // foo bar "foo \" bar" foo -> foo, bar "foo \" bar" foo -> bar, "foo \" bar" foo ->
821        //
822        inline token getToken(std::wstring buffer, char split, bool escape = false) {
823                std::wstring::size_type pos = std::wstring::npos;
824                if ((escape) && (buffer[0] == '\"')) {
825                        do {
826                                pos = buffer.find('\"');
827                        }
828                        while (((pos != std::wstring::npos)&&(pos > 1))&&(buffer[pos-1] == '\\'));
829                } else
830                        pos = buffer.find(split);
831                if (pos == std::wstring::npos)
832                        return token(buffer, _T(""));
833                if (pos == buffer.length()-1)
834                        return token(buffer.substr(0, pos), _T(""));
835                return token(buffer.substr(0, pos-1), buffer.substr(++pos));
836        }
837
838
839
840        template<class char_type>
841        struct ci_char_traits : public std::char_traits<char_type> {
842                static bool eq( char_type c1, char_type c2 ) {
843                        return toupper(c1) == toupper(c2);
844                }
845
846                static bool ne( char_type c1, char_type c2 ) {
847                        return toupper(c1) != toupper(c2);
848                }
849
850                static bool lt( char_type c1, char_type c2 ) {
851                        return toupper(c1) <  toupper(c2);
852                }
853
854                static int compare( const char_type* s1, const char_type* s2, size_t n ) {
855#ifdef WIN32
856                        return memicmp( s1, s2, n );
857#else
858                        while (n-- && eq(*s1, *s2))
859                                ++s1, ++s2;
860                        return lt(*s2, *s1) - lt(*s1, *s2);
861#endif
862                }
863
864                static const char* find( const char_type* s, int n, char_type a ) {
865                        while( n-- > 0 && toupper(*s) != toupper(a) ) {
866                                ++s;
867                        }
868                        return s;
869                }
870        };
871        typedef std::basic_string<wchar_t, ci_char_traits<wchar_t> > wci_string;
872
873        template<class _E>
874        struct blind_traits : public std::char_traits<_E>
875        {
876               
877                static bool eq(const _E& x, const _E& y) {
878                        return boost::algorithm::iequals(x,y);
879                }
880                static bool lt(const _E& x, const _E& y) {
881                        return ilexicographical_compare(x, y);
882                }
883/*
884                static int compare(const _E *x, const _E *y, size_t n) {
885                        return ilexicographical_compare(x, y);
886                        return _wcsnicmp( x, y, n );
887                }
888
889                //  There's no memichr(), so we roll our own.  It ain't rocket science.
890                static const _E * / *__cdecl* / find(const _E *buf, size_t len, const _E& ch) {
891                        //  Jerry says that x86s have special mojo for memchr(), so the
892                        //  memchr() calls end up being reasonably efficient in practice.
893                        const _E *pu = (const _E *)memchr(buf, ch, len);
894                        const _E *pl = (const _E *)memchr(buf, tolower( ch ), len);
895                        if ( ! pu )
896                                return pl;  //  Might be NULL; if so, NULL's the word.
897                        else if ( ! pl )
898                                return pu;
899                        else
900                                //  If either one was NULL, we return the other; if neither is
901                                //  NULL, we return the lesser of the two.
902                                return ( pu < pl ) ? pu : pl;
903                }
904
905                //  I'm reasonably sure that this is eq() for wide characters.  Maybe.
906                static bool eq_int_type(const long& ch1, const long& ch2) {
907                        return std::char_traits<_E>::eq_int_type( tolower( ch1 ), tolower( ch2 ) );
908                }
909                */
910        };
911
912        //  And here's our case-blind string class.
913        //typedef std::basic_string<char, blind_traits<char>, std::allocator<char> >  blindstr;
914        typedef std::basic_string<wchar_t, blind_traits<wchar_t>, std::allocator<wchar_t> >  blindstr;
915
916
917
918
919        class StrICmp
920        {
921        public:
922                StrICmp(const std::string &Lang = "english") : m_locE(Lang.c_str())
923                {
924                }
925                class CharLessI
926                {
927                public:
928                        CharLessI(std::locale &locE) : m_locE(locE)
929                        {
930                        }
931                        template<typename T>
932                        bool operator()(T c1, T c2)
933                        {
934                                return std::tolower(c1, m_locE) < std::tolower(c2, m_locE);
935                        }
936                private:
937                        std::locale &m_locE;
938                };
939                template<typename T>
940                int operator()(const T &s1, const T &s2) const
941                {
942                        if (std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), CharLessI(m_locE)))
943                                return -1;
944                        if (std::lexicographical_compare(s2.begin(), s2.end(), s1.begin(), s1.end(), CharLessI(m_locE)))
945                                return 1;
946                        return 0;
947                }
948        private:
949                std::locale m_locE;
950        };
951
952        template<typename T>
953        int StrCmpI(const T &s1, const T &s2, const std::string &Lang = "english")
954        {
955                return StrICmp(Lang)(s1, s2);
956        }
957
958#define MK_FORMAT_FTD(min, key, val) \
959        if (mtm->tm_year > min) \
960        strEx::replace(format, key, strEx::itos(val));  \
961        else  \
962        strEx::replace(format, key, _T("0"));
963#ifdef WIN32
964        inline std::wstring format_time_delta(struct tm *mtm, std::wstring format = _T("%Y years %m months %d days %H hours %M minutes")) {
965                // "Date: %Y-%m-%d %H:%M:%S"
966                MK_FORMAT_FTD(70, _T("%Y"), mtm->tm_year);
967                MK_FORMAT_FTD(0, _T("%m"), mtm->tm_mon);
968                MK_FORMAT_FTD(0, _T("%d"), mtm->tm_mday-1);
969                MK_FORMAT_FTD(0, _T("%H"), mtm->tm_hour);
970                MK_FORMAT_FTD(0, _T("%M"), mtm->tm_min);
971                MK_FORMAT_FTD(0, _T("%S"), mtm->tm_sec);
972                return format;
973        }
974        inline std::wstring format_time_delta(time_t time, std::wstring format = _T("%Y years %m months %d days %H hours %M minutes")) {
975                struct tm nt; // = new struct tm;
976#if (_MSC_VER > 1300)  // 1300 == VC++ 7.0
977                if (gmtime_s(&nt, &time) != 0)
978                        return _T("");
979#else
980                nt = gmtime(&time);
981                if (nt == NULL)
982                        return "";
983#endif
984                return format_time_delta(&nt, format);
985        }
986        inline std::wstring format_filetime_delta(unsigned long long filetime, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
987                if (filetime == 0)
988                        return _T("ZERO");
989                //filetime -= (SECS_BETWEEN_EPOCHS * SECS_TO_100NS);
990                filetime /= SECS_TO_100NS;
991                return format_time_delta(static_cast<time_t>(filetime), format);
992        }
993#endif
994
995#ifdef _DEBUG
996        inline void test_getToken(std::wstring in1, char in2, std::wstring out1, std::wstring out2) {
997                token t = getToken(in1, in2);
998                std::wcout << _T("strEx::test_getToken(") << in1 << _T(", ") << in2 << _T(") : ");
999                if ((t.first == out1) && (t.second == out2))
1000                        std::wcout << _T("Succeeded") << std::endl;
1001                else
1002                        std::wcout << _T("Failed [") << out1 << _T("=") << t.first << _T(", ") << out2 << _T("=") << t.second << _T("]") << std::endl;
1003        }
1004        inline void run_test_getToken() {
1005                test_getToken(_T(""), '&', _T(""), _T(""));
1006                test_getToken(_T("&"), '&', _T(""), _T(""));
1007                test_getToken(_T("&&"), '&', _T(""), _T("&"));
1008                test_getToken(_T("foo"), '&', _T("foo"), _T(""));
1009                test_getToken(_T("foo&"), '&', _T("foo"), _T(""));
1010                test_getToken(_T("foo&bar"), '&', _T("foo"), _T("bar"));
1011                test_getToken(_T("foo&bar&test"), '&', _T("foo"), _T("bar&test"));
1012        }
1013
1014        inline void test_replace(std::wstring source, std::wstring replace, std::wstring with, std::wstring out) {
1015                std::wcout << _T("strEx::test_replace(") << source << _T(", ") << replace << _T(", ") << with << _T(") : ");
1016                std::wstring s = source;
1017                strEx::replace(s, replace, with);
1018                if (s == out)
1019                        std::wcout << _T("Succeeded") << std::endl;
1020                else
1021                        std::wcout << _T("Failed [") << s << _T("=") << out << _T("]") << std::endl;
1022        }
1023        inline void run_test_replace() {
1024                test_replace(_T(""), _T(""), _T(""), _T(""));
1025                test_replace(_T("foo"), _T(""), _T(""), _T("foo"));
1026                test_replace(_T("foobar"), _T("foo"), _T(""), _T("bar"));
1027                test_replace(_T("foobar"), _T("foo"), _T("bar"), _T("barbar"));
1028        }
1029
1030#endif
1031
1032        template<typename T>
1033        inline void parse_command(T &cmd_line, std::list<T> &args) {
1034                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'\"'));
1035                BOOST_FOREACH(T s, tok)
1036                        args.push_back(s);
1037        }
1038        template<typename T>
1039        inline void parse_command(T cmd_line, T &cmd, std::list<T> &args) {
1040                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'\"'));
1041                bool first = true;
1042                BOOST_FOREACH(T s, tok)
1043                {
1044                        if (first) {
1045                                cmd = s;
1046                                first = false;
1047                        } else {
1048                                args.push_back(s);
1049                        }
1050
1051                }
1052        }
1053        /*
1054        template<typename T = std::string>
1055        inline void parse_command(T &string, std::list<T> &list) {
1056                boost::tokenizer<boost::escaped_list_separator<char>, T::const_iterator, T > tok(string, boost::escaped_list_separator<char>('\\', ' ', '\"'));
1057                BOOST_FOREACH(T s, tok)
1058                        list.push_back(s);
1059        }
1060        */
1061
1062}
1063
1064namespace nscp {
1065        namespace helpers {
1066                template <typename T> std::string to_string(const T& arg) {
1067                        try {
1068                                return boost::lexical_cast<std::string>(arg) ;
1069                        }
1070                        catch(...) {
1071                                return "";
1072                        }
1073                }
1074                template <typename T> std::string to_string(const std::string& arg) {
1075                        return arg;
1076                }
1077                template <typename T> std::string to_string(const std::wstring& arg) {
1078                        return utf8::cvt<std::string>(arg);
1079                }
1080                template <typename T> std::string to_string(const wchar_t* arg) {
1081                        return utf8::cvt<std::string>(std::wstring(arg));
1082                }
1083                template <typename T> std::wstring to_wstring(const T& arg) {
1084                        try {
1085                                return boost::lexical_cast<std::wstring>(arg) ;
1086                        }
1087                        catch(...) {
1088                                return _T("");
1089                        }
1090                }
1091                template <typename T> std::wstring to_wstring(const std::wstring& arg) {
1092                        return arg;
1093                }
1094                template <typename T> std::wstring to_wstring(const std::string& arg) {
1095                        return utf8::cvt<std::wstring>(arg);
1096                }
1097        }
1098}
1099
Note: See TracBrowser for help on using the repository browser.