1 // Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : CorbaTypeManipulator.hxx
24 // Author : Eric Fayolle (EDF)
26 // Modified by : $LastChangedBy$
27 // Date : $LastChangedDate: 2007-02-07 18:26:44 +0100 (mer, 07 fév 2007) $
30 #ifndef _CORBA_TYPE_MANIPULATION_HXX_
31 #define _CORBA_TYPE_MANIPULATION_HXX_
33 #include "utilities.h"
37 #include <omniORB4/CORBA.h>
39 // Classes manipulation
40 // -------------------
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
47 // Les classes présentes quatre méthodes :
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
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
70 // correspond au mapping corba des type any, struct,
71 // union, séquence en paramètre IN
72 typedef const T & CorbaInType;
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) {
81 // Pb si ownerShip == True car appel par l'utilisateur de relPointer !
82 static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
86 static inline void relPointer(InnerType * dataPtr) {
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);
94 static inline Type clone(CorbaInType data) {
98 // Operation de création
99 static inline Type create (size_t size=1) {
103 // Operation de destruction d'une donnee
104 static inline void delete_data(Type data) {
108 // Renvoie la taille de la donnée
109 static inline size_t size(Type data) {
113 // Dump de l'objet pour deboguage: neant car on ne connait pas sa structure
114 static inline void dump (CorbaInType data) {}
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
129 // correspond au mapping corba des types simples en paramètre IN
130 typedef T CorbaInType;
134 // Operation de recuperation des donnees venant de l'ORB : une copie par affectation simple
135 static inline Type get_data(CorbaInType data) {
139 static inline InnerType * const getPointer(Type & data, bool getOwnerShip = false) {
141 // if (getOwnerShip) {
142 // ptr =new InnerType[1];*ptr=data;
149 // static inline void relPointer(InnerType * dataPtr) {
154 // Je ne sais pas comment l'implémenter sans faire
156 //static inline InnerType * allocPointer(size_t size=1) {
157 // return new InnerType[1];
160 // Operation de clonage : une copie par affectation simple
161 static inline Type clone(Type data) {
165 // Inutile car Type == CorbaInType
166 // static inline Type clone(CorbaInType data) {
170 // Operation de création
171 // static inline Type create(size_t size=1,InnerType * data=NULL,
172 // bool giveOwnerShip=false) {
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
184 static inline size_t size(Type data) {
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;
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 {
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
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 &
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 !
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é.
232 if (SALOME::VerbosityActivated())
233 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1 ------------------" << std::endl;
235 if ( data.release() ) {
236 InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
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;
244 return new seq_T (max, len, p_data, true);
247 if (SALOME::VerbosityActivated())
248 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(recopie) bis ------" << &data << "------------" << std::endl;
250 // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
251 return new seq_T(data);
255 static inline size_t size(Type data) {
256 return data->length();
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()
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) ;
272 static inline Type clone(CorbaInType data) {
273 return new seq_T (data);
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) {
286 p_data = data->get_buffer(true);
289 p_data = data->get_buffer(false);
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);
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);
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 ) {
316 tmp = new seq_T(size,size,data,giveOwnerShip);
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 ) {
326 InnerType *dataPtr = getPointer(data,false);
328 for (size_t i = 0; i< isize; ++i)
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;
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 ) {
351 char* *dataPtr = getPointer(data,false);
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]);
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;
369 // TODO : Vérifier la conformité de l'implémentation par rapport
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 {
381 typedef seq_T * Type;
382 typedef const seq_T & CorbaInType;
383 typedef elem_T InnerType;
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);
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;
405 return new seq_T (len, p_data, true);
408 if (SALOME::VerbosityActivated())
409 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Duplication pour en devenir propriétaire -----------" << std::endl;
411 // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
412 return new seq_T(data);
415 static inline size_t size(Type data) {
416 return data->length();
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);
424 static inline Type clone(CorbaInType data) {
425 return new seq_T (data);
428 // Operation de destruction d'une donnee CORBA
429 static inline void delete_data(Type data) {
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) {
443 p_data = data->get_buffer(true);
446 p_data = data->get_buffer(false);
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
453 static inline void relPointer(InnerType * dataPtr) {
454 seq_T::freebuf(dataPtr);
457 // Permet d'allouer un buffer pour la séquence
458 static inline InnerType * allocPointer(size_t size ) {
459 return seq_T::allocbuf(size);
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 ) {
474 tmp = new seq_T(size,data,giveOwnerShip);
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;