source: nscp/include/strEx.h @ c391984

0.4.00.4.10.4.2
Last change on this file since c391984 was c391984, checked in by Michael Medin <michael@…>, 2 years ago

0.4.x:

  • tweaks to the build environment to make the installer work
  • fixed Unicode issue
  • fixed performance data
  • improved so alias doesn't re-process the data so much
  • Property mode set to 100644
File size: 27.8 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 <types.hpp>
23
24#include <string>
25#include <sstream>
26#include <iomanip>
27#include <utility>
28#include <list>
29#include <functional>
30#include <time.h>
31#include <algorithm>
32#include <locale>
33#include <iostream>
34
35#include <cctype>
36
37#include <unicode_char.hpp>
38
39#include <boost/lexical_cast.hpp>
40#include <boost/date_time.hpp>
41#include <boost/algorithm/string.hpp>
42#include <boost/foreach.hpp>
43//#include <boost/date_time/local_time/local_date_time.hpp>
44//#include <boost/date_time/gregorian/conversion.hpp>
45//boost::local_time::local_date_time
46
47
48#ifdef _DEBUG
49#include <iostream>
50#endif
51
52
53
54
55#include <string>
56#include <locale>
57
58namespace boost
59{
60        template<>
61        inline std::wstring lexical_cast<std::wstring, std::string>(const std::string& arg)
62        {
63                std::wstring result;
64                std::locale loc;
65                for(unsigned int i= 0; i < arg.size(); ++i)
66                {
67                        result += std::use_facet<std::ctype<wchar_t> >(loc).widen(arg[i]);
68                }
69                return result;
70        }
71
72        template<>
73        inline std::string lexical_cast<std::string, std::wstring>(const std::wstring& arg)
74        {
75                std::string result;
76                std::locale loc;
77                for(unsigned int i= 0; i < arg.size(); ++i)
78                        result += std::use_facet<std::ctype<wchar_t> >(loc).narrow(arg[i], 0);
79                return result;
80        }
81}
82
83namespace net {
84
85        struct url {
86                std::wstring protocol;
87                std::wstring host;
88                std::wstring path;
89                std::wstring query;
90
91        };
92        inline url parse(const std::wstring& url_s) {
93                url ret;
94                const std::wstring prot_end(_T("://"));
95                std::wstring::const_iterator prot_i = std::search(url_s.begin(), url_s.end(), prot_end.begin(), prot_end.end());
96                ret.protocol.reserve(std::distance(url_s.begin(), prot_i));
97                std::transform(url_s.begin(), prot_i, std::back_inserter(ret.protocol), std::ptr_fun<int,int>(std::tolower)); // protocol is icase
98                if( prot_i == url_s.end() )
99                        return ret;
100                std::advance(prot_i, prot_end.length());
101                std::wstring::const_iterator path_i = std::find(prot_i, url_s.end(), L'/');
102                ret.host.reserve(std::distance(prot_i, path_i));
103                std::transform(prot_i, path_i, std::back_inserter(ret.host), std::ptr_fun<int,int>(std::tolower)); // host is icase
104                std::wstring::const_iterator query_i = std::find(path_i, url_s.end(), L'?');
105                ret.path.assign(path_i, query_i);
106                if( query_i != url_s.end() )
107                        ++query_i;
108                ret.query.assign(query_i, url_s.end());
109                return ret;
110        }
111
112
113}
114namespace strEx {
115        class string_exception : public std::exception {
116                std::wstring _what;
117        public:
118                string_exception(std::wstring what) : _what(what) {}
119                std::wstring what() {
120                        return _what;
121                }
122                virtual ~string_exception() throw();
123        };
124        namespace s {
125                inline std::string itos(float i) {
126                        std::stringstream ss;
127                        ss << i;
128                        return ss.str();
129                }
130                inline std::string itos(int i) {
131                        std::stringstream ss;
132                        ss << i;
133                        return ss.str();
134                }
135                inline std::string itos(unsigned int i) {
136                        std::stringstream ss;
137                        ss << i;
138                        return ss.str();
139                }
140        }
141
142        inline std::wstring strip_hex(std::wstring str) {
143                std::wstring ret; ret.reserve(str.size());
144                BOOST_FOREACH(wchar_t c, str)
145                {
146                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
147                                ret.push_back(L'?');
148                        else
149                                ret.push_back(c);
150                }
151                return ret;
152        }
153        inline std::string strip_hex(std::string str) {
154                std::string ret; ret.reserve(str.size());
155                BOOST_FOREACH(char c, str)
156                {
157                        if (c==0||c==7||c==10||c==11||c==12||c==13||c==127)
158                                ret.push_back('?');
159                        else
160                                ret.push_back(c);
161                }
162                return ret;
163        }
164
165        inline void append_list(std::wstring &lst, std::wstring &append, std::wstring sep = _T(", ")) {
166                if (append.empty())
167                        return;
168                if (!lst.empty())
169                        lst += sep;
170                lst += append;
171        }
172        inline void append_list_ex(std::wstring &lst, std::wstring append, std::wstring sep = _T(", ")) {
173                if (append.empty())
174                        return;
175                if (!lst.empty())
176                        lst += sep;
177                lst += append;
178        }
179        inline std::string wstring_to_string( const std::wstring& str ) {
180                return boost::lexical_cast<std::string>(str) ;
181        }
182        inline std::wstring string_to_wstring( const std::string& str ) {
183                return boost::lexical_cast<std::wstring>(str) ;
184        }
185
186        inline std::wstring format_buffer(const wchar_t* buf, unsigned int len) {
187                std::wstringstream ss;
188                std::wstring chars;
189                for (unsigned int i=0;i<len;i++) {
190                        ss << std::hex << buf[i];
191                        ss << _T(", ");
192                        if (buf[i] >= ' ' && buf[i] <= 'z')
193                                chars += buf[i];
194                        else
195                                chars += '?';
196                        if (i%32==0) {
197                                ss << chars;
198                                ss << _T("\n");
199                                chars = _T("");
200                        }
201                }
202                return ss.str();
203        }
204        inline std::string format_buffer(const char* buf, unsigned int len) {
205                std::stringstream ss;
206                std::string chars;
207                for (unsigned int i=0;i<len;i++) {
208                        if (i%32==0) {
209                                if (i > 0) {
210                                        ss << chars;
211                                        ss << "\n";
212                                }
213                                chars = "";
214                                ss << std::hex << std::setw(8) << std::setfill('0') << i;
215                                ss << ": ";
216                        }
217                        ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(buf[i]));
218                        ss << ", ";
219                        if (buf[i] < 30 || buf[i] == 127)
220                                chars += '?';
221                        else
222                                chars += buf[i];
223                }
224                return ss.str();
225        }
226        inline std::wstring format_date(boost::posix_time::ptime date, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
227                std::locale locale_local ("");
228
229                boost::gregorian::wdate_facet *date_output = new boost::gregorian::wdate_facet();
230                std::locale locale_adjusted (locale_local, date_output);
231
232                std::wstringstream date_ss;
233                date_ss.imbue(locale_adjusted);
234
235                date_output->format(format.c_str());
236                date_ss << date;
237
238                std::wstring ss = date_ss.str();
239                return ss;
240        }
241#ifdef WIN32
242        inline std::wstring format_date(const SYSTEMTIME &time, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
243                TCHAR buf[51];
244
245                struct tm tmTime;
246                memset(&tmTime, 0, sizeof(tmTime));
247
248                tmTime.tm_sec = time.wSecond; // seconds after the minute - [0,59]
249                tmTime.tm_min = time.wMinute; // minutes after the hour - [0,59]
250                tmTime.tm_hour = time.wHour;  // hours since midnight - [0,23]
251                tmTime.tm_mday = time.wDay;  // day of the month - [1,31]
252                tmTime.tm_mon = time.wMonth-1; // months since January - [0,11]
253                tmTime.tm_year = time.wYear-1900; // years since 1900
254                tmTime.tm_wday = time.wDayOfWeek; // days since Sunday - [0,6]
255
256                size_t l = wcsftime(buf, 50, format.c_str(), &tmTime);
257                if (l <= 0 || l >= 50)
258                        return _T("");
259                buf[l] = 0;
260                return buf;
261        }
262#endif
263
264
265        inline std::wstring format_date(std::time_t time, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
266                return format_date(boost::posix_time::from_time_t(time), format);
267        }
268
269       
270        static const __int64 SECS_BETWEEN_EPOCHS = 11644473600;
271        static const __int64 SECS_TO_100NS = 10000000;
272        inline unsigned long long filetime_to_time(unsigned long long filetime) {
273                return (filetime - (SECS_BETWEEN_EPOCHS * SECS_TO_100NS)) / SECS_TO_100NS;
274        }
275        inline std::wstring format_filetime(unsigned long long filetime, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
276                if (filetime == 0)
277                        return _T("ZERO");
278                return format_date(static_cast<time_t>(filetime_to_time(filetime)), format);
279        }
280
281        inline void replace(std::wstring &string, std::wstring replace, std::wstring with) {
282                std::wstring::size_type pos = string.find(replace);
283                std::wstring::size_type len = replace.length();
284                while (pos != std::wstring::npos) {
285                        string = string.substr(0,pos)+with+string.substr(pos+len);
286                        if (with.find(replace) != std::wstring::npos) // If the replace containes the key look after the replace!
287                                pos = string.find(replace, pos+with.length());
288                        else
289                                pos = string.find(replace, pos+1);
290                }
291        }
292        inline std::wstring ctos(wchar_t c) {
293                return std::wstring(1, c);
294        }
295        inline wchar_t stoc(std::wstring str) {
296                if (str.length() == 0)
297                        return L' ';
298                return str[0];
299        }
300        inline std::wstring itos(unsigned int i) {
301                std::wstringstream ss;
302                ss << i;
303                return ss.str();
304        }
305        inline std::wstring itos(int i) {
306                std::wstringstream ss;
307                ss << i;
308                return ss.str();
309        }
310        inline std::wstring itos(unsigned long long i) {
311                std::wstringstream ss;
312                ss << i;
313                return ss.str();
314        }
315        inline std::wstring itos(long long i) {
316                std::wstringstream ss;
317                ss << i;
318                return ss.str();
319        }
320        /*
321        inline std::wstring itos(__int64 i) {
322                std::wstringstream ss;
323                ss << i;
324                return ss.str();
325        }
326        */
327        inline std::wstring itos(unsigned long i) {
328                std::wstringstream ss;
329                ss << i;
330                return ss.str();
331        }
332        inline std::wstring itos(double i) {
333                std::wstringstream ss;
334                ss << i;
335                return ss.str();
336        }
337        inline std::wstring itos_non_sci(double i) {
338                std::wstringstream ss;
339                if (i < 10)
340                        ss.precision(20);
341                ss << std::noshowpoint << std::fixed << i;
342                std::wstring s = ss.str();
343                std::wstring::size_type pos = s.find_last_not_of('0');
344                if (pos == std::wstring::npos)
345                        return s;
346                if (s[pos] != '.')
347                        pos++;
348                return s.substr(0, pos);
349        }
350        inline std::wstring itos(float i) {
351                std::wstringstream ss;
352                ss << i;
353                return ss.str();
354        }
355        inline std::wstring ihextos(unsigned int i) {
356                std::wstringstream ss;
357                ss << std::hex << i;
358                return ss.str();
359        }
360        inline int stoi(std::wstring s) {
361                return boost::lexical_cast<int>(s.c_str());
362        }
363        inline double stod(std::wstring s) {
364                return boost::lexical_cast<double>(s.c_str());
365        }
366        inline long long stoi64(std::wstring s) {
367                return boost::lexical_cast<long long>(s.c_str());
368        }
369        inline unsigned stoui_as_time(std::wstring time, unsigned int smallest_unit = 1000) {
370                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
371                std::wstring::size_type pend = time.find_first_not_of(_T("0123456789"));
372                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::wstring::npos?time:time.substr(0,pend).c_str());
373                if (p == std::wstring::npos)
374                        return value * smallest_unit;
375                else if ( (time[p] == 's') || (time[p] == 'S') )
376                        return value * 1000;
377                else if ( (time[p] == 'm') || (time[p] == 'M') )
378                        return value * 60 * 1000;
379                else if ( (time[p] == 'h') || (time[p] == 'H') )
380                        return value * 60 * 60 * 1000;
381                else if ( (time[p] == 'd') || (time[p] == 'D') )
382                        return value * 24 * 60 * 60 * 1000;
383                else if ( (time[p] == 'w') || (time[p] == 'W') )
384                        return value * 7 * 24 * 60 * 60 * 1000;
385                return value * smallest_unit;
386        }
387        inline unsigned stoui_as_time_sec(std::wstring time, unsigned int smallest_unit = 1) {
388                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
389                std::wstring::size_type pend = time.find_first_not_of(_T("0123456789"));
390                unsigned int value = boost::lexical_cast<unsigned int>(pend==std::wstring::npos?time:time.substr(0,pend).c_str());
391                if (p == std::wstring::npos)
392                        return value * smallest_unit;
393                else if ( (time[p] == 's') || (time[p] == 'S') )
394                        return value;
395                else if ( (time[p] == 'm') || (time[p] == 'M') )
396                        return value * 60;
397                else if ( (time[p] == 'h') || (time[p] == 'H') )
398                        return value * 60 * 60;
399                else if ( (time[p] == 'd') || (time[p] == 'D') )
400                        return value * 24 * 60 * 60;
401                else if ( (time[p] == 'w') || (time[p] == 'W') )
402                        return value * 7 * 24 * 60 * 60;
403                return value * smallest_unit;
404        }
405        inline long stol_as_time_sec(std::wstring time, unsigned int smallest_unit = 1) {
406                long neg = 1;
407                if (time.length() > 1 && time[0] == L'-')
408                        return -(long)stoui_as_time_sec(time.substr(1), smallest_unit);
409                return stoui_as_time_sec(time, smallest_unit);
410        }
411
412        inline unsigned long long stoi64_as_time(std::wstring time, unsigned int smallest_unit = 1000) {
413                std::wstring::size_type p = time.find_first_of(_T("sSmMhHdDwW"));
414                if (p == std::wstring::npos)
415                        return boost::lexical_cast<long long>(time) * smallest_unit;
416                unsigned long long value = boost::lexical_cast<long long>(time.substr(0, p));
417                if ( (time[p] == 's') || (time[p] == 'S') )
418                        return value * 1000;
419                else if ( (time[p] == 'm') || (time[p] == 'M') )
420                        return value * 60 * 1000;
421                else if ( (time[p] == 'h') || (time[p] == 'H') )
422                        return value * 60 * 60 * 1000;
423                else if ( (time[p] == 'd') || (time[p] == 'D') )
424                        return value * 24 * 60 * 60 * 1000;
425                else if ( (time[p] == 'w') || (time[p] == 'W') )
426                        return value * 7 * 24 * 60 * 60 * 1000;
427                return value * smallest_unit;
428        }
429
430
431#define WEEK    (7 * 24 * 60 * 60 * 1000)
432#define DAY             (24 * 60 * 60 * 1000)
433#define HOUR    (60 * 60 * 1000)
434#define MIN             (60 * 1000)
435#define SEC             (1000)
436        inline std::wstring itos_as_time(unsigned long long time) {
437                if (time > WEEK) {
438                        unsigned int w = static_cast<unsigned int>(time/WEEK);
439                        unsigned int d = static_cast<unsigned int>((time-(w*WEEK))/DAY);
440                        unsigned int h = static_cast<unsigned int>((time-(w*WEEK)-(d*DAY))/HOUR);
441                        unsigned int m = static_cast<unsigned int>((time-(w*WEEK)-(d*DAY)-(h*HOUR))/MIN);
442                        return itos(w) + _T("w ") + itos(d) + _T("d ") + itos(h) + _T(":") + itos(m);
443                }
444                else if (time > DAY) {
445                        unsigned int d = static_cast<unsigned int>((time)/DAY);
446                        unsigned int h = static_cast<unsigned int>((time-(d*DAY))/HOUR);
447                        unsigned int m = static_cast<unsigned int>((time-(d*DAY)-(h*HOUR))/MIN);
448                        return itos(d) + _T("d ") + itos(h) + _T(":") + itos(m);
449                }
450                else if (time > HOUR) {
451                        unsigned int h = static_cast<unsigned int>((time)/HOUR);
452                        unsigned int m = static_cast<unsigned int>((time-(h*HOUR))/MIN);
453                        return itos(h) + _T(":") + itos(m);
454                } else if (time > MIN) {
455                        return _T("0:") + itos(static_cast<unsigned int>(time/(60 * 1000)));
456                } else if (time > SEC)
457                        return itos(static_cast<unsigned int>(time/(1000))) + _T("s");
458                return itos(static_cast<unsigned int>(time));
459        }
460
461        inline long long stoi64_as_BKMG(std::wstring s) {
462                std::wstring::size_type p = s.find_first_of(_T("BMKGT"));
463                if (p == std::wstring::npos)
464                        return boost::lexical_cast<long long>(s.c_str());
465                else if (s[p] == 'B')
466                        return boost::lexical_cast<long long>(s.c_str());
467                else if (s[p] == 'K')
468                        return boost::lexical_cast<long long>(s.c_str())*1024;
469                else if (s[p] == 'M')
470                        return boost::lexical_cast<long long>(s.c_str())*1024*1024;
471                else if (s[p] == 'G')
472                        return boost::lexical_cast<long long>(s.c_str())*1024*1024*1024;
473                else if (s[p] == 'T')
474                        return boost::lexical_cast<long long>(s.c_str())*1024*1024*1024*1024;
475                else
476                        return boost::lexical_cast<long long>(s.c_str());
477        }
478#define BKMG_RANGE _T("BKMGTP")
479#define BKMG_SIZE 5
480
481        inline std::wstring itos_as_BKMG(unsigned long long i) {
482                double cpy = static_cast<double>(i);
483                wchar_t postfix[] = BKMG_RANGE;
484                int idx = 0;
485                while ((cpy > 999)&&(idx<BKMG_SIZE)) {
486                        cpy/=1024;
487                        idx++;
488                }
489                std::wstringstream ss;
490                ss << std::setprecision(3);
491                ss << cpy;
492                std::wstring ret = ss.str(); // itos(cpy);
493                ret += postfix[idx];
494                return ret;
495        }
496        inline std::wstring format_BKMG(unsigned long long i, std::wstring unit) {
497                double cpy = static_cast<double>(i);
498                wchar_t postfix[] = BKMG_RANGE;
499                if (unit.length() != 1)
500                        return itos(cpy);
501                for (int i=0;i<BKMG_SIZE;i++) {
502                        if (unit[0] == postfix[i]) {
503                                std::wstringstream ss;
504                                ss << std::setiosflags(std::ios::fixed) << std::setprecision(3) << cpy;
505                                std::wstring s = ss.str();
506                                std::wstring::size_type pos = s.find_last_not_of(_T("0"));
507                                if (pos != std::string::npos) {
508                                        s = s.substr(0,pos);
509                                }
510                                return s;
511                        }
512                        cpy/=1024;
513                }
514                return itos(cpy);
515        }
516        inline std::wstring find_proper_unit_BKMG(unsigned long long i) {
517                double cpy = static_cast<double>(i);
518                wchar_t postfix[] = BKMG_RANGE;
519                int idx = 0;
520                while ((cpy > 999)&&(idx<BKMG_SIZE)) {
521                        cpy/=1024;
522                        idx++;
523                }
524                return std::wstring(1, postfix[idx]);
525        }
526
527        typedef std::list<std::wstring> splitList;
528        inline splitList splitEx(const std::wstring str, const std::wstring key) {
529                splitList ret;
530                std::wstring::size_type pos = 0, lpos = 0;
531                while ((pos = str.find(key, pos)) !=  std::wstring::npos) {
532                        ret.push_back(str.substr(lpos, pos-lpos));
533                        lpos = ++pos;
534                }
535                if (lpos < str.size())
536                        ret.push_back(str.substr(lpos));
537                return ret;
538        }
539        typedef std::vector<std::wstring> splitVector;
540        inline splitVector splitV(const std::wstring str, const std::wstring key) {
541                splitVector ret;
542                std::wstring::size_type pos = 0, lpos = 0;
543                while ((pos = str.find(key, pos)) !=  std::wstring::npos) {
544                        ret.push_back(str.substr(lpos, pos-lpos));
545                        lpos = ++pos;
546                }
547                if (lpos < str.size())
548                        ret.push_back(str.substr(lpos));
549                return ret;
550        }
551        inline std::wstring joinEx(splitList lst, std::wstring key) {
552                std::wstring ret;
553                for (splitList::const_iterator it = lst.begin(); it != lst.end(); ++it) {
554                        if (!ret.empty())
555                                ret += key;
556                        ret += *it;
557                }
558                return ret;
559        }
560
561
562
563        inline std::wstring trim_right(const std::wstring &source , const std::wstring& t = _T(" "))
564        {
565                std::wstring str = source;
566                return str.erase( str.find_last_not_of(t) + 1);
567        }
568
569        inline std::wstring trim_left( const std::wstring& source, const std::wstring& t = _T(" "))
570        {
571                std::wstring str = source;
572                return str.erase(0 , source.find_first_not_of(t) );
573        }
574
575        inline std::wstring trim(const std::wstring& source, const std::wstring& t = _T(" "))
576        {
577                std::wstring str = source;
578                return trim_left( trim_right( str , t) , t );
579        }
580        inline std::pair<std::wstring,std::wstring> split(std::wstring str, std::wstring key) {
581                std::wstring::size_type pos = str.find(key);
582                if (pos == std::wstring::npos)
583                        return std::pair<std::wstring,std::wstring>(str, _T(""));
584                return std::pair<std::wstring,std::wstring>(str.substr(0, pos), str.substr(pos+key.length()));
585        }
586        typedef std::pair<std::wstring,std::wstring> token;
587        // foo bar "foo \" bar" foo -> foo, bar "foo \" bar" foo -> bar, "foo \" bar" foo ->
588        //
589        inline token getToken(std::wstring buffer, char split, bool escape = false) {
590                std::wstring::size_type pos = std::wstring::npos;
591                if ((escape) && (buffer[0] == '\"')) {
592                        do {
593                                pos = buffer.find('\"');
594                        }
595                        while (((pos != std::wstring::npos)&&(pos > 1))&&(buffer[pos-1] == '\\'));
596                } else
597                        pos = buffer.find(split);
598                if (pos == std::wstring::npos)
599                        return token(buffer, _T(""));
600                if (pos == buffer.length()-1)
601                        return token(buffer.substr(0, pos), _T(""));
602                return token(buffer.substr(0, pos-1), buffer.substr(++pos));
603        }
604
605
606
607        template<class char_type>
608        struct ci_char_traits : public std::char_traits<char_type> {
609                static bool eq( char_type c1, char_type c2 ) {
610                        return toupper(c1) == toupper(c2);
611                }
612
613                static bool ne( char_type c1, char_type c2 ) {
614                        return toupper(c1) != toupper(c2);
615                }
616
617                static bool lt( char_type c1, char_type c2 ) {
618                        return toupper(c1) <  toupper(c2);
619                }
620
621                static int compare( const char_type* s1, const char_type* s2, size_t n ) {
622#ifdef WIN32
623                        return memicmp( s1, s2, n );
624#else
625                        while (n-- && eq(*s1, *s2))
626                                ++s1, ++s2;
627                        return lt(*s2, *s1) - lt(*s1, *s2);
628#endif
629                }
630
631                static const char* find( const char_type* s, int n, char_type a ) {
632                        while( n-- > 0 && toupper(*s) != toupper(a) ) {
633                                ++s;
634                        }
635                        return s;
636                }
637        };
638        typedef std::basic_string<wchar_t, ci_char_traits<wchar_t> > wci_string;
639
640        template<class _E>
641        struct blind_traits : public std::char_traits<_E>
642        {
643               
644                static bool eq(const _E& x, const _E& y) {
645                        return boost::algorithm::iequals(x,y);
646                }
647                static bool lt(const _E& x, const _E& y) {
648                        return ilexicographical_compare(x, y);
649                }
650/*
651                static int compare(const _E *x, const _E *y, size_t n) {
652                        return ilexicographical_compare(x, y);
653                        return _wcsnicmp( x, y, n );
654                }
655
656                //  There's no memichr(), so we roll our own.  It ain't rocket science.
657                static const _E * / *__cdecl* / find(const _E *buf, size_t len, const _E& ch) {
658                        //  Jerry says that x86s have special mojo for memchr(), so the
659                        //  memchr() calls end up being reasonably efficient in practice.
660                        const _E *pu = (const _E *)memchr(buf, ch, len);
661                        const _E *pl = (const _E *)memchr(buf, tolower( ch ), len);
662                        if ( ! pu )
663                                return pl;  //  Might be NULL; if so, NULL's the word.
664                        else if ( ! pl )
665                                return pu;
666                        else
667                                //  If either one was NULL, we return the other; if neither is
668                                //  NULL, we return the lesser of the two.
669                                return ( pu < pl ) ? pu : pl;
670                }
671
672                //  I'm reasonably sure that this is eq() for wide characters.  Maybe.
673                static bool eq_int_type(const long& ch1, const long& ch2) {
674                        return std::char_traits<_E>::eq_int_type( tolower( ch1 ), tolower( ch2 ) );
675                }
676                */
677        };
678
679        //  And here's our case-blind string class.
680        //typedef std::basic_string<char, blind_traits<char>, std::allocator<char> >  blindstr;
681        typedef std::basic_string<wchar_t, blind_traits<wchar_t>, std::allocator<wchar_t> >  blindstr;
682
683
684
685
686        class StrICmp
687        {
688        public:
689                StrICmp(const std::string &Lang = "english") : m_locE(Lang.c_str())
690                {
691                }
692                class CharLessI
693                {
694                public:
695                        CharLessI(std::locale &locE) : m_locE(locE)
696                        {
697                        }
698                        template<typename T>
699                        bool operator()(T c1, T c2)
700                        {
701                                return std::tolower(c1, m_locE) < std::tolower(c2, m_locE);
702                        }
703                private:
704                        std::locale &m_locE;
705                };
706                template<typename T>
707                int operator()(const T &s1, const T &s2) const
708                {
709                        if (std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), CharLessI(m_locE)))
710                                return -1;
711                        if (std::lexicographical_compare(s2.begin(), s2.end(), s1.begin(), s1.end(), CharLessI(m_locE)))
712                                return 1;
713                        return 0;
714                }
715        private:
716                std::locale m_locE;
717        };
718
719        template<typename T>
720        int StrCmpI(const T &s1, const T &s2, const std::string &Lang = "english")
721        {
722                return StrICmp(Lang)(s1, s2);
723        }
724
725#define MK_FORMAT_FTD(min, key, val) \
726        if (mtm->tm_year > min) \
727        strEx::replace(format, key, strEx::itos(val));  \
728        else  \
729        strEx::replace(format, key, _T("0"));
730#ifdef WIN32
731        inline std::wstring format_time_delta(struct tm *mtm, std::wstring format = _T("%Y years %m months %d days %H hours %M minutes")) {
732                // "Date: %Y-%m-%d %H:%M:%S"
733                MK_FORMAT_FTD(70, _T("%Y"), mtm->tm_year);
734                MK_FORMAT_FTD(0, _T("%m"), mtm->tm_mon);
735                MK_FORMAT_FTD(0, _T("%d"), mtm->tm_mday-1);
736                MK_FORMAT_FTD(0, _T("%H"), mtm->tm_hour);
737                MK_FORMAT_FTD(0, _T("%M"), mtm->tm_min);
738                MK_FORMAT_FTD(0, _T("%S"), mtm->tm_sec);
739                return format;
740        }
741        inline std::wstring format_time_delta(time_t time, std::wstring format = _T("%Y years %m months %d days %H hours %M minutes")) {
742                struct tm nt; // = new struct tm;
743#if (_MSC_VER > 1300)  // 1300 == VC++ 7.0
744                if (gmtime_s(&nt, &time) != 0)
745                        return _T("");
746#else
747                nt = gmtime(&time);
748                if (nt == NULL)
749                        return "";
750#endif
751                return format_time_delta(&nt, format);
752        }
753        inline std::wstring format_filetime_delta(unsigned long long filetime, std::wstring format = _T("%Y-%m-%d %H:%M:%S")) {
754                if (filetime == 0)
755                        return _T("ZERO");
756                //filetime -= (SECS_BETWEEN_EPOCHS * SECS_TO_100NS);
757                filetime /= SECS_TO_100NS;
758                return format_time_delta(static_cast<time_t>(filetime), format);
759        }
760#endif
761
762#ifdef _DEBUG
763        inline void test_getToken(std::wstring in1, char in2, std::wstring out1, std::wstring out2) {
764                token t = getToken(in1, in2);
765                std::wcout << _T("strEx::test_getToken(") << in1 << _T(", ") << in2 << _T(") : ");
766                if ((t.first == out1) && (t.second == out2))
767                        std::wcout << _T("Succeeded") << std::endl;
768                else
769                        std::wcout << _T("Failed [") << out1 << _T("=") << t.first << _T(", ") << out2 << _T("=") << t.second << _T("]") << std::endl;
770        }
771        inline void run_test_getToken() {
772                test_getToken(_T(""), '&', _T(""), _T(""));
773                test_getToken(_T("&"), '&', _T(""), _T(""));
774                test_getToken(_T("&&"), '&', _T(""), _T("&"));
775                test_getToken(_T("foo"), '&', _T("foo"), _T(""));
776                test_getToken(_T("foo&"), '&', _T("foo"), _T(""));
777                test_getToken(_T("foo&bar"), '&', _T("foo"), _T("bar"));
778                test_getToken(_T("foo&bar&test"), '&', _T("foo"), _T("bar&test"));
779        }
780
781        inline void test_replace(std::wstring source, std::wstring replace, std::wstring with, std::wstring out) {
782                std::wcout << _T("strEx::test_replace(") << source << _T(", ") << replace << _T(", ") << with << _T(") : ");
783                std::wstring s = source;
784                strEx::replace(s, replace, with);
785                if (s == out)
786                        std::wcout << _T("Succeeded") << std::endl;
787                else
788                        std::wcout << _T("Failed [") << s << _T("=") << out << _T("]") << std::endl;
789        }
790        inline void run_test_replace() {
791                test_replace(_T(""), _T(""), _T(""), _T(""));
792                test_replace(_T("foo"), _T(""), _T(""), _T("foo"));
793                test_replace(_T("foobar"), _T("foo"), _T(""), _T("bar"));
794                test_replace(_T("foobar"), _T("foo"), _T("bar"), _T("barbar"));
795        }
796
797#endif
798
799        template<typename T>
800        inline void parse_command(T &cmd_line, std::list<T> &args) {
801                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'\"'));
802                BOOST_FOREACH(T s, tok)
803                        args.push_back(s);
804        }
805        template<typename T>
806        inline void parse_command(T cmd_line, T &cmd, std::list<T> &args) {
807                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'\"'));
808                bool first = true;
809                BOOST_FOREACH(T s, tok)
810                {
811                        if (first) {
812                                cmd = s;
813                                first = false;
814                        } else {
815                                args.push_back(s);
816                        }
817
818                }
819        }
820        /*
821        template<typename T = std::string>
822        inline void parse_command(T &string, std::list<T> &list) {
823                boost::tokenizer<boost::escaped_list_separator<char>, T::const_iterator, T > tok(string, boost::escaped_list_separator<char>('\\', ' ', '\"'));
824                BOOST_FOREACH(T s, tok)
825                        list.push_back(s);
826        }
827        */
828
829}
830
831namespace nscp {
832        namespace helpers {
833                template <typename T> std::string to_string(const T& arg) {
834                        try {
835                                return boost::lexical_cast<std::string>(arg) ;
836                        }
837                        catch(...) {
838                                return "";
839                        }
840                }
841                template <typename T> std::wstring to_wstring(const T& arg) {
842                        try {
843                                return boost::lexical_cast<std::wstring>(arg) ;
844                        }
845                        catch(...) {
846                                return _T("");
847                        }
848                }
849        }
850}
851
852namespace utf8 {
853        /** Converts a std::wstring into a std::string with UTF-8 encoding. */
854        template<typename StringT>
855        StringT cvt(std::wstring const & string);
856
857        /** Converts a std::String with UTF-8 encoding into a std::wstring.     */
858        template<typename StringT>
859        StringT cvt(std::string const & string );
860
861        /** Nop specialization for std::string. */
862        template <>
863        inline std::string cvt(std::string const & string) {
864                return string;
865        }
866
867        /** Nop specialization for std::wstring. */
868        template<>
869        inline std::wstring cvt(std::wstring const & rc_string) {
870                return rc_string;
871        }
872
873        template<>
874        inline std::string cvt(std::wstring const & str) {
875                // figure out how many narrow characters we are going to get
876                int nChars = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0, NULL, NULL);
877                if (nChars == 0)
878                        return "";
879
880                // convert the wide string to a narrow string
881                // nb: slightly naughty to write directly into the string like this
882                std::string buf;
883                buf.resize(nChars);
884                WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), const_cast<char*>(buf.c_str()), nChars, NULL, NULL);
885                return buf ;
886        }
887
888        template<>
889        inline std::wstring cvt(std::string const & str) {
890                // figure out how many wide characters we are going to get
891                int nChars = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
892                if (nChars == 0)
893                        return L"";
894
895                // convert the narrow string to a wide string
896                // nb: slightly naughty to write directly into the string like this
897                std::wstring buf;
898                buf.resize(nChars);
899                MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), const_cast<wchar_t*>(buf.c_str()), nChars);
900                return buf;
901        }
902}
Note: See TracBrowser for help on using the repository browser.