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_
37 // Classes manipulation
38 // -------------------
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
45 // Les classes présentes quatre méthodes :
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
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
68 // correspond au mapping corba des type any, struct,
69 // union, séquence en paramètre IN
70 typedef const T & CorbaInType;
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) {
79 // Pb si ownerShip == True car appel par l'utilisateur de relPointer !
80 static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
84 static inline void relPointer(InnerType * dataPtr) {
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);
92 static inline Type clone(CorbaInType data) {
96 // Operation de création
97 static inline Type create (size_t size=1) {
101 // Operation de destruction d'une donnee
102 static inline void delete_data(Type data) {
106 // Renvoie la taille de la donnée
107 static inline size_t size(Type data) {
111 // Dump de l'objet pour deboguage: neant car on ne connait pas sa structure
112 static inline void dump (CorbaInType data) {}
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
127 // correspond au mapping corba des types simples en paramètre IN
128 typedef T CorbaInType;
132 // Operation de recuperation des donnees venant de l'ORB : une copie par affectation simple
133 static inline Type get_data(CorbaInType data) {
137 static inline InnerType * const getPointer(Type & data, bool getOwnerShip = false) {
139 // if (getOwnerShip) {
140 // ptr =new InnerType[1];*ptr=data;
147 // static inline void relPointer(InnerType * dataPtr) {
152 // Je ne sais pas comment l'implémenter sans faire
154 //static inline InnerType * allocPointer(size_t size=1) {
155 // return new InnerType[1];
158 // Operation de clonage : une copie par affectation simple
159 static inline Type clone(Type data) {
163 // Inutile car Type == CorbaInType
164 // static inline Type clone(CorbaInType data) {
168 // Operation de création
169 // static inline Type create(size_t size=1,InnerType * data=NULL,
170 // bool giveOwnerShip=false) {
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
182 static inline size_t size(Type data) {
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;
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 {
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
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 &
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 !
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é.
231 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1 ------------------" << std::endl;
233 if ( data.release() ) {
234 InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
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).
240 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(0 copy) bis ------"<< p_data <<"------------" << std::endl;
243 return new seq_T (max, len, p_data, true);
246 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(recopie) bis ------"<< &data <<"------------" << std::endl;
248 // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
249 return new seq_T(data);
253 static inline size_t size(Type data) {
254 return data->length();
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()
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) ;
270 static inline Type clone(CorbaInType data) {
271 return new seq_T (data);
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) {
284 p_data = data->get_buffer(true);
287 p_data = data->get_buffer(false);
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);
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);
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 ) {
314 tmp = new seq_T(size,size,data,giveOwnerShip);
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 ) {
324 InnerType *dataPtr = getPointer(data,false);
326 for (int i = 0; i< isize; ++i)
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;
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 ) {
349 char* *dataPtr = getPointer(data,false);
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]);
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;
367 // TODO : Vérifier la conformité de l'implémentation par rapport
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 {
379 typedef seq_T * Type;
380 typedef const seq_T & CorbaInType;
381 typedef elem_T InnerType;
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);
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.
401 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Pas de Duplication -----------" << std::endl;
403 return new seq_T (len, p_data, true);
406 std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Duplication pour en devenir propriétaire -----------" << std::endl;
408 // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
409 return new seq_T(data);
413 static inline size_t size(Type data) {
414 return data->length();
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);
422 static inline Type clone(CorbaInType data) {
423 return new seq_T (data);
426 // Operation de destruction d'une donnee CORBA
427 static inline void delete_data(Type data) {
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) {
441 p_data = data->get_buffer(true);
444 p_data = data->get_buffer(false);
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
451 static inline void relPointer(InnerType * dataPtr) {
452 seq_T::freebuf(dataPtr);
455 // Permet d'allouer un buffer pour la séquence
456 static inline InnerType * allocPointer(size_t size ) {
457 return seq_T::allocbuf(size);
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 ) {
472 tmp = new seq_T(size,data,giveOwnerShip);
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;