Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
String.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* String.cc (C) 2000-2023 */
9/* */
10/* Chaîne de caractères unicode. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/base/String.h"
15#include "arccore/base/StringBuilder.h"
16#include "arccore/base/CStringUtils.h"
17#include "arccore/base/APReal.h"
18#include "arccore/base/TraceInfo.h"
19#include "arccore/base/FatalErrorException.h"
20#include "arccore/base/StringView.h"
22
23#include "arccore/base/internal/StringImpl.h"
24
25#include <iostream>
26#include <cstring>
27#include <limits>
28#include <vector>
29
30#define A_FASTLOCK(ptr)
31/*!
32 * \file StringUtils.h
33 *
34 * \brief Fonctions utilitaires sur les chaînes de caractères.
35 */
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arccore
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
46String(const std::string& str)
47: m_p(new StringImpl(str))
48, m_const_ptr_size(-1)
49{
50 m_p->addReference();
51}
52
53/*---------------------------------------------------------------------------*/
54/*---------------------------------------------------------------------------*/
55
57String(std::string_view str)
58: m_p(new StringImpl(str))
59, m_const_ptr_size(-1)
60{
61 m_p->addReference();
62}
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
69: m_p(new StringImpl(str.toStdStringView()))
70, m_const_ptr(nullptr)
71, m_const_ptr_size(-1)
72{
73 m_p->addReference();
74}
75
76/*---------------------------------------------------------------------------*/
77/*---------------------------------------------------------------------------*/
78
80String(const UCharConstArrayView& ustr)
81: m_p(new StringImpl(ustr))
82, m_const_ptr_size(-1)
83{
84 m_p->addReference();
85}
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
91String(const Span<const Byte>& ustr)
92: m_p(new StringImpl(ustr))
93, m_const_ptr_size(-1)
94{
95 m_p->addReference();
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
102String(StringImpl* impl)
103: m_p(impl)
104, m_const_ptr_size(-1)
105{
106 if (m_p)
107 m_p->addReference();
108}
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
114String(const char* str,Integer len)
115: m_p(new StringImpl(std::string_view(str,len)))
116, m_const_ptr_size(-1)
117{
118 m_p->addReference();
119}
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
125String(char* str)
126: m_p(new StringImpl(str))
127, m_const_ptr_size(-1)
128{
129 m_p->addReference();
130}
131
132/*---------------------------------------------------------------------------*/
133/*---------------------------------------------------------------------------*/
134
136String(const char* str,bool do_alloc)
137: m_p(nullptr)
138, m_const_ptr(nullptr)
139, m_const_ptr_size(-1)
140{
141 if (do_alloc){
142 m_p = new StringImpl(str);
143 m_p->addReference();
144 }
145 else{
146 m_const_ptr = str;
147 if (m_const_ptr)
148 m_const_ptr_size = std::strlen(str);
149 }
150}
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
154
156String(const String& str)
157: m_p(str.m_p)
158, m_const_ptr(str.m_const_ptr)
159, m_const_ptr_size(str.m_const_ptr_size)
160{
161 if (m_p)
162 m_p->addReference();
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
169operator=(const String& str)
170{
171 if (str.m_p)
172 str.m_p->addReference();
173 _removeReferenceIfNeeded();
174 _copyFields(str);
175 return (*this);
176}
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180
182operator=(String&& str)
183{
184 _removeReferenceIfNeeded();
185
186 _copyFields(str);
187 str._resetFields();
188
189 return (*this);
190
191}
192
193/*---------------------------------------------------------------------------*/
194/*---------------------------------------------------------------------------*/
195
198{
199 return this->operator=(String(str));
200}
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204
206operator=(std::string_view str)
207{
208 return this->operator=(String(str));
209}
210
211/*---------------------------------------------------------------------------*/
212/*---------------------------------------------------------------------------*/
213
215operator=(const std::string& str)
216{
217 return this->operator=(String(str));
218}
219
220/*---------------------------------------------------------------------------*/
221/*---------------------------------------------------------------------------*/
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
225
226const char* String::
227localstr() const
228{
229 if (m_const_ptr)
230 return m_const_ptr;
231 if (m_p)
232 return m_p->toStdStringView().data();
233 return "";
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
239void String::
240_removeImplReference()
241{
242 m_p->removeReference();
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248ConstArrayView<UChar> String::
249_internalUtf16BE() const
250{
251 A_FASTLOCK(this);
252 if (!m_p){
253 if (m_const_ptr){
254 _checkClone();
255 }
256 }
257 if (m_p)
258 return m_p->utf16();
259 return ConstArrayView<UChar>();
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
266utf16() const
267{
268 return _internalUtf16BE();
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
275utf8() const
276{
277 if (m_p)
278 return m_p->largeUtf8().smallView();
279 if (m_const_ptr){
280 Int64 ts = m_const_ptr_size+1;
282 return ByteConstArrayView(s,reinterpret_cast<const Byte*>(m_const_ptr));
283 }
284 return ByteConstArrayView();
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
291bytes() const
292{
293 if (m_p)
294 return m_p->bytes();
295 if (m_const_ptr)
296 return Span<const Byte>(reinterpret_cast<const Byte*>(m_const_ptr),m_const_ptr_size);
297 return Span<const Byte>();
298}
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
304null() const
305{
306 if (m_const_ptr)
307 return false;
308 return m_p==0;
309}
310
311/*---------------------------------------------------------------------------*/
312/*---------------------------------------------------------------------------*/
313
315empty() const
316{
317 if (m_const_ptr)
318 return m_const_ptr[0]=='\0';
319 if (m_p)
320 return m_p->empty();
321 return true;
322}
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
328len() const
329{
330 auto x = this->toStdStringView();
331 return arccoreCheckArraySize(x.size());
332}
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
336
338length() const
339{
340 auto x = this->toStdStringView();
341 return x.size();
342}
343
344/*---------------------------------------------------------------------------*/
345/*---------------------------------------------------------------------------*/
346
347std::string_view String::
348toStdStringView() const
349{
350 if (m_const_ptr){
351#ifdef ARCCORE_CHECK
352 Int64 xlen = std::strlen(m_const_ptr);
353 if (xlen!=m_const_ptr_size)
354 ARCCORE_FATAL("Bad length (computed={0} stored={1})",xlen,m_const_ptr_size);
355#endif
356 return _viewFromConstChar();
357 }
358 if (m_p)
359 return m_p->toStdStringView();
360 return std::string_view();
361}
362
363/*---------------------------------------------------------------------------*/
364/*---------------------------------------------------------------------------*/
365
367view() const
368{
369 if (m_const_ptr)
370 return StringView(_viewFromConstChar());
371 if (m_p)
372 return m_p->view();
373 return StringView();
374}
375
376/*---------------------------------------------------------------------------*/
377/*---------------------------------------------------------------------------*/
378
379String::operator StringView() const
380{
381 return view();
382}
383
384/*---------------------------------------------------------------------------*/
385/*---------------------------------------------------------------------------*/
386
387void String::
388_checkClone() const
389{
390 if (m_const_ptr || !m_p){
391 std::string_view sview;
392 if (m_const_ptr)
393 sview = _viewFromConstChar();
394 m_p = new StringImpl(sview);
395 m_p->addReference();
396 m_const_ptr = nullptr;
397 m_const_ptr_size = -1;
398 return;
399 }
400 if (m_p->nbReference()!=1){
401 StringImpl* old_p = m_p;
402 m_p = m_p->clone();
403 m_p->addReference();
404 old_p->removeReference();
405 }
406}
407
408/*---------------------------------------------------------------------------*/
409/*---------------------------------------------------------------------------*/
410
412clone() const
413{
414 if (m_p)
415 return String(m_p->clone());
416 return String(*this);
417}
418
419/*---------------------------------------------------------------------------*/
420/*---------------------------------------------------------------------------*/
421
422String& String::
423_append(const String& str)
424{
425 if (str.null())
426 return *this;
427 _checkClone();
428 if (str.m_const_ptr){
429 m_p = m_p->append(str._viewFromConstChar());
430 }
431 else
432 m_p = m_p->append(str.m_p);
433 return *this;
434}
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
441{
442 String s2(s);
443 s2._checkClone();
444 s2.m_p = s2.m_p->replaceWhiteSpace();
445 return s2;
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
453{
454 if (s.null())
455 return String();
456 String s2(s);
457 s2._checkClone();
458 s2.m_p = s2.m_p->collapseWhiteSpace();
459 return s2;
460}
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464
466upper() const
467{
468 String s2(*this);
469 s2._checkClone();
470 s2.m_p = s2.m_p->toUpper();
471 return s2;
472}
473
474/*---------------------------------------------------------------------------*/
475/*---------------------------------------------------------------------------*/
476
478lower() const
479{
480 String s2(*this);
481 s2._checkClone();
482 s2.m_p = s2.m_p->toLower();
483 return s2;
484}
485
486/*---------------------------------------------------------------------------*/
487/*---------------------------------------------------------------------------*/
488
490operator+(std::string_view str) const
491{
492 if (str.empty())
493 return (*this);
494 String s2(*this);
495 return s2._append(str);
496}
497
498/*---------------------------------------------------------------------------*/
499/*---------------------------------------------------------------------------*/
500
502operator+(const std::string& str) const
503{
504 if (str.empty())
505 return (*this);
506 String s2(*this);
507 return s2._append(str);
508}
509
510/*---------------------------------------------------------------------------*/
511/*---------------------------------------------------------------------------*/
512
514operator+(const String& str) const
515{
516 String s2(*this);
517 return s2._append(str);
518}
519
520/*---------------------------------------------------------------------------*/
521/*---------------------------------------------------------------------------*/
522
523String String::
524fromNumber(unsigned long v)
525{
526 return StringFormatterArg(v).value();
527}
528
529String String::
530fromNumber(unsigned int v)
531{
532 return StringFormatterArg(v).value();
533}
534
535String String::
536fromNumber(double v)
537{
538 return StringFormatterArg(v).value();
539}
540
541String String::
542fromNumber(long double v)
543{
544 return StringFormatterArg(v).value();
545}
546
547String String::
548fromNumber(int v)
549{
550 return StringFormatterArg(v).value();
551}
552
553String String::
554fromNumber(long v)
555{
556 return StringFormatterArg(v).value();
557}
558
559String String::
560fromNumber(unsigned long long v)
561{
562 return StringFormatterArg(v).value();
563}
564
565String String::
566fromNumber(long long v)
567{
568 return StringFormatterArg(v).value();
569}
570
571String String::
572fromNumber(const APReal& v)
573{
574 return StringFormatterArg(v).value();
575}
576
577String String::
578fromNumber(double v,Integer nb_digit_after_point)
579{
580 Int64 mulp = 1;
581 for( Integer z=0; z<nb_digit_after_point; ++z )
582 mulp *= 10;
583 Int64 p = (Int64)(v * (Real)mulp);
584 Int64 after_digit = p % mulp;
585 Int64 before_digit = p / mulp;
586 StringBuilder s(String::fromNumber(before_digit) + ".");
587 {
588 Integer nb_zero = 0;
589 Int64 mv = mulp / 10;
590 for( Integer i=0; i<(nb_digit_after_point-1); ++i ){
591 if (after_digit>=mv){
592 break;
593 }
594 ++nb_zero;
595 mv /= 10;
596 }
597 for( Integer i=0; i<nb_zero; ++i )
598 s += "0";
599 }
600 s += String::fromNumber(after_digit);
601 return s;
602}
603
604/*---------------------------------------------------------------------------*/
605/*---------------------------------------------------------------------------*/
606
607String String::
608operator+(unsigned long v) const
609{
610 String s2(*this);
611 return s2._append(String::fromNumber(v));
612}
613
614String String::
615operator+(unsigned int v) const
616{
617 String s2(*this);
618 return s2._append(String::fromNumber(v));
619}
620
621String String::
622operator+(double v) const
623{
624 String s2(*this);
625 return s2._append(String::fromNumber(v));
626}
627
628String String::
629operator+(long double v) const
630{
631 String s2(*this);
632 return s2._append(String::fromNumber(v));
633}
634
635String String::
636operator+(int v) const
637{
638 String s2(*this);
639 return s2._append(String::fromNumber(v));
640}
641
642String String::
643operator+(long v) const
644{
645 String s2(*this);
646 return s2._append(String::fromNumber(v));
647}
648
649String String::
650operator+(unsigned long long v) const
651{
652 String s2(*this);
653 return s2._append(String::fromNumber(v));
654}
655
656String String::
657operator+(long long v) const
658{
659 String s2(*this);
660 return s2._append(String::fromNumber(v));
661}
662
663String String::
664operator+(const APReal& v) const
665{
666 String s2(*this);
667 return s2._append(String::fromNumber(v));
668}
669
670/*---------------------------------------------------------------------------*/
671/*---------------------------------------------------------------------------*/
672
673bool String::
674isLess(const String& b) const
675{
676 if (m_const_ptr){
677 if (b.m_const_ptr)
678 return CStringUtils::isLess(m_const_ptr,b.m_const_ptr);
679 if (b.m_p){
680 if (b.m_p->isEqual(m_const_ptr))
681 return false;
682 return !(b.m_p->isLessThan(m_const_ptr));
683 }
684 // b est la chaîne nulle mais pas moi.
685 return false;
686 }
687
688 if (b.m_const_ptr){
689 if (m_p)
690 return m_p->isLessThan(b.m_const_ptr);
691 // Je suis la chaîne nulle mais pas b.
692 return true;
693 }
694
695 if (m_p){
696 if (b.m_p)
697 return m_p->isLessThan(b.m_p);
698 // b est la chaine nulle mais pas moi
699 return false;
700 }
701
702 // Je suis la chaine nulle
703 return b.m_p==nullptr;
704}
705
706/*---------------------------------------------------------------------------*/
707/*---------------------------------------------------------------------------*/
708
709String String::
710fromUtf8(Span<const Byte> bytes)
711{
712 return String(new StringImpl(bytes));
713}
714
715/*---------------------------------------------------------------------------*/
716/*---------------------------------------------------------------------------*/
717
719internalDump(std::ostream& ostr) const
720{
721 ostr << "StringDump(m_const_ptr=" << (void*)m_const_ptr << ",m_p=" << m_p;
722 if (m_p){
723 ostr << ",";
724 m_p->internalDump(ostr);
725 }
726 ostr << ")";
727}
728
729/*---------------------------------------------------------------------------*/
730/*---------------------------------------------------------------------------*/
731
733hashCode() const
734{
736 Int32 h = 0;
737 Int64 n = s.size();
738 for( Int64 i=0; i<n; ++i ){
739 h = (h << 5) - h + s[i];
740 }
741 return h;
742}
743
744/*---------------------------------------------------------------------------*/
745/*---------------------------------------------------------------------------*/
746
747void StringFormatterArg::
748_formatReal(Real avalue)
749{
750 std::ostringstream ostr;
751 ostr.precision(std::numeric_limits<Real>::digits10);
752 ostr << avalue;
753 m_str_value = ostr.str();
754}
755
756/*---------------------------------------------------------------------------*/
757/*---------------------------------------------------------------------------*/
758
760{
761 public:
762 StringFormatter(const String& format)
763 : m_format(format), m_current_arg(0) {}
764 public:
765 void addArg(const String& ostr)
766 {
767 char buf[20];
768 Integer nb_z = 0;
769 Integer z = m_current_arg;
770 ++m_current_arg;
771 if (z>=100){
772 // N'arrive normalement jamais car seul ce fichier a accès à cette
773 // méthode.
774 std::cerr << "Too many args (maximum is 100)";
775 return;
776 }
777 else if (z>=10){
778 nb_z = 2;
779 buf[0] = (char)('0' + (z / 10));
780 buf[1] = (char)('0' + (z % 10));
781 }
782 else{
783 nb_z = 1;
784 buf[0] = (char)('0' + z);
785 }
786 buf[nb_z] = '}';
787 ++nb_z;
788 buf[nb_z] = '\0';
789
790 std::string str = m_format.localstr();
791 const char* local_str = str.c_str();
792 // TODO: ne pas utiliser de String mais un StringBuilder pour format
793 const Int64 slen = str.length();
794 for( Int64 i=0; i<slen; ++i ){
795 if (local_str[i]=='{'){
796 if (i+nb_z>=slen)
797 break;
798 bool is_ok = true;
799 for( Integer j=0; j<nb_z; ++j )
800 if (local_str[i+1+j]!=buf[j]){
801 is_ok = false;
802 break;
803 }
804 if (is_ok){
805 std::string str1(local_str,local_str+i);
806 std::string str2(local_str+i+1+nb_z);
807 m_format = String(str1) + ostr + str2;
808 // Il faut quitter tout de suite car str n'est plus valide
809 // puisque m_format a changé.
810 break;
811 }
812 }
813 }
814 }
815 public:
816 const String& value() const { return m_format; }
817 public:
818 String m_format;
819 Integer m_current_arg;
820 public:
821};
822
823/*---------------------------------------------------------------------------*/
824/*---------------------------------------------------------------------------*/
825
826String String::
827format(const String& str)
828{
829 return str;
830}
831
832/*---------------------------------------------------------------------------*/
833/*---------------------------------------------------------------------------*/
834
835String String::
836format(const String& str,const StringFormatterArg& arg1)
837{
838 StringFormatter sf(str);
839 sf.addArg(arg1.value());
840 return sf.value();
841}
842
843/*---------------------------------------------------------------------------*/
844/*---------------------------------------------------------------------------*/
845
846String String::
847format(const String& str,const StringFormatterArg& arg1,
848 const StringFormatterArg& arg2)
849{
850 StringFormatter sf(str);
851 sf.addArg(arg1.value());
852 sf.addArg(arg2.value());
853 return sf.value();
854}
855
856/*---------------------------------------------------------------------------*/
857/*---------------------------------------------------------------------------*/
858
859String String::
860format(const String& str,const StringFormatterArg& arg1,
861 const StringFormatterArg& arg2,
862 const StringFormatterArg& arg3)
863{
864 StringFormatter sf(str);
865 sf.addArg(arg1.value());
866 sf.addArg(arg2.value());
867 sf.addArg(arg3.value());
868 return sf.value();
869}
870
871/*---------------------------------------------------------------------------*/
872/*---------------------------------------------------------------------------*/
873
874String String::
875format(const String& str,const StringFormatterArg& arg1,
876 const StringFormatterArg& arg2,
877 const StringFormatterArg& arg3,
878 const StringFormatterArg& arg4)
879{
880 StringFormatter sf(str);
881 sf.addArg(arg1.value());
882 sf.addArg(arg2.value());
883 sf.addArg(arg3.value());
884 sf.addArg(arg4.value());
885 return sf.value();
886}
887
888/*---------------------------------------------------------------------------*/
889/*---------------------------------------------------------------------------*/
890
891String String::
892format(const String& str,const StringFormatterArg& arg1,
893 const StringFormatterArg& arg2,
894 const StringFormatterArg& arg3,
895 const StringFormatterArg& arg4,
896 const StringFormatterArg& arg5)
897{
898 StringFormatter sf(str);
899 sf.addArg(arg1.value());
900 sf.addArg(arg2.value());
901 sf.addArg(arg3.value());
902 sf.addArg(arg4.value());
903 sf.addArg(arg5.value());
904 return sf.value();
905}
906
907/*---------------------------------------------------------------------------*/
908/*---------------------------------------------------------------------------*/
909
910String String::
911format(const String& str,const StringFormatterArg& arg1,
912 const StringFormatterArg& arg2,
913 const StringFormatterArg& arg3,
914 const StringFormatterArg& arg4,
915 const StringFormatterArg& arg5,
916 const StringFormatterArg& arg6)
917{
918 StringFormatter sf(str);
919 sf.addArg(arg1.value());
920 sf.addArg(arg2.value());
921 sf.addArg(arg3.value());
922 sf.addArg(arg4.value());
923 sf.addArg(arg5.value());
924 sf.addArg(arg6.value());
925 return sf.value();
926}
927
928/*---------------------------------------------------------------------------*/
929/*---------------------------------------------------------------------------*/
930
931String String::
932format(const String& str,const StringFormatterArg& arg1,
933 const StringFormatterArg& arg2,
934 const StringFormatterArg& arg3,
935 const StringFormatterArg& arg4,
936 const StringFormatterArg& arg5,
937 const StringFormatterArg& arg6,
938 const StringFormatterArg& arg7)
939{
940 StringFormatter sf(str);
941 sf.addArg(arg1.value());
942 sf.addArg(arg2.value());
943 sf.addArg(arg3.value());
944 sf.addArg(arg4.value());
945 sf.addArg(arg5.value());
946 sf.addArg(arg6.value());
947 sf.addArg(arg7.value());
948 return sf.value();
949}
950
951/*---------------------------------------------------------------------------*/
952/*---------------------------------------------------------------------------*/
953
954String String::
955format(const String& str,const StringFormatterArg& arg1,
956 const StringFormatterArg& arg2,
957 const StringFormatterArg& arg3,
958 const StringFormatterArg& arg4,
959 const StringFormatterArg& arg5,
960 const StringFormatterArg& arg6,
961 const StringFormatterArg& arg7,
962 const StringFormatterArg& arg8)
963{
964 StringFormatter sf(str);
965 sf.addArg(arg1.value());
966 sf.addArg(arg2.value());
967 sf.addArg(arg3.value());
968 sf.addArg(arg4.value());
969 sf.addArg(arg5.value());
970 sf.addArg(arg6.value());
971 sf.addArg(arg7.value());
972 sf.addArg(arg8.value());
973 return sf.value();
974}
975
976/*---------------------------------------------------------------------------*/
977/*---------------------------------------------------------------------------*/
978
979String String::
980format(const String& str,const StringFormatterArg& arg1,
981 const StringFormatterArg& arg2,
982 const StringFormatterArg& arg3,
983 const StringFormatterArg& arg4,
984 const StringFormatterArg& arg5,
985 const StringFormatterArg& arg6,
986 const StringFormatterArg& arg7,
987 const StringFormatterArg& arg8,
988 const StringFormatterArg& arg9)
989{
990 StringFormatter sf(str);
991 sf.addArg(arg1.value());
992 sf.addArg(arg2.value());
993 sf.addArg(arg3.value());
994 sf.addArg(arg4.value());
995 sf.addArg(arg5.value());
996 sf.addArg(arg6.value());
997 sf.addArg(arg7.value());
998 sf.addArg(arg8.value());
999 sf.addArg(arg9.value());
1000 return sf.value();
1001}
1002
1003/*---------------------------------------------------------------------------*/
1004/*---------------------------------------------------------------------------*/
1005
1006String String::
1007concat(const StringFormatterArg& arg1)
1008{
1009 return arg1.value();
1010}
1011
1012String String::
1013concat(const StringFormatterArg& arg1,
1014 const StringFormatterArg& arg2)
1015{
1016 return arg1.value()+arg2.value();
1017}
1018
1019String String::
1020concat(const StringFormatterArg& arg1,
1021 const StringFormatterArg& arg2,
1022 const StringFormatterArg& arg3)
1023{
1024 return arg1.value()+arg2.value()+arg3.value();
1025}
1026
1027String String::
1028concat(const StringFormatterArg& arg1,
1029 const StringFormatterArg& arg2,
1030 const StringFormatterArg& arg3,
1031 const StringFormatterArg& arg4)
1032{
1033 return arg1.value()+arg2.value()+arg3.value()+arg4.value();
1034}
1035
1036/*---------------------------------------------------------------------------*/
1037/*---------------------------------------------------------------------------*/
1038
1040plural(const Integer n, const String & str, const bool with_number)
1041{
1042 return String::plural(n, str, str+"s", with_number);
1043}
1044
1045namespace
1046{
1047inline int
1048_abs(Integer a)
1049{
1050 return (a>0) ? a : (-a);
1051}
1052}
1053
1055plural(const Integer n, const String & str, const String & str2, const bool with_number)
1056{
1057 if (with_number)
1058 return String::concat(n, " ", ((_abs(n) > 1)?str2:str) );
1059 else
1060 return ((_abs(n) > 1)?str2:str);
1061}
1062
1063/*---------------------------------------------------------------------------*/
1064/*---------------------------------------------------------------------------*/
1065
1067contains(const String& arg1) const
1068{
1069 // Considère que la chaîne nulle est incluse dans toute chaîne
1070 if (arg1.null())
1071 return true;
1072 if (null())
1073 return false;
1074 std::string_view a = this->toStdStringView();
1075 std::string_view b = arg1.toStdStringView();
1076 return a.find(b) != std::string_view::npos;
1077}
1078
1079/*---------------------------------------------------------------------------*/
1080/*---------------------------------------------------------------------------*/
1081
1083endsWith(const String& s) const
1084{
1085 Span<const Byte> v = bytes();
1086 Span<const Byte> ref = s.bytes();
1087 Int64 ref_size = ref.size();
1088 Int64 v_size = v.size();
1089 if (ref_size>v_size)
1090 return false;
1091 const Byte* v_begin = &v[v_size-ref_size];
1092 return std::memcmp(v_begin,ref.data(),ref_size)==0;
1093}
1094
1095/*---------------------------------------------------------------------------*/
1096/*---------------------------------------------------------------------------*/
1097
1099startsWith(const String& s) const
1100{
1101 Span<const Byte> v = bytes();
1102 Span<const Byte> ref = s.bytes();
1103 Int64 ref_size = ref.size();
1104 Int64 v_size = v.size();
1105 if (ref_size>v_size)
1106 return false;
1107 return memcmp(v.data(),ref.data(),ref_size)==0;
1108}
1109
1110/*---------------------------------------------------------------------------*/
1111/*---------------------------------------------------------------------------*/
1112
1114substring(Int64 pos) const
1115{
1116 return substring(pos,length()-pos);
1117}
1118
1119/*---------------------------------------------------------------------------*/
1120/*---------------------------------------------------------------------------*/
1121
1123substring(Int64 pos,Int64 len) const
1124{
1125 if (pos<0)
1126 pos = 0;
1127 //TODO: normalement le _checkClone() n'est pas utile
1128 _checkClone();
1129 String s2(StringImpl::substring(m_p,pos,len));
1130 return s2;
1131}
1132
1133/*---------------------------------------------------------------------------*/
1134/*---------------------------------------------------------------------------*/
1135
1136String String::
1137join(String delim,ConstArrayView<String> strs)
1138{
1139 StringBuilder sb;
1140 for( Integer i=0, n=strs.size(); i<n; ++i ){
1141 if (i!=0)
1142 sb += delim;
1143 sb += strs[i];
1144 }
1145 return sb.toString();
1146}
1147
1148/*---------------------------------------------------------------------------*/
1149/*---------------------------------------------------------------------------*/
1150
1151extern "C++" bool
1152operator==(const String& a,const String& b)
1153{
1154 //cout << "COMPARE String String a='" << a << "' b='" << b << "'\n";
1155 if (a.m_const_ptr){
1156 if (b.m_const_ptr)
1157 return CStringUtils::isEqual(a.m_const_ptr,b.m_const_ptr);
1158 if (b.m_p)
1159 return b.m_p->isEqual(a.m_const_ptr);
1160 // Si je suis ici, 'b' est la chaine nulle et pas 'a'
1161 return false;
1162 }
1163
1164 if (b.m_const_ptr){
1165 if (a.m_p)
1166 return a.m_p->isEqual(b.m_const_ptr);
1167 return false;
1168 }
1169 if (a.m_p){
1170 if (b.m_p)
1171 return a.m_p->isEqual(b.m_p);
1172 // b est la chaine nulle mais pas moi
1173 return false;
1174 }
1175
1176 // Je suis la chaine nulle
1177 return b.m_p==nullptr;
1178}
1179
1180extern "C++" bool
1181operator==(const String& a,const char* b)
1182{
1183 return a==String(b);
1184}
1185
1186
1187extern "C++" bool
1188operator==(const char* a,const String& b)
1189{
1190 return String(a)==b;
1191}
1192
1193extern "C++" bool
1194operator<(const String& a,const String& b)
1195{
1196 bool v = a.isLess(b);
1197 //cout << "IsLess a='" << a << "' b='" << b << "' v=" << v << '\n';
1198 /*cout << "COMPARE A=" << a << " B=" << b << " V=" << v;
1199 if (a.m_const_ptr)
1200 cout << " AConst = " << a.m_const_ptr;
1201 if (b.m_const_ptr)
1202 cout << " BConst = " << b.m_const_ptr;
1203 cout << '\n';*/
1204 return v;
1205}
1206
1207extern "C++" String
1208operator+(const char* a,const String& b)
1209{
1210 return String(a)+b;
1211}
1212
1213/*---------------------------------------------------------------------------*/
1214/*---------------------------------------------------------------------------*/
1215
1216namespace
1217{
1218bool global_write_utf8 = false;
1219}
1220std::ostream&
1221operator<<(std::ostream& o,const String& str)
1222{
1223 // A utiliser plus tard lorsque l'encodage par défaut sera UTF8
1224 if (global_write_utf8)
1225 str.writeBytes(o);
1226 else
1227 o << str.localstr();
1228
1229 return o;
1230}
1231
1232/*---------------------------------------------------------------------------*/
1233/*---------------------------------------------------------------------------*/
1234
1236writeBytes(std::ostream& o) const
1237{
1238 Span<const Byte> v = this->bytes();
1239 Int64 vlen = v.size();
1240 o.write((const char*)v.data(),vlen);
1241}
1242
1243/*---------------------------------------------------------------------------*/
1244/*---------------------------------------------------------------------------*/
1245
1246std::istream&
1247operator>>(std::istream& i,String& str)
1248{
1249 std::string s;
1250 i >> s;
1251 str = s;
1252 return i;
1253}
1254
1255/*---------------------------------------------------------------------------*/
1256/*---------------------------------------------------------------------------*/
1257
1259{
1260 public:
1261 static std::vector<UChar>
1262 toUtf16BE(const String& str)
1263 {
1264 ConstArrayView<UChar> x{ str._internalUtf16BE() };
1265 Int32 n = x.size();
1266 if (n==0)
1267 return {};
1268 // x contient normalement toujours un zéro terminal que l'on ne met
1269 // pas dans le vecteur
1270 return { x.begin(), x.begin()+(n-1) };
1271 }
1272};
1273
1274/*---------------------------------------------------------------------------*/
1275/*---------------------------------------------------------------------------*/
1276
1277std::vector<UChar> StringUtils::
1278asUtf16BE(const String& str)
1279{
1280 return StringUtilsImpl::toUtf16BE(str);
1281}
1282
1283/*---------------------------------------------------------------------------*/
1284/*---------------------------------------------------------------------------*/
1285
1286} // End namespace Arccore
1287
1288/*---------------------------------------------------------------------------*/
1289/*---------------------------------------------------------------------------*/
1290
Fonctions utilitaires sur les chaînes de caractères.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:209
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
Definition Span.h:419
Vue d'un tableau d'éléments de type T.
Definition Span.h:510
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
Vue sur une chaîne de caractères UTF-8.
Definition StringView.h:47
Chaîne de caractères unicode.
ByteConstArrayView utf8() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:275
void writeBytes(std::ostream &o) const
Écrit la chaîne au format UTF-8 sur le flot o.
Definition String.cc:1236
ConstArrayView< UChar > utf16() const
Retourne la conversion de l'instance dans l'encodage UTF-16.
Definition String.cc:266
StringView view() const
Retourne une vue sur la chaîne actuelle.
Definition String.cc:367
void internalDump(std::ostream &ostr) const
Affiche les infos internes de la classe.
Definition String.cc:719
bool contains(const String &s) const
Indique si la chaîne contient s.
Definition String.cc:1067
String & operator=(const String &str)
Copie str dans cette instance.
Definition String.cc:169
bool empty() const
Vrai si la chaîne est vide (nulle ou "")
Definition String.cc:315
String upper() const
Transforme tous les caractères de la chaîne en majuscules.
Definition String.cc:466
Span< const Byte > bytes() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:291
String clone() const
Clone cette chaîne.
Definition String.cc:412
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Definition String.cc:452
bool startsWith(const String &s) const
Indique si la chaîne commence par les caractères de s.
Definition String.cc:1099
friend ARCCORE_BASE_EXPORT String operator+(const char *a, const String &b)
Ajoute deux chaînes.
Definition String.cc:1208
Integer len() const
Retourne la longueur de la chaîne en 32 bits.
Definition String.cc:328
String()
Crée une chaîne nulle.
static String plural(const Integer n, const String &str, const bool with_number=true)
Forme standard du pluriel par ajout d'un 's'.
Definition String.cc:1040
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
Int64 length() const
Retourne la longueur de la chaîne.
Definition String.cc:338
String lower() const
Transforme tous les caractères de la chaîne en minuscules.
Definition String.cc:478
static String replaceWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Definition String.cc:440
std::string_view toStdStringView() const
Retourne une vue de la STL sur la chaîne actuelle.
Definition String.cc:348
String substring(Int64 pos) const
Sous-chaîne commençant à la position pos.
Definition String.cc:1114
bool endsWith(const String &s) const
Indique si la chaîne se termine par les caractères de s.
Definition String.cc:1083
Int32 hashCode() const
Calcule une valeur de hashage pour cette chaîne de caractères.
Definition String.cc:733
ARCCORE_BASE_EXPORT bool isLess(const char *s1, const char *s2)
Retourne true si s1 est inférieur (ordre alphabétique) à s2 , false sinon.
ARCCORE_BASE_EXPORT bool isEqual(const char *s1, const char *s2)
Retourne true si s1 et s2 sont identiques, false sinon.
Espace de nom de Arccore.
Definition ArcaneTypes.h:24
double Real
Type représentant un réel.
Int32 Integer
Type représentant un entier.
bool operator<(const APReal &a, const APReal &b)
Emulation d'un réel en précision arbitraire.
constexpr __host__ __device__ Integer arccoreCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
std::int64_t Int64
Type entier signé sur 64 bits.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition BaseTypes.h:138
std::int32_t Int32
Type entier signé sur 32 bits.
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:43