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