1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a zlib-style license that can
4  *  be found in the License.txt file in the root of the source tree.
5  */
6 
7 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 //
9 // More methods for std::(w)string
10 //
11 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 
13 //---------------------------------------------------------------------------
14 #include "ZenLib/PreComp.h"
15 #ifdef __BORLANDC__
16     #pragma hdrstop
17 #endif
18 //---------------------------------------------------------------------------
19 
20 //---------------------------------------------------------------------------
21 #include "ZenLib/Conf_Internal.h"
22 //---------------------------------------------------------------------------
23 
24 //---------------------------------------------------------------------------
25 #ifdef ZENLIB_USEWX
26     #include <wx/strconv.h>
27     #include <wx/datetime.h>
28 #else //ZENLIB_USEWX
29     #ifdef ZENLIB_STANDARD
30         #undef WINDOWS
31     #endif
32     #ifdef WINDOWS
33         #undef __TEXT
34         #include <windows.h>
35         #include <tchar.h>
36     #endif
37 #endif //ZENLIB_USEWX
38 #ifdef __MINGW32__
39     #include <windows.h>
40 #endif //__MINGW32__
41 #include <algorithm>
42 #include <iomanip>
43 #include <cmath>
44 #include <ctime>
45 #include "ZenLib/OS_Utils.h"
46 #include "ZenLib/File.h"
47 using namespace std;
48 //---------------------------------------------------------------------------
49 
50 namespace ZenLib
51 {
52 
53 int16u Ztring_ISO_8859_2[96]=
54 {
55     0x00A0,
56     0x0104,
57     0x02D8,
58     0x0141,
59     0x00A4,
60     0x013D,
61     0x015A,
62     0x00A7,
63     0x00A8,
64     0x0160,
65     0x015E,
66     0x0164,
67     0x0179,
68     0x00AD,
69     0x017D,
70     0x017B,
71     0x00B0,
72     0x0105,
73     0x02DB,
74     0x0142,
75     0x00B4,
76     0x013E,
77     0x015B,
78     0x02C7,
79     0x00B8,
80     0x0161,
81     0x015F,
82     0x0165,
83     0x017A,
84     0x02DD,
85     0x017E,
86     0x017C,
87     0x0154,
88     0x00C1,
89     0x00C2,
90     0x0102,
91     0x00C4,
92     0x0139,
93     0x0106,
94     0x00C7,
95     0x010C,
96     0x00C9,
97     0x0118,
98     0x00CB,
99     0x011A,
100     0x00CD,
101     0x00CE,
102     0x010E,
103     0x0110,
104     0x0143,
105     0x0147,
106     0x00D3,
107     0x00D4,
108     0x0150,
109     0x00D6,
110     0x00D7,
111     0x0158,
112     0x016E,
113     0x00DA,
114     0x0170,
115     0x00DC,
116     0x00DD,
117     0x0162,
118     0x00DF,
119     0x0155,
120     0x00E1,
121     0x00E2,
122     0x0103,
123     0x00E4,
124     0x013A,
125     0x0107,
126     0x00E7,
127     0x010D,
128     0x00E9,
129     0x0119,
130     0x00EB,
131     0x011B,
132     0x00ED,
133     0x00EE,
134     0x010F,
135     0x0111,
136     0x0144,
137     0x0148,
138     0x00F3,
139     0x00F4,
140     0x0151,
141     0x00F6,
142     0x00F7,
143     0x0159,
144     0x016F,
145     0x00FA,
146     0x0171,
147     0x00FC,
148     0x00FD,
149     0x0163,
150     0x02D9,
151 };
152 
153 //---------------------------------------------------------------------------
154 Ztring EmptyZtring;
155 //---------------------------------------------------------------------------
156 
157 //---------------------------------------------------------------------------
158 #if defined(STREAM_MISSING)
159     #if defined (_UNICODE)
160         #if defined (MACOS) || defined (MACOSX)
161             #define _tnprintf swprintf
162         #else
163             #define _tnprintf snwprintf
164         #endif
165     #else
166         #define _tnprintf snprintf
167     #endif
168 #else
169     typedef basic_stringstream<Char>  tStringStream;
170     typedef basic_istringstream<Char> tiStringStream;
171     typedef basic_ostringstream<Char> toStringStream;
172 #endif
173 //---------------------------------------------------------------------------
174 
175 //***************************************************************************
176 // Operators
177 //***************************************************************************
178 
operator ()(size_type Pos)179 Char &Ztring::operator() (size_type Pos)
180 {
181     if (Pos>size())
182         resize(Pos);
183     return operator[] (Pos);
184 }
185 
186 //***************************************************************************
187 // Assign
188 //***************************************************************************
189 
Assign_FromFile(const Ztring & FileName)190 bool Ztring::Assign_FromFile (const Ztring &FileName)
191 {
192     File F;
193     if (!F.Open(FileName))
194         return false;
195     int64u F_Size=F.Size_Get();
196     if (F_Size>((size_t)-1)-1)
197         return false;
198 
199     //Creating buffer
200     int8u* Buffer=new int8u[(size_t)F_Size+1];
201     size_t Buffer_Offset=0;
202 
203     //Reading the file
204     while(Buffer_Offset<F_Size)
205     {
206         size_t BytesRead=F.Read(Buffer+Buffer_Offset, (size_t)F_Size-Buffer_Offset);
207         if (BytesRead==0)
208             break; //Read is finished
209         Buffer_Offset+=BytesRead;
210     }
211     if (Buffer_Offset<F_Size)
212     {
213         delete[] Buffer;
214         return false;
215     }
216     Buffer[Buffer_Offset]='\0';
217 
218     //Filling
219     assign((const Char*)Buffer);
220     delete[] Buffer;
221 
222     return true;
223 }
224 
225 //***************************************************************************
226 // Conversions
227 //***************************************************************************
228 
From_Unicode(const wchar_t S)229 Ztring& Ztring::From_Unicode (const wchar_t S)
230 {
231     #ifdef _UNICODE
232         append(1, S);
233     #else
234         From_Unicode(&S, 1);
235     #endif
236     return *this;
237 }
238 
From_Unicode(const wchar_t * S)239 Ztring& Ztring::From_Unicode (const wchar_t* S)
240 {
241     if (S==NULL)
242         return *this;
243 
244     #ifdef _UNICODE
245         assign(S);
246     #else
247         #ifdef ZENLIB_USEWX
248             size_type OK=wxConvCurrent->WC2MB(NULL, S, 0);
249             if (OK!=0 && OK!=Error)
250                 assign(wxConvCurrent->cWC2MB(S));
251         #else //ZENLIB_USEWX
252             #ifdef WINDOWS
253                 int Size=WideCharToMultiByte(CP_UTF8, 0, S, -1, NULL, 0, NULL, NULL);
254                 if (Size!=0)
255                 {
256                     char* AnsiString=new char[Size+1];
257                     WideCharToMultiByte(CP_UTF8, 0, S, -1, AnsiString, Size, NULL, NULL);
258                     AnsiString[Size]='\0';
259                     assign (AnsiString);
260                     delete[] AnsiString;
261                 }
262                 else
263                     clear();
264             #else //WINDOWS
265                 size_t Size=wcstombs(NULL, S, 0);
266                 if (Size!=0 && Size!=(size_t)-1)
267                 {
268                     char* AnsiString=new char[Size+1];
269                     Size=wcstombs(AnsiString, S, wcslen(S));
270                     AnsiString[Size]='\0';
271                     assign (AnsiString);
272                     delete[] AnsiString;
273                 }
274                 else
275                     clear();
276             #endif
277         #endif //ZENLIB_USEWX
278     #endif
279     return *this;
280 }
281 
From_Unicode(const wchar_t * S,size_type Start,size_type Length)282 Ztring& Ztring::From_Unicode (const wchar_t *S, size_type Start, size_type Length)
283 {
284     if (S==NULL)
285         return *this;
286 
287     if (Length==Error)
288         Length=wcslen(S+Start);
289     wchar_t* Temp=new wchar_t[Length+1];
290     wcsncpy (Temp, S+Start, Length);
291     Temp[Length]=__T('\0');
292 
293     From_Unicode(Temp);
294     delete[] Temp; //Temp=NULL;
295     return *this;
296 }
297 
From_UTF8(const char * S)298 Ztring& Ztring::From_UTF8 (const char* S)
299 {
300     if (S==NULL)
301         return *this;
302 
303     #ifdef ZENLIB_USEWX
304         size_type OK=wxConvUTF8.MB2WC(NULL, S, 0);
305         if (OK!=0 && OK!=Error)
306             #ifdef _UNICODE
307                 assign(wxConvUTF8.cMB2WC(S).data());
308             #else
309                 assign(wxConvCurrent->cWC2MB(wxConvUTF8.cMB2WC(S)));
310             #endif
311     #else //ZENLIB_USEWX
312         #ifdef _UNICODE
313             // Don't use MultiByteToWideChar(), some characters are not well decoded
314             clear();
315             const int8u* Z=(const int8u*)S;
316             while (*Z) //0 is end
317             {
318                 //1 byte
319                 if (*Z<0x80)
320                 {
321                     operator += ((wchar_t)(*Z));
322                     Z++;
323                 }
324                 //2 bytes
325                 else if ((*Z&0xE0)==0xC0)
326                 {
327                     if ((*(Z+1)&0xC0)==0x80)
328                     {
329                         operator += ((((wchar_t)(*Z&0x1F))<<6)|(*(Z+1)&0x3F));
330                         Z+=2;
331                     }
332                     else
333                     {
334                         clear();
335                         return *this; //Bad character
336                     }
337                 }
338                 //3 bytes
339                 else if ((*Z&0xF0)==0xE0)
340                 {
341                     if ((*(Z+1)&0xC0)==0x80 && (*(Z+2)&0xC0)==0x80)
342                     {
343                         operator += ((((wchar_t)(*Z&0x0F))<<12)|((*(Z+1)&0x3F)<<6)|(*(Z+2)&0x3F));
344                         Z+=3;
345                     }
346                     else
347                     {
348                         clear();
349                         return *this; //Bad character
350                     }
351                 }
352                 //4 bytes
353                 else if ((*Z&0xF8)==0xF0)
354                 {
355                     if ((*(Z+1)&0xC0)==0x80 && (*(Z+2)&0xC0)==0x80 && (*(Z+3)&0xC0)==0x80)
356                     {
357                         #if defined(_MSC_VER)
358                             #pragma warning(push)
359                             #pragma warning(disable:4127)
360                         #endif //defined(_MSC_VER)
361                         if (sizeof(wchar_t) == 2)
362                         #if defined(_MSC_VER)
363                             #pragma warning(pop)
364                         #endif //defined(_MSC_VER)
365                         {
366                             int32u Value = ((((int32u)(*Z&0x0F))<<18)|((*(Z+1)&0x3F)<<12)|((*(Z+2)&0x3F)<<6)|(*(Z+3)&0x3F));
367                             operator += (0xD800|((Value>>10)-0x40));
368                             operator += (0xDC00| (Value&0x3FF));
369                         }
370                         else
371                             operator += ((((wchar_t)(*Z&0x0F))<<18)|((*(Z+1)&0x3F)<<12)|((*(Z+2)&0x3F)<<6)|(*(Z+3)&0x3F));
372                         Z+=4;
373                     }
374                     else
375                     {
376                         clear();
377                         return *this; //Bad character
378                     }
379                 }
380                 else
381                 {
382                     clear();
383                     return *this; //Bad character
384                 }
385             }
386         #else
387             assign(S); //Not implemented
388         #endif
389     #endif //ZENLIB_USEWX
390     return *this;
391 }
392 
From_UTF8(const char * S,size_type Start,size_type Length)393 Ztring& Ztring::From_UTF8 (const char* S, size_type Start, size_type Length)
394 {
395     if (S==NULL)
396         return *this;
397 
398     if (Length==Error)
399         Length=strlen(S+Start);
400     char* Temp=new char[Length+1];
401     strncpy (Temp, S+Start, Length);
402     Temp[Length]='\0';
403 
404     From_UTF8(Temp);
405     delete[] Temp; //Temp=NULL;
406     return *this;
407 }
408 
From_UTF16(const char * S)409 Ztring& Ztring::From_UTF16 (const char* S)
410 {
411     if (S==NULL)
412         return *this;
413 
414          if ((unsigned char)S[0]==(unsigned char)0xFF && (unsigned char)S[1]==(unsigned char)0xFE)
415         return From_UTF16LE(S+2);
416     else if ((unsigned char)S[0]==(unsigned char)0xFE && (unsigned char)S[1]==(unsigned char)0xFF)
417         return From_UTF16BE(S+2);
418     else if ((unsigned char)S[0]==(unsigned char)0x00 && (unsigned char)S[1]==(unsigned char)0x00)
419     {
420         clear(); //No begin!
421         return *this;
422     }
423     else
424         return From_UTF16LE(S); //Not sure, default
425 }
426 
From_UTF16(const char * S,size_type Start,size_type Length)427 Ztring& Ztring::From_UTF16 (const char* S, size_type Start, size_type Length)
428 {
429     if (S==NULL)
430         return *this;
431 
432     if (Length<2)
433         return *this;
434 
435          if ((unsigned char)S[0]==(unsigned char)0xFF && (unsigned char)S[1]==(unsigned char)0xFE)
436         return From_UTF16LE(S+2, Start, Length-2);
437     else if ((unsigned char)S[0]==(unsigned char)0xFE && (unsigned char)S[1]==(unsigned char)0xFF)
438         return From_UTF16BE(S+2, Start, Length-2);
439     else if ((unsigned char)S[0]==(unsigned char)0x00 && (unsigned char)S[1]==(unsigned char)0x00)
440     {
441         clear(); //No begin!
442         return *this;
443     }
444     else
445         return From_UTF16LE(S, Start, Length); //Not sure, default
446 }
447 
From_UTF16BE(const char * S)448 Ztring& Ztring::From_UTF16BE (const char* S)
449 {
450     if (S==NULL)
451         return *this;
452 
453     #ifdef ZENLIB_USEWX
454         //clear(); return *this;
455         wxMBConvUTF16BE wxConvUTF16BE;
456         size_type OK=wxConvUTF16BE.MB2WC(NULL, S, 0);
457         if (OK!=0 && OK!=Error)
458             #ifdef _UNICODE
459                 assign(wxConvUTF16BE.cMB2WC(S).data());
460             #else
461                 assign(wxConvCurrent->cWC2MB(wxConvUTF16BE.cMB2WC(S)));
462             #endif
463     #else //ZENLIB_USEWX
464         #ifdef WINDOWS
465             clear();
466             const wchar_t* SW=(const wchar_t*)S;
467             size_t Pos=0;
468             while (SW[Pos]!=__T('\0'))
469             {
470                 Char Temp=(Char)(((SW[Pos]&0xFF00)>>8)+((SW[Pos]&0x00FF)<<8));
471                 append(1, Temp);
472                 Pos++;
473             }
474         #else //WINDOWS
475             clear();
476             while (S[0]!=0 || S[1]!=0)
477             {
478                 append(1, (Char)BigEndian2int16u(S));
479                 S+=2;
480             }
481         #endif
482     #endif //ZENLIB_USEWX
483     return *this;
484 }
485 
From_UTF16BE(const char * S,size_type Start,size_type Length)486 Ztring& Ztring::From_UTF16BE (const char* S, size_type Start, size_type Length)
487 {
488     if (S==NULL)
489         return *this;
490 
491     if (Length==Error)
492     {
493         Length=0;
494         while(S[Length]!=0x0000)
495             Length++;
496     }
497     else
498         Length&=(size_t)-2; //odd number
499 
500     char* Temp=new char[Length+2];
501     memcpy (Temp, S+Start, Length);
502     Temp[Length+0]=0x00;
503     Temp[Length+1]=0x00;
504     reserve(Length);
505     From_UTF16BE(Temp);
506     delete[] Temp; //Temp=NULL;
507     return *this;
508 }
509 
From_UTF16LE(const char * S)510 Ztring& Ztring::From_UTF16LE (const char* S)
511 {
512     if (S==NULL)
513         return *this;
514 
515     #ifdef ZENLIB_USEWX
516         //clear(); return *this;
517         wxMBConvUTF16LE wxConvUTF16LE;
518         size_type OK=wxConvUTF16LE.MB2WC(NULL, S, 0);
519         if (OK!=0 && OK!=Error)
520             #ifdef _UNICODE
521                 assign(wxConvUTF16LE.cMB2WC(S).data());
522             #else
523                 assign(wxConvCurrent->cWC2MB(wxConvUTF16LE.cMB2WC(S)));
524             #endif
525     #else //ZENLIB_USEWX
526         #ifdef WINDOWS
527             #ifdef UNICODE
528                 const wchar_t* SW=(const wchar_t*)S;
529                 assign(SW);
530             #else
531                 clear(); //Not implemented
532             #endif
533         #else //WINDOWS
534             clear();
535             while (S[0]!=0 || S[1]!=0)
536             {
537                 append(1, (Char)LittleEndian2int16u(S));
538                 S+=2;
539             }
540         #endif
541     #endif //ZENLIB_USEWX
542     return *this;
543 }
544 
From_UTF16LE(const char * S,size_type Start,size_type Length)545 Ztring& Ztring::From_UTF16LE (const char* S, size_type Start, size_type Length)
546 {
547     if (S==NULL)
548         return *this;
549 
550     if (Length==Error)
551     {
552         Length=0;
553         while(S[Length]!=0x0000)
554             Length+=2;
555     }
556     else
557         Length&=(size_t)-2; //odd number
558 
559     char* Temp=new char[Length+2];
560     memcpy (Temp, S+Start, Length);
561     Temp[Length+0]=0x00;
562     Temp[Length+1]=0x00;
563     From_UTF16LE(Temp);
564     delete[] Temp; //Temp=NULL;
565     return *this;
566 }
567 
From_Local(const char * S)568 Ztring& Ztring::From_Local (const char* S)
569 {
570     if (S==NULL)
571         return *this;
572 
573     #ifdef _UNICODE
574         #ifdef ZENLIB_USEWX
575             size_type OK=wxConvCurrent->MB2WC(NULL, S, 0);
576             if (OK!=0 && OK!=Error)
577                 assign(wxConvCurrent->cMB2WC(S).data());
578         #else //ZENLIB_USEWX
579             #ifdef WINDOWS
580                 int Size=MultiByteToWideChar(CP_ACP, 0, S, -1, NULL, 0);
581                 if (Size!=0)
582                 {
583                     wchar_t* WideString=new wchar_t[Size+1];
584                     MultiByteToWideChar(CP_ACP, 0, S, -1, WideString, Size);
585                     WideString[Size]=L'\0';
586                     assign (WideString);
587                     delete[] WideString; //WideString=NULL;
588                 }
589                 else
590                     clear();
591             #else //WINDOWS
592                 size_t Size=mbsrtowcs(NULL, &S, 0, NULL);
593                 if (Size!=0 && Size!=(size_t)-1)
594                 {
595                     wchar_t* WideString=new wchar_t[Size+1];
596                     Size=mbsrtowcs(WideString, &S, Size, NULL);
597                     WideString[Size]=L'\0';
598                     assign (WideString);
599                     delete[] WideString; //WideString=NULL;
600                 }
601                 else
602                     clear();
603             #endif
604         #endif //ZENLIB_USEWX
605     #else
606         assign(S);
607     #endif
608     return *this;
609 }
610 
From_Local(const char * S,size_type Start,size_type Length)611 Ztring& Ztring::From_Local (const char* S, size_type Start, size_type Length)
612 {
613     if (S==NULL)
614         return *this;
615 
616     if (Length==Error)
617         Length=strlen(S+Start);
618     #ifdef _UNICODE
619         char* Temp=new char[Length+1];
620         strncpy (Temp, S+Start, Length);
621         Temp[Length]='\0';
622         From_Local(Temp);
623         delete[] Temp; //Temp=NULL;
624     #else
625         assign(S+Start, Length);
626         if (find(__T('\0'))!=std::string::npos)
627             resize(find(__T('\0')));
628     #endif
629     return *this;
630 }
631 
From_ISO_8859_1(const char * S)632 Ztring& Ztring::From_ISO_8859_1(const char* S)
633 {
634     size_t Length = strlen(S);
635     wchar_t* Temp = new wchar_t[Length +1];
636 
637     for (size_t Pos=0; Pos<Length+1; Pos++)
638         Temp[Pos]=(wchar_t)((int8u)S[Pos]);
639 
640     From_Unicode(Temp);
641     delete[] Temp;
642     return *this;
643 }
644 
From_ISO_8859_1(const char * S,size_type Start,size_type Length)645 Ztring& Ztring::From_ISO_8859_1(const char* S, size_type Start, size_type Length)
646 {
647     if (S==NULL)
648         return *this;
649 
650     if (Length==Error)
651         Length=strlen(S+Start);
652     #ifdef _UNICODE
653         char* Temp = new char[Length+1];
654         strncpy(Temp, S +Start, Length);
655         Temp[Length] = '\0';
656         From_ISO_8859_1(Temp);
657         delete[] Temp;
658     #else
659         assign(S +Start, Length);
660         if (find(__T('\0')) != std::string::npos)
661             resize(find(__T('\0')));
662     #endif
663     return *this;
664 }
665 
From_ISO_8859_2(const char * S)666 Ztring& Ztring::From_ISO_8859_2(const char* S)
667 {
668     size_t Length = strlen(S);
669     wchar_t* Temp = new wchar_t[Length +1];
670 
671     for (size_t Pos=0; Pos<Length+1; Pos++)
672     {
673         if ((int8u)S[Pos]>=0xA0)
674             Temp[Pos]=(wchar_t)Ztring_ISO_8859_2[((int8u)S[Pos])-0xA0];
675         else
676             Temp[Pos]=(wchar_t)((int8u)S[Pos]);
677     }
678 
679     From_Unicode(Temp);
680     delete[] Temp;
681     return *this;
682 }
683 
From_ISO_8859_2(const char * S,size_type Start,size_type Length)684 Ztring& Ztring::From_ISO_8859_2(const char* S, size_type Start, size_type Length)
685 {
686     if (S==NULL)
687         return *this;
688 
689     if (Length==Error)
690         Length=strlen(S+Start);
691     #ifdef _UNICODE
692         char* Temp = new char[Length+1];
693         strncpy(Temp, S +Start, Length);
694         Temp[Length] = '\0';
695         From_ISO_8859_2(Temp);
696         delete[] Temp;
697     #else
698         assign(S +Start, Length);
699         if (find(__T('\0')) != std::string::npos)
700             resize(find(__T('\0')));
701     #endif
702     return *this;
703 }
704 
From_GUID(const int128u S)705 Ztring& Ztring::From_GUID (const int128u S)
706 {
707     Ztring S1;
708     S1.From_CC1((int8u) ((S.hi&0x000000FF00000000LL)>>32)); append(S1);
709     S1.From_CC1((int8u) ((S.hi&0x0000FF0000000000LL)>>40)); append(S1);
710     S1.From_CC1((int8u) ((S.hi&0x00FF000000000000LL)>>48)); append(S1);
711     S1.From_CC1((int8u) ((S.hi&0xFF00000000000000LL)>>56)); append(S1); append(__T("-"));
712     S1.From_CC1((int8u) ((S.hi&0x0000000000FF0000LL)>>16)); append(S1);
713     S1.From_CC1((int8u) ((S.hi&0x00000000FF000000LL)>>24)); append(S1); append(__T("-"));
714     S1.From_CC1((int8u) ( S.hi&0x00000000000000FFLL     )); append(S1);
715     S1.From_CC1((int8u) ((S.hi&0x000000000000FF00LL)>> 8)); append(S1); append(__T("-"));
716     S1.From_CC2((int16u)((S.lo&0xFFFF000000000000LL)>>48)); append(S1); append(__T("-"));
717     S1.From_CC2((int16u)((S.lo&0x0000FFFF00000000LL)>>32)); append(S1);
718     S1.From_CC2((int16u)((S.lo&0x00000000FFFF0000LL)>>16)); append(S1);
719     S1.From_CC2((int16u)( S.lo&0x000000000000FFFFLL     )); append(S1);
720 
721     return *this;
722 }
723 
From_UUID(const int128u S)724 Ztring& Ztring::From_UUID (const int128u S)
725 {
726     Ztring S1;
727     S1.From_CC2((int16u)((S.hi&0xFFFF000000000000LL)>>48)); assign(S1);
728     S1.From_CC2((int16u)((S.hi&0x0000FFFF00000000LL)>>32)); append(S1); append(__T("-"));
729     S1.From_CC2((int16u)((S.hi&0x00000000FFFF0000LL)>>16)); append(S1); append(__T("-"));
730     S1.From_CC2((int16u)( S.hi&0x000000000000FFFFLL     )); append(S1); append(__T("-"));
731     S1.From_CC2((int16u)((S.lo&0xFFFF000000000000LL)>>48)); append(S1); append(__T("-"));
732     S1.From_CC2((int16u)((S.lo&0x0000FFFF00000000LL)>>32)); append(S1);
733     S1.From_CC2((int16u)((S.lo&0x00000000FFFF0000LL)>>16)); append(S1);
734     S1.From_CC2((int16u)( S.lo&0x000000000000FFFFLL     )); append(S1);
735 
736     return *this;
737 }
738 
From_CC4(const int32u S)739 Ztring& Ztring::From_CC4 (const int32u S)
740 {
741     clear();
742     for (int8s i=(4-1)*8; i>=0; i-=8)
743     {
744         int32u Value=(S&(0xFF<<i))>>i;
745         if (Value<0x20)
746         {
747             if (!i || (i!=24  && !(S&(0xFFFFFFFF>>(32-i)))))
748                 return *this; // Trailing 0 are fine
749 
750             // Not valid, using 0x as fallback
751             clear();
752             append(__T("0x"));
753             append(Ztring().From_CC1((int8u)((S&0xFF000000)>>24)));
754             append(Ztring().From_CC1((int8u)((S&0x00FF0000)>>16)));
755             append(Ztring().From_CC1((int8u)((S&0x0000FF00)>> 8)));
756             append(Ztring().From_CC1((int8u)((S&0x000000FF)    )));
757             return *this;
758         }
759         append(1, (Char)(Value));
760     }
761     return *this;
762 }
763 
From_CC3(const int32u S)764 Ztring& Ztring::From_CC3 (const int32u S)
765 {
766     clear();
767     for (int8s i=(3-1)*8; i>=0; i-=8)
768     {
769         int32u Value=(S&(0xFF<<i))>>i;
770         if (Value<0x20)
771         {
772             if (!i || (i!=16  && !(S&(0xFFFFFF>>(24-i)))))
773                 return *this; // Trailing 0 are fine
774 
775             // Not valid, using 0x as fallback
776             clear();
777             append(__T("0x"));
778             append(Ztring().From_CC1((int8u)((S&0x00FF0000)>>16)));
779             append(Ztring().From_CC1((int8u)((S&0x0000FF00)>> 8)));
780             append(Ztring().From_CC1((int8u)((S&0x000000FF)    )));
781             return *this;
782         }
783         append(1, (Char)(Value));
784     }
785     return *this;
786 }
787 
From_CC2(const int16u S)788 Ztring& Ztring::From_CC2 (const int16u S)
789 {
790     clear();
791     Ztring Pos1; Pos1.From_Number(S, 16);
792     resize(4-Pos1.size(), __T('0'));
793     append(Pos1);
794     MakeUpperCase();
795 
796     return *this;
797 }
798 
From_CC1(const int8u S)799 Ztring& Ztring::From_CC1 (const int8u S)
800 {
801     clear();
802     Ztring Pos1; Pos1.From_Number(S, 16);
803     resize(2-Pos1.size(), __T('0'));
804     append(Pos1);
805     MakeUpperCase();
806 
807     return *this;
808 }
809 
From_Number(const int8s I,int8u Radix)810 Ztring& Ztring::From_Number (const int8s I, int8u Radix)
811 {
812     #if defined(STREAM_MISSING)
813         if (Radix==0)
814         {
815             clear();
816             return *this;
817         }
818         Char* C1=new Char[33];
819         #ifdef __MINGW32__
820             _itot (I, C1, Radix);
821         #else
822             _tnprintf(C1, 32, Radix==10?__T("%d"):(Radix==16?__T("%x"):(Radix==8?__T("%o"):__T(""))), I);
823         #endif
824         assign (C1);
825         delete[] C1; //C1=NULL;
826     #else
827         toStringStream Stream;
828         #ifdef UNICODE
829             Stream << setbase(Radix) << I;
830         #else //UNICODE
831             Stream << setbase(Radix) << (size_t)I; //On linux (at least), (un)signed char is detected as a char
832         #endif //UNICODE
833         assign(Stream.str());
834     #endif
835     MakeUpperCase();
836     return *this;
837 }
838 
From_Number(const int8u I,int8u Radix)839 Ztring& Ztring::From_Number (const int8u I, int8u Radix)
840 {
841     #if defined(STREAM_MISSING)
842         if (Radix==0)
843         {
844             clear();
845             return *this;
846         }
847         Char* C1=new Char[33];
848         #ifdef __MINGW32__
849             _ultot (I, C1, Radix);
850         #else
851             _tnprintf(C1, 32, Radix==10?__T("%d"):(Radix==16?__T("%x"):(Radix==8?__T("%o"):__T(""))), I);
852         #endif
853         assign (C1);
854         delete[] C1; //C1=NULL;
855     #else
856         if (Radix==2)
857         {
858             clear();
859             for (int8u Pos=0; Pos<8; Pos++)
860             {
861                 if (I<(((int8u)1)<<Pos))
862                     break;
863                 insert(0, 1, (I&(((int8u)1)<<Pos))?__T('1'):__T('0'));
864             }
865         }
866         else
867         {
868             toStringStream Stream;
869             #ifdef UNICODE
870                 Stream << setbase(Radix) << I;
871             #else //UNICODE
872                 Stream << setbase(Radix) << (size_t)I; //On linux (at least), (un)signed char is detected as a char
873             #endif //UNICODE
874             assign(Stream.str());
875         }
876     #endif
877     MakeUpperCase();
878     return *this;
879 }
880 
From_Number(const int16s I,int8u Radix)881 Ztring& Ztring::From_Number (const int16s I, int8u Radix)
882 {
883     #if defined(STREAM_MISSING)
884         if (Radix==0)
885         {
886             clear();
887             return *this;
888         }
889         Char* C1=new Char[33];
890         #ifdef __MINGW32__
891             _itot (I, C1, Radix);
892         #else
893             _tnprintf(C1, 32, Radix==10?__T("%d"):(Radix==16?__T("%x"):(Radix==8?__T("%o"):__T(""))), I);
894         #endif
895         assign (C1);
896         delete[] C1; //C1=NULL;
897     #else
898         toStringStream Stream;
899         Stream << setbase(Radix) << I;
900         assign(Stream.str());
901     #endif
902     MakeUpperCase();
903     return *this;
904 }
905 
From_Number(const int16u I,int8u Radix)906 Ztring& Ztring::From_Number (const int16u I, int8u Radix)
907 {
908     #if defined(STREAM_MISSING)
909         if (Radix==0)
910         {
911             clear();
912             return *this;
913         }
914         Char* C1=new Char[33];
915         #ifdef __MINGW32__
916             _ultot (I, C1, Radix);
917         #else
918             _tnprintf(C1, 32, Radix==10?__T("%u"):(Radix==16?__T("%x"):(Radix==8?__T("%o"):__T(""))), I);
919         #endif
920         assign (C1);
921         delete[] C1; //C1=NULL;
922     #else
923         if (Radix==2)
924         {
925             clear();
926             for (int8u Pos=0; Pos<16; Pos++)
927             {
928                 if (I<(((int16u)1)<<Pos))
929                     break;
930                 insert(0, 1, (I&(((int16u)1)<<Pos))?__T('1'):__T('0'));
931             }
932         }
933         else
934         {
935             toStringStream Stream;
936             Stream << setbase(Radix) << I;
937             assign(Stream.str());
938         }
939     #endif
940     MakeUpperCase();
941     return *this;
942 }
943 
From_Number(const int32s I,int8u Radix)944 Ztring& Ztring::From_Number (const int32s I, int8u Radix)
945 {
946     #if defined(STREAM_MISSING)
947         if (Radix==0)
948         {
949             clear();
950             return *this;
951         }
952         Char* C1=new Char[33];
953         #ifdef __MINGW32__
954             _itot (I, C1, Radix);
955         #else
956             _tnprintf(C1, 32, Radix==10?__T("%ld"):(Radix==16?__T("%lx"):(Radix==8?__T("%lo"):__T(""))), I);
957         #endif
958         assign (C1);
959         delete[] C1; //C1=NULL;
960     #else
961         toStringStream Stream;
962         Stream << setbase(Radix) << I;
963         assign(Stream.str());
964     #endif
965     MakeUpperCase();
966     return *this;
967 }
968 
From_Number(const int32u I,int8u Radix)969 Ztring& Ztring::From_Number (const int32u I, int8u Radix)
970 {
971     #if defined(STREAM_MISSING)
972         if (Radix==0)
973         {
974             clear();
975             return *this;
976         }
977         Char* C1=new Char[33];
978         #ifdef __MINGW32__
979             _ultot (I, C1, Radix);
980         #else
981             _tnprintf(C1, 32, Radix==10?__T("%lu"):(Radix==16?__T("%lx"):(Radix==8?__T("%lo"):__T(""))), I);
982         #endif
983         assign (C1);
984         delete[] C1; //C1=NULL;
985     #else
986         if (Radix==2)
987         {
988             clear();
989             for (int8u Pos=0; Pos<32; Pos++)
990             {
991                 if (I<(((int32u)1)<<Pos))
992                     break;
993                 insert(0, 1, (I&(((int32u)1)<<Pos))?__T('1'):__T('0'));
994             }
995         }
996         else
997         {
998             toStringStream Stream;
999             Stream << setbase(Radix) << I;
1000             assign(Stream.str());
1001         }
1002     #endif
1003     MakeUpperCase();
1004     return *this;
1005 }
1006 
From_Number(const int64s I,int8u Radix)1007 Ztring& Ztring::From_Number (const int64s I, int8u Radix)
1008 {
1009     #if defined(STREAM_MISSING)
1010         if (Radix==0)
1011         {
1012             clear();
1013             return *this;
1014         }
1015         Char* C1=new Char[65];
1016         #ifdef __MINGW32__
1017             _i64tot (I, C1, Radix);
1018         #else
1019             _tnprintf(C1, 64, Radix==10?__T("%lld"):(Radix==16?__T("%llx"):(Radix==8?__T("%llo"):__T(""))), I);
1020         #endif
1021         assign (C1);
1022         delete[] C1; //C1=NULL;
1023     #else
1024         toStringStream Stream;
1025         Stream << setbase(Radix) << I;
1026         assign(Stream.str());
1027     #endif
1028     MakeUpperCase();
1029     return *this;
1030 }
1031 
From_Number(const int64u I,int8u Radix)1032 Ztring& Ztring::From_Number (const int64u I, int8u Radix)
1033 {
1034     #if defined(STREAM_MISSING)
1035         if (Radix==0)
1036         {
1037             clear();
1038             return *this;
1039         }
1040         Char* C1=new Char[65]; C1[0] = 0;
1041         #ifdef __MINGW32__
1042             _ui64tot (I, C1, Radix);
1043         #else
1044             _tnprintf(C1, 64, Radix==10?__T("%llu"):(Radix==16?__T("%llx"):(Radix==8?__T("%llo"):__T(""))), I);
1045         #endif
1046         assign (C1);
1047         delete[] C1; //C1=NULL;
1048     #else
1049         if (Radix==2)
1050         {
1051             clear();
1052             for (int8u Pos=0; Pos<32; Pos++)
1053             {
1054                 if (I<(((int64u)1)<<Pos))
1055                     break;
1056                 insert(0, 1, (I&(((int64u)1)<<Pos))?__T('1'):__T('0'));
1057             }
1058         }
1059         else
1060         {
1061             toStringStream Stream;
1062             Stream << setbase(Radix) << I;
1063             assign(Stream.str());
1064         }
1065     #endif
1066     MakeUpperCase();
1067     return *this;
1068 }
1069 
From_Number(const int128u I,int8u Radix)1070 Ztring& Ztring::From_Number (const int128u I, int8u Radix)
1071 {
1072     From_Local(I.toString(Radix));
1073 
1074     return *this;
1075 }
1076 
From_Number(const float32 F,int8u Precision,ztring_t Options)1077 Ztring& Ztring::From_Number (const float32 F, int8u Precision, ztring_t Options)
1078 {
1079     #if defined(STREAM_MISSING)
1080         Char C1[100];
1081         _tnprintf (C1, 99, (Ztring(__T("%."))+Ztring::ToZtring(Precision)+__T("f")).c_str(), F);
1082         assign(C1);
1083     #else
1084         toStringStream Stream;
1085         Stream << setprecision(Precision) << fixed << F;
1086         assign(Stream.str());
1087         #if defined(__BORLANDC__)
1088             FindAndReplace(__T(","), __T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
1089         #endif
1090     #endif
1091 
1092     if ((Options & Ztring_NoZero && size()>0) && find(__T('.'))!=string::npos)
1093     {
1094         while (size()>0 && ((*this)[size()-1]==__T('0')))
1095             resize(size()-1);
1096         if (size()>0 && (*this)[size()-1]==__T('.'))
1097             resize(size()-1);
1098     }
1099 
1100     return *this;
1101 }
1102 
From_Number(const float64 F,int8u Precision,ztring_t Options)1103 Ztring& Ztring::From_Number (const float64 F, int8u Precision, ztring_t Options)
1104 {
1105     #if defined(STREAM_MISSING)
1106         Char C1[100];
1107         _tnprintf (C1, 99, (Ztring(__T("%."))+Ztring::ToZtring(Precision)+__T("f")).c_str(), F);
1108         assign(C1);
1109     #else
1110         toStringStream Stream;
1111         Stream << setprecision(Precision) << fixed << F;
1112         assign(Stream.str());
1113         #if defined(__BORLANDC__)
1114             FindAndReplace(__T(","), __T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
1115         #endif
1116     #endif
1117 
1118     if ((Options & Ztring_NoZero && size()>0) && find(__T('.'))!=string::npos)
1119     {
1120         while (size()>0 && ((*this)[size()-1]==__T('0')))
1121             resize(size()-1);
1122         if (size()>0 && (*this)[size()-1]==__T('.'))
1123             resize(size()-1);
1124     }
1125 
1126     return *this;
1127 }
1128 
From_Number(const float80 F,int8u Precision,ztring_t Options)1129 Ztring& Ztring::From_Number (const float80 F, int8u Precision, ztring_t Options)
1130 {
1131     #if defined(STREAM_MISSING)
1132         Char C1[100];
1133         _tnprintf (C1, 99, (Ztring(__T("%."))+Ztring::ToZtring(Precision)+__T("f")).c_str(), F);
1134         assign(C1);
1135     #else
1136         toStringStream Stream;
1137         Stream << setprecision(Precision) << fixed << F;
1138         assign(Stream.str());
1139         #if defined(__BORLANDC__)
1140             FindAndReplace(__T(","), __T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
1141         #endif
1142     #endif
1143 
1144     if ((Options & Ztring_NoZero && size()>0) && find(__T('.'))!=string::npos)
1145     {
1146         while (size()>0 && ((*this)[size()-1]==__T('0')))
1147             resize(size()-1);
1148         if (size()>0 && (*this)[size()-1]==__T('.'))
1149             resize(size()-1);
1150     }
1151 
1152     return *this;
1153 }
1154 
1155 #ifdef SIZE_T_IS_LONG
From_Number(const size_t I,int8u Radix)1156 Ztring& Ztring::From_Number (const size_t I, int8u Radix)
1157 {
1158     #if defined(STREAM_MISSING)
1159         Char C1[100];
1160         _tnprintf(C1, 64, Radix==10?__T("%zu"):(Radix==16?__T("%zx"):(Radix==8?__T("%zo"):__T(""))), I);
1161         assign(C1);
1162     #else
1163         toStringStream Stream;
1164         Stream << setbase(Radix) << I;
1165         assign(Stream.str());
1166         #if defined(__BORLANDC__)
1167             FindAndReplace(__T(","), __T(".")); //Borland C++ Builder 2010+Windows Seven put a comma for istringstream, but does not support comma for ostringstream
1168         #endif
1169     #endif
1170     MakeUpperCase();
1171     return *this;
1172 }
1173 #endif //SIZE_T_IS_LONG
1174 
From_BCD(const int8u I)1175 Ztring& Ztring::From_BCD     (const int8u I)
1176 {
1177     #if defined(STREAM_MISSING)
1178         clear();
1179         append(1, __T('0')+I/0x10);
1180         append(1, __T('0')+I%0x10);
1181     #else
1182         toStringStream Stream;
1183         Stream << I/0x10;
1184         Stream << I%0x10;
1185         assign(Stream.str());
1186     #endif
1187     return *this;
1188 }
1189 
1190 //---------------------------------------------------------------------------
Duration_From_Milliseconds(const int64s Value_)1191 Ztring& Ztring::Duration_From_Milliseconds (const int64s Value_)
1192 {
1193     int64s Value=Value_;
1194     bool Negative=false;
1195     if (Value<0)
1196     {
1197         Value=-Value;
1198         Negative=true;
1199     }
1200 
1201     int64u HH=(int8u)(Value/1000/60/60);
1202     int64u MM=Value/1000/60   -((HH*60));
1203     int64u Stream=Value/1000      -((HH*60+MM)*60);
1204     int64u MS=Value           -((HH*60+MM)*60+Stream)*1000;
1205     Ztring DateT;
1206     Ztring Date;
1207     DateT.From_Number(HH); if (DateT.size()<2){DateT=Ztring(__T("0"))+DateT;}
1208     Date+=DateT;
1209     Date+=__T(":");
1210     DateT.From_Number(MM); if (DateT.size()<2){DateT=Ztring(__T("0"))+DateT;}
1211     Date+=DateT;
1212     Date+=__T(":");
1213     DateT.From_Number(Stream); if (DateT.size()<2){DateT=Ztring(__T("0"))+DateT;}
1214     Date+=DateT;
1215     Date+=__T(".");
1216     DateT.From_Number(MS); if (DateT.size()<2){DateT=Ztring(__T("00"))+DateT;} else if (DateT.size()<3){DateT=Ztring(__T("0"))+DateT;}
1217     Date+=DateT;
1218     if (Negative)
1219     {
1220         assign(__T("-"));
1221         append(Date);
1222     }
1223     else
1224         assign (Date.c_str());
1225     return *this;
1226 }
1227 
1228 //---------------------------------------------------------------------------
Duration_From_Milliseconds(const int64u Value)1229 Ztring& Ztring::Duration_From_Milliseconds (const int64u Value)
1230 {
1231     int64u HH=(int8u)(Value/1000/60/60);
1232     int64u MM=Value/1000/60   -((HH*60));
1233     int64u Stream=Value/1000      -((HH*60+MM)*60);
1234     int64u MS=Value           -((HH*60+MM)*60+Stream)*1000;
1235     Ztring DateT;
1236     Ztring Date;
1237     DateT.From_Number(HH); if (DateT.size()<2){DateT=Ztring(__T("0"))+DateT;}
1238     Date+=DateT;
1239     Date+=__T(":");
1240     DateT.From_Number(MM); if (DateT.size()<2){DateT=Ztring(__T("0"))+DateT;}
1241     Date+=DateT;
1242     Date+=__T(":");
1243     DateT.From_Number(Stream); if (DateT.size()<2){DateT=Ztring(__T("0"))+DateT;}
1244     Date+=DateT;
1245     Date+=__T(".");
1246     DateT.From_Number(MS); if (DateT.size()<2){DateT=Ztring(__T("00"))+DateT;} else if (DateT.size()<3){DateT=Ztring(__T("0"))+DateT;}
1247     Date+=DateT;
1248     assign (Date.c_str());
1249     return *this;
1250 }
1251 
Date_From_Milliseconds_1601(const int64u Value)1252 Ztring& Ztring::Date_From_Milliseconds_1601 (const int64u Value)
1253 {
1254     if (Value>=11644473600000LL) //Values <1970 are not supported
1255     {
1256         Date_From_Seconds_1970((int32u)((Value-11644473600000LL)/1000));
1257         append(__T("."));
1258         Ztring Milliseconds; Milliseconds.From_Number(Value%1000);
1259         while (Milliseconds.size()<3)
1260             Milliseconds+=__T('0');
1261         append(Milliseconds);
1262     }
1263     else
1264         clear(); //Not supported
1265 
1266     return *this;
1267 }
1268 
Date_From_Seconds_1601(const int64u Value)1269 Ztring& Ztring::Date_From_Seconds_1601 (const int64u Value)
1270 {
1271     return Date_From_Seconds_1970(((int64s)Value)-11644473600LL);
1272 }
1273 
Date_From_Seconds_1900(const int32u Value)1274 Ztring& Ztring::Date_From_Seconds_1900 (const int32u Value)
1275 {
1276     if (Value>2208988800)
1277         return Date_From_Seconds_1970(((int64s)Value)-2208988800);
1278     else
1279         return Date_From_Seconds_1970(((int64s)Value)+0x100000000LL-2208988800); //Value is considering to loop e.g. NTP value
1280 }
1281 
Date_From_Seconds_1900(const int64s Value)1282 Ztring& Ztring::Date_From_Seconds_1900 (const int64s Value)
1283 {
1284     return Date_From_Seconds_1970(Value-2208988800);
1285 }
1286 
Date_From_Seconds_1904(const int32u Value)1287 Ztring& Ztring::Date_From_Seconds_1904 (const int32u Value)
1288 {
1289     return Date_From_Seconds_1970(((int64s)Value)-2082844800);
1290 }
1291 
Date_From_Seconds_1904(const int64u Value)1292 Ztring& Ztring::Date_From_Seconds_1904 (const int64u Value)
1293 {
1294     return Date_From_Seconds_1970(((int64s)Value)-2082844800);
1295 }
1296 
Date_From_Seconds_1904(const int64s Value)1297 Ztring& Ztring::Date_From_Seconds_1904 (const int64s Value)
1298 {
1299     return Date_From_Seconds_1970(Value-2082844800);
1300 }
1301 
Date_From_Seconds_1970(const int32u Value)1302 Ztring& Ztring::Date_From_Seconds_1970 (const int32u Value)
1303 {
1304     return Date_From_Seconds_1970((int64s)Value);
1305 }
1306 
Date_From_Seconds_1970(const int32s Value)1307 Ztring& Ztring::Date_From_Seconds_1970 (const int32s Value)
1308 {
1309     return Date_From_Seconds_1970((int64s)Value);
1310 }
1311 
Date_From_Seconds_1970(const int64s Value)1312 Ztring& Ztring::Date_From_Seconds_1970 (const int64s Value)
1313 {
1314     time_t Time=(time_t)Value;
1315     #if defined(HAVE_GMTIME_R)
1316     struct tm Gmt_Temp;
1317     struct tm *Gmt=gmtime_r(&Time, &Gmt_Temp);
1318     #elif defined(_MSC_VER)
1319     struct tm Gmt_Temp;
1320     errno_t gmtime_s_Result=gmtime_s(&Gmt_Temp , &Time);
1321     struct tm* Gmt=gmtime_s_Result?NULL:&Gmt_Temp;
1322     #else
1323     #ifdef __GNUC__
1324     #warning "This version of ZenLib is not thread safe"
1325     #endif
1326     struct tm *Gmt=gmtime(&Time);
1327     #endif
1328     if (!Gmt)
1329     {
1330         clear();
1331         return *this;
1332     }
1333     Ztring DateT;
1334     Ztring Date=__T("UTC ");
1335     Date+=Ztring::ToZtring((Gmt->tm_year+1900));
1336     Date+=__T("-");
1337     DateT.From_Number(Gmt->tm_mon+1); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_mon+1);}
1338     Date+=DateT;
1339     Date+=__T("-");
1340     DateT.From_Number(Gmt->tm_mday); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_mday);}
1341     Date+=DateT;
1342     Date+=__T(" ");
1343     DateT.From_Number(Gmt->tm_hour); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_hour);}
1344     Date+=DateT;
1345     Date+=__T(":");
1346     DateT=Ztring::ToZtring(Gmt->tm_min); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_min);}
1347     Date+=DateT;
1348     Date+=__T(":");
1349     DateT.From_Number(Gmt->tm_sec); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_sec);}
1350     Date+=DateT;
1351     assign (Date.c_str());
1352     return *this;
1353 }
1354 
Date_From_Seconds_1970_Local(const int32u Value)1355 Ztring& Ztring::Date_From_Seconds_1970_Local (const int32u Value)
1356 {
1357     time_t Time=(time_t)Value;
1358     #if defined(HAVE_LOCALTIME_R)
1359     struct tm Gmt_Temp;
1360     struct tm *Gmt=localtime_r(&Time, &Gmt_Temp);
1361     #elif defined(_MSC_VER)
1362     struct tm Gmt_Temp;
1363     errno_t localtime_s_Result=localtime_s(&Gmt_Temp , &Time);
1364     struct tm* Gmt=localtime_s_Result?NULL:&Gmt_Temp;
1365     #else
1366     #ifdef __GNUC__
1367     #warning "This version of ZenLib is not thread safe"
1368     #endif
1369     struct tm *Gmt=localtime(&Time);
1370     #endif
1371     Ztring DateT;
1372     Ztring Date;
1373     if (Gmt)
1374     {
1375     Date+=Ztring::ToZtring((Gmt->tm_year+1900));
1376     Date+=__T("-");
1377     DateT.From_Number(Gmt->tm_mon+1); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_mon+1);}
1378     Date+=DateT;
1379     Date+=__T("-");
1380     DateT.From_Number(Gmt->tm_mday); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_mday);}
1381     Date+=DateT;
1382     Date+=__T(" ");
1383     DateT.From_Number(Gmt->tm_hour); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_hour);}
1384     Date+=DateT;
1385     Date+=__T(":");
1386     DateT=Ztring::ToZtring(Gmt->tm_min); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_min);}
1387     Date+=DateT;
1388     Date+=__T(":");
1389     DateT.From_Number(Gmt->tm_sec); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Gmt->tm_sec);}
1390     Date+=DateT;
1391     assign (Date.c_str());
1392     }
1393     return *this;
1394 }
1395 
Date_From_String(const char * Value,size_t Value_Size)1396 Ztring& Ztring::Date_From_String (const char* Value, size_t Value_Size)
1397 {
1398     //Only the year
1399     if (Value_Size<10)
1400     {
1401         From_UTF8(Value, 0, Value_Size);
1402         return *this;
1403     }
1404 
1405     #ifdef ZENLIB_USEWX
1406         Ztring ToReturn=__T("UTC ");
1407         wxDateTime Date;
1408         Ztring DateS;
1409         DateS.From_Local(Value, Value_Size).c_str();
1410         if (!DateS.empty() && DateS[DateS.size()-1]==__T('\n'))
1411             DateS.resize(DateS.size()-1);
1412 
1413         //Some strange formating : exactly 24 bytes (or 25 with 0x0A at the end) and Year is at the end
1414         if (DateS.size()==24 && DateS[23]>=__T('0') && DateS[23]<=__T('9') && DateS[21]>=__T('0') && DateS[21]<=__T('9') && DateS[19]==__T(' '))
1415             Date.ParseFormat(DateS.c_str(), __T("%a %b %d %H:%M:%S %Y"));
1416         //ISO date
1417         else if (DateS.size()==10 && (DateS[4]<__T('0') || DateS[4]>__T('9')) && (DateS[7]<__T('0') || DateS[7]>__T('9')))
1418         {
1419             DateS[4]=__T('-');
1420             DateS[7]=__T('-');
1421             ToReturn+=DateS;
1422         }
1423         //Default
1424         else
1425             Date.ParseDateTime(DateS.c_str());
1426 
1427         if (ToReturn.size()<5)
1428         {
1429             ToReturn+=Date.FormatISODate();
1430             ToReturn+=__T(" ");
1431             ToReturn+=Date.FormatISOTime();
1432         }
1433         else
1434             ToReturn+=DateS;
1435 
1436         assign (ToReturn.c_str());
1437     #else //ZENLIB_USEWX
1438         Ztring DateS; DateS.From_UTF8(Value, 0, Value_Size);
1439         //Unix style formating : exactly 24 bytes (or 25 with 0x0A at the end) and Year is at the end
1440         if ((DateS.size()==24 || (DateS.size()==25 && DateS[24]==__T('\n'))) && DateS[23]>=__T('0') && DateS[23]<=__T('9') && DateS[21]>=__T('0') && DateS[21]<=__T('9') && DateS[19]==__T(' '))
1441         {
1442             clear();
1443             append(1, DateS[20]);
1444             append(1, DateS[21]);
1445             append(1, DateS[22]);
1446             append(1, DateS[23]);
1447             append(1, __T('-'));
1448                  if (DateS[4]==__T('J') && DateS[5]==__T('a') && DateS[6]==__T('n') && DateS[7]==__T(' '))
1449             {
1450                 append(1, __T('0'));
1451                 append(1, __T('1'));
1452             }
1453             else if (DateS[4]==__T('F') && DateS[5]==__T('e') && DateS[6]==__T('b') && DateS[7]==__T(' '))
1454             {
1455                 append(1, __T('0'));
1456                 append(1, __T('2'));
1457             }
1458             else if (DateS[4]==__T('M') && DateS[5]==__T('a') && DateS[6]==__T('r') && DateS[7]==__T(' '))
1459             {
1460                 append(1, __T('0'));
1461                 append(1, __T('3'));
1462             }
1463             else if (DateS[4]==__T('A') && DateS[5]==__T('p') && DateS[6]==__T('r') && DateS[7]==__T(' '))
1464             {
1465                 append(1, __T('0'));
1466                 append(1, __T('4'));
1467             }
1468             else if (DateS[4]==__T('M') && DateS[5]==__T('a') && DateS[6]==__T('y') && DateS[7]==__T(' '))
1469             {
1470                 append(1, __T('0'));
1471                 append(1, __T('5'));
1472             }
1473             else if (DateS[4]==__T('J') && DateS[5]==__T('u') && DateS[6]==__T('n') && DateS[7]==__T(' '))
1474             {
1475                 append(1, __T('0'));
1476                 append(1, __T('6'));
1477             }
1478             else if (DateS[4]==__T('J') && DateS[5]==__T('u') && DateS[6]==__T('l') && DateS[7]==__T(' '))
1479             {
1480                 append(1, __T('0'));
1481                 append(1, __T('7'));
1482             }
1483             else if (DateS[4]==__T('A') && DateS[5]==__T('u') && DateS[6]==__T('g') && DateS[7]==__T(' '))
1484             {
1485                 append(1, __T('0'));
1486                 append(1, __T('8'));
1487             }
1488             else if (DateS[4]==__T('S') && DateS[5]==__T('e') && DateS[6]==__T('p') && DateS[7]==__T(' '))
1489             {
1490                 append(1, __T('0'));
1491                 append(1, __T('9'));
1492             }
1493             else if (DateS[4]==__T('O') && DateS[5]==__T('c') && DateS[6]==__T('t') && DateS[7]==__T(' '))
1494             {
1495                 append(1, __T('1'));
1496                 append(1, __T('0'));
1497             }
1498             else if (DateS[4]==__T('N') && DateS[5]==__T('o') && DateS[6]==__T('v') && DateS[7]==__T(' '))
1499             {
1500                 append(1, __T('1'));
1501                 append(1, __T('1'));
1502             }
1503             else if (DateS[4]==__T('D') && DateS[5]==__T('e') && DateS[6]==__T('c') && DateS[7]==__T(' '))
1504             {
1505                 append(1, __T('1'));
1506                 append(1, __T('2'));
1507             }
1508             else
1509             {
1510                 assign(DateS);
1511                 return *this;
1512             }
1513             append(1, __T('-'));
1514             append(1, DateS[8]);
1515             append(1, DateS[9]);
1516             append(1, __T(' '));
1517             append(1, DateS[11]);
1518             append(1, DateS[12]);
1519             append(1, __T(':'));
1520             append(1, DateS[14]);
1521             append(1, DateS[15]);
1522             append(1, __T(':'));
1523             append(1, DateS[17]);
1524             append(1, DateS[18]);
1525         }
1526         else if (DateS.size()==20 && DateS[4]==__T('-') && DateS[7]==__T('-') && DateS[10]==__T('T') && DateS[13]==__T(':') && DateS[16]==__T(':') && DateS[19]==__T('Z'))
1527         {
1528             DateS.resize(19);
1529             DateS[10]=__T(' ');
1530             assign(__T("UTC "));
1531             append(DateS);
1532         }
1533         else if (DateS.size()==23 && DateS[4]==__T('-') && DateS[7]==__T('-') && DateS[10]==__T(' ') && DateS[14]==__T(' ') && DateS[17]==__T(':') && DateS[20]==__T(':'))
1534         {
1535             DateS.erase(10, 4);
1536             //assign(__T("UTC ")); //Is not UTC
1537             append(DateS);
1538         }
1539         else
1540             From_UTF8(Value, 0, Value_Size); //Not implemented
1541     #endif //ZENLIB_USEWX
1542     return *this;
1543 }
1544 
Date_From_Numbers(const int8u Year,const int8u Month,const int8u Day,const int8u Hour,const int8u Minute,const int8u Second)1545 Ztring& Ztring::Date_From_Numbers (const int8u Year, const int8u Month, const int8u Day, const int8u Hour, const int8u Minute, const int8u Second)
1546 {
1547     Ztring DateT;
1548     Ztring Date=__T("UTC ");
1549     DateT.From_Number(Year); if (DateT.size()<2){DateT=Ztring(__T("200"))+Ztring::ToZtring(Year);}; if (DateT.size()<3){DateT=Ztring(__T("20"))+Ztring::ToZtring(Year);}
1550     Date+=DateT;
1551     Date+=__T("-");
1552     DateT.From_Number(Month); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Month);}
1553     Date+=DateT;
1554     Date+=__T("-");
1555     DateT.From_Number(Day); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Day);}
1556     Date+=DateT;
1557     Date+=__T(" ");
1558     DateT.From_Number(Hour); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Hour);}
1559     Date+=DateT;
1560     Date+=__T(":");
1561     DateT=Ztring::ToZtring(Minute); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Minute);}
1562     Date+=DateT;
1563     Date+=__T(":");
1564     DateT.From_Number(Second); if (DateT.size()<2){DateT=Ztring(__T("0"))+Ztring::ToZtring(Second);}
1565     Date+=DateT;
1566     assign (Date.c_str());
1567     return *this;
1568 }
1569 
1570 #ifndef WSTRING_MISSING
1571 //---------------------------------------------------------------------------
To_Unicode() const1572 std::wstring Ztring::To_Unicode () const
1573 {
1574     #ifdef _UNICODE
1575         return c_str();
1576     #else //_UNICODE
1577         #ifdef ZENLIB_USEWX
1578             return wxConvCurrent->cMB2WC(c_str()).data();
1579         #else //ZENLIB_USEWX
1580             return std::wstring(); //Not implemented
1581         #endif //ZENLIB_USEWX
1582     #endif //_UNICODE
1583 }
1584 #endif //WSTRING_MISSING
1585 
To_UTF8() const1586 std::string Ztring::To_UTF8 () const
1587 {
1588     #ifdef _UNICODE
1589         //Correction thanks to Andrew Jang
1590         // Don't use WideCharToMultiByte(), some characters are not well converted
1591         std::string ToReturn;
1592         ToReturn.reserve(size()); // more efficient
1593 
1594         const wchar_t* Z=c_str();
1595 
1596         while (*Z)
1597         {
1598             if (*Z < 0x80)
1599             {
1600                 ToReturn += (char)(*(Z++));
1601                 continue;
1602             }
1603 
1604             int32u wc; // must be unsigned.
1605 
1606             #if defined(_MSC_VER)
1607                 #pragma warning(push)
1608                 #pragma warning(disable:4127)
1609             #endif //defined(_MSC_VER)
1610             if (sizeof(wchar_t) == 2)
1611             #if defined(_MSC_VER)
1612                 #pragma warning(pop)
1613             #endif //defined(_MSC_VER)
1614             {
1615                 if (((*Z) & 0xFC00) == 0xD800)
1616                 {
1617                     //UTF-16
1618                     wc =( (((int16u) *Z) & 0x3FF) + 0x40) << 10;
1619                     Z++;
1620                     wc |= (((int16u) *Z) & 0x3FF);
1621                 }
1622                 else
1623                 wc = (int16u) *Z; // avoid a cast problem if wchar_t is signed.
1624             }
1625             else
1626                 wc = *Z;
1627 
1628             int count;
1629 
1630             // refer to http://en.wikipedia.org/wiki/UTF-8#Description
1631 
1632             if (wc < 0x80)
1633                 count = 1;
1634             else if (wc < 0x800)
1635                 count = 2;
1636             else if (wc < 0x10000)
1637                 count = 3;
1638             else if (wc < 0x200000)
1639                 count = 4;
1640             else if (wc < 0x4000000)
1641                 count = 5;
1642             else if (wc <= 0x7fffffff)
1643                 count = 6;
1644             else
1645                 break;  // bad character
1646 
1647             int64u utfbuf = 0; // 8 bytes
1648             char* utf8chars = (char*) &utfbuf;
1649 
1650             switch (count)
1651             {
1652             case 6:
1653                 utf8chars[5] = 0x80 | (wc & 0x3f);
1654                 wc = (wc >> 6) | 0x4000000;
1655                 /* fallthrough */
1656             case 5:
1657                 utf8chars[4] = 0x80 | (wc & 0x3f);
1658                 wc = (wc >> 6) | 0x200000;
1659                 /* fallthrough */
1660             case 4:
1661                 utf8chars[3] = 0x80 | (wc & 0x3f);
1662                 wc = (wc >> 6) | 0x10000;
1663                 /* fallthrough */
1664             case 3:
1665                 utf8chars[2] = 0x80 | (wc & 0x3f);
1666                 wc = (wc >> 6) | 0x800;
1667                 /* fallthrough */
1668             case 2:
1669                 utf8chars[1] = 0x80 | (wc & 0x3f);
1670                 wc = (wc >> 6) | 0xc0;
1671                 /* fallthrough */
1672             case 1:
1673                 utf8chars[0] = (char) wc;
1674             }
1675 
1676             ToReturn += utf8chars;
1677 
1678             ++Z;
1679         }
1680 
1681         return ToReturn;
1682     #else
1683         #ifdef ZENLIB_USEWX
1684             return wxConvUTF8.cWC2MB(wxConvCurrent->cMB2WC(c_str())).data();
1685         #else //ZENLIB_USEWX
1686             return c_str(); //Not implemented
1687         #endif //ZENLIB_USEWX
1688     #endif
1689 }
1690 
To_Local() const1691 std::string Ztring::To_Local () const
1692 {
1693     #ifdef _UNICODE
1694         #ifdef ZENLIB_USEWX
1695             wxCharBuffer C=wxConvCurrent->cWC2MB(c_str());
1696             if (C.data())
1697                 return C.data();
1698             else
1699                 return std::string();
1700         #else //ZENLIB_USEWX
1701             #ifdef WINDOWS
1702                 int Size=WideCharToMultiByte(CP_ACP, 0, c_str(), -1, NULL, 0, NULL, NULL);
1703                 if (Size!=0)
1704                 {
1705                     char* AnsiString=new char[Size+1];
1706                     WideCharToMultiByte(CP_ACP, 0, c_str(), -1, AnsiString, Size, NULL, NULL);
1707                     AnsiString[Size]='\0';
1708                     std::string ToReturn(AnsiString);
1709                     delete[] AnsiString; //AnsiString=NULL;
1710                     return ToReturn;
1711                 }
1712                 else
1713                     return std::string();
1714             #else //WINDOWS
1715                 if (empty())
1716                     return std::string();
1717 
1718                 size_t Size=wcstombs(NULL, c_str(), 0);
1719                 if (Size!=0 && Size!=(size_t)-1)
1720                 {
1721                     char* AnsiString=new char[Size+1];
1722                     Size=wcstombs(AnsiString, c_str(), Size);
1723                     if (Size!=0 && Size!=(size_t)-1)
1724                     {
1725                         AnsiString[Size]='\0';
1726                         std::string ToReturn(AnsiString);
1727                         delete[] AnsiString; //AnsiString=NULL;
1728                         return ToReturn;
1729                     }
1730 
1731                     //Failed
1732                     delete[] AnsiString; //AnsiString=NULL;
1733                 }
1734 
1735                 //Trying with bad chars
1736                 char* Result=new char[MB_CUR_MAX];
1737                 std::string AnsiString;
1738                 for (size_t Pos=0; Pos<size(); Pos++)
1739                 {
1740                     size_t Result_Size=wcrtomb(Result, operator[](Pos), 0);
1741                     if (Result_Size && Result_Size!=(size_t)-1)
1742                         AnsiString.append(Result, Result_Size);
1743                     else
1744                         AnsiString+='?';
1745                 }
1746                 delete[] Result; //Result=NULL;
1747                 return AnsiString;
1748             #endif
1749         #endif //ZENLIB_USEWX
1750     #else
1751         return c_str();
1752     #endif
1753 }
1754 
1755 //---------------------------------------------------------------------------
To_UUID() const1756 int128u Ztring::To_UUID () const
1757 {
1758     if (size()!=36)
1759         return 0;
1760 
1761     Ztring Temp=*this;
1762 
1763     for (size_t Pos=0; Pos<36; Pos++)
1764     {
1765         if ((Temp[Pos]< __T('0') || Temp[Pos]> __T('9'))
1766          && (Temp[Pos]< __T('A') || Temp[Pos]> __T('F'))
1767          && (Temp[Pos]< __T('a') || Temp[Pos]> __T('f')))
1768             return 0;
1769         if (Temp[Pos]>=__T('A') && Temp[Pos]<=__T('F'))
1770         {
1771             Temp[Pos]-=__T('A');
1772             Temp[Pos]+=__T('9')+1;
1773         }
1774         if (Temp[Pos]>=__T('a') && Temp[Pos]<=__T('f'))
1775         {
1776             Temp[Pos]-=__T('a');
1777             Temp[Pos]+=__T('9')+1;
1778         }
1779 
1780         switch(Pos)
1781         {
1782             case  7 :
1783             case 12 :
1784             case 17 :
1785             case 22 :
1786                         if (at(Pos+1)!=__T('-'))
1787                             return 0;
1788                         Pos++; //Skipping dash in the test
1789         }
1790     }
1791 
1792     int128u I;
1793     I.hi=((int64u)((int8u)(Temp[ 0]-'0'))<<60)
1794        | ((int64u)((int8u)(Temp[ 1]-'0'))<<56)
1795        | ((int64u)((int8u)(Temp[ 2]-'0'))<<52)
1796        | ((int64u)((int8u)(Temp[ 3]-'0'))<<48)
1797        | ((int64u)((int8u)(Temp[ 4]-'0'))<<44)
1798        | ((int64u)((int8u)(Temp[ 5]-'0'))<<40)
1799        | ((int64u)((int8u)(Temp[ 6]-'0'))<<36)
1800        | ((int64u)((int8u)(Temp[ 7]-'0'))<<32)
1801        | ((int64u)((int8u)(Temp[ 9]-'0'))<<28)
1802        | ((int64u)((int8u)(Temp[10]-'0'))<<24)
1803        | ((int64u)((int8u)(Temp[11]-'0'))<<20)
1804        | ((int64u)((int8u)(Temp[12]-'0'))<<16)
1805        | ((int64u)((int8u)(Temp[14]-'0'))<<12)
1806        | ((int64u)((int8u)(Temp[15]-'0'))<< 8)
1807        | ((int64u)((int8u)(Temp[16]-'0'))<< 4)
1808        | ((int64u)((int8u)(Temp[17]-'0'))    );
1809     I.lo=((int64u)((int8u)(Temp[19]-'0'))<<60)
1810        | ((int64u)((int8u)(Temp[20]-'0'))<<56)
1811        | ((int64u)((int8u)(Temp[21]-'0'))<<52)
1812        | ((int64u)((int8u)(Temp[22]-'0'))<<48)
1813        | ((int64u)((int8u)(Temp[24]-'0'))<<44)
1814        | ((int64u)((int8u)(Temp[25]-'0'))<<40)
1815        | ((int64u)((int8u)(Temp[26]-'0'))<<36)
1816        | ((int64u)((int8u)(Temp[27]-'0'))<<32)
1817        | ((int64u)((int8u)(Temp[28]-'0'))<<28)
1818        | ((int64u)((int8u)(Temp[29]-'0'))<<24)
1819        | ((int64u)((int8u)(Temp[30]-'0'))<<20)
1820        | ((int64u)((int8u)(Temp[31]-'0'))<<16)
1821        | ((int64u)((int8u)(Temp[32]-'0'))<<12)
1822        | ((int64u)((int8u)(Temp[33]-'0'))<< 8)
1823        | ((int64u)((int8u)(Temp[34]-'0'))<< 4)
1824        | ((int64u)((int8u)(Temp[35]-'0'))    );
1825 
1826     return I;
1827 }
1828 
1829 //---------------------------------------------------------------------------
To_CC4() const1830 int32u Ztring::To_CC4 () const
1831 {
1832     int32u I;
1833     I =((int32u)((int8u)at(0))<<24)
1834      | ((int32u)((int8u)at(1))<<16)
1835      | ((int32u)((int8u)at(2))<< 8)
1836      | ((int32u)((int8u)at(3))    );
1837 
1838     return I;
1839 }
1840 
1841 //---------------------------------------------------------------------------
1842 //Operateur ToInt
To_int8s(int8u Radix,ztring_t Options) const1843 int8s Ztring::To_int8s (int8u Radix, ztring_t Options) const
1844 {
1845     //Integrity
1846     if (empty())
1847         return 0;
1848 
1849     //Conversion
1850     int I;
1851     #if defined(STREAM_MISSING)
1852         #ifdef __MINGW32__
1853             I=_ttoi(c_str());
1854         #elif defined(UNICODE)
1855             std::string S=To_UTF8();
1856             I=atoi(S.c_str());
1857         #else //UNICODE
1858             I=atoi(c_str());
1859         #endif //UNICODE
1860     #else
1861         tStringStream Stream(*this);
1862         Stream >> setbase(Radix) >> I;
1863         if (Stream.fail())
1864             return 0;
1865     #endif
1866 
1867     //Rounded
1868     if (Options==Ztring_Rounded && find(__T('.'))!=Error)
1869     {
1870         float80 F=To_float80();
1871         F-=I;
1872         if (F>=0.5f)
1873             return (int8s)I+1;
1874     }
1875 
1876     return (int8s)I;
1877 }
1878 
1879 //---------------------------------------------------------------------------
1880 //Operateur ToInt
To_int8u(int8u Radix,ztring_t Options) const1881 int8u Ztring::To_int8u (int8u Radix, ztring_t Options) const
1882 {
1883     //Integrity
1884     if (empty())
1885         return 0;
1886 
1887     //Conversion
1888     unsigned int I;
1889     #if defined(STREAM_MISSING)
1890         #ifdef __MINGW32__
1891             I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFF - Replaced by i64 version to support, but not good
1892         #elif defined(UNICODE)
1893             std::string S=To_UTF8();
1894             I=atoi(S.c_str());
1895         #else //defined(UNICODE)
1896             I=atoi(c_str());
1897         #endif //defined(UNICODE)
1898     #else
1899         tStringStream Stream(*this);
1900         Stream >> setbase(Radix) >> I;
1901         if (Stream.fail())
1902             return 0;
1903     #endif
1904 
1905     //Rounded
1906     if (Options==Ztring_Rounded && find(__T('.'))!=std::string::npos)
1907     {
1908         float32 F=To_float32();
1909         F-=I;
1910         if (F>=0.5f)
1911             return (int8u)I+1;
1912     }
1913 
1914     return (int8u)I;
1915 }
1916 
1917 //---------------------------------------------------------------------------
1918 //Operateur ToInt
To_int16s(int8u Radix,ztring_t Options) const1919 int16s Ztring::To_int16s (int8u Radix, ztring_t Options) const
1920 {
1921     //Integrity
1922     if (empty())
1923         return 0;
1924 
1925     //Conversion
1926     int I;
1927     #if defined(STREAM_MISSING)
1928         #ifdef __MINGW32__
1929             I=_ttoi(c_str());
1930         #elif defined(UNICODE)
1931             std::string S=To_UTF8();
1932             I=atoi(S.c_str());
1933         #else //defined(UNICODE)
1934             I=atoi(c_str());
1935         #endif //defined(UNICODE)
1936     #else
1937         tStringStream Stream(*this);
1938         Stream >> setbase(Radix) >> I;
1939         if (Stream.fail())
1940             return 0;
1941     #endif
1942 
1943     //Rounded
1944     if (Options==Ztring_Rounded && find(__T('.'))!=Error)
1945     {
1946         float80 F=To_float80();
1947         F-=I;
1948         if (F>=0.5f)
1949             return (int16s)I+1;
1950     }
1951 
1952     return (int16s)I;
1953 }
1954 
1955 //---------------------------------------------------------------------------
1956 //Operateur ToInt
To_int16u(int8u Radix,ztring_t Options) const1957 int16u Ztring::To_int16u (int8u Radix, ztring_t Options) const
1958 {
1959     //Integrity
1960     if (empty())
1961         return 0;
1962 
1963     //Conversion
1964     unsigned int I;
1965     #if defined(STREAM_MISSING)
1966         #ifdef __MINGW32__
1967             I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFF - Replaced by i64 version to support, but not good
1968         #elif defined(UNICODE)
1969             std::string S=To_UTF8();
1970             I=atoi(S.c_str());
1971         #else //defined(UNICODE)
1972             I=atoi(c_str());
1973         #endif //defined(UNICODE)
1974     #else
1975         tStringStream Stream(*this);
1976         Stream >> setbase(Radix) >> I;
1977         if (Stream.fail())
1978             return 0;
1979     #endif
1980 
1981     //Rounded
1982     if (Options==Ztring_Rounded && find(__T('.'))!=std::string::npos)
1983     {
1984         float32 F=To_float32();
1985         F-=I;
1986         if (F>=0.5f)
1987             return (int16u)I+1;
1988     }
1989 
1990     return (int16u)I;
1991 }
1992 
1993 //---------------------------------------------------------------------------
1994 //Operateur ToInt
To_int32s(int8u Radix,ztring_t Options) const1995 int32s Ztring::To_int32s (int8u Radix, ztring_t Options) const
1996 {
1997     //Integrity
1998     if (empty())
1999         return 0;
2000 
2001     //Conversion
2002     int32s I;
2003     #if defined(STREAM_MISSING)
2004         #ifdef __MINGW32__
2005             I=_ttoi(c_str());
2006         #elif defined(UNICODE)
2007             std::string S=To_UTF8();
2008             I=atol(S.c_str());
2009         #else //defined(UNICODE)
2010             I=atol(c_str());
2011         #endif //defined(UNICODE)
2012     #else
2013         tStringStream Stream(*this);
2014         Stream >> setbase(Radix) >> I;
2015         if (Stream.fail())
2016             return 0;
2017     #endif
2018 
2019     //Rounded
2020     if (Options==Ztring_Rounded && find(__T('.'))!=Error)
2021     {
2022         float80 F=To_float80();
2023         F-=I;
2024         if (F>=0.5f)
2025             return I+1;
2026     }
2027 
2028     return I;
2029 }
2030 
2031 //---------------------------------------------------------------------------
2032 //Operateur ToInt
To_int32u(int8u Radix,ztring_t Options) const2033 int32u Ztring::To_int32u (int8u Radix, ztring_t Options) const
2034 {
2035     //Integrity
2036     if (empty())
2037         return 0;
2038 
2039     //Conversion
2040     int32u I;
2041     #if defined(STREAM_MISSING)
2042         #ifdef __MINGW32__
2043             I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFF - Replaced by i64 version to support, but not good
2044         #elif defined(UNICODE)
2045             std::string S=To_UTF8();
2046             I=atol(S.c_str());
2047         #else //defined(UNICODE)
2048             I=atol(c_str());
2049         #endif //defined(UNICODE)
2050     #else
2051         tStringStream Stream(*this);
2052         Stream >> setbase(Radix) >> I;
2053         if (Stream.fail())
2054             return 0;
2055     #endif
2056 
2057     //Rounded
2058     if (Options==Ztring_Rounded && find(__T('.'))!=std::string::npos)
2059     {
2060         float32 F=To_float32();
2061         F-=I;
2062         if (F>=0.5f)
2063             return I+1;
2064     }
2065 
2066     return I;
2067 }
2068 
2069 //---------------------------------------------------------------------------
2070 //Operateur ToInt
To_int64s(int8u Radix,ztring_t Options) const2071 int64s Ztring::To_int64s (int8u Radix, ztring_t Options) const
2072 {
2073     //Integrity
2074     if (empty())
2075         return 0;
2076 
2077     //Conversion
2078     int64s I;
2079     #if defined(STREAM_MISSING)
2080         #ifdef __MINGW32__
2081             I=_ttoi64(c_str());
2082         #elif defined(UNICODE)
2083             std::string S=To_UTF8();
2084             I=atoll(S.c_str());
2085         #else //defined(UNICODE)
2086             I=atoll(c_str());
2087         #endif //defined(UNICODE)
2088     #else
2089         tStringStream Stream(*this);
2090         Stream >> setbase(Radix) >> I;
2091         if (Stream.fail())
2092             return 0;
2093     #endif
2094 
2095     //Rounded
2096     if (Options==Ztring_Rounded && find(__T('.'))!=std::string::npos)
2097     {
2098         float32 F=To_float32();
2099         F-=I;
2100         if (F>0.5f)
2101             return I+1;
2102     }
2103 
2104     return I;
2105 }
2106 
2107 //---------------------------------------------------------------------------
2108 //Operateur ToInt
To_int64u(int8u Radix,ztring_t Options) const2109 int64u Ztring::To_int64u (int8u Radix, ztring_t Options) const
2110 {
2111     //Integrity
2112     if (empty())
2113         return 0;
2114 
2115     //Conversion
2116     int64u I;
2117     #if defined(STREAM_MISSING)
2118         #ifdef __MINGW32__
2119             I=_ttoi64(c_str()); //TODO : I>0x7FFFFFFFFFFFFFFF
2120         #elif defined(UNICODE)
2121             std::string S=To_UTF8();
2122             I=atoll(S.c_str());
2123         #else //defined(UNICODE)
2124             I=atoll(c_str());
2125         #endif //defined(UNICODE)
2126     #else
2127         tStringStream Stream(*this);
2128         Stream >> setbase(Radix) >> I;
2129         if (Stream.fail())
2130             return 0;
2131     #endif
2132 
2133     //Rounded
2134     if (Options==Ztring_Rounded && find(__T('.'))!=std::string::npos)
2135     {
2136         float32 F=To_float32();
2137         F-=I;
2138         if (F>=0.5f)
2139             return I+1;
2140     }
2141 
2142     return I;
2143 }
2144 
2145 //---------------------------------------------------------------------------
To_int128u(int8u,ztring_t) const2146 int128u Ztring::To_int128u (int8u, ztring_t) const
2147 {
2148     if (size()!=32)
2149         return 0;
2150 
2151     Ztring Temp=*this;
2152 
2153     for (size_t Pos=0; Pos<32; Pos++)
2154     {
2155         if ((Temp[Pos]< __T('0') || Temp[Pos]> __T('9'))
2156          && (Temp[Pos]< __T('A') || Temp[Pos]> __T('F'))
2157          && (Temp[Pos]< __T('a') || Temp[Pos]> __T('f')))
2158             return 0;
2159         if (Temp[Pos]>=__T('A') && Temp[Pos]<=__T('F'))
2160         {
2161             Temp[Pos]-=__T('A');
2162             Temp[Pos]+=__T('9')+1;
2163         }
2164         if (Temp[Pos]>=__T('a') && Temp[Pos]<=__T('f'))
2165         {
2166             Temp[Pos]-=__T('a');
2167             Temp[Pos]+=__T('9')+1;
2168         }
2169     }
2170 
2171     int128u I;
2172     I.hi=((int64u)((int8u)(Temp[ 0]-'0'))<<60)
2173        | ((int64u)((int8u)(Temp[ 1]-'0'))<<56)
2174        | ((int64u)((int8u)(Temp[ 2]-'0'))<<52)
2175        | ((int64u)((int8u)(Temp[ 3]-'0'))<<48)
2176        | ((int64u)((int8u)(Temp[ 4]-'0'))<<44)
2177        | ((int64u)((int8u)(Temp[ 5]-'0'))<<40)
2178        | ((int64u)((int8u)(Temp[ 6]-'0'))<<36)
2179        | ((int64u)((int8u)(Temp[ 7]-'0'))<<32)
2180        | ((int64u)((int8u)(Temp[ 8]-'0'))<<28)
2181        | ((int64u)((int8u)(Temp[ 9]-'0'))<<24)
2182        | ((int64u)((int8u)(Temp[10]-'0'))<<20)
2183        | ((int64u)((int8u)(Temp[11]-'0'))<<16)
2184        | ((int64u)((int8u)(Temp[12]-'0'))<<12)
2185        | ((int64u)((int8u)(Temp[13]-'0'))<< 8)
2186        | ((int64u)((int8u)(Temp[14]-'0'))<< 4)
2187        | ((int64u)((int8u)(Temp[15]-'0'))    );
2188     I.lo=((int64u)((int8u)(Temp[16]-'0'))<<60)
2189        | ((int64u)((int8u)(Temp[17]-'0'))<<56)
2190        | ((int64u)((int8u)(Temp[18]-'0'))<<52)
2191        | ((int64u)((int8u)(Temp[19]-'0'))<<48)
2192        | ((int64u)((int8u)(Temp[20]-'0'))<<44)
2193        | ((int64u)((int8u)(Temp[21]-'0'))<<40)
2194        | ((int64u)((int8u)(Temp[22]-'0'))<<36)
2195        | ((int64u)((int8u)(Temp[23]-'0'))<<32)
2196        | ((int64u)((int8u)(Temp[24]-'0'))<<28)
2197        | ((int64u)((int8u)(Temp[25]-'0'))<<24)
2198        | ((int64u)((int8u)(Temp[26]-'0'))<<20)
2199        | ((int64u)((int8u)(Temp[27]-'0'))<<16)
2200        | ((int64u)((int8u)(Temp[28]-'0'))<<12)
2201        | ((int64u)((int8u)(Temp[29]-'0'))<< 8)
2202        | ((int64u)((int8u)(Temp[30]-'0'))<< 4)
2203        | ((int64u)((int8u)(Temp[31]-'0'))    );
2204 
2205     return I;
2206 }
2207 
2208 //---------------------------------------------------------------------------
2209 //Operateur ToFloat
To_float32(ztring_t) const2210 float32 Ztring::To_float32(ztring_t) const
2211 {
2212     //Integrity
2213     if (empty())
2214         return 0;
2215 
2216     //Conversion
2217     #if defined(STREAM_MISSING)
2218         #ifdef UNICODE
2219             return (wcstod(c_str(),NULL));
2220         #else
2221             return (strtod(c_str(),NULL));
2222         #endif
2223     #else
2224         float32 F;
2225         tStringStream Stream(*this);
2226         Stream >> F;
2227         if (Stream.fail())
2228             return 0;
2229 
2230         return F;
2231     #endif
2232 }
2233 
2234 //---------------------------------------------------------------------------
2235 //Operateur ToFloat
To_float64(ztring_t) const2236 float64 Ztring::To_float64(ztring_t) const
2237 {
2238     //Integrity
2239     if (empty())
2240         return 0;
2241 
2242     //Conversion
2243     #if defined(STREAM_MISSING)
2244         #ifdef UNICODE
2245             return (wcstod(c_str(),NULL)); //TODO verify no wcstold
2246         #else
2247             return (strtod(c_str(),NULL)); //TODO verify no strtold
2248         #endif
2249     #else
2250         float64 F;
2251         tStringStream Stream(*this);
2252         Stream >> F;
2253         if (Stream.fail())
2254             return 0;
2255 
2256         return F;
2257     #endif
2258 }
2259 
2260 //---------------------------------------------------------------------------
2261 //Operateur ToFloat
To_float80(ztring_t) const2262 float80 Ztring::To_float80(ztring_t) const
2263 {
2264     //Integrity
2265     if (empty())
2266         return 0;
2267 
2268     //Conversion
2269     #if defined(STREAM_MISSING)
2270         #ifdef UNICODE
2271             return (wcstod(c_str(),NULL)); //TODO verify no wcstold
2272         #else
2273             return (strtod(c_str(),NULL)); //TODO verify no strtold
2274         #endif
2275     #else
2276         float80 F;
2277         tStringStream Stream(*this);
2278         Stream >> F;
2279         if (Stream.fail())
2280             return 0;
2281 
2282         return F;
2283     #endif
2284 }
2285 
2286 //***************************************************************************
2287 // Edition
2288 //***************************************************************************
2289 
2290 //---------------------------------------------------------------------------
2291 // Retourne une partie de la chaine
SubString(const tstring & Begin,const tstring & End,size_type Pos,ztring_t Options) const2292 Ztring Ztring::SubString (const tstring &Begin, const tstring &End, size_type Pos, ztring_t Options) const
2293 {
2294     //Recherche Debut
2295     size_type I_Debut=find(Begin, Pos);
2296     if (I_Debut==Error)
2297         return Ztring();
2298     I_Debut+=Begin.size();
2299 
2300     //gestion fin NULL
2301     if (End.empty())
2302         return substr(I_Debut);
2303 
2304     //Recherche Fin
2305     size_type I_Fin=find(End, I_Debut);
2306     if (I_Fin==Error)
2307     {
2308         if (Options & Ztring_AddLastItem)
2309             return substr(I_Debut);
2310         else
2311             return Ztring();
2312     }
2313 
2314     return substr(I_Debut, I_Fin-I_Debut);
2315 }
2316 
2317 //---------------------------------------------------------------------------
2318 //FindAndReplace
FindAndReplace(const ZenLib::tstring & ToFind,const ZenLib::tstring & ReplaceBy,size_type Pos,ZenLib::ztring_t Options)2319 Ztring::size_type Ztring::FindAndReplace (const ZenLib::tstring &ToFind, const ZenLib::tstring &ReplaceBy, size_type Pos, ZenLib::ztring_t Options)
2320 {
2321     if (ToFind.empty())
2322         return 0;
2323 
2324     size_type Count=0;
2325     size_type Middle=Pos;
2326     while (!(Count==1 && !(Options&Ztring_Recursive)) && (Middle=find(ToFind, Middle))!=npos)
2327     {
2328         replace(Middle, ToFind.length(), ReplaceBy);
2329         Middle += ReplaceBy.length();
2330         Count++;
2331     }
2332 
2333     return Count;
2334 }
2335 
2336 //---------------------------------------------------------------------------
2337 //test if it is a number
IsNumber() const2338 bool Ztring::IsNumber() const
2339 {
2340     if (empty())
2341         return false;
2342 
2343     bool OK=true;
2344     size_t Size=size();
2345     for (size_t Pos=0; Pos<Size; Pos++)
2346         if (operator[](Pos)<__T('0') || operator[](Pos)>__T('9'))
2347         {
2348             OK=false;
2349             break;
2350         }
2351     return OK;
2352 }
2353 
2354 //---------------------------------------------------------------------------
2355 //Mise en minuscules
MakeLowerCase()2356 Ztring &Ztring::MakeLowerCase()
2357 {
2358     transform(begin(), end(), begin(), (int(*)(int))tolower); //(int(*)(int)) is a patch for unix
2359     return *this;
2360 }
2361 
2362 //---------------------------------------------------------------------------
2363 // Mise en majuscules
MakeUpperCase()2364 Ztring &Ztring::MakeUpperCase()
2365 {
2366     transform(begin(), end(), begin(), (int(*)(int))toupper); //(int(*)(int)) is a patch for unix
2367     return *this;
2368 }
2369 
2370 //---------------------------------------------------------------------------
2371 // Remove leading whitespaces from a string
TrimLeft(Char ToTrim)2372 Ztring &Ztring::TrimLeft(Char ToTrim)
2373 {
2374     size_type First=0;
2375     while (First<size() && operator[](First)==ToTrim)
2376         First++;
2377     assign (c_str()+First);
2378     return *this;
2379 }
2380 
2381 //---------------------------------------------------------------------------
2382 // Remove trailing whitespaces from a string
TrimRight(Char ToTrim)2383 Ztring &Ztring::TrimRight(Char ToTrim)
2384 {
2385     if (size()==0)
2386         return *this;
2387 
2388     size_type Last=size()-1;
2389     while (Last!=(size_type)-1 && operator[](Last)==ToTrim)
2390         Last--;
2391     assign (c_str(), Last+1);
2392     return *this;
2393 }
2394 
2395 //---------------------------------------------------------------------------
2396 // Remove leading and trailing whitespaces from a string
Trim(Char ToTrim)2397 Ztring &Ztring::Trim(Char ToTrim)
2398 {
2399     TrimLeft(ToTrim);
2400     TrimRight(ToTrim);
2401     return *this;
2402 }
2403 
2404 //---------------------------------------------------------------------------
2405 // Quotes a string
Quote(Char ToTrim)2406 Ztring &Ztring::Quote(Char ToTrim)
2407 {
2408     assign(tstring(1, ToTrim)+c_str()+ToTrim);
2409     return *this;
2410 }
2411 
2412 //***************************************************************************
2413 // Information
2414 //***************************************************************************
2415 
2416 //---------------------------------------------------------------------------
2417 //Count
Count(const Ztring & ToCount,ztring_t) const2418 Ztring::size_type Ztring::Count (const Ztring &ToCount, ztring_t) const
2419 {
2420     size_type Count=0;
2421     for (size_type Pos=0; Pos<=size(); Pos++)
2422         if (find(ToCount, Pos)!=npos)
2423         {
2424             Count++;
2425             Pos+=ToCount.size()-1; //-1 because the loop will add 1
2426         }
2427     return Count;
2428 }
2429 
2430 //---------------------------------------------------------------------------
2431 //Compare
Compare(const Ztring & ToCompare,const Ztring & Comparator,ztring_t Options) const2432 bool Ztring::Compare (const Ztring &ToCompare, const Ztring &Comparator, ztring_t Options) const
2433 {
2434     //Integers management
2435     if (IsNumber() && ToCompare.IsNumber())
2436     {
2437         int64s Left=To_int64s();
2438         int64s Right=ToCompare.To_int64s();
2439         if (Comparator==__T("==")) return (Left==Right);
2440         if (Comparator==__T("<"))  return (Left< Right);
2441         if (Comparator==__T("<=")) return (Left<=Right);
2442         if (Comparator==__T(">=")) return (Left>=Right);
2443         if (Comparator==__T(">"))  return (Left> Right);
2444         if (Comparator==__T("!=")) return (Left!=Right);
2445         if (Comparator==__T("<>")) return (Left!=Right);
2446         return false;
2447     }
2448 
2449     //Case sensitive option
2450     if (!(Options & Ztring_CaseSensitive))
2451     {
2452         //Need to copy strings and make it lowercase
2453         Ztring Left (c_str());
2454         Ztring Right (ToCompare.c_str());
2455         Left.MakeLowerCase();
2456         Right.MakeLowerCase();
2457 
2458         //string comparasion
2459         if (Comparator==__T("==")) return (Left==Right);
2460         if (Comparator==__T("IN")) {if (Left.find(Right)!=string::npos) return true; else return false;}
2461         if (Comparator==__T("<"))  return (Left< Right);
2462         if (Comparator==__T("<=")) return (Left<=Right);
2463         if (Comparator==__T(">=")) return (Left>=Right);
2464         if (Comparator==__T(">"))  return (Left> Right);
2465         if (Comparator==__T("!=")) return (Left!=Right);
2466         if (Comparator==__T("<>")) return (Left!=Right);
2467         return false;
2468     }
2469     else
2470     {
2471         //string comparasion
2472         if (Comparator==__T("==")) return (*this==ToCompare);
2473         if (Comparator==__T("IN")) {if (this->find(ToCompare)!=string::npos) return true; else return false;}
2474         if (Comparator==__T("<"))  return (*this< ToCompare);
2475         if (Comparator==__T("<=")) return (*this<=ToCompare);
2476         if (Comparator==__T(">=")) return (*this>=ToCompare);
2477         if (Comparator==__T(">"))  return (*this> ToCompare);
2478         if (Comparator==__T("!=")) return (*this!=ToCompare);
2479         if (Comparator==__T("<>")) return (*this!=ToCompare);
2480         return false;
2481     }
2482 }
2483 
2484 } //namespace
2485