Version: 7.8.0
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
CorbaTypeManipulator.hxx
1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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, or (at your option) any later version.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 
23 // File : CorbaTypeManipulator.hxx
24 // Author : Eric Fayolle (EDF)
25 // Module : KERNEL
26 // Modified by : $LastChangedBy$
27 // Date : $LastChangedDate: 2007-02-07 18:26:44 +0100 (mer, 07 fév 2007) $
28 // Id : $Id$
29 //
30 #ifndef _CORBA_TYPE_MANIPULATION_HXX_
31 #define _CORBA_TYPE_MANIPULATION_HXX_
32 
33 #include <iostream>
34 #include <cstring>
35 #include <omniORB4/CORBA.h>
36 
37 //#define MYDEBUG
38 
39 // Classes manipulation
40 // -------------------
41 //
42 // Ces différentes classes permettent d'unifier la manipulation des
43 // différents types de données dans un port datastream
44 // Les données sont maniées par valeur ou par pointeur
45 // pour éviter les recopies de gros volume de données
46 
47 // Les classes présentes quatre méthodes :
48 // - clone
49 // - get_data
50 // - delete_data
51 // - dump
52 // et
53 // trois types :
54 // - Type : Le type CORBA de la donnée manipulée
55 // - InType : Le mapping CORBA pour un paramètre IN du type manipulé
56 // - InnerType : Type interne des valeurs d'un type contenant
57 
58 // Cette classe permet de manipuler des types CORBA
59 // any, struct, union et sequence (utiliser plutôt les seq_manipulator)
60 // Ces types sont manipulés par pointeur.
61 // Les données reçues de CORBA sont systématiquement
62 // dupliquées pour être conservées.
63 // Quelque soit le type de donnée, les données sont considérées
64 // comme une donnée unique (retour de size() == 1)
65 template <typename T >
67 {
68 public:
69  typedef T * Type;
70  // correspond au mapping corba des type any, struct,
71  // union, séquence en paramètre IN
72  typedef const T & CorbaInType;
73  typedef T InnerType;
74 
75  // Operation de recuperation des donnees venant de l'ORB et
76  // creation d'une copie (memoire spécialement allouee)
77  static inline Type get_data(CorbaInType data) {
78  return new T(data);
79  }
80 
81  // Pb si ownerShip == True car appel par l'utilisateur de relPointer !
82  static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
83  return data;
84  }
85 
86  static inline void relPointer(InnerType * dataPtr) {
87  delete dataPtr;
88  }
89 
90  // Operation de clonage : par defaut, creation d'une copie en memoire allouee pour l'occasion
91  static inline Type clone(Type data) {
92  return new T (* data);
93  }
94  static inline Type clone(CorbaInType data) {
95  return new T (data);
96  }
97 
98  // Operation de création
99  static inline Type create (size_t size=1) {
100  return new T();
101  }
102 
103  // Operation de destruction d'une donnee
104  static inline void delete_data(Type data) {
105  delete data;
106  }
107 
108  // Renvoie la taille de la donnée
109  static inline size_t size(Type data) {
110  return 1;
111  }
112 
113  // Dump de l'objet pour deboguage: neant car on ne connait pas sa structure
114  static inline void dump (CorbaInType data) {}
115 };
116 
117 
118 // Gére les types CORBA atomiques ('Int', 'Char', 'Float', ...)
119 // Gére les types enums
120 // Gére les références d'objets CORBA
121 // Ces types sont manipulés par valeur
122 // Les méthodes getPointer ... ne devrait pas être utilisée
123 // pour ce types de données
124 template <typename T>
126 {
127 public:
128  typedef T Type;
129  // correspond au mapping corba des types simples en paramètre IN
130  typedef T CorbaInType;
131  typedef T InnerType;
132 
133 
134  // Operation de recuperation des donnees venant de l'ORB : une copie par affectation simple
135  static inline Type get_data(CorbaInType data) {
136  return data;
137  }
138 
139  static inline InnerType * const getPointer(Type & data, bool getOwnerShip = false) {
140 // InnerType * ptr;
141 // if (getOwnerShip) {
142 // ptr =new InnerType[1];*ptr=data;
143 // return ptr;
144 // } else
145 // return &data;
146  return &data;
147  }
148 
149 // static inline void relPointer(InnerType * dataPtr) {
150 // return;
151 // delete[] dataPtr;
152 // }
153 
154 // Je ne sais pas comment l'implémenter sans faire
155 // d'allocation heap
156 //static inline InnerType * allocPointer(size_t size=1) {
157 // return new InnerType[1];
158  //}
159 
160  // Operation de clonage : une copie par affectation simple
161  static inline Type clone(Type data) {
162  return data;
163  }
164 
165  // Inutile car Type == CorbaInType
166  // static inline Type clone(CorbaInType data) {
167  // return data;
168  // }
169 
170  // Operation de création
171 // static inline Type create(size_t size=1,InnerType * data=NULL,
172 // bool giveOwnerShip=false) {
173 // Type dummy;
174 // if (dataPtr)
175 // return *data;
176 // else
177 // return dummy;
178 // }
179 
180  // Operation de destruction d'une donnee: rien a faire car pas de memoire a liberer
181  static inline void delete_data(Type data) {}
182  // Renvoie la taille de la donnée
183 
184  static inline size_t size(Type data) {
185  return 1;
186  }
187 
188  // Dump de l'objet pour deboguage : Affiche la donnee
189  static void inline dump (CorbaInType data) {
190  std::cerr << "[atom_manipulation] Data : " << data << std::endl;
191  }
192 };
193 
194 
195 // Gére un type sequence de taille illimitee (Unbounded)
196 // Ces types sont manipulés par pointeur
197 template <typename seq_T,typename elem_T>
199 
200 public:
201  typedef seq_T * Type; // Type de donnée abstrait manipulé par GenericPort::Put,Get,..
202  typedef const seq_T & CorbaInType; // Mapping corba de la séquence en paramètre IN
203  typedef elem_T InnerType; // Il n'existe pas dans CORBA de seq_T::elem_T
204  // C'est la raison d'être du second paramètre template de seq_u_mani
205 
206  // Operation de recuperation des donnees venant de l'ORB
207  // Remarque : On a un paramètre d'entrée de type const seq_T &
208  // et en sortie un seq_T *
209  static inline Type get_data(CorbaInType data) {
210  CORBA::Long len = data.length();
211  CORBA::Long max = data.maximum();
212  // Récupère et devient propriétaire des données reçues dans la séquence.
213  // La séquence reçue (mais pas le buffer) sera désallouée au retour
214  // de la méthode CORBA qui a reçu le type CorbaInType en paramètre
215  // (ex: GenericPort::put)
216  // REM : Le mapping CORBA du type séquence IN est : const seq &
217 
218  // OLD : On ne teste pas si le flag release de la séquence est à true ou false
219  // OLD : ( pour des séquences de chaines ou d'objrefs )
220  // OLD : -> Si on est collocalisé le port uses doit créer une copie pour éviter la modification
221  // OLD : du contenu de la séquence lorsque l'utilisateur modifie ses données dans son programme (0 copie)
222  // OLD : ATTENTION TESTER p194 si le pointeur est null (release flag==false)
223  // OLD : -> La séquence n'était pas propriétaire des données !
224 
225  // Le flag release() de la séquence est à false si elle n'est pas propriétaire du buffer
226  // En collocalité release() renvoie false car
227  // l'appelé n'est pas propriétaire de la séquence. On effectue alors
228  // une copie pour éviter de perturber les structures de données de l'appelant.
229  // En non collocalisé on recrée une séquence avec le buffer de la première dont on
230  // a demandé la propriété.
231 
232 #ifdef MYDEBUG
233  std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1 ------------------" << std::endl;
234 #endif
235  if ( data.release() ) {
236  InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
237 
238  // Crée une nouvelle sequence propriétaire des données du buffer (pas de recopie)
239  // Les données de la nouvelle séquence seront automatiquement désallouées
240  // par appel à la méthode freebuf dans le destructeur de la séquence (cf delete_data).
241 #ifdef MYDEBUG
242  std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(0 copy) bis ------"<< p_data <<"------------" << std::endl;
243 #endif
244 
245  return new seq_T (max, len, p_data, true);
246  }
247 #ifdef MYDEBUG
248  std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1(recopie) bis ------"<< &data <<"------------" << std::endl;
249 #endif
250  // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
251  return new seq_T(data);
252 
253  }
254 
255  static inline size_t size(Type data) {
256  return data->length();
257  }
258 
259  // Operation de destruction d'une donnee
260  static inline void delete_data(Type data) {
261  //La séquence est détruite par appel à son destructeur
262  //Ce destructeur prend en compte la nécessité de détruire ou non
263  //les données contenues en fonction de son flag interne release()
264  delete data;
265  }
266 
267  // Operation de clonage : par defaut creation d'une copie en memoire allouee pour l'occasion
268  // Utilisation du constructeur du type seq_T
269  static inline Type clone(Type data) {
270  return new seq_T (*data) ;
271  }
272  static inline Type clone(CorbaInType data) {
273  return new seq_T (data);
274  }
275 
276  // Permet d'obtenir un pointeur sur le buffer de la séquence :
277  // Si ownerShip=True, la séquence n'est plus propriétaire du buffer
278  // (son pointeur de buffer interne est aussi réinitialisé)
279  // On détruit également explicitement la séquence (mais pas le buffer !)
280  // Si ownerShip=False, la séquence reste propriétaire du buffer
281  // et l'utilisateur devra appeler delete_data sur la séquence contenante pour
282  // détruire à la fois la séquence et le buffer contenu.
283  static inline InnerType * const getPointer(Type data, bool ownerShip = false) {
284  InnerType * p_data;
285  if (ownerShip) {
286  p_data = data->get_buffer(true);
287  delete_data(data);
288  } else
289  p_data = data->get_buffer(false);
290  return p_data;
291  }
292 
293  // Permet de désallouer le buffer dont on détient le pointeur après appel
294  // à la méthode getPointer avec ownerShip=True
295  static inline void relPointer(InnerType * dataPtr) {
296  seq_T::freebuf(dataPtr);
297  }
298 
299  // Permet d'allouer un buffer compatible avec le type séquence
300  static inline InnerType * allocPointer(size_t size ) {
301  return seq_T::allocbuf(size);
302  }
303 
304  // Opération de création de la séquence CORBA soit
305  // - Vide et de taille size
306  // - Utilisant les données du pointeur *data de taille size
307  // (généralement pas de recopie qlq soit l'ownership )
308  // data doit avoir été alloué par allocPointer si giveOwnerShip = true
309  static inline Type create(size_t size, InnerType * const data = NULL,
310  bool giveOwnerShip = false ) {
311  Type tmp;
312  if (!data) {
313  tmp = new seq_T();
314  tmp->length(size);
315  } else {
316  tmp = new seq_T(size,size,data,giveOwnerShip);
317  }
318  return tmp;
319  }
320 
321  // Copie le contenu de la séquence dans le buffer idata de taille isize
322  // pour les types non pointeur
323  template <typename T >
324  static inline void copy( Type data, T * const idata, size_t isize ) {
325 
326  InnerType *dataPtr = getPointer(data,false);
327 
328  for (int i = 0; i< isize; ++i)
329  idata[i]=dataPtr[i];
330 
331  // Le mode de recopie suivant ne permet pas la conversion de type (ex int -> CORBA::Long)
332  //OLD: Type tmp = new seq_T(isize,isize,idata,false);
333  //OLD: // giveOwnerShip == false -> seul le contenu du buffer data est détruit et remplacé
334  //OLD: // par celui de data dans l'affectation suivante :
335  //OLD: // ---> ATTENTION SI LA TAILLE DU BUFFER EST TROP PETITE, QUE FAIT CORBA !
336  //OLD: // corruption mémoire
337  //OLD: // Cependant ce cas devrait pas arrivé (on s'assure dans les couches supérieures
338  //OLD: // de la taille correcte du buffer de recopie)
339  //OLD: // Si giveOwnerShip était == true -> le buffer et son contenu serait détruit puis une
340  //OLD: // allocation de la taille du buffer de data serait effectué avant la copie des données
341  //OLD: // tmp = data;
342  }
343 
344  // Copie le contenu de la séquence de char* dans le buffer idata de taille isize
345  // La généralisation de la recopie profonde est difficile du fait que CORBA ne renvoie pas
346  // pas des objets de haut niveau de type std::vector<std::string> (avec des interfaces d'accès identiques)
347  // mais un type simple C comme char *Tab[N]. On doit alors utiliser une méthode de recopie spécifique
348  // comme l'appel C strcpy.
349  static inline void copy( Type data, char* * const idata, size_t isize ) {
350 
351  char* *dataPtr = getPointer(data,false);
352 
353  // Si idata[i] n'a pas été alloué suffisament grand,
354  // il y a corruption de la mémoire
355  for (int i = 0; i< isize; ++i)
356  strcpy(idata[i],dataPtr[i]);
357  }
358 
359  // Dump de l'objet pour deboguage
360  static void inline dump (CorbaInType data) {
361  // Affiche la longueur des donnees
362  std::cerr << "[seq_u_manipulation] Data length: " << data.length() << std::endl;
363  // Affiche la longueur des donnees
364  std::cerr << "[seq_u_manipulation] Data max: " << data.maximum() << std::endl;
365  }
366 };
367 
368 
369 // TODO : Vérifier la conformité de l'implémentation par rapport
370 // au type unbounded
371 
372 // Gére un type sequence de taille limitée (bounded)
373 // Ces types sont manipulés par pointeur
374 // Cette classe diffère de la seq_u_manipulation
375 // par la signature du constructeur de la séquence
376 // utilisé dans le methode get_data
377 template <typename seq_T,typename elem_T>
379 
380 public:
381  typedef seq_T * Type;
382  typedef const seq_T & CorbaInType;
383  typedef elem_T InnerType;
384 
385 
386  // Operation de recuperation des donnees venant de l'ORB
387  // Sans opération de notre part, ces données seraient perdues
388  // au retour de la méthode put de GenericPort.
389  // Remarque : On a un paramètre d'entrée de type const seq_T &
390  // et en sortie un seq_T *
391  static inline Type get_data(CorbaInType data) {
392  CORBA::Long len = data.length();
393  // Récupère et devient propriétaire des données reçues dans la séquence
394  // la séquence sera désalloué (mais pas le buffer)
395  // au retour de la méthode put (car mapping de type IN : const seq & )
396  if ( data.release() ) {
397  InnerType * p_data = const_cast<seq_T &>(data).get_buffer(true);
398 
399  // Crée une nouvelle sequence propriétaire des données du buffer (généralement pas de recopie)
400  // Les données seront automatiquement désallouées par appel interne à la méthode freebuf
401  // lors de la destruction de l'objet par appel à delete_data.
402 #ifdef MYDEBUG
403  std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Pas de Duplication -----------" << std::endl;
404 #endif
405  return new seq_T (len, p_data, true);
406  }
407 #ifdef MYDEBUG
408  std::cout << "----seq_u_manipulation::get_data(..)-- MARK 1bis Duplication pour en devenir propriétaire -----------" << std::endl;
409 #endif
410  // Crée une nouvelle sequence propriétaire des données du buffer (avec recopie)
411  return new seq_T(data);
412 
413  }
414 
415  static inline size_t size(Type data) {
416  return data->length();
417  }
418 
419  // Operation de clonage : par defaut creation d'une copie en memoire allouee pour l'occasion
420  // Utilisation du constructeur du type seq_T
421  static inline Type clone(Type data) {
422  return new seq_T (* data);
423  }
424  static inline Type clone(CorbaInType data) {
425  return new seq_T (data);
426  }
427 
428  // Operation de destruction d'une donnee CORBA
429  static inline void delete_data(Type data) {
430  delete data;
431  }
432 
433  // Permet d'obtenir un pointeur sur le buffer de la séquence :
434  // Si ownerShip=True, la séquence n'est plus propriétaire du buffer
435  // (son pointeur de buffer interne est aussi réinitialisé)
436  // On détruit également explicitement la séquence (mais pas le buffer !)
437  // Si ownerShip=False, la séquence reste propriétaire du buffer
438  // et l'utilisateur devra appeler delete_data sur la séquence contenante pour
439  // détruire à la fois la séquence et le buffer contenu.
440  static inline InnerType * const getPointer(Type data, bool getOwnerShip = false) {
441  InnerType * p_data;
442  if (getOwnerShip) {
443  p_data = data->get_buffer(true);
444  delete_data(data);
445  } else
446  p_data = data->get_buffer(false);
447  return p_data;
448  }
449 
450  // Permet de désallouer le buffer dont on détient le pointeur par appel
451  // à la méthode getPointer avec ownerShip=True si la séquence contenante
452  // à été détruite.
453  static inline void relPointer(InnerType * dataPtr) {
454  seq_T::freebuf(dataPtr);
455  }
456 
457  // Permet d'allouer un buffer pour la séquence
458  static inline InnerType * allocPointer(size_t size ) {
459  return seq_T::allocbuf(size);
460  }
461 
462  // Operation de création du type corba soit
463  // - Vide et de taille size
464  // - Utilisant les données du pointeur *data de taille size
465  // (généralement pas de recopie qlq soit l'ownership )
466  // data doit avoir été alloué par allocPointer si giveOwnerShip = true
467  static inline Type create(size_t size, InnerType * const data = NULL,
468  bool giveOwnerShip = false ) {
469  Type tmp;
470  if (!data) {
471  tmp = new seq_T();
472  tmp->length(size);
473  } else {
474  tmp = new seq_T(size,data,giveOwnerShip);
475  }
476  return tmp;
477  }
478 
479 
480  // Dump de l'objet pour deboguage
481  static inline void dump (CorbaInType data) {
482  // Affiche la longueur des donnees
483  std::cerr << "[seq_b_manipulation] Data length: " << data.length() << std::endl;
484  }
485 };
486 
487 #endif