Salome HOME
updated copyright message
[modules/kernel.git] / src / DSC / DSC_User / Datastream / CorbaTypeManipulator.hxx
1 // Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : CorbaTypeManipulator.hxx
24 //  Author : Eric Fayolle (EDF)
25 //  Module : KERNEL
26 // Modified by : $LastChangedBy$
27 // Date        : $LastChangedDate: 2007-02-07 18:26:44 +0100 (mer, 07 fév 2007) $
28 // Id          : $Id$
29 //
30 #ifndef _CORBA_TYPE_MANIPULATION_HXX_
31 #define _CORBA_TYPE_MANIPULATION_HXX_
32
33 #include "utilities.h"
34
35 #include <iostream>
36 #include <cstring>
37 #include <omniORB4/CORBA.h>
38
39 // Classes manipulation
40 // -------------------
41 //
42 // Ces différentes classes permettent d'unifier la manipulation des
43 // différents types de données dans un port datastream
44 // Les données sont maniées par valeur ou par pointeur 
45 // pour éviter les recopies de gros volume de données 
46
47 // Les classes présentes quatre méthodes :
48 // - clone
49 // - get_data
50 // - delete_data
51 // - dump
52 // et
53 // trois types :
54 // - Type      : Le type CORBA de la donnée manipulée
55 // - InType    : Le mapping CORBA pour un paramètre IN du type manipulé
56 // - InnerType : Type interne des valeurs d'un type contenant 
57
58 // Cette classe permet de manipuler des types CORBA 
59 // any, struct, union et sequence (utiliser plutôt les seq_manipulator)
60 // Ces types sont manipulés par pointeur.
61 // Les données reçues de CORBA sont systématiquement
62 // dupliquées pour être conservées.
63 // Quelque soit le type de donnée, les données sont considérées 
64 // comme une donnée unique (retour de size() == 1)
65 template <typename T >
66 class user_type_manipulation
67 {
68 public:
69   typedef T *       Type;
70   // correspond au mapping corba des type any, struct, 
71   //                  union, séquence en paramètre IN
72   typedef const T & CorbaInType; 
73   typedef T         InnerType;
74
75   // Operation de recuperation des donnees venant de l'ORB et
76   //  creation d'une copie (memoire spécialement allouee)
77   static inline Type get_data(CorbaInType data) {
78     return new T(data);
79   }
80
81   // Pb si ownerShip == True car appel par l'utilisateur de relPointer !
82   static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
83     return data;
84   }
85
86   static inline void relPointer(InnerType * dataPtr) {
87     delete dataPtr;
88   }
89
90   // Operation de clonage : par defaut, creation d'une copie en memoire allouee pour l'occasion
91   static inline Type clone(Type data) { 
92     return new T (* data);
93   } 
94   static inline Type clone(CorbaInType data) {
95     return new T (data);
96   }
97
98   // Operation de création
99   static inline Type create (size_t size=1) { 
100     return new T();
101   } 
102
103   // Operation de destruction d'une donnee
104   static inline void delete_data(Type data) {
105     delete data;
106   }
107   
108   // Renvoie la taille de la donnée
109   static inline size_t size(Type data) { 
110     return 1;
111   } 
112
113   // Dump de l'objet pour deboguage: neant car on ne connait pas sa structure
114   static inline void dump (CorbaInType data) {}
115 };
116
117
118 // Gére les types CORBA atomiques ('Int', 'Char', 'Float', ...)
119 // Gére les types enums
120 // Gére les références d'objets CORBA
121 // Ces types sont manipulés par valeur
122 // Les méthodes getPointer ... ne devrait pas être utilisée
123 // pour ce types de données
124 template <typename T>
125 class atom_manipulation
126 {
127 public:
128   typedef T Type;
129   // correspond au mapping corba des types simples en paramètre IN
130   typedef T CorbaInType; 
131   typedef T InnerType; 
132
133     
134   // Operation de recuperation des donnees venant de l'ORB : une copie par affectation simple
135   static inline Type get_data(CorbaInType data) {
136     return data;
137   }
138
139  static inline InnerType * const getPointer(Type & data, bool getOwnerShip = false) {
140 //    InnerType * ptr;
141 //     if (getOwnerShip) {
142 //       ptr =new InnerType[1];*ptr=data;
143 //       return ptr;
144 //     } else
145 //      return &data;
146    return &data;
147  }
148
149 //   static inline void relPointer(InnerType * dataPtr) {
150 //     return;
151 //         delete[] dataPtr;
152 //   }
153
154 // Je ne sais pas comment l'implémenter sans faire
155 // d'allocation heap
156 //static inline InnerType * allocPointer(size_t size=1) {
157 //    return  new InnerType[1];
158   //}
159
160   // Operation de clonage : une copie par affectation simple
161   static inline Type clone(Type data) {
162     return data;
163   }
164
165   // Inutile car Type == CorbaInType
166   //   static inline Type clone(CorbaInType data) {
167   //     return data;
168   //   }
169
170   // Operation de création
171 //   static inline Type create(size_t size=1,InnerType * data=NULL,
172 //                          bool giveOwnerShip=false) {
173 //     Type dummy;
174 //     if (dataPtr)
175 //       return *data;
176 //     else
177 //       return dummy;
178 //   } 
179     
180   // Operation de destruction d'une donnee: rien a faire car pas de memoire a liberer
181   static inline void delete_data(Type /*data*/) {}
182     // Renvoie la taille de la donnée
183
184   static inline size_t size(Type data) { 
185     return 1;
186   } 
187
188   // Dump de l'objet pour deboguage : Affiche la donnee
189   static void inline dump (CorbaInType data) {
190     std::cerr << "[atom_manipulation] Data : " << data << std::endl;
191   }
192 };
193
194
195 // Gére un type sequence de taille illimitee (Unbounded)
196 // Ces types sont manipulés par pointeur
197 template <typename seq_T,typename elem_T>
198 class seq_u_manipulation {
199   
200 public:
201   typedef seq_T *       Type;        // Type de donnée abstrait manipulé par GenericPort::Put,Get,..
202   typedef const seq_T & CorbaInType; // Mapping corba de la séquence en paramètre IN
203   typedef elem_T        InnerType;   // Il n'existe pas dans CORBA de seq_T::elem_T
204                                      // C'est la raison d'être du second paramètre template de seq_u_mani
205  
206   // Operation de recuperation des donnees venant de l'ORB
207   // Remarque : On a un paramètre d'entrée de type const seq_T &
208   //            et en sortie un seq_T *
209   static inline Type get_data(CorbaInType data) {
210     CORBA::Long len = data.length();
211     CORBA::Long max = data.maximum();
212     // Récupère et devient propriétaire des données reçues dans la séquence. 
213     // La séquence reçue (mais pas le buffer) sera désallouée au retour 
214     // de la méthode CORBA qui a reçu le type CorbaInType en paramètre
215     // (ex: GenericPort::put)
216     // REM : Le mapping CORBA du type séquence IN est : const seq &
217
218     // OLD : On ne teste pas si le flag release de la séquence est à true ou false 
219     // OLD : ( pour des séquences de chaines ou d'objrefs )
220     // OLD :   -> Si on est collocalisé le port uses doit créer une copie pour éviter la modification
221     // OLD : du contenu de la séquence lorsque l'utilisateur modifie ses données dans son programme (0 copie)
222     // OLD : ATTENTION TESTER p194 si le pointeur est null (release flag==false)
223     // OLD :   -> La séquence n'était pas propriétaire des données !
224
225     // Le flag release() de la séquence est à false si elle n'est pas propriétaire du buffer
226     // En  collocalité release() renvoie false car 
227     // l'appelé n'est pas propriétaire de la séquence. On effectue alors
228     // une copie pour éviter de perturber les structures de données de l'appelant.
229     // En non collocalisé on recrée une séquence avec le buffer de la première dont on
230     // a demandé la propriété.
231
232     if (SALOME::VerbosityActivated())
233       std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1 ------------------" << std::endl;
234
235     if ( data.release() ) {
236       InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
237
238     // Crée une nouvelle sequence propriétaire des données du buffer (pas de recopie)
239     // Les données de la nouvelle séquence seront automatiquement désallouées 
240     // par appel à la méthode freebuf dans le destructeur de la séquence (cf  delete_data).
241     if (SALOME::VerbosityActivated())
242       std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(0 copy) bis ------" <<  p_data << "------------" << std::endl;
243     
244       return  new seq_T (max, len, p_data, true);
245     }
246
247     if (SALOME::VerbosityActivated())
248       std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(recopie) bis ------" <<  &data << "------------" << std::endl;
249
250     // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)    
251     return new seq_T(data);
252
253   }
254
255   static inline size_t size(Type data) { 
256     return data->length();
257   } 
258
259   // Operation de destruction d'une donnee
260   static inline void delete_data(Type data) {
261     //La séquence est détruite par appel à son destructeur
262     //Ce destructeur prend en compte la nécessité de détruire ou non
263     //les données contenues en fonction de son flag interne release()
264     delete data;
265   }
266
267   // Operation de clonage : par defaut creation d'une copie en memoire allouee pour l'occasion
268   // Utilisation du constructeur du type seq_T
269   static inline Type clone(Type data) {
270     return new seq_T (*data) ;
271   }
272   static inline Type clone(CorbaInType data) {
273     return new seq_T (data);
274   }
275
276   // Permet d'obtenir un pointeur sur le buffer de la séquence :
277   // Si ownerShip=True, la séquence n'est plus propriétaire du buffer
278   //         (son pointeur de buffer interne est aussi réinitialisé) 
279   //       On détruit également explicitement la séquence (mais pas le buffer !)
280   // Si ownerShip=False, la séquence reste propriétaire du buffer
281   //    et l'utilisateur devra appeler delete_data sur la séquence contenante pour
282   //    détruire à la fois la séquence et le buffer contenu.
283   static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
284     InnerType * p_data;
285     if (ownerShip) {
286       p_data = data->get_buffer(true);
287       delete_data(data);
288     } else
289       p_data = data->get_buffer(false);
290     return p_data;
291   }
292
293   // Permet de désallouer le buffer dont on détient le pointeur après appel
294   // à la méthode getPointer avec ownerShip=True 
295   static inline void relPointer(InnerType * dataPtr) {
296     seq_T::freebuf(dataPtr);
297   }
298
299   // Permet d'allouer un buffer compatible avec le type séquence
300   static inline InnerType *  allocPointer(size_t size ) {
301     return seq_T::allocbuf(size);
302   }
303
304   // Opération de création de la séquence CORBA soit
305   // - Vide et de taille size
306   // - Utilisant les données du pointeur *data de taille size 
307   // (généralement pas de recopie qlq soit l'ownership )
308   // data doit avoir été alloué par allocPointer si giveOwnerShip = true  
309   static inline Type create(size_t size, InnerType * const data = NULL,
310                             bool giveOwnerShip = false ) { 
311     Type tmp;
312     if (!data) {
313       tmp = new seq_T();
314       tmp->length(size);
315     } else {
316       tmp = new seq_T(size,size,data,giveOwnerShip); 
317     }
318     return tmp;
319   } 
320
321   // Copie le contenu de la séquence dans le buffer idata de taille isize
322   // pour les types non pointeur
323   template <typename T >
324   static inline void copy( Type data, T * const idata, size_t isize ) { 
325     
326     InnerType *dataPtr  = getPointer(data,false);
327
328     for (size_t i = 0; i< isize; ++i) 
329       idata[i]=dataPtr[i];
330
331     // Le mode de recopie suivant ne permet pas  la conversion de type (ex int -> CORBA::Long)
332     //OLD:     Type tmp = new seq_T(isize,isize,idata,false); 
333     //OLD:     // giveOwnerShip == false -> seul le contenu du buffer data est détruit et remplacé
334     //OLD:     // par celui de data dans l'affectation suivante :
335     //OLD:     //       ---> ATTENTION SI LA TAILLE DU BUFFER EST TROP PETITE, QUE FAIT CORBA !
336     //OLD:     //              corruption mémoire
337     //OLD:     // Cependant ce cas devrait pas arrivé (on s'assure dans les couches supérieures
338     //OLD:     //  de la taille correcte du buffer de recopie)
339     //OLD:     // Si giveOwnerShip était == true -> le buffer et son contenu serait détruit puis une 
340     //OLD:     // allocation de la taille du buffer de data serait effectué avant la copie des données  
341     //OLD:     // tmp = data;
342   } 
343
344   // Copie le contenu de la séquence de char* dans le buffer idata de taille isize
345   // La généralisation de la recopie profonde est difficile du fait que CORBA ne renvoie pas
346   // pas des objets de haut niveau de type std::vector<std::string> (avec des  interfaces d'accès identiques) 
347   // mais un type simple C comme char *Tab[N]. On doit alors utiliser une méthode de recopie spécifique
348   // comme l'appel C strcpy.
349   static inline void copy( Type data, char* * const idata, size_t isize ) { 
350
351     char* *dataPtr  = getPointer(data,false);
352
353     // Si idata[i] n'a pas été alloué suffisament grand,
354     // il y a corruption de la mémoire
355     for (size_t i = 0; i< isize; ++i) 
356       strcpy(idata[i],dataPtr[i]);
357   }
358   
359   // Dump de l'objet pour deboguage
360   static void inline dump (CorbaInType data) {
361     // Affiche la longueur des donnees
362     std::cerr << "[seq_u_manipulation] Data length: " << data.length() << std::endl;
363     // Affiche la longueur des donnees
364     std::cerr << "[seq_u_manipulation] Data max: " << data.maximum() << std::endl;
365   }
366 };
367
368
369 // TODO : Vérifier la conformité de l'implémentation par rapport
370 //        au type unbounded
371
372 // Gére un type sequence de taille limitée (bounded)
373 // Ces types sont manipulés par pointeur
374 // Cette classe diffère de la seq_u_manipulation
375 // par la signature du constructeur de la séquence
376 // utilisé dans le methode get_data
377 template <typename seq_T,typename elem_T>
378 class seq_b_manipulation {
379   
380 public:
381   typedef seq_T *       Type;
382   typedef const seq_T & CorbaInType;
383   typedef elem_T        InnerType;
384
385
386   // Operation de recuperation des donnees venant de l'ORB
387   // Sans opération de notre part, ces données seraient perdues
388   // au retour de la méthode put de GenericPort.
389   // Remarque : On a un paramètre d'entrée de type const seq_T &
390   //            et en sortie un seq_T *
391   static inline Type get_data(CorbaInType data) {
392     CORBA::Long len = data.length();
393     // Récupère et devient propriétaire des données reçues dans la séquence 
394     // la séquence sera désalloué (mais pas le buffer)
395     // au retour de la méthode put (car mapping de type IN : const seq & )
396     if ( data.release() ) {
397       InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
398
399       // Crée une nouvelle sequence propriétaire des données du buffer (généralement pas de recopie)
400       // Les données seront automatiquement désallouées par appel interne à la méthode freebuf
401       // lors de la destruction de l'objet par appel à delete_data.
402       if (SALOME::VerbosityActivated())
403         std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Pas de Duplication  -----------" << std::endl;
404
405       return new seq_T (len, p_data, true);
406     }
407
408     if (SALOME::VerbosityActivated())
409       std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Duplication pour en devenir propriétaire -----------" << std::endl;
410
411     // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)    
412     return new seq_T(data);
413   }
414
415   static inline size_t size(Type data) { 
416     return data->length();
417   } 
418
419   // Operation de clonage : par defaut creation d'une copie en memoire allouee pour l'occasion
420   // Utilisation du constructeur du type seq_T  
421   static inline Type clone(Type data) {
422     return new seq_T (* data);
423   }
424   static inline Type clone(CorbaInType data) {
425     return new seq_T (data);
426   }
427
428   // Operation de destruction d'une donnee CORBA
429   static inline void delete_data(Type data) {
430     delete data;
431   }
432
433   // Permet d'obtenir un pointeur sur le buffer de la séquence :
434   // Si ownerShip=True, la séquence n'est plus propriétaire du buffer
435   //         (son pointeur de buffer interne est aussi réinitialisé) 
436   //       On détruit également explicitement la séquence (mais pas le buffer !)
437   // Si ownerShip=False, la séquence reste propriétaire du buffer
438   //    et l'utilisateur devra appeler delete_data sur la séquence contenante pour
439   //    détruire à la fois la séquence et le buffer contenu.
440   static inline InnerType * const getPointer(Type data, bool getOwnerShip = false) {
441     InnerType * p_data;
442     if (getOwnerShip) {
443       p_data = data->get_buffer(true);
444       delete_data(data);
445     } else
446       p_data = data->get_buffer(false);
447     return p_data;
448   }
449
450   // Permet de désallouer le buffer dont on détient le pointeur par appel
451   // à la méthode getPointer avec ownerShip=True si la séquence contenante
452   // à été détruite.
453   static inline void relPointer(InnerType * dataPtr) {
454     seq_T::freebuf(dataPtr);
455   }
456
457   // Permet d'allouer un buffer pour la séquence
458   static inline InnerType *  allocPointer(size_t size ) {
459     return seq_T::allocbuf(size);
460   }
461
462   // Operation de création du type corba soit
463   // - Vide et de taille size
464   // - Utilisant les données du pointeur *data de taille size 
465   // (généralement pas de recopie qlq soit l'ownership )
466   // data doit avoir été alloué par allocPointer si giveOwnerShip = true  
467   static inline Type create(size_t size, InnerType * const data = NULL,
468                             bool giveOwnerShip = false ) { 
469     Type tmp;
470     if (!data) {
471       tmp = new seq_T();
472       tmp->length(size);
473     } else {
474       tmp = new seq_T(size,data,giveOwnerShip); 
475     }
476     return tmp;
477   } 
478
479   
480   // Dump de l'objet pour deboguage
481   static inline void dump (CorbaInType data) {
482     // Affiche la longueur des donnees
483     std::cerr << "[seq_b_manipulation] Data length: " << data.length() << std::endl;
484   }
485 };
486
487 #endif