SALOME documentation central

src/DSC/DSC_User/Datastream/CorbaTypeManipulator.hxx

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