TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Type_info.cpp
1/****************************************************************************
2* Copyright (c) 2022, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Type_info.h>
17#include <Noms.h>
18#include <Synonyme_info.h>
19
20// B.Mathieu, 08/2004
21// The initialization of these static members is very important: they MUST be initialized
22// BEFORE the first call to the constructor Type_info::Type_info(...).
23// That constructor is called when initializing the static member info_obj of all Objet_U objects.
24// Risk of "static initialization order fiasco"
25// (see http://www.parashift.com/c++-faq-lite/ctors.html [10.11])
26// Currently OK because initialization is done with a constant value.
27
28// Array of pointers to types registered during construction of Type_info objects.
29// If multiple types share the same name (Type_info::n), only one is registered in Type_info::les_types.
30const Type_info** Type_info::les_types=0;
31// For each element of the "les_types" array, this value is 1 if the type name
32// is shared by multiple types, 0 otherwise. See "ajouter_type".
33int * Type_info::types_homonymes=0;
34
35int Type_info::nb_classes=0;
36int Type_info::les_types_memsize=0;
37
38
39// [ABN] I don't dare replacing this with STL for efficiency purpose - here we convert only what's needed for comparison
40static inline int strcmp_uppercase(const char *n1, const char *n2)
41{
42 int i = 0;
43 unsigned char c1, c2;
44 int delta;
45 do
46 {
47 c1 = (unsigned char) ::toupper(n1[i]);
48 c2 = (unsigned char) ::toupper(n2[i]);
49 delta = c1 - c2;
50 i++;
51 }
52 while ((delta == 0) && (c1 != 0) && (c2 != 0));
53 return delta;
54}
55
56// GF: to correctly free memory, at minimum the Nom must be destroyed.
58{
59 // Find where to remove the type in the array:
60 int index;
61 int existe_deja = search_type_info_name(name(), index);
62 if (existe_deja)
63 {
64 for (int i = index; i<nb_classes-1; i++)
65 {
66 les_types[i] = les_types[i+1];
67 types_homonymes[i] = types_homonymes[i+1];
68 }
69 nb_classes--;
70 }
71 if (name_)
72 {
73 delete name_;
74 name_=0;
75 delete synonym_;
76 synonym_=0;
77 delete synonym_name_;
78 synonym_name_=0;
79 }
80 if ((nb_classes==0)&& (les_types_memsize!=0))
81 {
82 delete [] les_types;
83 delete [] types_homonymes;
84 les_types_memsize=0;
85 }
86}
87
88/*! @brief Searches for the type named "nom" in the list of registered types using binary search.
89 *
90 * Strings are compared after conversion to uppercase.
91 * On return, "index" holds the index of the found type, or the index of the first type after it
92 * if not found (i.e. les_types[index-1]->n < nom < les_types[index]->n).
93 * Returns 1 if found, 0 otherwise.
94 *
95 * @param nom The type name to search for.
96 * @param index On return, the index of the type or the insertion point.
97 * @return 1 if the type was found, 0 otherwise.
98 */
99int Type_info::search_type_info_name(const char *nom, int& index)
100{
101 assert(nom != 0);
102 // [imin..imax] is the interval where the searched index lies
103 int imin = 0;
104 int imax = nb_classes;
105 while (imax > imin)
106 {
107 // milieu is always < imax
108 int milieu = (imin + imax) / 2;
109 int comparaison = strcmp_uppercase(nom, les_types[milieu]->name());
110 if (comparaison == 0)
111 {
112 index = milieu;
113 return 1;
114 }
115 if (comparaison < 0)
116 {
117 // nom < les_types[milieu]: searched index is <= milieu
118 imax = milieu;
119 }
120 else
121 {
122 // nom > les_types[milieu]: searched index is strictly > milieu
123 imin = milieu + 1;
124 }
125 }
126 index = imax;
127 return 0;
128}
129/*! @brief Constructor from a name and an array of base types.
130 *
131 * @param un_nom The name of the type to create.
132 * @param nb_base Number of base types in the bases array.
133 * @param the_bases Array specifying the base (parent) types of the type to create.
134 * @throws Exits with an error if the name is null.
135 */
136Type_info::Type_info(const char* un_nom, int nb_base, const Type_info** the_bases) :
137 names_(un_nom),
138 name_((Nom*)0),
139 synonym_name_((Nom*) 0),
140 nb_bases_(nb_base),
141 b(the_bases),
142 cree_instance(0)
143{
144 if(un_nom == 0)
145 {
146 Cerr << "Type_info::Type_info(const char* nom,Objet_U* (*f)()...)\n";
147 Cerr << " Error : name == 0" << finl;
148 assert(0);
150 }
151 ajouter_type(*this);
152}
153
154/*! @brief Constructor from a name, a factory function, and an array of base types.
155 *
156 * The function is used to create an instance of the appropriate type.
157 *
158 * @param un_nom The name of the type to create.
159 * @param f Factory function that creates an instance of this type.
160 * @param nb_base Number of base types in the bases array.
161 * @param the_bases Array specifying the base (parent) types of the type to create.
162 * @throws Exits with an error if the name is null.
163 */
164Type_info::Type_info(const char* un_nom,
165 Objet_U* (*f)(),
166 int nb_base,
167 const Type_info** the_bases) :
168 names_(un_nom),
169 name_((Nom*) 0),
170 synonym_name_((Nom*) 0),
171 nb_bases_(nb_base),
172 b(the_bases),
173 cree_instance(f)
174{
175 if(un_nom == 0)
176 {
177 Cerr << "Type_info::Type_info(const char* nom,Objet_U* (*f)()...)\n";
178 Cerr << " Error : name == 0" << finl;
179 assert(0);
181 }
182 ajouter_type(*this);
183}
184
185/*! @brief Static method called by Type_info constructors to add a new type to the list of registered types.
186 *
187 * Verifies that the type name does not already exist.
188 *
189 * @param type_info The Type_info to register.
190 */
191void Type_info::ajouter_type(const Type_info& type_info)
192{
193 // Split type_info.names_ into A if | is found (eg: n=A|B)
194 // and add a synonym B
195 Nom A("");
196 Nom B("");
197 int synonym_found=0;
198 int i = 0;
199 unsigned char c;
200 do // Start loop
201 {
202 c = type_info.names_[i];
203 // Find a |
204 if (c==124)
205 {
206 if (synonym_found==1)
207 {
208 Cerr << "More than 1 synonym found in " << type_info.names_ << finl;
209 Cerr << "Not supported yet !" << finl;
211 }
212 else
213 {
214 synonym_found=1;
215 i++;
216 c = type_info.names_[i];
217 if (c==0)
218 {
219 Cerr << "Error in a classname which can't finished by | : " << type_info.names_ << finl;
221 }
222 }
223 }
224 // Build the synonym name:
225 if (synonym_found)
226 B+=c;
227 else
228 A+=c;
229 i++;
230 }
231 while (c!=0); // End loop
232
233 name_ = new Nom(A);
234 if (synonym_found)
235 {
236 //Commented cause too verbose:
237 //Cerr << "Keyword " << A << " has a synonym: " << B << finl;
238 synonym_name_ = new Nom(B);
239 synonym_ = new Synonyme_info(synonym_name_->getChar(),name_->getChar());
240 }
241 // Check that there is enough space in the array:
242 if (les_types_memsize <= nb_classes + 1)
243 {
244 static const int INCREMENT = 512;
245 // Not enough space in the array: resize it.
246 les_types_memsize += INCREMENT;
247 const Type_info** nouveau = new const Type_info*[les_types_memsize];
248 for (int j = 0; j < nb_classes; j++)
249 nouveau[j] = les_types[j];
250 delete[] les_types;
251 les_types = nouveau;
252
253 int * temp = new int[les_types_memsize];
254 for (int j = 0; j < nb_classes; j++)
255 temp[j] = types_homonymes[j];
256 delete[] types_homonymes;
257 types_homonymes = temp;
258 }
259
260 // Find where to insert the type in the array:
261 int existe_deja=Synonyme_info::est_un_synonyme(type_info.name());
262 if (existe_deja)
263 {
264 Cerr<<" class "<<type_info.name()<<" already exists as a synonym which is forbidden!!!!"<<finl;
266 }
267 int index;
268 existe_deja = search_type_info_name(type_info.name(), index);
269 if (existe_deja)
270 {
271 types_homonymes[index] = 1;
272 // GF: if we have a homonym and the string_macro_trio macro works,
273 // there is a problem except for iterators
274 if (strcmp(string_macro_trio("VECT",titi),"VECT"))
275 {
276 if (strncmp(type_info.name(),"Iterateur_",10))
277 {
278 Cerr<<" type "<<type_info.name()<<" is in double and it is not allowed!!!!"<<finl;
280 }
281 }
282 }
283 else
284 {
285 // Insert the type in the array at position "index":
286 for (int j = nb_classes; j > index; j--)
287 {
288 les_types[j] = les_types[j-1];
289 types_homonymes[j] = types_homonymes[j-1];
290 }
291 les_types[index] = &type_info;
292 types_homonymes[index] = 0;
293 nb_classes++;
294 }
295}
296
297/*! @brief Writes the base types of the current type to an output stream.
298 *
299 * @param os Output stream.
300 * @return Reference to the modified output stream.
301 */
303{
304 int i= nb_bases_;
305 while(i--)
306 os << b[i]->name() << " ";
307 return os << finl;
308}
309
310/*! @brief Writes the full hierarchy of the considered type to an output stream.
311 *
312 * @param (Sortie& os) output stream
313 * @return (Sortie&) the modified output stream
314 */
316{
317 os << "There is " << nb_classes << " classes:" << finl;
318 int i= nb_classes;
319 while(i--)
320 {
321 os << les_types[i]->name() << " inherits from ";
322 les_types[i]->bases(os);
323 }
324 return os << flush;
325}
326
327/*! @brief Instantiates an Objet_U of the given type. If a class T whose Type_info has the name typ exists,
328 *
329 * instance returns a pointer to a new instance of T.
330 * Returns the null pointer otherwise.
331 *
332 * @param (const char* typ) string associated with a type
333 * @return (Objet_U*) pointer to a new Objet_U of type typ
334 */
336{
337 const Type_info * le_type = type_info_from_name(typ);
339 if (le_type)
340 instance = le_type->instance();
341 else
342 instance = 0;
343 return instance;
344}
345
346/*! @brief Creates an instance of the class associated with the type_info.
347 *
348 */
350{
351 if (cree_instance == 0)
352 {
353 Cerr << "Error in Type_info::instance()\n";
354 Cerr << " The type " << name() << " is not instantiable" << finl;
355 assert(0);
357 }
358 Objet_U * ainstance = (*cree_instance)();
359 return ainstance;
360}
361
362/*! @brief Tests whether a class of the given type exists. If a class T whose Type_info has the name nom exists,
363 *
364 * est_un_type returns 1, null pointer otherwise.
365 *
366 * @param (const char* nom) string associated with a type
367 * @return (int) return code (0 or 1)
368 */
369int Type_info::est_un_type(const char* nom)
370{
371 const Type_info * type = type_info_from_name(nom);
372 return (type != 0);
373}
374
375/*! @brief Tests whether a type belongs to the base types of the considered type. If direct == 0,
376 *
377 * returns 1 if (*p) is among the bases of (*this), 0 otherwise.
378 * If direct != 0, returns 1 if (*p) is among the bases of (*this)
379 * or any direct or indirect parent of (*this), 0 otherwise.
380 *
381 * @param (const Type_info* p) pointer to the type to search for
382 * @param (int direct) 0 to search the entire base hierarchy, non-zero for a direct search
383 * @return (int) return code (0 or 1)
384 */
385int Type_info::has_base(const Type_info* p, int direct) const
386{
387 // Search for p->name() in b
388 // if found return 1
389 // else if not direct return 0;
390 // else search in the bases of b
391 // B. Mathieu modification: test only on the address of type_info,
392 // not on the type name...
393 if (p == 0)
394 {
395 return 0;
396 }
397 else
398 {
399 if (p == this)
400 {
401 return 1;
402 }
403 else
404 {
405 for (int i = 0; i < nb_bases_; i++)
406 if (b[i] == p)
407 return 1;
408 if (!direct)
409 {
410 // Verify ancestors at higher levels
411 for (int i = 0; i < nb_bases_; i++)
412 if (b[i]->has_base(p, direct)) return 1;
413 }
414 }
415 }
416 return 0;
417}
418
419/*! @brief Tests whether a type belongs to the base types of the considered type. The type to search for is identified by its name.
420 *
421 * If direct == 0, returns 1 if the type named name is among the bases of (*this), 0 otherwise.
422 * If direct != 0, returns 1 if the type named name is among the bases of (*this)
423 * or any direct or indirect parent of (*this), 0 otherwise.
424 *
425 * @param (const Nom& name) the name of the type to search for
426 * @param (int direct) 0 to search the entire base hierarchy, non-zero for a direct search
427 * @return (int) return code (0 or 1)
428 */
429int Type_info::has_base(const Nom& aname, int direct) const
430{
431 // Search for aname in b
432 // if found return 1
433 // else if not direct return 0;
434 // else search in the bases of b
435 // B. Mathieu modification: compare Type_info addresses only,
436 // not the type name.
437
438 const Type_info * type = type_info_from_name(aname);
439 int resultat = has_base(type, direct);
440 return resultat;
441}
442
443/*! @brief Comparison on the name of a type. Returns 1 if the name string of the considered type and the given name are identical.
444 *
445 * Returns 0 otherwise.
446 *
447 */
448int Type_info::same(const Nom& other_name) const
449{
450 return strcmp(name(),other_name)==0;
451}
452
453/*! @brief Returns 1 if this==p, 0 otherwise.
454 *
455 */
456int Type_info::same(const Type_info* p) const
457{
458 return (this == p);
459}
460
461/*! @brief Returns the names of the subtypes for a given parent type.
462 *
463 * @param (const Type_info& mere) the parent type to search subtypes of
464 * @param (Noms& les_sous_types) the names of the subtypes
465 * @return (int) number of subtypes returned
466 */
468{
469 int compteur=0;
470 int i= nb_classes;
471 // Modif B. Mathieu: name() no longer returns a static.
472 const Nom& nom_mere = mere.name();
473 // Cerr << "---------" << (const char*) nom_mere << finl;
474 while(i--)
475 {
476 if( les_types[i]->has_base(nom_mere, 0) )
477 if (!les_types[i]->same(nom_mere))
478 {
479 compteur++;
480 }
481 }
482 // Cerr << compteur << finl ;
483 if(compteur==0) return 0;
484 les_sous_types.dimensionner(compteur);
485 compteur=0;
486 i= nb_classes;
487 while(i--)
488 {
489 if( les_types[i]->has_base(nom_mere, 0) )
490 if (!les_types[i]->same(nom_mere))
491 {
492 les_sous_types[compteur++]=les_types[i]->name();
493 }
494 }
495 return compteur;
496}
497
498/*! @brief Returns the names of the subtypes for a parent type identified by name.
499 *
500 * @param (const Nom& type) the name of the parent type to search subtypes of
501 * @param (Noms& les_sous_types) the names of the subtypes
502 * @return (int) number of subtypes returned
503 * @throws Exits with an error if the given name does not correspond to a type known to TRUST
504 */
505int Type_info::les_sous_types(const Nom& type, Noms& sous_types)
506{
507 if (!est_un_type(type))
508 {
509 Cerr << type << "is not a type recognized by TRUST Unitaire " << finl;
511 }
512 int i= nb_classes;
513 while(i--)
514 {
515 const Type_info& mere = *les_types[i];
516 if( les_types[i]->same(type) )
517 {
518 return les_sous_types(mere, sous_types);
519 }
520 }
521 return 0;
522}
523
524/*! @brief Static method that returns a pointer to the Type_info whose name is "type_name".
525 *
526 * If type_name is not a known type, returns a null pointer.
527 *
528 */
529
530const Type_info * Type_info::type_info_from_name(const char * type_name)
531{
532 const Type_info * type_info = nullptr;
533 if (type_name != 0)
534 {
535 int index;
536 if (search_type_info_name(type_name, index))
537 {
538 if (types_homonymes[index] == 0)
539 {
540 type_info = les_types[index];
541 }
542 else
543 {
544 // The type is registered but the name corresponds
545 // to multiple types...
546 Cerr << "const Type_info * Type_info::type_info_from_name(const char * type_name)\n";
547 Cerr << " The type " << type_name << " has several homonymous\n";
548 Cerr << " We doing as if the type is unknown..." << finl;
549 }
550 }
551 }
552 return type_info;
553}
554
555/*! @brief Returns 1 if the associated type is instantiable (cree_instance is non-null), 0 otherwise.
556 *
557 */
559{
560 return (cree_instance != 0);
561}
562
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
An array of character strings (VECT(Nom)).
Definition Noms.h:26
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
Definition Sortie.h:52
static int est_un_synonyme(const char *)
Tests whether a class synonym exists: if there is a class T whose Synonyme_info has.
Models type information for Objet_U objects.
Definition Type_info.h:30
int instanciable() const
Returns 1 if the associated type is instantiable (cree_instance is non-null), 0 otherwise.
static int les_sous_types(const Nom &, Noms &sous_types)
Returns the names of the subtypes for a parent type identified by name.
Type_info(const char *name, Objet_U *(*f)(), int nb_bases=0, const Type_info **bases=0)
Constructor from a name, a factory function, and an array of base types.
Objet_U * instance() const
Creates an instance of the class associated with the type_info.
int has_base(const Type_info *p, int direct=0) const
Tests whether a type belongs to the base types of the considered type. If direct == 0,...
int same(const Type_info *p) const
Returns 1 if this==p, 0 otherwise.
static int est_un_type(const char *)
Tests whether a class of the given type exists. If a class T whose Type_info has the name nom exists,...
static Sortie & hierarchie(Sortie &)
Writes the full hierarchy of the considered type to an output stream.
static const Type_info * type_info_from_name(const char *type_name)
Static method that returns a pointer to the Type_info whose name is "type_name".
Sortie & bases(Sortie &) const
Writes the base types of the current type to an output stream.
const Nom & name() const
Definition Type_info.h:36