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