00001 // Copyright (C) 2007-2011 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.1.6.1 2011-06-01 13:51:41 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