Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
String.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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-2025 */
9/* */
10/* Unicode character string. */
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/NotSupportedException.h"
21#include "arccore/base/StringView.h"
23
24#include "arccore/base/internal/StringImpl.h"
25
26#include <iostream>
27#include <cstring>
28#include <limits>
29#include <vector>
30
31#define A_FASTLOCK(ptr)
32
33/*!
34 * \file StringUtils.h
35 *
36 * \brief Utility functions for character strings.
37 */
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42namespace Arcane
43{
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
49String(const std::string& str)
50: m_p(new StringImpl(str))
51, m_const_ptr_size(-1)
52{
53 m_p->addReference();
54}
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58
60String(std::string_view str)
61: m_p(new StringImpl(str))
62, m_const_ptr_size(-1)
63{
64 m_p->addReference();
65}
66
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
72: m_p(new StringImpl(str.toStdStringView()))
73, m_const_ptr(nullptr)
74, m_const_ptr_size(-1)
75{
76 m_p->addReference();
77}
78
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
83String(const UCharConstArrayView& ustr)
84: m_p(new StringImpl(ustr))
85, m_const_ptr_size(-1)
86{
87 m_p->addReference();
88}
89
90/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
92
94String(const Span<const Byte>& ustr)
95: m_p(new StringImpl(ustr))
96, m_const_ptr_size(-1)
97{
98 m_p->addReference();
99}
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
105String(StringImpl* impl)
106: m_p(impl)
107, m_const_ptr_size(-1)
108{
109 if (m_p)
110 m_p->addReference();
111}
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
117String(const char* str, Integer len)
118: m_p(new StringImpl(std::string_view(str, len)))
119, m_const_ptr_size(-1)
120{
121 m_p->addReference();
122}
123
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
128String(char* str)
129: m_p(new StringImpl(str))
130, m_const_ptr_size(-1)
131{
132 m_p->addReference();
133}
134
135/*---------------------------------------------------------------------------*/
136/*---------------------------------------------------------------------------*/
137
139String(const char* str, bool do_alloc)
140: m_p(nullptr)
141, m_const_ptr(nullptr)
142, m_const_ptr_size(-1)
143{
144 if (do_alloc) {
145 m_p = new StringImpl(str);
146 m_p->addReference();
147 }
148 else {
149 m_const_ptr = str;
150 if (m_const_ptr)
151 m_const_ptr_size = std::strlen(str);
152 }
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
159String(const String& str)
160: m_p(str.m_p)
161, m_const_ptr(str.m_const_ptr)
162, m_const_ptr_size(str.m_const_ptr_size)
163{
164 if (m_p)
165 m_p->addReference();
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
172operator=(const String& str)
173{
174 if (str.m_p)
175 str.m_p->addReference();
176 _removeReferenceIfNeeded();
177 _copyFields(str);
178 return (*this);
179}
180
181/*---------------------------------------------------------------------------*/
182/*---------------------------------------------------------------------------*/
183
185operator=(String&& str)
186{
187 _removeReferenceIfNeeded();
188
189 _copyFields(str);
190 str._resetFields();
191
192 return (*this);
193}
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
200{
201 return this->operator=(String(str));
202}
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
208operator=(std::string_view str)
209{
210 return this->operator=(String(str));
211}
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215
217operator=(const std::string& str)
218{
219 return this->operator=(String(str));
220}
221
222/*---------------------------------------------------------------------------*/
223/*---------------------------------------------------------------------------*/
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228const char* String::
229localstr() const
230{
231 if (m_const_ptr)
232 return m_const_ptr;
233 if (m_p)
234 return m_p->toStdStringView().data();
235 return "";
236}
237
238/*---------------------------------------------------------------------------*/
239/*---------------------------------------------------------------------------*/
240
241void String::
242_removeImplReference()
243{
244 m_p->removeReference();
245}
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250ConstArrayView<UChar> String::
251_internalUtf16BE() const
252{
253 A_FASTLOCK(this);
254 if (!m_p) {
255 if (m_const_ptr) {
256 _checkClone();
257 }
258 }
259 if (m_p)
260 return m_p->utf16();
261 return ConstArrayView<UChar>();
262}
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
268utf16() const
269{
270 return _internalUtf16BE();
271}
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
277utf8() const
278{
279 if (m_p)
280 return m_p->largeUtf8().smallView();
281 if (m_const_ptr) {
282 Int64 ts = m_const_ptr_size + 1;
284 return ByteConstArrayView(s, reinterpret_cast<const Byte*>(m_const_ptr));
285 }
286 return ByteConstArrayView();
287}
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
293bytes() const
294{
295 if (m_p)
296 return m_p->bytes();
297 if (m_const_ptr)
298 return Span<const Byte>(reinterpret_cast<const Byte*>(m_const_ptr), m_const_ptr_size);
299 return Span<const Byte>();
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
306null() const
307{
308 if (m_const_ptr)
309 return false;
310 return m_p == 0;
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
317empty() const
318{
319 if (m_const_ptr)
320 return m_const_ptr[0] == '\0';
321 if (m_p)
322 return m_p->empty();
323 return true;
324}
325
326/*---------------------------------------------------------------------------*/
327/*---------------------------------------------------------------------------*/
328
330len() const
331{
332 auto x = this->toStdStringView();
333 return arccoreCheckArraySize(x.size());
334}
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
340length() const
341{
342 auto x = this->toStdStringView();
343 return x.size();
344}
345
346/*---------------------------------------------------------------------------*/
347/*---------------------------------------------------------------------------*/
348
349std::string_view String::
350toStdStringView() const
351{
352 if (m_const_ptr) {
353#ifdef ARCCORE_CHECK
354 Int64 xlen = std::strlen(m_const_ptr);
355 if (xlen != m_const_ptr_size)
356 ARCCORE_FATAL("Bad length (computed={0} stored={1})", xlen, m_const_ptr_size);
357#endif
358 return _viewFromConstChar();
359 }
360 if (m_p)
361 return m_p->toStdStringView();
362 return std::string_view();
363}
364
365/*---------------------------------------------------------------------------*/
366/*---------------------------------------------------------------------------*/
367
369view() const
370{
371 if (m_const_ptr)
372 return StringView(_viewFromConstChar());
373 if (m_p)
374 return m_p->view();
375 return StringView();
376}
377
378/*---------------------------------------------------------------------------*/
379/*---------------------------------------------------------------------------*/
380
381String::operator StringView() const
382{
383 return view();
384}
385
386/*---------------------------------------------------------------------------*/
387/*---------------------------------------------------------------------------*/
388
389void String::
390_checkClone() const
391{
392 if (m_const_ptr || !m_p) {
393 std::string_view sview;
394 if (m_const_ptr)
395 sview = _viewFromConstChar();
396 m_p = new StringImpl(sview);
397 m_p->addReference();
398 m_const_ptr = nullptr;
399 m_const_ptr_size = -1;
400 return;
401 }
402 if (m_p->nbReference() != 1) {
403 StringImpl* old_p = m_p;
404 m_p = m_p->clone();
405 m_p->addReference();
406 old_p->removeReference();
407 }
408}
409
410/*---------------------------------------------------------------------------*/
411/*---------------------------------------------------------------------------*/
412
414clone() const
415{
416 if (m_p)
417 return String(m_p->clone());
418 return String(*this);
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
424String& String::
425_append(const String& str)
426{
427 if (str.null())
428 return *this;
429 _checkClone();
430 if (str.m_const_ptr) {
431 m_p = m_p->append(str._viewFromConstChar());
432 }
433 else
434 m_p = m_p->append(str.m_p);
435 return *this;
436}
437
438/*---------------------------------------------------------------------------*/
439/*---------------------------------------------------------------------------*/
440
443{
444 String s2(s);
445 s2._checkClone();
446 s2.m_p = s2.m_p->replaceWhiteSpace();
447 return s2;
448}
449
450/*---------------------------------------------------------------------------*/
451/*---------------------------------------------------------------------------*/
452
455{
456 if (s.null())
457 return String();
458 String s2(s);
459 s2._checkClone();
460 s2.m_p = s2.m_p->collapseWhiteSpace();
461 return s2;
462}
463
464/*---------------------------------------------------------------------------*/
465/*---------------------------------------------------------------------------*/
466
468upper() const
469{
470 String s2(*this);
471 s2._checkClone();
472 s2.m_p = s2.m_p->toUpper();
473 return s2;
474}
475
476/*---------------------------------------------------------------------------*/
477/*---------------------------------------------------------------------------*/
478
480lower() const
481{
482 String s2(*this);
483 s2._checkClone();
484 s2.m_p = s2.m_p->toLower();
485 return s2;
486}
487
488/*---------------------------------------------------------------------------*/
489/*---------------------------------------------------------------------------*/
490
492operator+(std::string_view str) const
493{
494 if (str.empty())
495 return (*this);
496 String s2(*this);
497 return s2._append(str);
498}
499
500/*---------------------------------------------------------------------------*/
501/*---------------------------------------------------------------------------*/
502
504operator+(const std::string& str) const
505{
506 if (str.empty())
507 return (*this);
508 String s2(*this);
509 return s2._append(str);
510}
511
512/*---------------------------------------------------------------------------*/
513/*---------------------------------------------------------------------------*/
514
516operator+(const String& str) const
517{
518 String s2(*this);
519 return s2._append(str);
520}
521
522/*---------------------------------------------------------------------------*/
523/*---------------------------------------------------------------------------*/
524
525String String::
526fromNumber(unsigned long v)
527{
528 return StringFormatterArg(v).value();
529}
530
531String String::
532fromNumber(unsigned int v)
533{
534 return StringFormatterArg(v).value();
535}
536
537String String::
538fromNumber(double v)
539{
540 return StringFormatterArg(v).value();
541}
542
543String String::
544fromNumber(long double v)
545{
546 return StringFormatterArg(v).value();
547}
548
549String String::
550fromNumber(int v)
551{
552 return StringFormatterArg(v).value();
553}
554
555String String::
556fromNumber(long v)
557{
558 return StringFormatterArg(v).value();
559}
560
561String String::
562fromNumber(unsigned long long v)
563{
564 return StringFormatterArg(v).value();
565}
566
567String String::
568fromNumber(long long v)
569{
570 return StringFormatterArg(v).value();
571}
572
573String String::
574fromNumber(const APReal& v)
575{
576 return StringFormatterArg(v).value();
577}
578
579String String::
580fromNumber(double v, Integer nb_digit_after_point)
581{
582 Int64 mulp = 1;
583 for (Integer z = 0; z < nb_digit_after_point; ++z)
584 mulp *= 10;
585 Int64 p = (Int64)(v * (Real)mulp);
586 Int64 after_digit = p % mulp;
587 Int64 before_digit = p / mulp;
588 StringBuilder s(String::fromNumber(before_digit) + ".");
589 {
590 Integer nb_zero = 0;
591 Int64 mv = mulp / 10;
592 for (Integer i = 0; i < (nb_digit_after_point - 1); ++i) {
593 if (after_digit >= mv) {
594 break;
595 }
596 ++nb_zero;
597 mv /= 10;
598 }
599 for (Integer i = 0; i < nb_zero; ++i)
600 s += "0";
601 }
602 s += String::fromNumber(after_digit);
603 return s;
604}
605
606/*---------------------------------------------------------------------------*/
607/*---------------------------------------------------------------------------*/
608
610operator+(unsigned long v) const
611{
612 String s2(*this);
613 return s2._append(String::fromNumber(v));
614}
615
617operator+(unsigned int v) const
618{
619 String s2(*this);
620 return s2._append(String::fromNumber(v));
621}
622
624operator+(double v) const
625{
626 String s2(*this);
627 return s2._append(String::fromNumber(v));
628}
629
631operator+(long double v) const
632{
633 String s2(*this);
634 return s2._append(String::fromNumber(v));
635}
636
638operator+(int v) const
639{
640 String s2(*this);
641 return s2._append(String::fromNumber(v));
642}
643
645operator+(long v) const
646{
647 String s2(*this);
648 return s2._append(String::fromNumber(v));
649}
650
652operator+(unsigned long long v) const
653{
654 String s2(*this);
655 return s2._append(String::fromNumber(v));
656}
657
659operator+(long long v) const
660{
661 String s2(*this);
662 return s2._append(String::fromNumber(v));
663}
664
666operator+(const APReal& v) const
667{
668 String s2(*this);
669 return s2._append(String::fromNumber(v));
670}
671
672/*---------------------------------------------------------------------------*/
673/*---------------------------------------------------------------------------*/
674
675bool String::
676isLess(const String& b) const
677{
678 if (m_const_ptr) {
679 if (b.m_const_ptr)
680 return CStringUtils::isLess(m_const_ptr, b.m_const_ptr);
681 if (b.m_p) {
682 if (b.m_p->isEqual(m_const_ptr))
683 return false;
684 return !(b.m_p->isLessThan(m_const_ptr));
685 }
686 // b est la chaîne nulle mais pas moi.
687 return false;
688 }
689
690 if (b.m_const_ptr) {
691 if (m_p)
692 return m_p->isLessThan(b.m_const_ptr);
693 // Je suis la chaîne nulle mais pas b.
694 return true;
695 }
696
697 if (m_p) {
698 if (b.m_p)
699 return m_p->isLessThan(b.m_p);
700 // b est la chaine nulle mais pas moi
701 return false;
702 }
703
704 // Je suis la chaine nulle
705 return b.m_p == nullptr;
706}
707
708/*---------------------------------------------------------------------------*/
709/*---------------------------------------------------------------------------*/
710
711String String::
712fromUtf8(Span<const Byte> bytes)
713{
714 return String(new StringImpl(bytes));
715}
716
717/*---------------------------------------------------------------------------*/
718/*---------------------------------------------------------------------------*/
719
721internalDump(std::ostream& ostr) const
722{
723 ostr << "StringDump(m_const_ptr=" << (void*)m_const_ptr << ",m_p=" << m_p;
724 if (m_p) {
725 ostr << ",";
726 m_p->internalDump(ostr);
727 }
728 ostr << ")";
729}
730
731/*---------------------------------------------------------------------------*/
732/*---------------------------------------------------------------------------*/
733
735hashCode() const
736{
738 Int32 h = 0;
739 Int64 n = s.size();
740 for (Int64 i = 0; i < n; ++i) {
741 h = (h << 5) - h + s[i];
742 }
743 return h;
744}
745
746/*---------------------------------------------------------------------------*/
747/*---------------------------------------------------------------------------*/
748
749void StringFormatterArg::
750_formatReal(Real avalue)
751{
752 std::ostringstream ostr;
753 ostr.precision(std::numeric_limits<Real>::digits10);
754 ostr << avalue;
755 m_str_value = ostr.str();
756}
757
758/*---------------------------------------------------------------------------*/
759/*---------------------------------------------------------------------------*/
760
761class StringFormatter
762{
763 public:
764
765 StringFormatter(const String& format)
766 : m_format(format)
767 , m_current_arg(0)
768 {}
769
770 public:
771
772 void addArg(const String& ostr)
773 {
774 char buf[20];
775 Integer nb_z = 0;
776 Integer z = m_current_arg;
777 ++m_current_arg;
778 if (z >= 100) {
779 // N'arrive normalement jamais car seul ce fichier a accès à cette
780 // méthode.
781 std::cerr << "Too many args (maximum is 100)";
782 return;
783 }
784 else if (z >= 10) {
785 nb_z = 2;
786 buf[0] = (char)('0' + (z / 10));
787 buf[1] = (char)('0' + (z % 10));
788 }
789 else {
790 nb_z = 1;
791 buf[0] = (char)('0' + z);
792 }
793 buf[nb_z] = '}';
794 ++nb_z;
795 buf[nb_z] = '\0';
796
797 std::string str = m_format.localstr();
798 const char* local_str = str.c_str();
799 // TODO: ne pas utiliser de String mais un StringBuilder pour format
800 const Int64 slen = str.length();
801 for (Int64 i = 0; i < slen; ++i) {
802 if (local_str[i] == '{') {
803 if (i + nb_z >= slen)
804 break;
805 bool is_ok = true;
806 for (Integer j = 0; j < nb_z; ++j)
807 if (local_str[i + 1 + j] != buf[j]) {
808 is_ok = false;
809 break;
810 }
811 if (is_ok) {
812 std::string str1(local_str, local_str + i);
813 std::string str2(local_str + i + 1 + nb_z);
814 m_format = String(str1) + ostr + str2;
815 // Il faut quitter tout de suite car str n'est plus valide
816 // puisque m_format a changé.
817 break;
818 }
819 }
820 }
821 }
822
823 public:
824
825 const String& value() const { return m_format; }
826
827 public:
828
829 String m_format;
830 Integer m_current_arg;
831
832 public:
833};
834
835/*---------------------------------------------------------------------------*/
836/*---------------------------------------------------------------------------*/
837
838String String::
839format(const String& str)
840{
841 return str;
842}
843
844/*---------------------------------------------------------------------------*/
845/*---------------------------------------------------------------------------*/
846
847String String::
848format(const String& str, const StringFormatterArg& arg1)
849{
850 StringFormatter sf(str);
851 sf.addArg(arg1.value());
852 return sf.value();
853}
854
855/*---------------------------------------------------------------------------*/
856/*---------------------------------------------------------------------------*/
857
858String String::
859format(const String& str, const StringFormatterArg& arg1,
860 const StringFormatterArg& arg2)
861{
862 StringFormatter sf(str);
863 sf.addArg(arg1.value());
864 sf.addArg(arg2.value());
865 return sf.value();
866}
867
868/*---------------------------------------------------------------------------*/
869/*---------------------------------------------------------------------------*/
870
871String String::
872format(const String& str, const StringFormatterArg& arg1,
873 const StringFormatterArg& arg2,
874 const StringFormatterArg& arg3)
875{
876 StringFormatter sf(str);
877 sf.addArg(arg1.value());
878 sf.addArg(arg2.value());
879 sf.addArg(arg3.value());
880 return sf.value();
881}
882
883/*---------------------------------------------------------------------------*/
884/*---------------------------------------------------------------------------*/
885
886String String::
887format(const String& str, const StringFormatterArg& arg1,
888 const StringFormatterArg& arg2,
889 const StringFormatterArg& arg3,
890 const StringFormatterArg& arg4)
891{
892 StringFormatter sf(str);
893 sf.addArg(arg1.value());
894 sf.addArg(arg2.value());
895 sf.addArg(arg3.value());
896 sf.addArg(arg4.value());
897 return sf.value();
898}
899
900/*---------------------------------------------------------------------------*/
901/*---------------------------------------------------------------------------*/
902
903String String::
904format(const String& str, const StringFormatterArg& arg1,
905 const StringFormatterArg& arg2,
906 const StringFormatterArg& arg3,
907 const StringFormatterArg& arg4,
908 const StringFormatterArg& arg5)
909{
910 StringFormatter sf(str);
911 sf.addArg(arg1.value());
912 sf.addArg(arg2.value());
913 sf.addArg(arg3.value());
914 sf.addArg(arg4.value());
915 sf.addArg(arg5.value());
916 return sf.value();
917}
918
919/*---------------------------------------------------------------------------*/
920/*---------------------------------------------------------------------------*/
921
922String String::
923format(const String& str, const StringFormatterArg& arg1,
924 const StringFormatterArg& arg2,
925 const StringFormatterArg& arg3,
926 const StringFormatterArg& arg4,
927 const StringFormatterArg& arg5,
928 const StringFormatterArg& arg6)
929{
930 StringFormatter sf(str);
931 sf.addArg(arg1.value());
932 sf.addArg(arg2.value());
933 sf.addArg(arg3.value());
934 sf.addArg(arg4.value());
935 sf.addArg(arg5.value());
936 sf.addArg(arg6.value());
937 return sf.value();
938}
939
940/*---------------------------------------------------------------------------*/
941/*---------------------------------------------------------------------------*/
942
943String String::
944format(const String& str, const StringFormatterArg& arg1,
945 const StringFormatterArg& arg2,
946 const StringFormatterArg& arg3,
947 const StringFormatterArg& arg4,
948 const StringFormatterArg& arg5,
949 const StringFormatterArg& arg6,
950 const StringFormatterArg& arg7)
951{
952 StringFormatter sf(str);
953 sf.addArg(arg1.value());
954 sf.addArg(arg2.value());
955 sf.addArg(arg3.value());
956 sf.addArg(arg4.value());
957 sf.addArg(arg5.value());
958 sf.addArg(arg6.value());
959 sf.addArg(arg7.value());
960 return sf.value();
961}
962
963/*---------------------------------------------------------------------------*/
964/*---------------------------------------------------------------------------*/
965
966String String::
967format(const String& str, const StringFormatterArg& arg1,
968 const StringFormatterArg& arg2,
969 const StringFormatterArg& arg3,
970 const StringFormatterArg& arg4,
971 const StringFormatterArg& arg5,
972 const StringFormatterArg& arg6,
973 const StringFormatterArg& arg7,
974 const StringFormatterArg& arg8)
975{
976 StringFormatter sf(str);
977 sf.addArg(arg1.value());
978 sf.addArg(arg2.value());
979 sf.addArg(arg3.value());
980 sf.addArg(arg4.value());
981 sf.addArg(arg5.value());
982 sf.addArg(arg6.value());
983 sf.addArg(arg7.value());
984 sf.addArg(arg8.value());
985 return sf.value();
986}
987
988/*---------------------------------------------------------------------------*/
989/*---------------------------------------------------------------------------*/
990
991String String::
992format(const String& str, const StringFormatterArg& arg1,
993 const StringFormatterArg& arg2,
994 const StringFormatterArg& arg3,
995 const StringFormatterArg& arg4,
996 const StringFormatterArg& arg5,
997 const StringFormatterArg& arg6,
998 const StringFormatterArg& arg7,
999 const StringFormatterArg& arg8,
1000 const StringFormatterArg& arg9)
1001{
1002 StringFormatter sf(str);
1003 sf.addArg(arg1.value());
1004 sf.addArg(arg2.value());
1005 sf.addArg(arg3.value());
1006 sf.addArg(arg4.value());
1007 sf.addArg(arg5.value());
1008 sf.addArg(arg6.value());
1009 sf.addArg(arg7.value());
1010 sf.addArg(arg8.value());
1011 sf.addArg(arg9.value());
1012 return sf.value();
1013}
1014
1015/*---------------------------------------------------------------------------*/
1016/*---------------------------------------------------------------------------*/
1017
1018String String::
1019concat(const StringFormatterArg& arg1)
1020{
1021 return arg1.value();
1022}
1023
1024String String::
1025concat(const StringFormatterArg& arg1,
1026 const StringFormatterArg& arg2)
1027{
1028 return arg1.value() + arg2.value();
1029}
1030
1031String String::
1032concat(const StringFormatterArg& arg1,
1033 const StringFormatterArg& arg2,
1034 const StringFormatterArg& arg3)
1035{
1036 return arg1.value() + arg2.value() + arg3.value();
1037}
1038
1039String String::
1040concat(const StringFormatterArg& arg1,
1041 const StringFormatterArg& arg2,
1042 const StringFormatterArg& arg3,
1043 const StringFormatterArg& arg4)
1044{
1045 return arg1.value() + arg2.value() + arg3.value() + arg4.value();
1046}
1047
1048/*---------------------------------------------------------------------------*/
1049/*---------------------------------------------------------------------------*/
1050
1052plural(const Integer n, const String& str, const bool with_number)
1053{
1054 return String::plural(n, str, str + "s", with_number);
1055}
1056
1057namespace
1058{
1059 inline int
1060 _abs(Integer a)
1061 {
1062 return (a > 0) ? a : (-a);
1063 }
1064} // namespace
1065
1067plural(const Integer n, const String& str, const String& str2, const bool with_number)
1068{
1069 if (with_number)
1070 return String::concat(n, " ", ((_abs(n) > 1) ? str2 : str));
1071 else
1072 return ((_abs(n) > 1) ? str2 : str);
1073}
1074
1075/*---------------------------------------------------------------------------*/
1076/*---------------------------------------------------------------------------*/
1077
1079contains(const String& arg1) const
1080{
1081 // Consider the null string as included in any string
1082 if (arg1.null())
1083 return true;
1084 if (null())
1085 return false;
1086 std::string_view a = this->toStdStringView();
1087 std::string_view b = arg1.toStdStringView();
1088 return a.find(b) != std::string_view::npos;
1089}
1090
1091/*---------------------------------------------------------------------------*/
1092/*---------------------------------------------------------------------------*/
1093
1095endsWith(const String& s) const
1096{
1097 Span<const Byte> v = bytes();
1098 Span<const Byte> ref = s.bytes();
1099 Int64 ref_size = ref.size();
1100 Int64 v_size = v.size();
1101 if (ref_size > v_size)
1102 return false;
1103 const Byte* v_begin = &v[v_size - ref_size];
1104 return std::memcmp(v_begin, ref.data(), ref_size) == 0;
1105}
1106
1107/*---------------------------------------------------------------------------*/
1108/*---------------------------------------------------------------------------*/
1109
1111startsWith(const String& s) const
1112{
1113 Span<const Byte> v = bytes();
1114 Span<const Byte> ref = s.bytes();
1115 Int64 ref_size = ref.size();
1116 Int64 v_size = v.size();
1117 if (ref_size > v_size)
1118 return false;
1119 return memcmp(v.data(), ref.data(), ref_size) == 0;
1120}
1121
1122/*---------------------------------------------------------------------------*/
1123/*---------------------------------------------------------------------------*/
1124
1126substring(Int64 pos) const
1127{
1128 return substring(pos, length() - pos);
1129}
1130
1131/*---------------------------------------------------------------------------*/
1132/*---------------------------------------------------------------------------*/
1133
1135substring(Int64 pos, Int64 len) const
1136{
1137 if (pos < 0)
1138 pos = 0;
1139 //TODO: normally _checkClone() is not useful
1140 _checkClone();
1141 String s2(StringImpl::substring(m_p, pos, len));
1142 return s2;
1143}
1144
1145/*---------------------------------------------------------------------------*/
1146/*---------------------------------------------------------------------------*/
1147
1148String String::
1149join(String delim, ConstArrayView<String> strs)
1150{
1151 StringBuilder sb;
1152 for (Integer i = 0, n = strs.size(); i < n; ++i) {
1153 if (i != 0)
1154 sb += delim;
1155 sb += strs[i];
1156 }
1157 return sb.toString();
1158}
1159
1160/*---------------------------------------------------------------------------*/
1161/*---------------------------------------------------------------------------*/
1162
1163extern "C++" bool
1164operator==(const String& a, const String& b)
1165{
1166 //cout << "COMPARE String String a='" << a << "' b='" << b << "'\n";
1167 if (a.m_const_ptr) {
1168 if (b.m_const_ptr)
1169 return CStringUtils::isEqual(a.m_const_ptr, b.m_const_ptr);
1170 if (b.m_p)
1171 return b.m_p->isEqual(a.m_const_ptr);
1172 // If I am here, 'b' is the null string and not 'a'
1173 return false;
1174 }
1175
1176 if (b.m_const_ptr) {
1177 if (a.m_p)
1178 return a.m_p->isEqual(b.m_const_ptr);
1179 return false;
1180 }
1181 if (a.m_p) {
1182 if (b.m_p)
1183 return a.m_p->isEqual(b.m_p);
1184 // b is the null string but not me
1185 return false;
1186 }
1187
1188 // I am the null string
1189 return b.m_p == nullptr;
1190}
1191
1192extern "C++" bool
1193operator==(const String& a, const char* b)
1194{
1195 return a == String(b);
1196}
1197
1198extern "C++" bool
1199operator==(const char* a, const String& b)
1200{
1201 return String(a) == b;
1202}
1203
1204extern "C++" bool
1205operator<(const String& a, const String& b)
1206{
1207 bool v = a.isLess(b);
1208 //cout << "IsLess a='" << a << "' b='" << b << "' v=" << v << '\n';
1209 /*cout << "COMPARE A=" << a << " B=" << b << " V=" << v;
1210 if (a.m_const_ptr)
1211 cout << " AConst = " << a.m_const_ptr;
1212 if (b.m_const_ptr)
1213 cout << " BConst = " << b.m_const_ptr;
1214 cout << '\n';*/
1215 return v;
1216}
1217
1218extern "C++" String
1219operator+(const char* a, const String& b)
1220{
1221 return String(a) + b;
1222}
1223
1224/*---------------------------------------------------------------------------*/
1225/*---------------------------------------------------------------------------*/
1226
1227namespace
1228{
1229 bool global_write_utf8 = false;
1230}
1231std::ostream&
1232operator<<(std::ostream& o, const String& str)
1233{
1234 // To be used later when the default encoding is UTF8
1235 if (global_write_utf8)
1236 str.writeBytes(o);
1237 else
1238 o << str.localstr();
1239
1240 return o;
1241}
1242
1243/*---------------------------------------------------------------------------*/
1244/*---------------------------------------------------------------------------*/
1245
1247writeBytes(std::ostream& o) const
1248{
1249 Span<const Byte> v = this->bytes();
1250 Int64 vlen = v.size();
1251 o.write((const char*)v.data(), vlen);
1252}
1253
1254/*---------------------------------------------------------------------------*/
1255/*---------------------------------------------------------------------------*/
1256
1257std::istream&
1258operator>>(std::istream& i, String& str)
1259{
1260 std::string s;
1261 i >> s;
1262 str = s;
1263 return i;
1264}
1265
1266/*---------------------------------------------------------------------------*/
1267/*---------------------------------------------------------------------------*/
1268
1270{
1271 public:
1272
1273 static std::vector<UChar>
1274 toUtf16BE(const String& str)
1275 {
1276 ConstArrayView<UChar> x{ str._internalUtf16BE() };
1277 Int32 n = x.size();
1278 if (n == 0)
1279 return {};
1280 // x normally always contains a terminal zero that is not put into
1281 // the vector
1282 return { x.begin(), x.begin() + (n - 1) };
1283 }
1284};
1285
1286/*---------------------------------------------------------------------------*/
1287/*---------------------------------------------------------------------------*/
1288
1289std::vector<UChar> StringUtils::
1290asUtf16BE(const String& str)
1291{
1292 return StringUtilsImpl::toUtf16BE(str);
1293}
1294
1295/*---------------------------------------------------------------------------*/
1296/*---------------------------------------------------------------------------*/
1297
1298std::wstring StringUtils::
1299convertToStdWString([[maybe_unused]] const String& str)
1300{
1301#ifdef ARCCORE_OS_WIN32
1302 ConstArrayView<UChar> utf16 = str.utf16();
1303 const wchar_t* wdata = reinterpret_cast<const wchar_t*>(utf16.data());
1304 const size_t wlen = utf16.size();
1305 std::wstring_view wstr_view(wdata, wlen);
1306 return std::wstring(wstr_view);
1307#else
1308 ARCCORE_THROW(NotSupportedException, "This function is only supported on Win32");
1309#endif
1310}
1311
1312/*---------------------------------------------------------------------------*/
1313/*---------------------------------------------------------------------------*/
1314
1315String StringUtils::
1316convertToArcaneString([[maybe_unused]] const std::wstring_view& wstr)
1317{
1318#ifdef ARCCORE_OS_WIN32
1319 const UChar* ux = reinterpret_cast<const UChar*>(wstr.data());
1320 Int32 len = arccoreCheckArraySize(wstr.length());
1321 ConstArrayView<UChar> buf(len, ux);
1322 return String(buf);
1323#else
1324 ARCCORE_THROW(NotSupportedException, "This function is only supported on Win32");
1325#endif
1326}
1327
1328/*---------------------------------------------------------------------------*/
1329/*---------------------------------------------------------------------------*/
1330
1331} // namespace Arcane
1332
1333/*---------------------------------------------------------------------------*/
1334/*---------------------------------------------------------------------------*/
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCCORE_THROW(exception_class,...)
Macro to throw an exception with formatting.
Utility functions for character strings.
Emulation of real number in arbitrary precision.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr const_iterator begin() const noexcept
Iterator over the first element of the array.
constexpr Integer size() const noexcept
Number of elements in the array.
constexpr __host__ __device__ pointer data() const noexcept
Pointer to the start of the view.
Definition Span.h:539
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:327
View of an array of elements of type T.
Definition Span.h:635
Unicode character string constructor.
String toString() const
Returns the constructed character string.
View of a UTF-8 character string.
Definition StringView.h:44
bool startsWith(const String &s) const
Indicates if the string starts with the characters of s.
Definition String.cc:1111
bool null() const
Returns true if the string is null.
Definition String.cc:306
static String plural(const Integer n, const String &str, const bool with_number=true)
Standard plural form by adding an 's'.
Definition String.cc:1052
String upper() const
Transforms all characters in the string to uppercase.
Definition String.cc:468
Int64 length() const
Returns the length of the string.
Definition String.cc:340
String clone() const
Clones this string.
Definition String.cc:414
String lower() const
Transforms all characters in the string to lowercase.
Definition String.cc:480
void writeBytes(std::ostream &o) const
Writes the string in UTF-8 format to the stream o.
Definition String.cc:1247
void internalDump(std::ostream &ostr) const
Displays the internal information of the class.
Definition String.cc:721
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
ByteConstArrayView utf8() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:277
friend bool operator==(const String &a, const String &b)
Compares two unicode strings.
Definition String.cc:1164
friend String operator+(const char *a, const String &b)
Adds two strings.
Definition String.cc:1219
Int32 hashCode() const
Calculates a hash value for this character string.
Definition String.cc:735
static String replaceWhiteSpace(const String &rhs)
Performs whitespace character normalization.
Definition String.cc:442
Span< const Byte > bytes() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:293
bool endsWith(const String &s) const
Indicates if the string ends with the characters of s.
Definition String.cc:1095
bool empty() const
True if the string is empty (null or "").
Definition String.cc:317
static String collapseWhiteSpace(const String &rhs)
Performs whitespace character normalization.
Definition String.cc:454
ConstArrayView< UChar > utf16() const
Returns the conversion of the instance into UTF-16 encoding.
Definition String.cc:268
StringView view() const
Returns a view of the current string.
Definition String.cc:369
String & operator=(const String &str)
Copies str into this instance.
Definition String.cc:172
bool contains(const String &s) const
Indicates if the string contains s.
Definition String.cc:1079
std::string_view toStdStringView() const
Returns an STL view of the current string.
Definition String.cc:350
Integer len() const
Returns the length of the string in 32 bits.
Definition String.cc:330
String substring(Int64 pos) const
Substring starting at position pos.
Definition String.cc:1126
bool isLess(const char *s1, const char *s2)
Returns true if s1 is less than (alphabetical order) s2 , false otherwise.
bool isEqual(const char *s1, const char *s2)
Returns true if s1 and s2 are identical, false otherwise.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
constexpr __host__ __device__ Integer arccoreCheckArraySize(unsigned long long size)
Checks that size can be converted into an 'Integer' to serve as an array size. If possible,...
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
bool operator<(const Item &item1, const Item &item2)
Compare two entities.
Definition Item.h:566
std::istream & operator>>(std::istream &istr, eItemKind &item_kind)
Input operator from a stream.
double Real
Type representing a real number.
ConstArrayView< UChar > UCharConstArrayView
C equivalent of a 1D array of unicode characters.
Definition UtilsTypes.h:478
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:43
unsigned short UChar
Type of a unicode character.
Definition BaseTypes.h:47
std::ostream & operator<<(std::ostream &ostr, eItemKind item_kind)
Output operator for a stream.
std::int32_t Int32
Signed integer type of 32 bits.