Arcane  v4.1.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
StringVariableReplace.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* StringVariableReplace.cc (C) 2000-2025 */
9/* */
10/* Classe permettant de remplacer les symboles d'une chaine de caractères */
11/* par une autre chaine de caractères définie dans les arguments de */
12/* lancement. */
13/* Un symbole est défini par une chaine de caractères entourée de @. */
14/* Exemple : @mon_symbole@ */
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/core/internal/StringVariableReplace.h"
18
19#include "arcane/utils/CommandLineArguments.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/SmallArray.h"
22#include "arcane/utils/StringBuilder.h"
23#include "arcane/utils/String.h"
24#include "arcane/utils/FatalErrorException.h"
25#include "arcane/utils/List.h"
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30namespace Arcane
31{
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36String StringVariableReplace::
37replaceWithCmdLineArgs(StringView string_with_symbols, bool fatal_if_not_found, bool fatal_if_invalid)
38{
39 StringList args;
41 const CommandLineArguments cla{ args };
42 ParameterListWithCaseOption parameters;
43 parameters.addParameters(cla.parameters());
44 return replaceWithCmdLineArgs(parameters, string_with_symbols, fatal_if_not_found, fatal_if_invalid);
45}
46
98String StringVariableReplace::
99replaceWithCmdLineArgs(const ParameterListWithCaseOption& parameter_list, StringView string_with_symbols,
100 bool fatal_if_not_found, bool fatal_if_invalid)
101{
102 // Si la variable d'environnement ARCANE_REPLACE_SYMBOLS_IN_DATASET n'est pas
103 // définie, on ne touche pas à la chaine de caractères.
104 if (platform::getEnvironmentVariable("ARCANE_REPLACE_SYMBOLS_IN_DATASET").null() &&
105 parameter_list.getParameterOrNull("ARCANE_REPLACE_SYMBOLS_IN_DATASET").null()) {
106 return string_with_symbols;
107 }
108
109 if (string_with_symbols.empty())
110 return string_with_symbols;
111
112 Integer nb_at = 0;
113 Integer nb_at_with_escape = 0;
114
115 // Les arrobases peuvent être échappées. Il est nécessaire de les différencier pour avoir
116 // la taille du tableau des morceaux et pour vérifier la validité de la chaine de caractères.
117 _countChar(string_with_symbols, '@', nb_at, nb_at_with_escape);
118 if (nb_at == 0 && nb_at_with_escape == 0)
119 return string_with_symbols;
120
121 // Si le nombre d'arrobases est impaire, il y a forcément une incohérence.
122 if (fatal_if_invalid && nb_at % 2 == 1) {
123 ARCANE_FATAL("Invalid nb of @");
124 }
125
126 // Une arrobase sépare la chaine en deux morceaux. Donc le nombre de morceaux sera de "nb_at + 1".
127 // On ajoute les arrobases échappées. Ces arrobases sont considérées comme un symbole spécial et
128 // génèrent deux morceaux (donc "nb_at_with_escape * 2").
129 const Integer size_array_w_splits = (nb_at + 1) + (nb_at_with_escape * 2);
130
131 // Dans un cas valide, le nombre de morceaux doit être impaire.
132 // Dans le cas où l'utilisateur désactive le fatal_if_invalid et que le nombre de morceaux est paire,
133 // il ne faut pas qu'on considère le morceau final comme un symbole (voir la boucle plus bas pour comprendre).
134 const Integer max_index = size_array_w_splits % 2 == 0 ? size_array_w_splits - 1 : size_array_w_splits;
135
136 SmallArray<StringView> string_splited(size_array_w_splits);
137 _splitString(string_with_symbols, string_splited, '@');
138
139 StringBuilder combined{};
140
141 // Dans le tableau, les morceaux ayant une position impaire sont les élements entre arrobases
142 // et donc des symboles.
143 for (Integer i = 0; i < max_index; ++i) {
144 StringView part{ string_splited[i] };
145 if (part.empty())
146 continue;
147
148 // Les morceaux avec une position paire ne sont pas des symboles.
149 // On traite aussi le cas particulier des arrobases échappées.
150 if (i % 2 == 0 || part.bytes()[0] == '@') {
151 combined.append(part);
152 }
153 else {
154 String reference_input = parameter_list.getParameterOrNull(part);
155 if (reference_input.null()) {
156 if (fatal_if_not_found) {
157 ARCANE_FATAL("Symbol @{0}@ not found in the parameter list", part);
158 }
159 }
160 else {
161 combined.append(reference_input);
162 }
163 }
164 }
165
166 // Dans le cas où l'utilisateur désactive le fatal_if_invalid, le dernier morceau
167 // est à une position impaire mais n'est pas un symbole, donc on le rajoute ici.
168 if (size_array_w_splits % 2 == 0) {
169 combined.append(string_splited[string_splited.size() - 1]);
170 }
171
172 return combined.toString();
173}
174
175/*---------------------------------------------------------------------------*/
176/*---------------------------------------------------------------------------*/
177
194_splitString(StringView str_view, ArrayView<StringView> str_view_array, char c)
195{
196 /*
197 aa@aa -> "aa", "aa" 2 (fatal_if_invalid)
198 @aa@aa@aa@ -> "", "aa", "aa", "aa", "" 5
199 @aa@@aa@ -> "", "aa", "", "aa", "" 5
200 @ -> "", "" 2 (fatal_if_invalid)
201 @aa@ -> "", "aa", "" 3
202 @aa@aa\@aa -> "", "aa", "aa", "@", "aa" 5
203 @aa@\@@aa@ -> "", "aa", "", "@", "", "aa", "" 7
204 @aa@@aa@ -> "", "aa", "", "aa", "" 5
205 \@aa -> "", "@", "aa" 3
206 @aa@aa@aa -> "", "aa", "aa", "aa" 4 (fatal_if_invalid)
207 @aa@aa -> "", "aa", "aa" 3
208 */
209
210 Span<const Byte> str_span = str_view.bytes();
211
212 Int64 offset = 0;
213 Int64 len = str_view.length();
214 Integer index = 0;
215 bool previous_backslash = false;
216
217 for (Int64 i = 0; i < len; ++i) {
218 // Si on trouve une arrobase.
219 if (str_span[i] == c) {
220 // Si cette arrobase est précédée par un backslash.
221 if (previous_backslash) {
222 // On enregistre le morceau qu'on parcourait, sans le backslash.
223 str_view_array[index++] = str_view.subView(offset, i - 1 - offset);
224 // On rajoute l'arrobase.
225 str_view_array[index++] = str_view.subView(i, 1);
226
227 offset = i + 1;
228 previous_backslash = false;
229 }
230 else {
231 // On enregistre le morceau qu'on parcourait, sans l'arrobase.
232 str_view_array[index++] = str_view.subView(offset, i - offset);
233
234 offset = i + 1;
235 }
236 }
237 // Si on trouve un backslash.
238 else if (str_span[i] == '\\') {
239 // Et qu'on avait déjà trouvé un backslash, on n'y touche pas.
240 if (previous_backslash)
241 previous_backslash = false;
242 else
243 previous_backslash = true;
244 }
245 else {
246 previous_backslash = false;
247 }
248 }
249 // On ajoute le dernier morceau.
250 str_view_array[index] = str_view.subView(offset, len - offset);
251}
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
266_countChar(StringView str_view, char c, Integer& count_c, Integer& count_c_with_escape)
267{
268 count_c = 0;
269 count_c_with_escape = 0;
270 bool previous_backslash = false;
271
272 for (const Byte byte : str_view.bytes()) {
273 if (byte == c) {
274 if (previous_backslash) {
275 count_c_with_escape++;
276 previous_backslash = false;
277 }
278 else {
279 count_c++;
280 }
281 }
282 else if (byte == '\\') {
283 // On avait déjà trouvé un backslash, on n'y touche pas.
284 if (previous_backslash)
285 previous_backslash = false;
286 else
287 previous_backslash = true;
288 }
289 else {
290 previous_backslash = false;
291 }
292 }
293}
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
297
298} // namespace Arcane
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
Liste de paramètres avec informations pour surcharger les options du jeu de données.
String getParameterOrNull(const String &param_name) const
Récupère le paramètre de nom param_name.
Tableau 1D de données avec buffer pré-alloué sur la pile.
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
static void _countChar(StringView str_view, char c, Integer &count_c, Integer &count_c_with_escape)
Méthode permettant de compter le nombre de caractères séparateurs dans une chaine de caractères.
static void _splitString(StringView str_view, ArrayView< StringView > str_view_array, char c)
Méthode permettant de splitter la chaine "str_view" en plusieurs morceaux. Les splits seront entre le...
Vue sur une chaîne de caractères UTF-8.
Definition StringView.h:47
constexpr Span< const Byte > bytes() const ARCCORE_NOEXCEPT
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition StringView.h:96
constexpr Int64 length() const ARCCORE_NOEXCEPT
Longueur en octet de la chaîne de caractères.
Definition StringView.h:99
StringView subView(Int64 pos) const
Sous-chaîne commençant à la position pos.
Definition StringView.cc:37
constexpr bool empty() const ARCCORE_NOEXCEPT
Vrai si la chaîne est nulle ou vide.
Definition StringView.h:105
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:305
void fillCommandLineArguments(StringList &arg_list)
Remplit arg_list avec les arguments de la ligne de commande.
ARCCORE_BASE_EXPORT String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
List< String > StringList
Tableau de chaînes de caractères unicode.
Definition UtilsTypes.h:513
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:43