1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, 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.
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
22 // File : CorbaTypeManipulator.hxx
23 // Author : Eric Fayolle (EDF)
25 // Modified by : $LastChangedBy$
26 // Date : $LastChangedDate: 2007-02-07 18:26:44 +0100 (mer, 07 fév 2007) $
29 #ifndef _CORBA_TYPE_MANIPULATION_HXX_
30 #define _CORBA_TYPE_MANIPULATION_HXX_
38 // Classes manipulation
39 // -------------------
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
46 // Les classes présentes quatre méthodes :
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
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
69 // correspond au mapping corba des type any, struct,
70 // union, séquence en paramètre IN
71 typedef const T & CorbaInType;
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) {
80 // Pb si ownerShip == True car appel par l'utilisateur de relPointer !
81 static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
85 static inline void relPointer(InnerType * dataPtr) {
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);
93 static inline Type clone(CorbaInType data) {
97 // Operation de création
98 static inline Type create (size_t size=1) {
102 // Operation de destruction d'une donnee
103 static inline void delete_data(Type data) {
107 // Renvoie la taille de la donnée
108 static inline size_t size(Type data) {
112 // Dump de l'objet pour deboguage: neant car on ne connait pas sa structure
113 static inline void dump (CorbaInType data) {}
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
128 // correspond au mapping corba des types simples en paramètre IN
129 typedef T CorbaInType;
133 // Operation de recuperation des donnees venant de l'ORB : une copie par affectation simple
134 static inline Type get_data(CorbaInType data) {
138 static inline InnerType * const getPointer(Type & data, bool getOwnerShip = false) {
140 // if (getOwnerShip) {
141 // ptr =new InnerType[1];*ptr=data;
148 // static inline void relPointer(InnerType * dataPtr) {
153 // Je ne sais pas comment l'implémenter sans faire
155 //static inline InnerType * allocPointer(size_t size=1) {
156 // return new InnerType[1];
159 // Operation de clonage : une copie par affectation simple
160 static inline Type clone(Type data) {
164 // Inutile car Type == CorbaInType
165 // static inline Type clone(CorbaInType data) {
169 // Operation de création
170 // static inline Type create(size_t size=1,InnerType * data=NULL,
171 // bool giveOwnerShip=false) {
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
183 static inline size_t size(Type data) {
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;
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 {
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
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 &
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 !
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é.
232 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1 ------------------" << std::endl;
234 if ( data.release() ) {
235 InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
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).
241 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 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(recopie) bis ------"<< &data <<"------------" << std::endl;
249 // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
250 return new seq_T(data);
254 static inline size_t size(Type data) {
255 return data->length();
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()
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) ;
271 static inline Type clone(CorbaInType data) {
272 return new seq_T (data);
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) {
285 p_data = data->get_buffer(true);
288 p_data = data->get_buffer(false);
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);
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);
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 ) {
315 tmp = new seq_T(size,size,data,giveOwnerShip);
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 ) {
325 InnerType *dataPtr = getPointer(data,false);
327 for (int i = 0; i< isize; ++i)
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;
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 ) {
350 char* *dataPtr = getPointer(data,false);
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]);
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;
368 // TODO : Vérifier la conformité de l'implémentation par rapport
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 {
380 typedef seq_T * Type;
381 typedef const seq_T & CorbaInType;
382 typedef elem_T InnerType;
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);
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.
402 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Pas de Duplication -----------" << std::endl;
404 return new seq_T (len, p_data, true);
407 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Duplication pour en devenir propriétaire -----------" << std::endl;
409 // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
410 return new seq_T(data);
414 static inline size_t size(Type data) {
415 return data->length();
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);
423 static inline Type clone(CorbaInType data) {
424 return new seq_T (data);
427 // Operation de destruction d'une donnee CORBA
428 static inline void delete_data(Type data) {
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) {
442 p_data = data->get_buffer(true);
445 p_data = data->get_buffer(false);
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
452 static inline void relPointer(InnerType * dataPtr) {
453 seq_T::freebuf(dataPtr);
456 // Permet d'allouer un buffer pour la séquence
457 static inline InnerType * allocPointer(size_t size ) {
458 return seq_T::allocbuf(size);
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 ) {
473 tmp = new seq_T(size,data,giveOwnerShip);
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;