Back to index

salome-kernel  6.5.0
CorbaTypeManipulator.hxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  File   : CorbaTypeManipulator.hxx
00024 //  Author : Eric Fayolle (EDF)
00025 //  Module : KERNEL
00026 // Modified by : $LastChangedBy$
00027 // Date        : $LastChangedDate: 2007-02-07 18:26:44 +0100 (mer, 07 fév 2007) $
00028 // Id          : $Id: CorbaTypeManipulator.hxx,v 1.3.2.2.10.2.12.1 2012-04-12 14:05:06 vsr Exp $
00029 //
00030 #ifndef _CORBA_TYPE_MANIPULATION_HXX_
00031 #define _CORBA_TYPE_MANIPULATION_HXX_
00032 
00033 #include <iostream>
00034 #include <cstring>
00035 #include <CORBA.h>
00036 
00037 //#define MYDEBUG
00038 
00039 // Classes manipulation
00040 // -------------------
00041 //
00042 // Ces différentes classes permettent d'unifier la manipulation des
00043 // différents types de données dans un port datastream
00044 // Les données sont maniées par valeur ou par pointeur 
00045 // pour éviter les recopies de gros volume de données 
00046 
00047 // Les classes présentes quatre méthodes :
00048 // - clone
00049 // - get_data
00050 // - delete_data
00051 // - dump
00052 // et
00053 // trois types :
00054 // - Type      : Le type CORBA de la donnée manipulée
00055 // - InType    : Le mapping CORBA pour un paramètre IN du type manipulé
00056 // - InnerType : Type interne des valeurs d'un type contenant 
00057 
00058 // Cette classe permet de manipuler des types CORBA 
00059 // any, struct, union et sequence (utiliser plutôt les seq_manipulator)
00060 // Ces types sont manipulés par pointeur.
00061 // Les données reçues de CORBA sont systématiquement
00062 // dupliquées pour être conservées.
00063 // Quelque soit le type de donnée, les données sont considérées 
00064 // comme une donnée unique (retour de size() == 1)
00065 template <typename T >
00066 class user_type_manipulation
00067 {
00068 public:
00069   typedef T *       Type;
00070   // correspond au mapping corba des type any, struct, 
00071   //                  union, séquence en paramètre IN
00072   typedef const T & CorbaInType; 
00073   typedef T         InnerType;
00074 
00075   // Operation de recuperation des donnees venant de l'ORB et
00076   //  creation d'une copie (memoire spécialement allouee)
00077   static inline Type get_data(CorbaInType data) {
00078     return new T(data);
00079   }
00080 
00081   // Pb si ownerShip == True car appel par l'utilisateur de relPointer !
00082   static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
00083     return data;
00084   }
00085 
00086   static inline void relPointer(InnerType * dataPtr) {
00087     delete dataPtr;
00088   }
00089 
00090   // Operation de clonage : par defaut, creation d'une copie en memoire allouee pour l'occasion
00091   static inline Type clone(Type data) { 
00092     return new T (* data);
00093   } 
00094   static inline Type clone(CorbaInType data) {
00095     return new T (data);
00096   }
00097 
00098   // Operation de création
00099   static inline Type create (size_t size=1) { 
00100     return new T();
00101   } 
00102 
00103   // Operation de destruction d'une donnee
00104   static inline void delete_data(Type data) {
00105     delete data;
00106   }
00107   
00108   // Renvoie la taille de la donnée
00109   static inline size_t size(Type data) { 
00110     return 1;
00111   } 
00112 
00113   // Dump de l'objet pour deboguage: neant car on ne connait pas sa structure
00114   static inline void dump (CorbaInType data) {}
00115 };
00116 
00117 
00118 // Gére les types CORBA atomiques ('Int', 'Char', 'Float', ...)
00119 // Gére les types enums
00120 // Gére les références d'objets CORBA
00121 // Ces types sont manipulés par valeur
00122 // Les méthodes getPointer ... ne devrait pas être utilisée
00123 // pour ce types de données
00124 template <typename T>
00125 class atom_manipulation
00126 {
00127 public:
00128   typedef T Type;
00129   // correspond au mapping corba des types simples en paramètre IN
00130   typedef T CorbaInType; 
00131   typedef T InnerType; 
00132 
00133     
00134   // Operation de recuperation des donnees venant de l'ORB : une copie par affectation simple
00135   static inline Type get_data(CorbaInType data) {
00136     return data;
00137   }
00138 
00139  static inline InnerType * const getPointer(Type & data, bool getOwnerShip = false) {
00140 //    InnerType * ptr;
00141 //     if (getOwnerShip) {
00142 //       ptr =new InnerType[1];*ptr=data;
00143 //       return ptr;
00144 //     } else
00145 //      return &data;
00146    return &data;
00147  }
00148 
00149 //   static inline void relPointer(InnerType * dataPtr) {
00150 //     return;
00151 //         delete[] dataPtr;
00152 //   }
00153 
00154 // Je ne sais pas comment l'implémenter sans faire
00155 // d'allocation heap
00156 //static inline InnerType * allocPointer(size_t size=1) {
00157 //    return  new InnerType[1];
00158   //}
00159 
00160   // Operation de clonage : une copie par affectation simple
00161   static inline Type clone(Type data) {
00162     return data;
00163   }
00164 
00165   // Inutile car Type == CorbaInType
00166   //   static inline Type clone(CorbaInType data) {
00167   //     return data;
00168   //   }
00169 
00170   // Operation de création
00171 //   static inline Type create(size_t size=1,InnerType * data=NULL,
00172 //                          bool giveOwnerShip=false) {
00173 //     Type dummy;
00174 //     if (dataPtr)
00175 //       return *data;
00176 //     else
00177 //       return dummy;
00178 //   } 
00179     
00180   // Operation de destruction d'une donnee: rien a faire car pas de memoire a liberer
00181   static inline void delete_data(Type data) {}
00182     // Renvoie la taille de la donnée
00183 
00184   static inline size_t size(Type data) { 
00185     return 1;
00186   } 
00187 
00188   // Dump de l'objet pour deboguage : Affiche la donnee
00189   static void inline dump (CorbaInType data) {
00190     std::cerr << "[atom_manipulation] Data : " << data << std::endl;
00191   }
00192 };
00193 
00194 
00195 // Gére un type sequence de taille illimitee (Unbounded)
00196 // Ces types sont manipulés par pointeur
00197 template <typename seq_T,typename elem_T>
00198 class seq_u_manipulation {
00199   
00200 public:
00201   typedef seq_T *       Type;        // Type de donnée abstrait manipulé par GenericPort::Put,Get,..
00202   typedef const seq_T & CorbaInType; // Mapping corba de la séquence en paramètre IN
00203   typedef elem_T        InnerType;   // Il n'existe pas dans CORBA de seq_T::elem_T
00204                                      // C'est la raison d'être du second paramètre template de seq_u_mani
00205  
00206   // Operation de recuperation des donnees venant de l'ORB
00207   // Remarque : On a un paramètre d'entrée de type const seq_T &
00208   //            et en sortie un seq_T *
00209   static inline Type get_data(CorbaInType data) {
00210     CORBA::Long len = data.length();
00211     CORBA::Long max = data.maximum();
00212     // Récupère et devient propriétaire des données reçues dans la séquence. 
00213     // La séquence reçue (mais pas le buffer) sera désallouée au retour 
00214     // de la méthode CORBA qui a reçu le type CorbaInType en paramètre
00215     // (ex: GenericPort::put)
00216     // REM : Le mapping CORBA du type séquence IN est : const seq &
00217 
00218     // OLD : On ne teste pas si le flag release de la séquence est à true ou false 
00219     // OLD : ( pour des séquences de chaines ou d'objrefs )
00220     // OLD :   -> Si on est collocalisé le port uses doit créer une copie pour éviter la modification
00221     // OLD : du contenu de la séquence lorsque l'utilisateur modifie ses données dans son programme (0 copie)
00222     // OLD : ATTENTION TESTER p194 si le pointeur est null (release flag==false)
00223     // OLD :   -> La séquence n'était pas propriétaire des données !
00224 
00225     // Le flag release() de la séquence est à false si elle n'est pas propriétaire du buffer
00226     // En  collocalité release() renvoie false car 
00227     // l'appelé n'est pas propriétaire de la séquence. On effectue alors
00228     // une copie pour éviter de perturber les structures de données de l'appelant.
00229     // En non collocalisé on recrée une séquence avec le buffer de la première dont on
00230     // a demandé la propriété.
00231 
00232 #ifdef MYDEBUG
00233     std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1 ------------------" << std::endl;
00234 #endif
00235     if ( data.release() ) {
00236       InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
00237 
00238     // Crée une nouvelle sequence propriétaire des données du buffer (pas de recopie)
00239     // Les données de la nouvelle séquence seront automatiquement désallouées 
00240     // par appel à la méthode freebuf dans le destructeur de la séquence (cf  delete_data).
00241 #ifdef MYDEBUG
00242       std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(0 copy) bis ------"<<  p_data <<"------------" << std::endl;
00243 #endif
00244     
00245       return  new seq_T (max, len, p_data, true);
00246     }
00247 #ifdef MYDEBUG
00248     std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(recopie) bis ------"<<  &data <<"------------" << std::endl;
00249 #endif
00250     // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)    
00251     return new seq_T(data);
00252 
00253   }
00254 
00255   static inline size_t size(Type data) { 
00256     return data->length();
00257   } 
00258 
00259   // Operation de destruction d'une donnee
00260   static inline void delete_data(Type data) {
00261     //La séquence est détruite par appel à son destructeur
00262     //Ce destructeur prend en compte la nécessité de détruire ou non
00263     //les données contenues en fonction de son flag interne release()
00264     delete data;
00265   }
00266 
00267   // Operation de clonage : par defaut creation d'une copie en memoire allouee pour l'occasion
00268   // Utilisation du constructeur du type seq_T
00269   static inline Type clone(Type data) {
00270     return new seq_T (*data) ;
00271   }
00272   static inline Type clone(CorbaInType data) {
00273     return new seq_T (data);
00274   }
00275 
00276   // Permet d'obtenir un pointeur sur le buffer de la séquence :
00277   // Si ownerShip=True, la séquence n'est plus propriétaire du buffer
00278   //         (son pointeur de buffer interne est aussi réinitialisé) 
00279   //       On détruit également explicitement la séquence (mais pas le buffer !)
00280   // Si ownerShip=False, la séquence reste propriétaire du buffer
00281   //    et l'utilisateur devra appeler delete_data sur la séquence contenante pour
00282   //    détruire à la fois la séquence et le buffer contenu.
00283   static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
00284     InnerType * p_data;
00285     if (ownerShip) {
00286       p_data = data->get_buffer(true);
00287       delete_data(data);
00288     } else
00289       p_data = data->get_buffer(false);
00290     return p_data;
00291   }
00292 
00293   // Permet de désallouer le buffer dont on détient le pointeur après appel
00294   // à la méthode getPointer avec ownerShip=True 
00295   static inline void relPointer(InnerType * dataPtr) {
00296     seq_T::freebuf(dataPtr);
00297   }
00298 
00299   // Permet d'allouer un buffer compatible avec le type séquence
00300   static inline InnerType *  allocPointer(size_t size ) {
00301     return seq_T::allocbuf(size);
00302   }
00303 
00304   // Opération de création de la séquence CORBA soit
00305   // - Vide et de taille size
00306   // - Utilisant les données du pointeur *data de taille size 
00307   // (généralement pas de recopie qlq soit l'ownership )
00308   // data doit avoir été alloué par allocPointer si giveOwnerShip = true  
00309   static inline Type create(size_t size, InnerType * const data = NULL,
00310                             bool giveOwnerShip = false ) { 
00311     Type tmp;
00312     if (!data) {
00313       tmp = new seq_T();
00314       tmp->length(size);
00315     } else {
00316       tmp = new seq_T(size,size,data,giveOwnerShip); 
00317     }
00318     return tmp;
00319   } 
00320 
00321   // Copie le contenu de la séquence dans le buffer idata de taille isize
00322   // pour les types non pointeur
00323   template <typename T >
00324   static inline void copy( Type data, T * const idata, size_t isize ) { 
00325     
00326     InnerType *dataPtr  = getPointer(data,false);
00327 
00328     for (int i = 0; i< isize; ++i) 
00329       idata[i]=dataPtr[i];
00330 
00331     // Le mode de recopie suivant ne permet pas  la conversion de type (ex int -> CORBA::Long)
00332     //OLD:     Type tmp = new seq_T(isize,isize,idata,false); 
00333     //OLD:     // giveOwnerShip == false -> seul le contenu du buffer data est détruit et remplacé
00334     //OLD:     // par celui de data dans l'affectation suivante :
00335     //OLD:     //       ---> ATTENTION SI LA TAILLE DU BUFFER EST TROP PETITE, QUE FAIT CORBA !
00336     //OLD:     //              corruption mémoire
00337     //OLD:     // Cependant ce cas devrait pas arrivé (on s'assure dans les couches supérieures
00338     //OLD:     //  de la taille correcte du buffer de recopie)
00339     //OLD:     // Si giveOwnerShip était == true -> le buffer et son contenu serait détruit puis une 
00340     //OLD:     // allocation de la taille du buffer de data serait effectué avant la copie des données  
00341     //OLD:     // tmp = data;
00342   } 
00343 
00344   // Copie le contenu de la séquence de char* dans le buffer idata de taille isize
00345   // La généralisation de la recopie profonde est difficile du fait que CORBA ne renvoie pas
00346   // pas des objets de haut niveau de type std::vector<std::string> (avec des  interfaces d'accès identiques) 
00347   // mais un type simple C comme char *Tab[N]. On doit alors utiliser une méthode de recopie spécifique
00348   // comme l'appel C strcpy.
00349   static inline void copy( Type data, char* * const idata, size_t isize ) { 
00350 
00351     char* *dataPtr  = getPointer(data,false);
00352 
00353     // Si idata[i] n'a pas été alloué suffisament grand,
00354     // il y a corruption de la mémoire
00355     for (int i = 0; i< isize; ++i) 
00356       strcpy(idata[i],dataPtr[i]);
00357   }
00358   
00359   // Dump de l'objet pour deboguage
00360   static void inline dump (CorbaInType data) {
00361     // Affiche la longueur des donnees
00362     std::cerr << "[seq_u_manipulation] Data length: " << data.length() << std::endl;
00363     // Affiche la longueur des donnees
00364     std::cerr << "[seq_u_manipulation] Data max: " << data.maximum() << std::endl;
00365   }
00366 };
00367 
00368 
00369 // TODO : Vérifier la conformité de l'implémentation par rapport
00370 //        au type unbounded
00371 
00372 // Gére un type sequence de taille limitée (bounded)
00373 // Ces types sont manipulés par pointeur
00374 // Cette classe diffère de la seq_u_manipulation
00375 // par la signature du constructeur de la séquence
00376 // utilisé dans le methode get_data
00377 template <typename seq_T,typename elem_T>
00378 class seq_b_manipulation {
00379   
00380 public:
00381   typedef seq_T *       Type;
00382   typedef const seq_T & CorbaInType;
00383   typedef elem_T        InnerType;
00384 
00385 
00386   // Operation de recuperation des donnees venant de l'ORB
00387   // Sans opération de notre part, ces données seraient perdues
00388   // au retour de la méthode put de GenericPort.
00389   // Remarque : On a un paramètre d'entrée de type const seq_T &
00390   //            et en sortie un seq_T *
00391   static inline Type get_data(CorbaInType data) {
00392     CORBA::Long len = data.length();
00393     // Récupère et devient propriétaire des données reçues dans la séquence 
00394     // la séquence sera désalloué (mais pas le buffer)
00395     // au retour de la méthode put (car mapping de type IN : const seq & )
00396      if ( data.release() ) {
00397        InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
00398 
00399     // Crée une nouvelle sequence propriétaire des données du buffer (généralement pas de recopie)
00400     // Les données seront automatiquement désallouées par appel interne à la méthode freebuf
00401     // lors de la destruction de l'objet par appel à delete_data.
00402 #ifdef MYDEBUG
00403     std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Pas de Duplication  -----------" << std::endl;
00404 #endif
00405        return new seq_T (len, p_data, true);
00406      }
00407 #ifdef MYDEBUG
00408     std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Duplication pour en devenir propriétaire -----------" << std::endl;
00409 #endif
00410     // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)    
00411     return new seq_T(data);
00412 
00413   }
00414 
00415   static inline size_t size(Type data) { 
00416     return data->length();
00417   } 
00418 
00419   // Operation de clonage : par defaut creation d'une copie en memoire allouee pour l'occasion
00420   // Utilisation du constructeur du type seq_T  
00421   static inline Type clone(Type data) {
00422     return new seq_T (* data);
00423   }
00424   static inline Type clone(CorbaInType data) {
00425     return new seq_T (data);
00426   }
00427 
00428   // Operation de destruction d'une donnee CORBA
00429   static inline void delete_data(Type data) {
00430     delete data;
00431   }
00432 
00433   // Permet d'obtenir un pointeur sur le buffer de la séquence :
00434   // Si ownerShip=True, la séquence n'est plus propriétaire du buffer
00435   //         (son pointeur de buffer interne est aussi réinitialisé) 
00436   //       On détruit également explicitement la séquence (mais pas le buffer !)
00437   // Si ownerShip=False, la séquence reste propriétaire du buffer
00438   //    et l'utilisateur devra appeler delete_data sur la séquence contenante pour
00439   //    détruire à la fois la séquence et le buffer contenu.
00440   static inline InnerType * const getPointer(Type data, bool getOwnerShip = false) {
00441     InnerType * p_data;
00442     if (getOwnerShip) {
00443       p_data = data->get_buffer(true);
00444       delete_data(data);
00445     } else
00446       p_data = data->get_buffer(false);
00447     return p_data;
00448   }
00449 
00450   // Permet de désallouer le buffer dont on détient le pointeur par appel
00451   // à la méthode getPointer avec ownerShip=True si la séquence contenante
00452   // à été détruite.
00453   static inline void relPointer(InnerType * dataPtr) {
00454     seq_T::freebuf(dataPtr);
00455   }
00456 
00457   // Permet d'allouer un buffer pour la séquence
00458   static inline InnerType *  allocPointer(size_t size ) {
00459     return seq_T::allocbuf(size);
00460   }
00461 
00462   // Operation de création du type corba soit
00463   // - Vide et de taille size
00464   // - Utilisant les données du pointeur *data de taille size 
00465   // (généralement pas de recopie qlq soit l'ownership )
00466   // data doit avoir été alloué par allocPointer si giveOwnerShip = true  
00467   static inline Type create(size_t size, InnerType * const data = NULL,
00468                             bool giveOwnerShip = false ) { 
00469     Type tmp;
00470     if (!data) {
00471       tmp = new seq_T();
00472       tmp->length(size);
00473     } else {
00474       tmp = new seq_T(size,data,giveOwnerShip); 
00475     }
00476     return tmp;
00477   } 
00478 
00479   
00480   // Dump de l'objet pour deboguage
00481   static inline void dump (CorbaInType data) {
00482     // Affiche la longueur des donnees
00483     std::cerr << "[seq_b_manipulation] Data length: " << data.length() << std::endl;
00484   }
00485 };
00486 
00487 #endif