1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Application Programming Interface //
9 // //
10 // Library: SAGA_API //
11 // //
12 //-------------------------------------------------------//
13 // //
14 // api_string.cpp //
15 // //
16 // Copyright (C) 2005 by Olaf Conrad //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. //
22 // //
23 // This library is free software; you can redistribute //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free //
26 // Software Foundation, either version 2.1 of the //
27 // License, or (at your option) any later version. //
28 // //
29 // This library is distributed in the hope that it will //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details. //
34 // //
35 // You should have received a copy of the GNU Lesser //
36 // General Public License along with this program; if //
37 // not, see <http://www.gnu.org/licenses/>. //
38 // //
39 //-------------------------------------------------------//
40 // //
41 // contact: Olaf Conrad //
42 // Institute of Geography //
43 // University of Goettingen //
44 // Goldschmidtstr. 5 //
45 // 37077 Goettingen //
46 // Germany //
47 // //
48 // e-mail: oconrad@saga-gis.org //
49 // //
50 ///////////////////////////////////////////////////////////
51
52 //---------------------------------------------------------
53 #include <math.h>
54
55 #include <wx/string.h>
56 #include <wx/datetime.h>
57 #include <wx/tokenzr.h>
58 #include <wx/wxcrt.h>
59 #include <wx/wxcrtvararg.h>
60 #include <wx/convauto.h>
61
62 #include "api_core.h"
63 #include "mat_tools.h"
64
65
66 ///////////////////////////////////////////////////////////
67 // //
68 // //
69 // //
70 ///////////////////////////////////////////////////////////
71
72 //---------------------------------------------------------
CSG_String(void)73 CSG_String::CSG_String(void)
74 {
75 m_pString = new wxString;
76 }
77
CSG_String(const CSG_String & String)78 CSG_String::CSG_String(const CSG_String &String)
79 {
80 m_pString = new wxString(*String.m_pString);
81 }
82
CSG_String(const char * String)83 CSG_String::CSG_String(const char *String)
84 {
85 m_pString = new wxString(String);
86 }
87
CSG_String(const wchar_t * String)88 CSG_String::CSG_String(const wchar_t *String)
89 {
90 m_pString = new wxString(String);
91 }
92
CSG_String(char Character,size_t nRepeat)93 CSG_String::CSG_String(char Character, size_t nRepeat)
94 {
95 m_pString = new wxString(Character, nRepeat);
96 }
97
CSG_String(wchar_t Character,size_t nRepeat)98 CSG_String::CSG_String(wchar_t Character, size_t nRepeat)
99 {
100 m_pString = new wxString(Character, nRepeat);
101 }
102
103 //---------------------------------------------------------
CSG_String(const class wxString * pString)104 CSG_String::CSG_String(const class wxString *pString)
105 {
106 if( pString )
107 m_pString = new wxString(*pString);
108 else
109 m_pString = new wxString;
110 }
111
Create(const class wxString * pString)112 bool CSG_String::Create(const class wxString *pString)
113 {
114 if( pString )
115 *m_pString = *pString;
116 else
117 m_pString->Clear();
118
119 return( true );
120 }
121
122 //---------------------------------------------------------
~CSG_String(void)123 CSG_String::~CSG_String(void)
124 {
125 delete(m_pString);
126 }
127
128
129 ///////////////////////////////////////////////////////////
130 // //
131 ///////////////////////////////////////////////////////////
132
133 //---------------------------------------------------------
operator =(const CSG_String & String)134 CSG_String & CSG_String::operator = (const CSG_String &String)
135 {
136 *m_pString = *String.m_pString;
137
138 return( *this );
139 }
140
operator =(const char * String)141 CSG_String & CSG_String::operator = (const char *String)
142 {
143 *m_pString = String;
144
145 return( *this );
146 }
147
operator =(const wchar_t * String)148 CSG_String & CSG_String::operator = (const wchar_t *String)
149 {
150 *m_pString = String;
151
152 return( *this );
153 }
154
operator =(char Character)155 CSG_String & CSG_String::operator = (char Character)
156 {
157 *m_pString = Character;
158
159 return( *this );
160 }
161
operator =(wchar_t Character)162 CSG_String & CSG_String::operator = (wchar_t Character)
163 {
164 *m_pString = Character;
165
166 return( *this );
167 }
168
169
170 ///////////////////////////////////////////////////////////
171 // //
172 ///////////////////////////////////////////////////////////
173
174 //---------------------------------------------------------
Length(void) const175 size_t CSG_String::Length(void) const
176 {
177 return( m_pString->Length() );
178 }
179
180 //---------------------------------------------------------
is_Empty(void) const181 bool CSG_String::is_Empty(void) const
182 {
183 return( m_pString->IsEmpty() );
184 }
185
186
187 ///////////////////////////////////////////////////////////
188 // //
189 ///////////////////////////////////////////////////////////
190
191 //---------------------------------------------------------
operator [](int i) const192 SG_Char CSG_String::operator [] (int i) const
193 {
194 if( i >= 0 && i < (int)Length() )
195 {
196 return( m_pString->GetChar(i) );
197 }
198
199 return( SG_T('\0') );
200 }
201
operator [](size_t i) const202 SG_Char CSG_String::operator [] (size_t i) const
203 {
204 if( i < Length() )
205 {
206 return( m_pString->GetChar(i) );
207 }
208
209 return( SG_T('\0') );
210 }
211
Get_Char(size_t i) const212 SG_Char CSG_String::Get_Char(size_t i) const
213 {
214 if( i < Length() )
215 {
216 return( m_pString->GetChar(i) );
217 }
218
219 return( SG_T('\0') );
220 }
221
222 //---------------------------------------------------------
Set_Char(size_t i,char Character)223 void CSG_String::Set_Char(size_t i, char Character)
224 {
225 m_pString->SetChar(i, Character);
226 }
227
Set_Char(size_t i,wchar_t Character)228 void CSG_String::Set_Char(size_t i, wchar_t Character)
229 {
230 m_pString->SetChar(i, Character);
231 }
232
233
234 ///////////////////////////////////////////////////////////
235 // //
236 ///////////////////////////////////////////////////////////
237
238 //---------------------------------------------------------
c_str(void) const239 const SG_Char * CSG_String::c_str(void) const
240 {
241 return( m_pString->c_str() );
242 }
243
244 //---------------------------------------------------------
b_str(void) const245 const char * CSG_String::b_str(void) const
246 {
247 return( *m_pString );
248 }
249
250 //---------------------------------------------------------
w_str(void) const251 const wchar_t * CSG_String::w_str(void) const
252 {
253 return( m_pString->wc_str() );
254 }
255
256
257 ///////////////////////////////////////////////////////////
258 // //
259 ///////////////////////////////////////////////////////////
260
261 //---------------------------------------------------------
Clear(void)262 void CSG_String::Clear(void)
263 {
264 m_pString->Clear();
265 }
266
267
268 ///////////////////////////////////////////////////////////
269 // //
270 ///////////////////////////////////////////////////////////
271
272 //---------------------------------------------------------
Format(const char * Format,...)273 CSG_String CSG_String::Format(const char *Format, ...)
274 {
275 CSG_String s;
276
277 #ifdef _SAGA_LINUX
278 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
279 va_list argptr; va_start(argptr, _Format);
280 s.m_pString->PrintfV(_Format, argptr);
281 #else
282 va_list argptr; va_start(argptr, Format);
283 s.m_pString->PrintfV(Format, argptr);
284 #endif
285
286 va_end(argptr);
287
288 return( s );
289 }
290
291 //---------------------------------------------------------
Format(const wchar_t * Format,...)292 CSG_String CSG_String::Format(const wchar_t *Format, ...)
293 {
294 CSG_String s;
295
296 #ifdef _SAGA_LINUX
297 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
298 va_list argptr; va_start(argptr, _Format);
299 s.m_pString->PrintfV(_Format, argptr);
300 #else
301 va_list argptr; va_start(argptr, Format);
302 s.m_pString->PrintfV(Format, argptr);
303 #endif
304
305 va_end(argptr);
306
307 return( s );
308 }
309
310 //---------------------------------------------------------
Printf(const char * Format,...)311 int CSG_String::Printf(const char *Format, ...)
312 {
313 #ifdef _SAGA_LINUX
314 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
315 va_list argptr; va_start(argptr, _Format);
316 int Result = m_pString->PrintfV(_Format, argptr);
317 #else
318 va_list argptr; va_start(argptr, Format);
319 int Result = m_pString->PrintfV(Format, argptr);
320 #endif
321
322 va_end(argptr);
323
324 return( Result );
325 }
326
327 //---------------------------------------------------------
Printf(const wchar_t * Format,...)328 int CSG_String::Printf(const wchar_t *Format, ...)
329 {
330 #ifdef _SAGA_LINUX
331 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
332 va_list argptr; va_start(argptr, _Format);
333 int Result = m_pString->PrintfV(_Format, argptr);
334 #else
335 va_list argptr; va_start(argptr, Format);
336 int Result = m_pString->PrintfV(Format, argptr);
337 #endif
338
339 va_end(argptr);
340
341 return( Result );
342 }
343
344
345 ///////////////////////////////////////////////////////////
346 // //
347 ///////////////////////////////////////////////////////////
348
349 //---------------------------------------------------------
Prepend(const CSG_String & String)350 CSG_String & CSG_String::Prepend(const CSG_String &String)
351 {
352 m_pString->Prepend(*String.m_pString);
353
354 return( *this );
355 }
356
357 //---------------------------------------------------------
Append(const CSG_String & String)358 CSG_String & CSG_String::Append(const CSG_String &String)
359 {
360 m_pString->Append(*String.m_pString);
361
362 return( *this );
363 }
364
365 //---------------------------------------------------------
Append(const char * String)366 CSG_String & CSG_String::Append(const char *String)
367 {
368 m_pString->Append(String);
369
370 return( *this );
371 }
372
373 //---------------------------------------------------------
Append(const wchar_t * String)374 CSG_String & CSG_String::Append(const wchar_t *String)
375 {
376 m_pString->Append(String);
377
378 return( *this );
379 }
380
381 //---------------------------------------------------------
Append(char Character,size_t nRepeat)382 CSG_String & CSG_String::Append(char Character, size_t nRepeat)
383 {
384 m_pString->Append(Character, nRepeat);
385
386 return( *this );
387 }
388
389 //---------------------------------------------------------
Append(wchar_t Character,size_t nRepeat)390 CSG_String & CSG_String::Append(wchar_t Character, size_t nRepeat)
391 {
392 m_pString->Append(Character, nRepeat);
393
394 return( *this );
395 }
396
397 //---------------------------------------------------------
operator +=(const CSG_String & String)398 void CSG_String::operator += (const CSG_String &String)
399 {
400 *m_pString += *String.m_pString;
401 }
402
operator +=(const char * String)403 void CSG_String::operator += (const char *String)
404 {
405 *m_pString += String;
406 }
407
operator +=(const wchar_t * String)408 void CSG_String::operator += (const wchar_t *String)
409 {
410 *m_pString += String;
411 }
412
operator +=(char Character)413 void CSG_String::operator += (char Character)
414 {
415 *m_pString += Character;
416 }
417
operator +=(wchar_t Character)418 void CSG_String::operator += (wchar_t Character)
419 {
420 *m_pString += Character;
421 }
422
423
424 ///////////////////////////////////////////////////////////
425 // //
426 ///////////////////////////////////////////////////////////
427
428 //---------------------------------------------------------
operator +(const CSG_String & String) const429 CSG_String CSG_String::operator + (const CSG_String &String) const
430 {
431 CSG_String s(*this);
432
433 s += String;
434
435 return( s );
436 }
437
operator +(const char * String) const438 CSG_String CSG_String::operator + (const char *String) const
439 {
440 CSG_String s(*this);
441
442 s += String;
443
444 return( s );
445 }
446
operator +(const wchar_t * String) const447 CSG_String CSG_String::operator + (const wchar_t *String) const
448 {
449 CSG_String s(*this);
450
451 s += String;
452
453 return( s );
454 }
455
456 //---------------------------------------------------------
operator +(char Character) const457 CSG_String CSG_String::operator + (char Character) const
458 {
459 CSG_String s(*this);
460
461 s += Character;
462
463 return( s );
464 }
465
operator +(wchar_t Character) const466 CSG_String CSG_String::operator + (wchar_t Character) const
467 {
468 CSG_String s(*this);
469
470 s += Character;
471
472 return( s );
473 }
474
475 //---------------------------------------------------------
operator +(const char * A,const CSG_String & B)476 CSG_String operator + (const char *A, const CSG_String &B)
477 {
478 CSG_String s(A);
479
480 s += B;
481
482 return( s );
483 }
484
operator +(const wchar_t * A,const CSG_String & B)485 CSG_String operator + (const wchar_t *A, const CSG_String &B)
486 {
487 CSG_String s(A);
488
489 s += B;
490
491 return( s );
492 }
493
operator +(char A,const CSG_String & B)494 CSG_String operator + (char A, const CSG_String &B)
495 {
496 CSG_String s(A);
497
498 s += B;
499
500 return( s );
501 }
502
operator +(wchar_t A,const CSG_String & B)503 CSG_String operator + (wchar_t A, const CSG_String &B)
504 {
505 CSG_String s(A);
506
507 s += B;
508
509 return( s );
510 }
511
512
513 ///////////////////////////////////////////////////////////
514 // //
515 ///////////////////////////////////////////////////////////
516
517 //---------------------------------------------------------
Cmp(const CSG_String & String) const518 int CSG_String::Cmp(const CSG_String &String) const
519 {
520 return( m_pString->Cmp(String.c_str()) );
521 }
522
523 //---------------------------------------------------------
CmpNoCase(const CSG_String & String) const524 int CSG_String::CmpNoCase(const CSG_String &String) const
525 {
526 return( m_pString->CmpNoCase(String.c_str()) );
527 }
528
529 //---------------------------------------------------------
is_Same_As(const CSG_String & String,bool bCase) const530 bool CSG_String::is_Same_As(const CSG_String &String, bool bCase) const
531 {
532 return( m_pString->IsSameAs(*String.m_pString, bCase) );
533 }
534
is_Same_As(char Character,bool bCase) const535 bool CSG_String::is_Same_As(char Character, bool bCase) const
536 {
537 return( m_pString->IsSameAs(Character, bCase) );
538 }
539
is_Same_As(wchar_t Character,bool bCase) const540 bool CSG_String::is_Same_As(wchar_t Character, bool bCase) const
541 {
542 return( m_pString->IsSameAs(Character, bCase) );
543 }
544
545 //---------------------------------------------------------
Make_Lower(void)546 CSG_String & CSG_String::Make_Lower(void)
547 {
548 m_pString->MakeLower();
549
550 return( *this );
551 }
552
553 //---------------------------------------------------------
Make_Upper(void)554 CSG_String & CSG_String::Make_Upper(void)
555 {
556 m_pString->MakeUpper();
557
558 return( *this );
559 }
560
561 ///////////////////////////////////////////////////////////
562 // //
563 ///////////////////////////////////////////////////////////
564
565 //---------------------------------------------------------
Replace(const CSG_String & sOld,const CSG_String & sNew,bool bReplaceAll)566 size_t CSG_String::Replace(const CSG_String &sOld, const CSG_String &sNew, bool bReplaceAll)
567 {
568 return( m_pString->Replace(*sOld.m_pString, *sNew.m_pString, bReplaceAll) );
569 }
570
571 //---------------------------------------------------------
Remove(size_t pos)572 CSG_String & CSG_String::Remove(size_t pos)
573 {
574 m_pString->Remove(pos);
575
576 return( *this );
577 }
578
579 //---------------------------------------------------------
Remove(size_t pos,size_t len)580 CSG_String & CSG_String::Remove(size_t pos, size_t len)
581 {
582 m_pString->Remove(pos, len);
583
584 return( *this );
585 }
586
587
588 ///////////////////////////////////////////////////////////
589 // //
590 ///////////////////////////////////////////////////////////
591
592 //---------------------------------------------------------
Trim(bool fromRight)593 int CSG_String::Trim(bool fromRight)
594 {
595 size_t n = m_pString->Length();
596
597 m_pString->Trim(fromRight);
598
599 return( (int)(n - m_pString->Length()) );
600 }
601
602 //---------------------------------------------------------
Trim_Both(void)603 int CSG_String::Trim_Both(void)
604 {
605 size_t n = m_pString->Length();
606
607 m_pString->Trim( true);
608 m_pString->Trim(false);
609
610 return( (int)(n - m_pString->Length()) );
611 }
612
613
614 ///////////////////////////////////////////////////////////
615 // //
616 ///////////////////////////////////////////////////////////
617
618 //---------------------------------------------------------
Find(char Character,bool fromEnd) const619 int CSG_String::Find(char Character, bool fromEnd) const
620 {
621 return( m_pString->Find(Character, fromEnd) );
622 }
623
Find(wchar_t Character,bool fromEnd) const624 int CSG_String::Find(wchar_t Character, bool fromEnd) const
625 {
626 return( m_pString->Find(Character, fromEnd) );
627 }
628
629 //---------------------------------------------------------
Find(const CSG_String & String) const630 int CSG_String::Find(const CSG_String &String) const
631 {
632 return( m_pString->Find(*String.m_pString) );
633 }
634
635 //---------------------------------------------------------
Contains(const CSG_String & String) const636 bool CSG_String::Contains(const CSG_String &String) const
637 {
638 return( m_pString->Contains(*String.m_pString) );
639 }
640
641
642 ///////////////////////////////////////////////////////////
643 // //
644 ///////////////////////////////////////////////////////////
645
646 //---------------------------------------------------------
AfterFirst(char Character) const647 CSG_String CSG_String::AfterFirst(char Character) const
648 {
649 return( CSG_String(m_pString->AfterFirst(Character).c_str().AsWChar()) );
650 }
651
AfterFirst(wchar_t Character) const652 CSG_String CSG_String::AfterFirst(wchar_t Character) const
653 {
654 return( CSG_String(m_pString->AfterFirst(Character).c_str().AsWChar()) );
655 }
656
657 //---------------------------------------------------------
AfterLast(char Character) const658 CSG_String CSG_String::AfterLast(char Character) const
659 {
660 return( CSG_String(m_pString->AfterLast(Character).c_str().AsWChar()) );
661 }
662
AfterLast(wchar_t Character) const663 CSG_String CSG_String::AfterLast(wchar_t Character) const
664 {
665 return( CSG_String(m_pString->AfterLast(Character).c_str().AsWChar()) );
666 }
667
668 //---------------------------------------------------------
BeforeFirst(char Character) const669 CSG_String CSG_String::BeforeFirst(char Character) const
670 {
671 return( CSG_String(m_pString->BeforeFirst(Character).c_str().AsWChar()) );
672 }
673
BeforeFirst(wchar_t Character) const674 CSG_String CSG_String::BeforeFirst(wchar_t Character) const
675 {
676 return( CSG_String(m_pString->BeforeFirst(Character).c_str().AsWChar()) );
677 }
678
679 //---------------------------------------------------------
BeforeLast(char Character) const680 CSG_String CSG_String::BeforeLast(char Character) const
681 {
682 return( CSG_String(m_pString->BeforeLast(Character).c_str().AsWChar()) );
683 }
684
BeforeLast(wchar_t Character) const685 CSG_String CSG_String::BeforeLast(wchar_t Character) const
686 {
687 return( CSG_String(m_pString->BeforeLast(Character).c_str().AsWChar()) );
688 }
689
690
691 ///////////////////////////////////////////////////////////
692 // //
693 ///////////////////////////////////////////////////////////
694
695 //---------------------------------------------------------
Right(size_t count) const696 CSG_String CSG_String::Right(size_t count) const
697 {
698 return( CSG_String(m_pString->Right(count).c_str().AsWChar()) );
699 }
700
701 //---------------------------------------------------------
Mid(size_t first,size_t count) const702 CSG_String CSG_String::Mid(size_t first, size_t count) const
703 {
704 return( CSG_String(m_pString->Mid(first, count <= 0 ? Length() : count).c_str().AsWChar()) );
705 }
706
707 //---------------------------------------------------------
Left(size_t count) const708 CSG_String CSG_String::Left(size_t count) const
709 {
710 return( CSG_String(m_pString->Left(count).c_str().AsWChar()) );
711 }
712
713
714 ///////////////////////////////////////////////////////////
715 // //
716 ///////////////////////////////////////////////////////////
717
718 //---------------------------------------------------------
is_Number(void) const719 bool CSG_String::is_Number(void) const
720 {
721 return( m_pString->IsNumber() );
722 }
723
724 //---------------------------------------------------------
asInt(void) const725 int CSG_String::asInt(void) const
726 {
727 int Value = 0;
728
729 asInt(Value);
730
731 return( Value );
732 }
733
asInt(int & Value) const734 bool CSG_String::asInt(int &Value) const
735 {
736 const wxChar *start = m_pString->c_str();
737 wxChar *end;
738
739 Value = wxStrtol(start, &end, 10);
740
741 return( end > start );
742 }
743
744 //---------------------------------------------------------
asDouble(void) const745 double CSG_String::asDouble(void) const
746 {
747 double Value = 0.0;
748
749 asDouble(Value);
750
751 return( Value );
752 }
753
asDouble(double & Value) const754 bool CSG_String::asDouble(double &Value) const
755 {
756 const wxChar *start = m_pString->c_str();
757 wxChar *end;
758
759 Value = wxStrtod(start, &end);
760
761 return( end > start );
762 }
763
764
765 ///////////////////////////////////////////////////////////
766 // //
767 ///////////////////////////////////////////////////////////
768
769 //---------------------------------------------------------
from_UTF8(const char * String,size_t Length)770 CSG_String CSG_String::from_UTF8(const char *String, size_t Length)
771 {
772 CSG_String s;
773
774 if( String )
775 {
776 if( !Length )
777 {
778 Length = strlen(String);
779 }
780
781 *s.m_pString = wxString::FromUTF8(String, Length);
782 }
783
784 return( s );
785 }
786
787 //---------------------------------------------------------
788 /**
789 * This function creates a single char array and fills it
790 * with the UTF-8 representation of this string object.
791 * If successful pString will point to the address of the
792 * allocated memory. Freeing memory is in response of the
793 * calling function.
794 */
795 //---------------------------------------------------------
to_UTF8(char ** pString) const796 size_t CSG_String::to_UTF8(char **pString) const
797 {
798 if( !is_Empty() )
799 {
800 const wxScopedCharBuffer Buffer = m_pString->utf8_str();
801
802 if( (*pString = (char *)SG_Malloc(Buffer.length())) != NULL )
803 {
804 memcpy(*pString, Buffer.data(), Buffer.length());
805
806 return( Buffer.length() );
807 }
808 }
809
810 *pString = NULL;
811
812 return( 0 );
813 }
814
815 //---------------------------------------------------------
to_UTF8(void) const816 CSG_Buffer CSG_String::to_UTF8(void) const
817 {
818 CSG_Buffer String;
819
820 if( !is_Empty() )
821 {
822 const wxScopedCharBuffer Buffer = m_pString->utf8_str();
823
824 String.Set_Data(Buffer.data(), Buffer.length() + 1);
825 }
826
827 return( String );
828 }
829
830
831 ///////////////////////////////////////////////////////////
832 // //
833 ///////////////////////////////////////////////////////////
834
835 //---------------------------------------------------------
836 /**
837 * This function creates a single char array and fills it
838 * with the multibyte representation of this string object.
839 * If successful pString will point to the address of the
840 * allocated memory. Freeing memory is in response of the
841 * calling function.
842 */
843 //---------------------------------------------------------
to_MBChar(char ** pString,int Encoding) const844 size_t CSG_String::to_MBChar(char **pString, int Encoding) const
845 {
846 CSG_Buffer String(to_MBChar(Encoding));
847
848 if( String.Get_Size() && (*pString = (char *)SG_Malloc(String.Get_Size())) != NULL )
849 {
850 memcpy(*pString, String.Get_Data(), String.Get_Size());
851
852 return( String.Get_Size() );
853 }
854
855 *pString = NULL;
856
857 return( 0 );
858 }
859
860 //---------------------------------------------------------
to_MBChar(int Encoding) const861 CSG_Buffer CSG_String::to_MBChar(int Encoding) const
862 {
863 CSG_Buffer String;
864
865 if( !is_Empty() )
866 {
867 wxScopedCharBuffer Buffer;
868
869 switch( Encoding ) // selecting the appropriate wxMBConv class
870 {
871 case SG_FILE_ENCODING_ANSI : Buffer = m_pString->mb_str(wxConvLibc ); break;
872 case SG_FILE_ENCODING_UTF7 : Buffer = m_pString->mb_str(wxConvUTF7 ); break;
873 case SG_FILE_ENCODING_UTF8 : Buffer = m_pString->mb_str(wxConvUTF8 ); break;
874 case SG_FILE_ENCODING_UTF16LE: Buffer = m_pString->mb_str(wxMBConvUTF16LE()); break;
875 case SG_FILE_ENCODING_UTF16BE: Buffer = m_pString->mb_str(wxMBConvUTF16BE()); break;
876 case SG_FILE_ENCODING_UTF32LE: Buffer = m_pString->mb_str(wxMBConvUTF32LE()); break;
877 case SG_FILE_ENCODING_UTF32BE: Buffer = m_pString->mb_str(wxMBConvUTF32BE()); break;
878 default : Buffer = m_pString->mb_str(wxConvAuto ()); break;
879 }
880
881 String.Set_Data(Buffer.data(), Buffer.length());
882 }
883
884 return( String );
885 }
886
887
888 ///////////////////////////////////////////////////////////
889 // //
890 ///////////////////////////////////////////////////////////
891
892 //---------------------------------------------------------
893 /**
894 * This function creates a single char array and fills it
895 * with the ASCII representation of this string object.
896 * If successful pString will point to the address of the
897 * allocated memory. Freeing memory is in response of the
898 * calling function.
899 */
900 //---------------------------------------------------------
to_ASCII(char ** pString,char Replace) const901 bool CSG_String::to_ASCII(char **pString, char Replace) const
902 {
903 if( !is_Empty() )
904 {
905 #if wxCHECK_VERSION(3, 1, 0)
906 const wxScopedCharBuffer Buffer = m_pString->ToAscii(Replace);
907 #else
908 const wxScopedCharBuffer Buffer = m_pString->ToAscii();
909 #endif
910
911 if( (*pString = (char *)SG_Malloc(Buffer.length())) != NULL )
912 {
913 memcpy(*pString, Buffer.data(), Buffer.length());
914
915 return( true );
916 }
917 }
918
919 return( false );
920 }
921
922 //---------------------------------------------------------
to_ASCII(char Replace) const923 CSG_Buffer CSG_String::to_ASCII(char Replace) const
924 {
925 CSG_Buffer String;
926
927 if( !is_Empty() )
928 {
929 #if wxCHECK_VERSION(3, 1, 0)
930 const wxScopedCharBuffer Buffer = m_pString->ToAscii(Replace);
931 #else
932 const wxScopedCharBuffer Buffer = m_pString->ToAscii();
933 #endif
934
935 String.Set_Data(Buffer.data(), Buffer.length());
936 }
937
938 return( String );
939 }
940
941 ///////////////////////////////////////////////////////////
942 // //
943 ///////////////////////////////////////////////////////////
944
945 //---------------------------------------------------------
946 /**
947 * This function returns the string as an std::string in the
948 * current locale encoding. Note that if the conversion of
949 * the string contents to the current locale fails, the
950 * return string will be empty.
951 */
952 //---------------------------------------------------------
to_StdString(void) const953 std::string CSG_String::to_StdString(void) const
954 {
955 return( m_pString->ToStdString() );
956 }
957
958 //---------------------------------------------------------
959 /**
960 * This function returns the string as an std::wstring.
961 */
962 //---------------------------------------------------------
to_StdWstring(void) const963 std::wstring CSG_String::to_StdWstring(void) const
964 {
965 return( m_pString->ToStdWstring() );
966 }
967
968
969 ///////////////////////////////////////////////////////////
970 // //
971 // //
972 // //
973 ///////////////////////////////////////////////////////////
974
975 //---------------------------------------------------------
CSG_Strings(void)976 CSG_Strings::CSG_Strings(void)
977 {}
978
979 //---------------------------------------------------------
CSG_Strings(const CSG_Strings & Strings)980 CSG_Strings::CSG_Strings(const CSG_Strings &Strings)
981 {
982 Create(Strings);
983 }
984
Create(const CSG_Strings & Strings)985 bool CSG_Strings::Create(const CSG_Strings &Strings)
986 {
987 Destroy();
988
989 return( Add(Strings) );
990 }
991
992 //---------------------------------------------------------
CSG_Strings(int nStrings,const SG_Char ** Strings)993 CSG_Strings::CSG_Strings(int nStrings, const SG_Char **Strings)
994 {
995 for(int i=0; i<nStrings; i++)
996 {
997 Add(Strings[i]);
998 }
999 }
1000
1001 //---------------------------------------------------------
~CSG_Strings(void)1002 CSG_Strings::~CSG_Strings(void)
1003 {
1004 Clear();
1005 }
1006
1007 //---------------------------------------------------------
Destroy(void)1008 bool CSG_Strings::Destroy(void)
1009 {
1010 for(size_t i=0; i<Get_Size(); i++)
1011 {
1012 delete((CSG_String *)m_Strings[i]);
1013 }
1014
1015 m_Strings.Destroy();
1016
1017 return( true );
1018 }
1019
1020 //---------------------------------------------------------
Add(const CSG_Strings & Strings)1021 bool CSG_Strings::Add(const CSG_Strings &Strings)
1022 {
1023 for(size_t i=0; i<Strings.Get_Size(); i++)
1024 {
1025 Add(Strings[i]);
1026 }
1027
1028 return( true );
1029 }
1030
1031 //---------------------------------------------------------
Add(const CSG_String & String)1032 bool CSG_Strings::Add(const CSG_String &String)
1033 {
1034 size_t i = Get_Size();
1035
1036 if( m_Strings.Inc_Array() )
1037 {
1038 m_Strings[i] = new CSG_String(String);
1039
1040 return( true );
1041 }
1042
1043 return( false );
1044 }
1045
1046 //---------------------------------------------------------
Ins(const CSG_String & String,size_t Index)1047 bool CSG_Strings::Ins(const CSG_String &String, size_t Index)
1048 {
1049 if( Index >= Get_Size() )
1050 {
1051 return( Add(String) );
1052 }
1053
1054 if( m_Strings.Inc_Array() )
1055 {
1056 for(size_t i=Get_Size()-1; i>Index; i--)
1057 {
1058 m_Strings[i] = m_Strings[i - 1];
1059 }
1060
1061 m_Strings[Index] = new CSG_String(String);
1062
1063 return( true );
1064 }
1065
1066 return( false );
1067 }
1068
1069 //---------------------------------------------------------
Del(size_t Index)1070 bool CSG_Strings::Del(size_t Index)
1071 {
1072 if( Index >= Get_Size() )
1073 {
1074 return( false );
1075 }
1076
1077 delete((CSG_String *)m_Strings[Index]);
1078
1079 for(size_t i=Index+1; i<Get_Size(); i++)
1080 {
1081 m_Strings[i - 1] = m_Strings[i];
1082 }
1083
1084 m_Strings.Dec_Array();
1085
1086 return( true );
1087 }
1088
1089 //---------------------------------------------------------
Set_Count(size_t Count)1090 bool CSG_Strings::Set_Count(size_t Count)
1091 {
1092 while( Del(Count) ) {}
1093
1094 for(size_t i=Get_Size(); i<Count; i++)
1095 {
1096 Add("");
1097 }
1098
1099 return( true );
1100 }
1101
1102 //---------------------------------------------------------
1103 class CSG_Index_Compare_Strings : public CSG_Index::CSG_Index_Compare
1104 {
1105 public:
1106 CSG_String **m_Values; bool m_Ascending;
1107
CSG_Index_Compare_Strings(CSG_String ** Values,bool Ascending)1108 CSG_Index_Compare_Strings(CSG_String **Values, bool Ascending) : m_Values(Values), m_Ascending(Ascending) {}
1109
Compare(const int _a,const int _b)1110 virtual int Compare (const int _a, const int _b)
1111 {
1112 int a = m_Ascending ? _a : _b;
1113 int b = m_Ascending ? _b : _a;
1114
1115 return( m_Values[a]->Cmp(*m_Values[b]) );
1116 }
1117 };
1118
1119 //---------------------------------------------------------
Sort(bool Ascending)1120 bool CSG_Strings::Sort(bool Ascending)
1121 {
1122 if( Get_Size() < 2 )
1123 {
1124 return( true );
1125 }
1126
1127 CSG_Index_Compare_Strings Compare((CSG_String **)m_Strings.Get_Array(), Ascending);
1128
1129 CSG_Index Index(Get_Count(), Compare);
1130
1131 CSG_Array_Pointer Strings(m_Strings);
1132
1133 for(size_t i=0; i<Get_Size(); i++)
1134 {
1135 m_Strings[i] = Strings[Index[i]];
1136 }
1137
1138 return( true );
1139 }
1140
1141
1142 ///////////////////////////////////////////////////////////
1143 // //
1144 // //
1145 // //
1146 ///////////////////////////////////////////////////////////
1147
1148 //---------------------------------------------------------
SG_is_Character_Numeric(int Character)1149 bool SG_is_Character_Numeric(int Character)
1150 {
1151 switch( Character )
1152 {
1153 case '0':
1154 case '1':
1155 case '2':
1156 case '3':
1157 case '4':
1158 case '5':
1159 case '6':
1160 case '7':
1161 case '8':
1162 case '9':
1163 case '-':
1164 case '+':
1165 case '.':
1166 case ',':
1167 case 'e':
1168 case 'E':
1169 return( true );
1170 }
1171
1172 return( false );
1173 }
1174
1175
1176 ///////////////////////////////////////////////////////////
1177 // //
1178 // //
1179 // //
1180 ///////////////////////////////////////////////////////////
1181
1182 //---------------------------------------------------------
SG_Printf(const CSG_String & Format)1183 int SG_Printf(const CSG_String &Format)
1184 {
1185 return( SG_Printf(Format.c_str()) );
1186 }
1187
SG_Printf(const char * Format,...)1188 int SG_Printf(const char *Format, ...)
1189 {
1190 #ifdef _SAGA_LINUX
1191 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
1192 va_list argptr; va_start(argptr, _Format); int ret = wxVprintf(_Format, argptr); va_end(argptr); return( ret );
1193 #else
1194 va_list argptr; va_start(argptr, Format); int ret = wxVprintf( Format, argptr); va_end(argptr); return( ret );
1195 #endif
1196 }
1197
SG_Printf(const wchar_t * Format,...)1198 int SG_Printf(const wchar_t *Format, ...)
1199 {
1200 #ifdef _SAGA_LINUX
1201 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
1202 va_list argptr; va_start(argptr, _Format); int ret = wxVprintf(_Format, argptr); va_end(argptr); return( ret );
1203 #else
1204 va_list argptr; va_start(argptr, Format); int ret = wxVprintf( Format, argptr); va_end(argptr); return( ret );
1205 #endif
1206 }
1207
1208 //---------------------------------------------------------
SG_FPrintf(FILE * Stream,const CSG_String & String)1209 int SG_FPrintf(FILE *Stream, const CSG_String &String)
1210 {
1211 return( SG_FPrintf(Stream, String.c_str()) );
1212 }
1213
SG_FPrintf(FILE * Stream,const char * Format,...)1214 int SG_FPrintf(FILE *Stream, const char *Format, ...)
1215 {
1216 #ifdef _SAGA_LINUX
1217 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
1218 va_list argptr; va_start(argptr, _Format); int ret = wxVfprintf(Stream, _Format, argptr); va_end(argptr); return( ret );
1219 #else
1220 va_list argptr; va_start(argptr, Format); int ret = wxVfprintf(Stream, Format, argptr); va_end(argptr); return( ret );
1221 #endif
1222 }
1223
SG_FPrintf(FILE * Stream,const wchar_t * Format,...)1224 int SG_FPrintf(FILE *Stream, const wchar_t *Format, ...)
1225 {
1226 #ifdef _SAGA_LINUX
1227 wxString _Format(Format); _Format.Replace("%s", "%ls"); // workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
1228 va_list argptr; va_start(argptr, _Format); int ret = wxVfprintf(Stream, _Format, argptr); va_end(argptr); return( ret );
1229 #else
1230 va_list argptr; va_start(argptr, Format); int ret = wxVfprintf(Stream, Format, argptr); va_end(argptr); return( ret );
1231 #endif
1232 }
1233
1234
1235 ///////////////////////////////////////////////////////////
1236 // //
1237 // //
1238 // //
1239 ///////////////////////////////////////////////////////////
1240
1241 //---------------------------------------------------------
SG_Get_CurrentTimeStr(bool bWithDate)1242 CSG_String SG_Get_CurrentTimeStr(bool bWithDate)
1243 {
1244 CSG_String s;
1245 wxDateTime t;
1246
1247 t.SetToCurrent();
1248
1249 if( bWithDate )
1250 {
1251 s.Append(t.FormatISODate().wc_str());
1252 s.Append(SG_T("/"));
1253 }
1254
1255 s.Append(t.FormatISOTime().wc_str());
1256
1257 return( s );
1258 }
1259
1260
1261 ///////////////////////////////////////////////////////////
1262 // //
1263 // //
1264 // //
1265 ///////////////////////////////////////////////////////////
1266
1267 //---------------------------------------------------------
SG_Double_To_Degree(double Value)1268 CSG_String SG_Double_To_Degree(double Value)
1269 {
1270 SG_Char c;
1271 int d, h;
1272 double s;
1273 CSG_String String;
1274
1275 if( Value < 0.0 )
1276 {
1277 Value = -Value;
1278 c = SG_T('-');
1279 }
1280 else
1281 {
1282 c = SG_T('+');
1283 }
1284
1285 Value = fmod(Value, 360.0);
1286 d = (int)Value;
1287 Value = 60.0 * (Value - d);
1288 h = (int)Value;
1289 Value = 60.0 * (Value - h);
1290 s = Value;
1291
1292 String.Printf(SG_T("%c%03d\xb0%02d'%02.*f''"), c, d, h, SG_Get_Significant_Decimals(s), s);
1293
1294 return( String );
1295 }
1296
1297 //---------------------------------------------------------
SG_Degree_To_Double(const CSG_String & String)1298 double SG_Degree_To_Double(const CSG_String &String)
1299 {
1300 double d, h, s, sig;
1301
1302 sig = 1.0;
1303 d = h = s = 0.0;
1304
1305 if( String.BeforeFirst('\xb0').asDouble(d) )
1306 {
1307 if( d < 0.0 )
1308 {
1309 sig = -1.0;
1310 d = -d;
1311 }
1312
1313 String.AfterFirst('\xb0').asDouble(h);
1314 String.AfterFirst('\'' ).asDouble(s);
1315 }
1316 else
1317 {
1318 String.asDouble(d);
1319 }
1320
1321 return( sig * (d + h / 60.0 + s / (60.0 * 60.0)) );
1322 }
1323
1324
1325 ///////////////////////////////////////////////////////////
1326 // //
1327 // //
1328 // //
1329 ///////////////////////////////////////////////////////////
1330
1331 //---------------------------------------------------------
SG_Get_Significant_Decimals(double Value,int maxDecimals)1332 int SG_Get_Significant_Decimals(double Value, int maxDecimals)
1333 {
1334 int Decimals;
1335 double Reminder;
1336
1337 Value = fabs(Value);
1338
1339 for(Decimals=0; Decimals<maxDecimals; Decimals++)
1340 {
1341 Reminder = Value - floor(Value);
1342
1343 if( Reminder == 0.0 )
1344 {
1345 return( Decimals );
1346 }
1347
1348 Value = 10.0 * Value;
1349 }
1350
1351 return( maxDecimals );
1352 }
1353
1354
1355 ///////////////////////////////////////////////////////////
1356 // //
1357 // //
1358 // //
1359 ///////////////////////////////////////////////////////////
1360
1361 //---------------------------------------------------------
SG_Flip_Decimal_Separators(CSG_String & String)1362 void SG_Flip_Decimal_Separators(CSG_String &String)
1363 {
1364 for(size_t i=0; i<String.Length(); i++)
1365 {
1366 switch( String[i] )
1367 {
1368 case SG_T('.'): String.Set_Char(i, ','); break;
1369 case SG_T(','): String.Set_Char(i, '.'); break;
1370 }
1371 }
1372 }
1373
1374
1375 ///////////////////////////////////////////////////////////
1376 // //
1377 // //
1378 // //
1379 ///////////////////////////////////////////////////////////
1380
1381 //---------------------------------------------------------
1382 /**
1383 * Returns floating point number 'Value' as formatted string.
1384 * The format depends on the 'Precision' value.
1385 * If Precision is -99 (the default) it will simply use %f format.
1386 * If 'Precision' is -98 the string will always be formatted
1387 * with the %e format specification (i.e. scientific: d.dddd e dd).
1388 * If Precision is zero (= 0) no decimals will be printed
1389 * If Precision is positive (> 0) it specifies the fix number
1390 * of decimals ("%.*f", Precision, Value),
1391 * if negative only significant decimals will be plotted up to a
1392 * maximum of the absolute value of 'Precision' digits.
1393 */
1394 //---------------------------------------------------------
SG_Get_String(double Value,int Precision)1395 CSG_String SG_Get_String(double Value, int Precision)
1396 {
1397 CSG_String s;
1398
1399 if ( Precision == -99 )
1400 {
1401 s.Printf("%f", Value);
1402 }
1403 else if( Precision == -98 )
1404 {
1405 s.Printf("%e", Value);
1406 }
1407 else if( Precision == 0 )
1408 {
1409 s.Printf("%d", (int)Value);
1410 }
1411 else if( Precision > 0 )
1412 {
1413 s.Printf("%.*f", Precision, Value);
1414 }
1415 else // if( Precision < 0 )
1416 {
1417 Precision = SG_Get_Significant_Decimals(Value, abs(Precision));
1418
1419 if( Precision == 0 )
1420 {
1421 s.Printf("%.0f", Value);
1422 }
1423 else // if( Precision > 0 )
1424 {
1425 s.Printf("%.*f", Precision, Value);
1426
1427 while( s.Length() > 1 && s[s.Length() - 1] == '0' )
1428 {
1429 s = s.Left(s.Length() - 1);
1430 }
1431
1432 if( s.Length() > 1 && (s[s.Length() - 1] == '.' || s[s.Length() - 1] == ',') )
1433 {
1434 s = s.Left(s.Length() - 1);
1435 }
1436 }
1437 }
1438
1439 s.Replace(",", ".");
1440
1441 return( s );
1442 }
1443
1444 //---------------------------------------------------------
SG_Get_String(int Value,int Precision)1445 CSG_String SG_Get_String(int Value, int Precision)
1446 {
1447 if( Precision > 0 )
1448 {
1449 return( SG_Get_String((double)Value, Precision) );
1450 }
1451
1452 if( Precision < 0 )
1453 {
1454 return( CSG_String::Format("%0*d", Precision, Value) );
1455 }
1456
1457 return( CSG_String::Format("%d", Value) );
1458 }
1459
1460
1461 ///////////////////////////////////////////////////////////
1462 // //
1463 // //
1464 // //
1465 ///////////////////////////////////////////////////////////
1466
1467 //---------------------------------------------------------
CSG_String_Tokenizer(void)1468 CSG_String_Tokenizer::CSG_String_Tokenizer(void)
1469 {
1470 m_pTokenizer = new wxStringTokenizer();
1471 }
1472
1473 //---------------------------------------------------------
CSG_String_Tokenizer(const CSG_String & String,const CSG_String & Delimiters,TSG_String_Tokenizer_Mode Mode)1474 CSG_String_Tokenizer::CSG_String_Tokenizer(const CSG_String &String, const CSG_String &Delimiters, TSG_String_Tokenizer_Mode Mode)
1475 {
1476 m_pTokenizer = new wxStringTokenizer();
1477
1478 Set_String(String, Delimiters, Mode);
1479 }
1480
1481 //---------------------------------------------------------
~CSG_String_Tokenizer(void)1482 CSG_String_Tokenizer::~CSG_String_Tokenizer(void)
1483 {
1484 delete(m_pTokenizer);
1485 }
1486
1487 //---------------------------------------------------------
Get_Tokens_Count(void) const1488 size_t CSG_String_Tokenizer::Get_Tokens_Count(void) const
1489 {
1490 return( m_pTokenizer->CountTokens() );
1491 }
1492
1493 //---------------------------------------------------------
Get_Last_Delimiter(void) const1494 SG_Char CSG_String_Tokenizer::Get_Last_Delimiter(void) const
1495 {
1496 return( m_pTokenizer->GetLastDelimiter() );
1497 }
1498
1499 //---------------------------------------------------------
Get_Next_Token(void)1500 CSG_String CSG_String_Tokenizer::Get_Next_Token(void)
1501 {
1502 wxString s(m_pTokenizer->GetNextToken());
1503
1504 return( &s );
1505 }
1506
1507 //---------------------------------------------------------
Get_Position(void) const1508 size_t CSG_String_Tokenizer::Get_Position(void) const
1509 {
1510 return( m_pTokenizer->GetPosition() );
1511 }
1512
1513 //---------------------------------------------------------
Get_String(void) const1514 CSG_String CSG_String_Tokenizer::Get_String(void) const
1515 {
1516 wxString s(m_pTokenizer->GetString());
1517
1518 return( &s );
1519 }
1520
1521 //---------------------------------------------------------
Has_More_Tokens(void) const1522 bool CSG_String_Tokenizer::Has_More_Tokens(void) const
1523 {
1524 return( m_pTokenizer->HasMoreTokens() );
1525 }
1526
1527 //---------------------------------------------------------
Set_String(const CSG_String & String,const CSG_String & Delimiters,TSG_String_Tokenizer_Mode Mode)1528 void CSG_String_Tokenizer::Set_String(const CSG_String &String, const CSG_String &Delimiters, TSG_String_Tokenizer_Mode Mode)
1529 {
1530 wxStringTokenizerMode _Mode;
1531
1532 switch( Mode )
1533 {
1534 default: _Mode = wxTOKEN_DEFAULT ; break;
1535 case SG_TOKEN_INVALID: _Mode = wxTOKEN_INVALID ; break;
1536 case SG_TOKEN_RET_EMPTY: _Mode = wxTOKEN_RET_EMPTY ; break;
1537 case SG_TOKEN_RET_EMPTY_ALL: _Mode = wxTOKEN_RET_EMPTY_ALL; break;
1538 case SG_TOKEN_RET_DELIMS: _Mode = wxTOKEN_RET_DELIMS ; break;
1539 case SG_TOKEN_STRTOK: _Mode = wxTOKEN_STRTOK ; break;
1540 }
1541
1542 m_pTokenizer->SetString(String.c_str(), Delimiters.c_str(), _Mode);
1543 }
1544
1545
1546 ///////////////////////////////////////////////////////////
1547 // //
1548 ///////////////////////////////////////////////////////////
1549
1550 //---------------------------------------------------------
SG_String_Tokenize(const CSG_String & String,const CSG_String & Delimiters,TSG_String_Tokenizer_Mode Mode)1551 CSG_Strings SG_String_Tokenize(const CSG_String &String, const CSG_String &Delimiters, TSG_String_Tokenizer_Mode Mode)
1552 {
1553 CSG_Strings Strings;
1554
1555 CSG_String_Tokenizer Tokenizer(String, Delimiters, Mode);
1556
1557 while( Tokenizer.Has_More_Tokens() )
1558 {
1559 Strings += Tokenizer.Get_Next_Token();
1560 }
1561
1562 return( Strings );
1563 }
1564
1565
1566 ///////////////////////////////////////////////////////////
1567 // //
1568 // //
1569 // //
1570 ///////////////////////////////////////////////////////////
1571
1572 //---------------------------------------------------------
1573