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