1 //===================================================================================================================
3 // DevicePipe.h - include file for TANGO device api class DevicePipe
6 // Copyright (C) : 2014,2015
7 // European Synchrotron Radiation Facility
8 // BP 220, Grenoble 38043
11 // This file is part of Tango.
13 // Tango is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
17 // Tango is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
18 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
21 // You should have received a copy of the GNU Lesser General Public License along with Tango.
22 // If not, see <http://www.gnu.org/licenses/>.
26 //===================================================================================================================
32 * Fundamental type for extracting data from a device pipe blob
34 * This is the fundamental type for extracting data from a device pipe blob
47 * Create a DataElement object.
49 * Create a DataElement object for device pipe blob extraction
51 * @param [in] name The data element name
52 * @param [in] value The data element value
54 DataElement(const string
&name
,T value
);
56 * Create a DataElement object.
58 * Create a DataElement object for device pipe blob extraction
60 * @param [in] name The data element name
62 DataElement(const string
&name
);
64 * Create a DataElement object.
66 * Create a DataElement object for device pipe blob extraction. Usefull for extraction into TANGO CORBA
67 * sequence. See DevicePipeBlob extraction method
69 * @param [in] value The data element value
75 string name
; ///< The data element name
76 T value
; ///< The data element value
80 DataElement
<T
>::DataElement(const string
&_na
,T _val
):name(_na
),value(_val
)
85 DataElement
<T
>::DataElement(const string
&_na
):name(_na
)
90 DataElement
<T
>::DataElement(T _val
):value(_val
)
95 DataElement
<T
>::DataElement()
102 * A device pipe blob. A blob is used to pack data to be sent through device pipe
107 * @headerfile tango.h
121 blobdenamenotset_flag
,
127 /**@name Constructors */
130 * Create a DevicePipeBlob object.
132 * Default constructor.
137 * Create a DevicePipeBlob object with name
139 * Create one instance of the DevicePipeBlob class and set its name
141 * @param [in] blob_name The blob name
143 DevicePipeBlob(const string
&blob_name
);
146 /**@name Get/Set methods */
153 * @param [in] blob_name The blob name
155 void set_name(const string
&blob_name
) {name
=blob_name
;}
161 * @return The blob name
163 const string
&get_name() {return name
;}
167 /**@name Inserting data into a DevicePipeBlob
171 * Insert data into a data blob
173 * According to the data to be inserted into the blob data element, several kinds of insetor methods have been
174 * implemented. You can insert data from:
175 * @li Scalar data type
177 * @li TANGO CORBA sequence types (by reference)
178 * @li TANGO CORBA sequence types (by pointer)
179 * @li DataElement<T> with T being scalar data type
180 * @li DataElement<T> with T being vector
181 * @li DataElement<T> with T being TANGO CORBA sequence type (by reference)
182 * @li DataElement<T> with T being TANGO CORBA sequence type (by pointer)
184 * When inserting data using a DataElement<T> instance, the data element name is also set.
185 * <B>For insertion from TANGO CORBA sequence type pointer, the insertion method consumes the
186 * memory allocated to store the data and it will be freed by the Tango layer.</B>
188 * Insert operators for the following scalar C++ types (and DataElement<T>)
204 * Insert operators for the following C++ vector types (and DataElement<T>)
207 * @li vector<DevLong>
208 * @li vector<DevLong64>
211 * @li vector<unsigned char>
212 * @li vector<unsigned short>
213 * @li vector<DevULong>
214 * @li vector<DevULong64>
215 * @li vector<DevSstring>
217 * @li vector<DevState>
219 * Insert operators for the following CORBA sequence types (and DataElement<T>):
220 * @li DevVarBooleanArray &
221 * @li DevVarShortArray &
222 * @li DevVarLongArray &
223 * @li DevVarLong64Array &
224 * @li DevVarFloatArray &
225 * @li DevVarDoubleArray &
226 * @li DevVarUCharArray &
227 * @li DevVarUShortArray &
228 * @li DevVarULongArray &
229 * @li DevVarULong64Array &
230 * @li DevVarStringArray &
231 * @li DevVarStateArray &
233 * Insert operators for the following CORBA sequence types <B>with memory consumption</B> (and DataElement<T>):
234 * @li DevVarBooleanArray *
235 * @li DevVarShortArray *
236 * @li DevVarLongArray *
237 * @li DevVarLong64Array *
238 * @li DevVarFloatArray *
239 * @li DevVarDoubleArray *
240 * @li DevVarUCharArray *
241 * @li DevVarUShortArray *
242 * @li DevVarULongArray *
243 * @li DevVarULong64Array *
244 * @li DevVarStringArray *
245 * @li DevVarStateArray *
247 * Here is an example of inserting data into a DevicePipeBlob instance. We insert
248 * 3 data element into the pipe blob with a DevLong, a vector of doubles and finally an array of 100 unsigned short
250 * DevicePipeBlob dpb("MyBlob");
252 * vector<string> de_names = {"FirstDE","SecondDE","ThirdDE"};
253 * dpb.set_data_elt_names(de_names);
256 * vector<double> v_db = {1.11,2.22};
257 * unsigned short *array = new unsigned short [100]; // The array is populated by a way or another
259 * DevVarUShortArray *dvush = create_DevVarUShortArray(array,100);
263 * dpb << dl << v_db << dvush;
265 * catch (DevFailed &e)
267 * cout << "DevicePipeBlob insertion failed" << endl;
272 * The same example of inserting data into a DevicePipeBlob instance when we want to set the data element name.
274 * DevicePipeBlob dpb("MyBlob");
276 * DataElement<DevLong> de_dl("FirstDE",666);
278 * vector<double> v_db = {1.11,2.22};
279 * DataElement<vector<double> > de_v_db("SecondDE",v_db);
281 * unsigned short *array = new unsigned short [100]; // The array is populated by a way or another
282 * DevVarUShortArray *dvush = create_DevVarUShortArray(array,100);
283 * DataElement<DevVarUShortArray *> de_dvush("ThirdDE",array);
287 * dpb << de_dl << de_v_db << de_dvush;
289 * catch (DevFailed &e)
291 * cout << "DevicePipeBlob insertion failed" << endl;
297 * It is also possible to do the insertion in a third way
299 * DevicePipeBlob dpb("MyBlob");
301 * vector<string> de_names{"FirstDE","SecondDE","ThirdDE"};
302 * dpb.set_data_elt_names(de_names);
305 * vector<double> v_db = {1.11,2.22};
306 * unsigned short *array = new unsigned short [100]; // The array is populated by a way or another
308 * DevVarUShortArray *dvush = create_DevVarUShortArray(array,100);
310 * dpb["FirstDE"] << dl;
311 * dpb["SecondDE"] << v_db;
312 * dpb["ThirdDE"] << dvush;
316 * @param [in] datum The data to be inserted into the DevicePipeBlob
317 * @exception WrongData if requested
319 DevicePipeBlob
& operator << (short &datum
);
321 * Set blob data element number
323 * Set the blob data element number
325 * @param [in] nb The blob data element number
327 void set_data_elt_nb(size_t nb
);
329 * Set blob data element number and names
331 * Set the blob data element number and names. The data element number is the number of names in the input
334 * @param [in] names The blob data element names
336 void set_data_elt_names(vector
<string
> &names
);
339 /**@name Extracting data from a DevicePipeBlob
343 * Extract data from a data blob
345 * According to the data inside blob data element, several kinds of extractor methods have been implemented. You
346 * can extract data into:
347 * @li Scalar data type
349 * @li TANGO CORBA sequence types
350 * @li DataElement<T> with T being scalar data type
351 * @li DataElement<T> with T being vector
352 * @li DataElement<T> with T being TANGO CORBA sequence type
354 * When extracting data using a DataElement<T> instance, the data element name is also returned.
355 * <B>For extraction into C++ vector, data are copied into the vector. It is not the case for extraction into TANGO
356 * CORBA sequence type. For extraction into TANGO CORBA sequence types, the extraction method consumes the
357 * memory allocated to store the data and it is the caller responsibility to delete this memory.</B>
359 * Extract operators for the following scalar C++ types (and DataElement<T>)
374 * Extract operators for the following C++ vector types (and DataElement<T>)
377 * @li vector<DevLong>
378 * @li vector<DevLong64>
381 * @li vector<unsigned char>
382 * @li vector<unsigned short>
383 * @li vector<DevULong>
384 * @li vector<DevULong64>
386 * @li vector<DevState>
388 * Extract operators for the following CORBA sequence types <B>with memory consumption</B> (and DataElement<T>):
389 * @li DevVarBooleanArray *
390 * @li DevVarShortArray *
391 * @li DevVarLongArray *
392 * @li DevVarLong64Array *
393 * @li DevVarFloatArray *
394 * @li DevVarDoubleArray *
395 * @li DevVarUCharArray *
396 * @li DevVarUShortArray *
397 * @li DevVarULongArray *
398 * @li DevVarULong64Array *
399 * @li DevVarStringArray *
400 * @li DevVarStateArray *
402 * Here is an example of extracting data from a DevicePipeBlob instance. We know that the DevicePipeBlob contains
403 * 3 data element with a DevLong, an array of doubles and finally an array of unsigned short
405 * DevicePipeBlob dpb = .....
408 * vector<double> v_db;
409 * DevVarUShortArray *dvush = new DevVarUShortArray();
413 * dpb >> dl >> v_db >> dvush;
415 * catch (DevFailed &e)
417 * cout << "DevicePipeBlob extraction failed" << endl;
423 * The same example of extracting data from a DevicePipeBlob instance when we want to retrieve the data element name.
425 * DevicePipeBlob dpb = .....
427 * DataElement<DevLong> de_dl;
428 * DataElement<vector<double> > de_v_db;
429 * DataElement<DevVarUShortArray *> de_dvush(new DevVarUShortArray());
433 * dpb >> de_dl >> de_v_db >> de_dvush;
435 * catch (DevFailed &e)
437 * cout << "DevicePipeBlob extraction failed" << endl;
441 * cout << "Data element name = " << de_dl.name << " - Value = " << de_dl.value << endl;
443 * delete de_dvush.value;
445 * It is also possible to do the extraction in a generic way
447 * DevicePipeBlob dpb = .....
449 * size_t nb_de = dpb.get_data_elt_nb();
450 * for (size_t loop = 0;loop < nb;loop++)
452 * int data_type = dpb.get_data_elt_type(loop);
453 * string de_name = dpb.get_data_elt_name(loop);
463 * case DEVVAR_DOUBLEARRAY:
465 * vector<double> v_db;
474 * Note that instead of using DevLong and vector<double> data, the extraction can be done using DataElement<T>
475 * instances. In this case, the call to the get_data_elt_name() method becomes useless.
477 * @param [out] datum The blob data
478 * @exception WrongData if requested
480 DevicePipeBlob
& operator >> (short &datum
);
482 * Get blob data element number
484 * Get the blob data element number
486 * @return The blob data element number
488 size_t get_data_elt_nb();
490 * Get blob data elements name
492 * Get the blob data elements name
494 * @return The blob data elements name
496 vector
<string
> get_data_elt_names();
498 * Get blob data element name
500 * Get the blob data element name for a single data element
502 * @param [in] ind The data element index within the blob
503 * @return The blob data element name
505 string
get_data_elt_name(size_t ind
);
507 * Get blob data element value type
509 * Get the blob data element value type for a single data element
511 * @param [in] ind The data element index within the blob
512 * @return The blob data element value type
514 int get_data_elt_type(size_t ind
);
517 /**@name Exception and error related methods methods
523 * It's a method which allows the user to switch on/off exception throwing when trying to extract data from a
524 * DevicePipeBlob object. The following flags are supported :
525 * @li @b isempty_flag - throw a WrongData exception (reason = API_EmptyDataElement) if user
526 * tries to extract data from one empty blob data element. By default, this flag
528 * @li @b wrongtype_flag - throw a WrongData exception (reason = API_IncompatibleArgumentType) if user
529 * tries to extract data with a type different than the type used for insertion. By default, this flag
531 * @li @b notenoughde_flag - throw a WrongData exception (reason = API_PipeWrongArg) if user
532 * tries to extract data from a DevicePipeBlob for a data element which does not exist. By default, this flag
534 * @li @b blobdenamenotset_flag - Throw a WrongData exception (reason = API_PipeNoDataElement) if user tries to
535 * insert data into the blob while the name or number of data element has not been set with methods
536 * set_data_elt_nb() or set_data_elt_names()
537 * @li @b mixing_flag - Throw a WrongData exception (reason = API_NotSupportedFeature) if user tries to mix
538 * insertion/extraction method (<< or >>) with operator[]
540 * @param [in] fl The exception flag
542 void exceptions(bitset
<numFlags
> fl
) {exceptions_flags
= fl
;}
546 * Returns the whole exception flags.
547 * The following is an example of how to use these exceptions related methods
549 * DevicePipeBlob dpb;
551 * bitset<DevicePipeBlob::numFlags> bs = dpb.exceptions();
552 * cout << "bs = " << bs << endl;
554 * dpb.set_exceptions(DevicePipeBlob::wrongtype_flag);
555 * bs = dpb.exceptions();
557 * cout << "bs = " << bs << endl;
560 * @return The exception flag
562 bitset
<numFlags
> exceptions() {return exceptions_flags
;}
564 * Reset one exception flag
566 * Resets one exception flag
568 * @param [in] fl The exception flag
570 void reset_exceptions(except_flags fl
) {exceptions_flags
.reset((size_t)fl
);}
572 * Set one exception flag
574 * Sets one exception flag. See DevicePipeBlob::exceptions() for a usage example.
576 * @param [in] fl The exception flag
578 void set_exceptions(except_flags fl
) {exceptions_flags
.set((size_t)fl
);}
580 * Check insertion/extraction success
582 * Allow the user to check if insertion/extraction into/from DevicePipeBlob instance was successfull. This
583 * method has to be used when exceptions are disabled.
585 * @return True if insertion/extraction has failed
589 * Get instance insertion/extraction state
591 * Allow the user to find out what was the reason of insertion/extraction into/from DevicePipeBlob failure. This
592 * method has to be used when exceptions are disabled.
593 * Here is an example of how methods has_failed() and state() could be used
595 * DevicePipeBlob dpb = ....
597 * bitset<DevicePipeBlob::numFlags> bs;
599 * dpb.exceptions(bs);
604 * if (dpb.has_failed() == true)
606 * bitset<DevicePipeBlob::numFlags> bs_err = dpb.state();
607 * if (bs_err.test(DevicePipeBlob::isempty_flag) == true)
612 * @return The error bit set.
614 bitset
<numFlags
> state() {return ext_state
;}
619 DevicePipeBlob(const DevicePipeBlob
&);
620 DevicePipeBlob
& operator=(const DevicePipeBlob
&);
622 DevicePipeBlob(DevicePipeBlob
&&);
623 DevicePipeBlob
& operator=(DevicePipeBlob
&&);
626 DevicePipeBlob
& operator << (DevBoolean
&);
627 // DevicePipeBlob & operator << (short &);
628 DevicePipeBlob
& operator << (DevLong
&);
629 DevicePipeBlob
& operator << (DevLong64
&);
630 DevicePipeBlob
& operator << (float &);
631 DevicePipeBlob
& operator << (double &);
632 DevicePipeBlob
& operator << (DevUChar
&);
633 DevicePipeBlob
& operator << (DevUShort
&);
634 DevicePipeBlob
& operator << (DevULong
&);
635 DevicePipeBlob
& operator << (DevULong64
&);
636 DevicePipeBlob
& operator << (DevString
&);
637 DevicePipeBlob
& operator << (DevState
&);
638 DevicePipeBlob
& operator << (DevEncoded
&);
639 DevicePipeBlob
& operator << (const string
&);
641 DevicePipeBlob
& operator << (DevicePipeBlob
&);
643 DevicePipeBlob
& operator << (vector
<DevBoolean
> &);
644 DevicePipeBlob
& operator << (vector
<short> &);
645 DevicePipeBlob
& operator << (vector
<DevLong
> &);
646 DevicePipeBlob
& operator << (vector
<DevLong64
> &);
647 DevicePipeBlob
& operator << (vector
<float> &);
648 DevicePipeBlob
& operator << (vector
<double> &);
649 DevicePipeBlob
& operator << (vector
<DevUChar
> &);
650 DevicePipeBlob
& operator << (vector
<DevUShort
> &);
651 DevicePipeBlob
& operator << (vector
<DevULong
> &);
652 DevicePipeBlob
& operator << (vector
<DevULong64
> &);
653 DevicePipeBlob
& operator << (vector
<DevString
> &);
654 DevicePipeBlob
& operator << (vector
<DevState
> &);
655 DevicePipeBlob
& operator << (vector
<DevEncoded
> &);
656 DevicePipeBlob
& operator << (vector
<string
> &);
658 DevicePipeBlob
& operator << (DevVarBooleanArray
&);
659 DevicePipeBlob
& operator << (DevVarShortArray
&);
660 DevicePipeBlob
& operator << (DevVarLongArray
&);
661 DevicePipeBlob
& operator << (DevVarLong64Array
&);
662 DevicePipeBlob
& operator << (DevVarFloatArray
&);
663 DevicePipeBlob
& operator << (DevVarDoubleArray
&);
664 DevicePipeBlob
& operator << (DevVarUCharArray
&);
665 DevicePipeBlob
& operator << (DevVarUShortArray
&);
666 DevicePipeBlob
& operator << (DevVarULongArray
&);
667 DevicePipeBlob
& operator << (DevVarULong64Array
&);
668 DevicePipeBlob
& operator << (DevVarStringArray
&);
669 DevicePipeBlob
& operator << (DevVarStateArray
&);
670 DevicePipeBlob
& operator << (DevVarEncodedArray
&);
672 DevicePipeBlob
& operator << (DevVarBooleanArray
*);
673 DevicePipeBlob
& operator << (DevVarShortArray
*);
674 DevicePipeBlob
& operator << (DevVarLongArray
*);
675 DevicePipeBlob
& operator << (DevVarLong64Array
*);
676 DevicePipeBlob
& operator << (DevVarFloatArray
*);
677 DevicePipeBlob
& operator << (DevVarDoubleArray
*);
678 DevicePipeBlob
& operator << (DevVarUCharArray
*);
679 DevicePipeBlob
& operator << (DevVarUShortArray
*);
680 DevicePipeBlob
& operator << (DevVarULongArray
*);
681 DevicePipeBlob
& operator << (DevVarULong64Array
*);
682 DevicePipeBlob
& operator << (DevVarStringArray
*);
683 DevicePipeBlob
& operator << (DevVarStateArray
*);
684 DevicePipeBlob
& operator << (DevVarEncodedArray
*);
686 //-------------------------------------------------------------------------------------------------
688 DevicePipeBlob
& operator >> (DevBoolean
&);
689 // DevicePipeBlob & operator >> (short &);
690 DevicePipeBlob
& operator >> (DevLong
&);
691 DevicePipeBlob
& operator >> (DevLong64
&);
692 DevicePipeBlob
& operator >> (float &);
693 DevicePipeBlob
& operator >> (double &);
694 DevicePipeBlob
& operator >> (DevUChar
&);
695 DevicePipeBlob
& operator >> (DevUShort
&);
696 DevicePipeBlob
& operator >> (DevULong
&);
697 DevicePipeBlob
& operator >> (DevULong64
&);
698 DevicePipeBlob
& operator >> (DevString
&);
699 DevicePipeBlob
& operator >> (DevState
&);
700 DevicePipeBlob
& operator >> (DevEncoded
&);
701 DevicePipeBlob
& operator >> (string
&);
703 DevicePipeBlob
& operator >> (DevicePipeBlob
&);
705 DevicePipeBlob
& operator >> (vector
<DevBoolean
> &);
706 DevicePipeBlob
& operator >> (vector
<short> &);
707 DevicePipeBlob
& operator >> (vector
<DevLong
> &);
708 DevicePipeBlob
& operator >> (vector
<DevLong64
> &);
709 DevicePipeBlob
& operator >> (vector
<float> &);
710 DevicePipeBlob
& operator >> (vector
<double> &);
711 DevicePipeBlob
& operator >> (vector
<DevUChar
> &);
712 DevicePipeBlob
& operator >> (vector
<DevUShort
> &);
713 DevicePipeBlob
& operator >> (vector
<DevULong
> &);
714 DevicePipeBlob
& operator >> (vector
<DevULong64
> &);
715 DevicePipeBlob
& operator >> (vector
<string
> &);
716 DevicePipeBlob
& operator >> (vector
<DevState
> &);
717 // DevicePipeBlob & operator >> (vector<DevEncoded> &);
719 DevicePipeBlob
& operator >> (DevVarBooleanArray
*);
720 DevicePipeBlob
& operator >> (DevVarShortArray
*);
721 DevicePipeBlob
& operator >> (DevVarLongArray
*);
722 DevicePipeBlob
& operator >> (DevVarLong64Array
*);
723 DevicePipeBlob
& operator >> (DevVarFloatArray
*);
724 DevicePipeBlob
& operator >> (DevVarDoubleArray
*);
725 DevicePipeBlob
& operator >> (DevVarUCharArray
*);
726 DevicePipeBlob
& operator >> (DevVarUShortArray
*);
727 DevicePipeBlob
& operator >> (DevVarULongArray
*);
728 DevicePipeBlob
& operator >> (DevVarULong64Array
*);
729 DevicePipeBlob
& operator >> (DevVarStringArray
*);
730 DevicePipeBlob
& operator >> (DevVarStateArray
*);
731 DevicePipeBlob
& operator >> (DevVarEncodedArray
*);
733 DevicePipeBlob
&operator[](const string
&);
735 const char *get_current_delt_name() {return (*extract_elt_array
)[extract_ctr
].name
.in();}
736 void set_current_delt_name(const string
&);
738 size_t get_extract_ind_from_name(const string
&);
739 size_t get_insert_ind_from_name(const string
&);
741 void reset_insert_ctr() {insert_ctr
=0;}
742 DevVarPipeDataEltArray
*get_insert_data() {return insert_elt_array
;}
743 const DevVarPipeDataEltArray
*get_extract_data() {return extract_elt_array
;}
745 void set_extract_data(const DevVarPipeDataEltArray
*_ptr
) {extract_elt_array
=_ptr
;}
746 void reset_insert_data_ptr() {insert_elt_array
=Tango_nullptr
;}
748 void reset_extract_ctr() {extract_ctr
=0;}
749 void set_extract_delete(bool _b
) {extract_delete
=_b
;}
751 void print(ostream
&,int,bool);
755 void throw_type_except(const string
&,const string
&);
756 void throw_too_many(const string
&,bool);
757 void throw_is_empty(const string
&);
758 void throw_name_not_set(const string
&);
759 void throw_mixing(const string
&);
762 string name
; // The blob name
763 bitset
<numFlags
> exceptions_flags
; // Exception flag
764 bitset
<numFlags
> ext_state
; // Extraction state
765 bool failed
; // Failed flag
767 DevVarPipeDataEltArray
*insert_elt_array
; // Ptr for data to be inserted (client write/Server read)
768 int insert_ctr
; // Ctr for inserting data elt
771 const DevVarPipeDataEltArray
*extract_elt_array
; // Ptr for data to be extracted (client read/Server write)
772 int extract_ctr
; // Ctr for extracting data elt
773 bool extract_delete
; // Flag to force extract ptr delete
776 class DevicePipeBlobExt
779 DevicePipeBlobExt() {};
782 #ifdef HAS_UNIQUE_PTR
783 unique_ptr
<DevicePipeBlobExt
> ext
;
785 DevicePipeBlobExt
*ext
; // Class extension
790 /****************************************************************************************
792 * The DevicePipe class *
793 * -------------------- *
795 ***************************************************************************************/
799 * Fundamental type for sending/receiving data from device pipes
801 * This is the fundamental type for sending/receiving data to/from device pipe.
806 * @headerfile tango.h
816 /**@name Constructors */
819 * Create a DevicePipe object.
821 * Default constructor. The instance is empty
826 * Create a DevicePipe object with name
828 * Create one instance of the DevicePipe class and set its name
830 * @param [in] pipe_name The pipe name
832 DevicePipe(const string
&pipe_name
);
834 * Create a DevicePipe object with name and root blob name.
836 * Create one instance of the DevicePipe class and set its name and its root blob name
838 * @param [in] pipe_name The pipe name
839 * @param [in] root_blob_name The root blob name
841 DevicePipe(const string
&pipe_name
,const string
&root_blob_name
);
844 /**@name Get/Set methods */
849 * Set the device pipe name
851 * @param [in] pipe_name The pipe name
853 void set_name(const string
&pipe_name
) {name
=pipe_name
;}
857 * Set the device pipe name
859 * @return The pipe name
861 const string
&get_name() {return name
;}
866 * Set the root blob name
868 * @param [in] root_blob_name The root blob name
870 void set_root_blob_name(const string
&root_blob_name
) {the_root_blob
.set_name(root_blob_name
);}
874 * Get the root blob name
876 * @return The root blob name
878 const string
&get_root_blob_name() {return the_root_blob
.get_name();}
881 /**@name Inserting data into a DevicePipe
886 * Insert data into a device pipe
888 * Inserting data into a DevicePipe instance is simlar to inserting data into a DevicePipeBlob class instance.
889 * See doc of DevicePipeBlob class insertion methods (DevicePipeBlob::operator<<) to get a complete documentation on
890 * how to insert data into a DevicePipe
892 * @param [in] datum The data to be inserted into the DevicePipe
893 * @exception WrongData if requested
895 DevicePipe
& operator << (short &datum
);
898 * Set blob data element number
900 * Set the blob data element number
902 * @param [in] nb The blob data element number
904 void set_data_elt_nb(size_t nb
) {the_root_blob
.set_data_elt_nb(nb
);}
906 * Set blob data element number and names
908 * Set the blob data element number and names. The data element number is the number of names in the input
911 * @param [in] names The blob data element names
913 void set_data_elt_names(vector
<string
> &names
) {the_root_blob
.set_data_elt_names(names
);}
916 /**@name Extracting data from a DevicePipe
921 * Extract data from a device pipe
923 * Extracting data from a DevicePipe instance is simlar to extracting data from a DevicePipeBlob class instance.
924 * See doc of DevicePipeBlob class extraction methods (DevicePipeBlob::operator>>) to get a complete documentation on
925 * how to extract data from a DevicePipe
927 * @param [in] datum The pipe data
928 * @exception WrongData if requested
930 DevicePipe
& operator >> (short &datum
);
933 * Get root blob data element number
935 * Get the root blob data element number
937 * @return The root blob data element number
939 size_t get_data_elt_nb() {return the_root_blob
.get_data_elt_nb();}
941 * Get root blob data elements name
943 * Get the root blob data elements name
945 * @return The root blob data elements name
947 vector
<string
> get_data_elt_names() {return the_root_blob
.get_data_elt_names();}
949 * Get root blob data element name
951 * Get root blob data element name for a single data element
953 * @param [in] ind The data element index within the root blob
954 * @return The root blob data element name
956 string
get_data_elt_name(size_t ind
) {return the_root_blob
.get_data_elt_name(ind
);}
958 * Get root blob data element value type
960 * Get root blob data element value type for a single data element
962 * @param [in] ind The data element index within the root blob
963 * @return The root blob data element value type
965 int get_data_elt_type(size_t ind
) {return the_root_blob
.get_data_elt_type(ind
);}
969 /**@name Exception and error related methods methods
975 * It's a method which allows the user to switch on/off exception throwing when trying to insert/extract data from a
976 * DevicePipe object. The following flags are supported :
977 * @li @b isempty_flag - throw a WrongData exception (reason = API_EmptyDataElement) if user
978 * tries to extract data from one empty pipe data element. By default, this flag
980 * @li @b wrongtype_flag - throw a WrongData exception (reason = API_IncompatibleArgumentType) if user
981 * tries to extract data with a type different than the type used for insertion. By default, this flag
983 * @li @b notenoughde_flag - throw a WrongData exception (reason = API_PipeWrongArg) if user
984 * tries to extract data from a DevicePipe for a data element which does not exist. By default, this flag
986 * @li @b blobdenamenotset_flag - Throw a WrongData exception (reason = API_PipeNoDataElement) if user tries to
987 * insert data into the blob while the name or number of data element has not been set with methods
988 * set_data_elt_nb() or set_data_elt_names()
989 * @li @b mixing_flag - Throw a WrongData exception (reason = API_NotSupportedFeature) if user tries to mix
990 * insertion/extraction method (<< or >>) with operator[]
992 * @param [in] fl The exception flag
994 void exceptions(bitset
<DevicePipeBlob::numFlags
> fl
) {the_root_blob
.exceptions(fl
);}
998 * Returns the whole exception flags.
999 * The following is an example of how to use these exceptions related methods
1003 * bitset<DevicePipeBlob::numFlags> bs = dp.exceptions();
1004 * cout << "bs = " << bs << endl;
1006 * dp.set_exceptions(DevicePipeBlob::wrongtype_flag);
1007 * bs = dp.exceptions();
1009 * cout << "bs = " << bs << endl;
1012 * @return The exception flag
1014 bitset
<DevicePipeBlob::numFlags
> exceptions() {return the_root_blob
.exceptions();}
1016 * Reset one exception flag
1018 * Resets one exception flag
1020 * @param [in] fl The exception flag
1022 void reset_exceptions(DevicePipeBlob::except_flags fl
) {the_root_blob
.reset_exceptions(fl
);}
1024 * Set one exception flag
1026 * Sets one exception flag. See DevicePipe::exceptions() for a usage example.
1028 * @param [in] fl The exception flag
1030 void set_exceptions(DevicePipeBlob::except_flags fl
) {the_root_blob
.set_exceptions(fl
);}
1032 * Check insertion/extraction success
1034 * Allow the user to check if insertion/extraction into/from DevicePipe instance was successfull. This
1035 * method has to be used when exceptions are disabled.
1037 * @return True if insertion/extraction has failed
1039 bool has_failed() {return the_root_blob
.has_failed();}
1041 * Get instance insertion/extraction state
1043 * Allow the user to find out what was the reason of insertion/extraction into/from DevicePipe failure. This
1044 * method has to be used when exceptions are disabled.
1045 * Here is an example of how methods has_failed() and state() could be used
1047 * DevicePipe dpb = ....
1049 * bitset<DevicePipeBlob::numFlags> bs;
1051 * dpb.exceptions(bs);
1056 * if (dpb.has_failed() == true)
1058 * bitset<DevicePipeBlob::numFlags> bs_err = dpb.state();
1059 * if (dpb.test(DevicePipeBlob::isempty_flag) == true)
1064 * @return The error bit set.
1066 bitset
<DevicePipeBlob::numFlags
> state() {return the_root_blob
.state();}
1070 * Print a DevicePipe instance
1072 * Is an utility function to easily print the contents of a DevicePipe object. This function knows all types
1073 * which could be inserted in a DevicePipe object and print them accordingly. A special string is printed if
1074 * the DevicePipe object is empty
1076 * DeviceProxy *dev = new DeviceProxy(“...”);
1079 * out = dev->read_pipe(“MyPipe”);
1080 * cout << “Pipe content: ” << out << endl;
1083 * @param [in] str The printing stream
1084 * @param [in] dd The instance to be printed
1086 friend ostream
&operator<<(ostream
&str
,DevicePipe
&dd
);
1090 DevicePipe(const DevicePipe
&);
1091 DevicePipe
& operator=(const DevicePipe
&);
1093 DevicePipe(DevicePipe
&&);
1094 DevicePipe
& operator=(DevicePipe
&&);
1098 void set_time(TimeVal
&_ti
) {time
=_ti
;}
1099 DevicePipeBlob
&get_root_blob() {return the_root_blob
;}
1101 DevicePipe
&operator[](const string
&);
1104 DevicePipeBlob the_root_blob
; // Root blob
1105 string name
; // Pipe name
1106 TimeVal time
; // When pipe has been read
1114 #ifdef HAS_UNIQUE_PTR
1115 unique_ptr
<DevicePipeExt
> ext
;
1117 DevicePipeExt
*ext
; // Class extension
1121 /****************************************************************************************
1123 * Some DevicePipe, DevicePipeBlob and DataElement helper functions *
1124 * ---------------------------------------------------------------- *
1126 ***************************************************************************************/
1128 DevicePipe
&operator>>(DevicePipe
&_dp
,char *&datum
);
1131 // For DataElement printing
1134 template <typename T
>
1135 ostream
&operator<<(ostream
&,DataElement
<T
> &);
1137 template <typename T
>
1138 ostream
&operator<<(ostream
&,DataElement
<vector
<T
> > &);
1140 template <typename T
>
1141 ostream
&operator<<(ostream
&,DataElement
<T
*> &);
1144 // For DevicePipe insertion
1147 template <typename T
>
1148 DevicePipe
&operator<<(DevicePipe
&,T
&);
1150 template <typename T
>
1151 DevicePipe
&operator<<(DevicePipe
&,T
*);
1153 template <typename T
>
1154 DevicePipe
&operator<<(DevicePipe
&, DataElement
<T
> &);
1157 // For DevicePipe extraction
1160 template <typename T
>
1161 DevicePipe
&operator>>(DevicePipe
&,T
&);
1163 template <typename T
>
1164 DevicePipe
&operator>>(DevicePipe
&,T
*);
1166 template <typename T
>
1167 DevicePipe
&operator>>(DevicePipe
&, DataElement
<T
> &);
1170 // For DevicePipeBlob insertion
1173 template <typename T
>
1174 DevicePipeBlob
&operator<<(DevicePipeBlob
&,T
&);
1176 template <typename T
>
1177 DevicePipeBlob
&operator<<(DevicePipeBlob
&,T
*);
1179 template <typename T
>
1180 DevicePipeBlob
&operator<<(DevicePipeBlob
&,DataElement
<T
> &);
1183 // For DevicePipeBlob extraction
1186 template <typename T
>
1187 DevicePipeBlob
&operator>>(DevicePipeBlob
&,T
&);
1189 template <typename T
>
1190 DevicePipeBlob
&operator>>(DevicePipeBlob
&,T
*);
1192 template <typename T
>
1193 DevicePipeBlob
&operator>>(DevicePipeBlob
&, DataElement
<T
> &);
1197 /****************************************************************************************
1199 * Some macros (shame on me, but I am too lazy) *
1200 * ------------------------------------------- *
1202 ***************************************************************************************/
1205 // A is the required value for the IDL enum descriminator
1206 // B is the IDL enum method to get data
1207 // C is data type name
1210 #define EXTRACT_BASIC_TYPE(A,B,C) \
1212 ext_state.reset(); \
1214 if (extract_elt_array == Tango_nullptr) \
1215 ext_state.set(isempty_flag); \
1216 else if (extract_ctr > (int)extract_elt_array->length() - 1) \
1217 ext_state.set(notenoughde_flag); \
1218 else if (extract_ctr == -1 && extract_ind == -1) \
1219 ext_state.set(mixing_flag); \
1223 if (extract_ind != -1) \
1224 ind = extract_ind; \
1226 ind = extract_ctr; \
1227 const AttrValUnion *uni_ptr = &((*extract_elt_array)[ind].value); \
1228 AttributeDataType adt = uni_ptr->_d(); \
1231 if (adt == ATT_NO_DATA) \
1233 if ((*extract_elt_array)[ind].inner_blob.length() == 0) \
1234 ext_state.set(isempty_flag); \
1236 ext_state.set(wrongtype_flag); \
1239 ext_state.set(wrongtype_flag); \
1243 datum = (uni_ptr->B())[0]; \
1244 if (extract_ind != -1) \
1251 if (ext_state.any() == true) \
1254 if (ext_state.test(isempty_flag) == true && exceptions_flags.test(isempty_flag) == true) \
1255 throw_is_empty("operator>>"); \
1257 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1258 throw_too_many("operator>>",true); \
1260 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1261 throw_mixing("operator>>"); \
1263 if (ext_state.test(wrongtype_flag) == true && exceptions_flags.test(wrongtype_flag) == true) \
1264 throw_type_except(C,"operator>>");
1268 // A is the required value for the IDL enum descriminator
1269 // B is the IDL enum method to get data
1270 // C is the CORBA sequence type name
1271 // D is data type name
1274 #define EXTRACT_VECTOR_TYPE(A,B,C,D) \
1276 ext_state.reset(); \
1278 if (extract_elt_array == Tango_nullptr) \
1279 ext_state.set(isempty_flag); \
1280 else if (extract_ctr > (int)extract_elt_array->length() - 1) \
1281 ext_state.set(notenoughde_flag); \
1282 else if (extract_ctr == -1 && extract_ind == -1) \
1283 ext_state.set(mixing_flag); \
1287 if (extract_ind != -1) \
1288 ind = extract_ind; \
1290 ind = extract_ctr; \
1291 const AttrValUnion *uni_ptr = &((*extract_elt_array)[ind].value); \
1292 AttributeDataType adt = uni_ptr->_d(); \
1295 if (adt == ATT_NO_DATA) \
1297 if ((*extract_elt_array)[ind].inner_blob.length() == 0) \
1298 ext_state.set(isempty_flag); \
1300 ext_state.set(wrongtype_flag); \
1303 ext_state.set(wrongtype_flag); \
1307 const C &dvsa = uni_ptr->B(); \
1309 if (extract_ind != -1) \
1316 if (ext_state.any() == true) \
1319 if (ext_state.test(isempty_flag) == true && exceptions_flags.test(isempty_flag) == true) \
1320 throw_is_empty("operator>>"); \
1322 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1323 throw_too_many("operator>>",true); \
1325 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1326 throw_mixing("operator>>"); \
1328 if (ext_state.test(wrongtype_flag) == true && exceptions_flags.test(wrongtype_flag) == true) \
1329 throw_type_except(D,"operator>>");
1332 // A is the required value for the IDL enum descriminator
1333 // B is the IDL enum method to get data
1334 // C is the CORBA sequence type name
1335 // D is data type name
1338 #define EXTRACT_SEQ_PTR_TYPE(A,B,C,D) \
1340 ext_state.reset(); \
1342 if (extract_elt_array == Tango_nullptr) \
1343 ext_state.set(isempty_flag); \
1344 else if (extract_ctr > (int)extract_elt_array->length() - 1) \
1345 ext_state.set(notenoughde_flag); \
1346 else if (extract_ctr == -1 && extract_ind == -1) \
1347 ext_state.set(mixing_flag); \
1351 if (extract_ind != -1) \
1352 ind = extract_ind; \
1354 ind = extract_ctr; \
1355 const AttrValUnion *uni_ptr = &((*extract_elt_array)[ind].value); \
1356 AttributeDataType adt = uni_ptr->_d(); \
1359 if (adt == ATT_NO_DATA) \
1361 if ((*extract_elt_array)[ind].inner_blob.length() == 0) \
1362 ext_state.set(isempty_flag); \
1364 ext_state.set(wrongtype_flag); \
1367 ext_state.set(wrongtype_flag); \
1371 C &dvsa = const_cast<C &>(uni_ptr->B()); \
1372 CORBA::Long max,len; \
1373 max = dvsa.maximum(); \
1374 len = dvsa.length(); \
1375 datum->replace(max,len,dvsa.get_buffer((CORBA::Boolean)true),true); \
1376 if (extract_ind != -1) \
1383 if (ext_state.any() == true) \
1386 if (ext_state.test(isempty_flag) == true && exceptions_flags.test(isempty_flag) == true) \
1387 throw_is_empty("operator>>"); \
1389 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1390 throw_too_many("operator>>",true); \
1392 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1393 throw_mixing("operator>>"); \
1395 if (ext_state.test(wrongtype_flag) == true && exceptions_flags.test(wrongtype_flag) == true) \
1396 throw_type_except(D,"operator>>");
1400 // A is the sequence CORBA name
1401 // B is the IDL enum method to set data
1404 #define INSERT_BASIC_TYPE(A,B) \
1406 ext_state.reset(); \
1408 if (insert_elt_array == Tango_nullptr) \
1409 ext_state.set(blobdenamenotset_flag); \
1410 else if (insert_ctr == -1 && insert_ind == -1) \
1411 ext_state.set(mixing_flag); \
1414 size_t nb_insert = insert_elt_array->length(); \
1415 if (nb_insert == 0 || insert_ctr > (int)nb_insert - 1) \
1416 ext_state.set(notenoughde_flag); \
1423 if (insert_ind != -1) \
1425 (*insert_elt_array)[insert_ind].value.B(dvsa); \
1426 (*insert_elt_array)[insert_ind].inner_blob_name = CORBA::string_dup(SCALAR_PIPE); \
1431 (*insert_elt_array)[insert_ctr].value.B(dvsa); \
1432 (*insert_elt_array)[insert_ctr].inner_blob_name = CORBA::string_dup(SCALAR_PIPE); \
1438 if (ext_state.any() == true) \
1441 if (ext_state.test(blobdenamenotset_flag) == true && exceptions_flags.test(blobdenamenotset_flag) == true) \
1442 throw_name_not_set("operator<<"); \
1444 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1445 throw_mixing("operator>>"); \
1447 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1448 throw_too_many("operator<<",false);
1452 // A is the sequence CORBA name
1453 // B is the IDL enum method to set data
1456 #define INSERT_VECTOR_TYPE(A,B) \
1458 ext_state.reset(); \
1460 if (insert_elt_array == Tango_nullptr) \
1461 ext_state.set(blobdenamenotset_flag); \
1462 else if (insert_ctr == -1 && insert_ind == -1) \
1463 ext_state.set(mixing_flag); \
1466 size_t nb_insert = insert_elt_array->length(); \
1467 if (nb_insert == 0 || insert_ctr > (int)nb_insert - 1) \
1468 ext_state.set(notenoughde_flag); \
1472 if (insert_ind != -1) \
1474 (*insert_elt_array)[insert_ind].value.B(dvsa); \
1475 A &dvsb = (*insert_elt_array)[insert_ind].value.B(); \
1476 dvsb.replace(datum.size(),datum.size(),&datum[0],false); \
1477 (*insert_elt_array)[insert_ind].inner_blob_name = CORBA::string_dup(ARRAY_PIPE); \
1482 (*insert_elt_array)[insert_ctr].value.B(dvsa); \
1483 A &dvsb = (*insert_elt_array)[insert_ctr].value.B(); \
1484 dvsb.replace(datum.size(),datum.size(),&datum[0],false); \
1485 (*insert_elt_array)[insert_ctr].inner_blob_name = CORBA::string_dup(ARRAY_PIPE); \
1491 if (ext_state.any() == true) \
1494 if (ext_state.test(blobdenamenotset_flag) == true && exceptions_flags.test(blobdenamenotset_flag) == true) \
1495 throw_name_not_set("operator<<"); \
1497 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1498 throw_mixing("operator>>"); \
1500 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1501 throw_too_many("operator<<",false);
1506 // A is the sequence CORBA name
1507 // B is the IDL enum method to set data
1510 #define INSERT_SEQ_TYPE(A,B) \
1512 ext_state.reset(); \
1514 if (insert_elt_array == Tango_nullptr) \
1515 ext_state.set(blobdenamenotset_flag); \
1516 else if (insert_ctr == -1 && insert_ind == -1) \
1517 ext_state.set(mixing_flag); \
1520 size_t nb_insert = insert_elt_array->length(); \
1521 if (nb_insert == 0 || insert_ctr > (int)nb_insert - 1) \
1522 ext_state.set(notenoughde_flag); \
1525 CORBA::Long max,len; \
1526 max = datum.maximum(); \
1527 len = datum.length(); \
1529 if (insert_ind != -1) \
1531 (*insert_elt_array)[insert_ind].value.B(dvsa); \
1532 A &dvsb = (*insert_elt_array)[insert_ind].value.B(); \
1533 dvsb.replace(max,len,datum.get_buffer(),false); \
1534 (*insert_elt_array)[insert_ind].inner_blob_name = CORBA::string_dup(ARRAY_PIPE); \
1539 (*insert_elt_array)[insert_ctr].value.B(dvsa); \
1540 A &dvsb = (*insert_elt_array)[insert_ctr].value.B(); \
1541 dvsb.replace(max,len,datum.get_buffer(),false); \
1542 (*insert_elt_array)[insert_ctr].inner_blob_name = CORBA::string_dup(ARRAY_PIPE); \
1548 if (ext_state.any() == true) \
1551 if (ext_state.test(blobdenamenotset_flag) == true && exceptions_flags.test(blobdenamenotset_flag) == true) \
1552 throw_name_not_set("operator<<"); \
1554 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1555 throw_mixing("operator>>"); \
1557 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1558 throw_too_many("operator<<",false);
1563 // A is the sequence CORBA name
1564 // B is the IDL enum method to set data
1567 #define INSERT_SEQ_PTR_TYPE(A,B) \
1569 ext_state.reset(); \
1571 if (insert_elt_array == Tango_nullptr) \
1572 ext_state.set(blobdenamenotset_flag); \
1573 else if (insert_ctr == -1 && insert_ind == -1) \
1574 ext_state.set(mixing_flag); \
1577 size_t nb_insert = insert_elt_array->length(); \
1578 if (nb_insert == 0 || insert_ctr > (int)nb_insert - 1) \
1579 ext_state.set(notenoughde_flag); \
1583 CORBA::Long max,len; \
1584 max = datum->maximum(); \
1585 len = datum->length(); \
1586 bool rel = datum->release(); \
1589 datum->replace(max,len,datum->get_buffer(),true); \
1591 if (insert_ind != -1) \
1593 (*insert_elt_array)[insert_ind].value.B(dvsa); \
1594 A &dvsb = (*insert_elt_array)[insert_ind].value.B(); \
1595 dvsb.replace(max,len,datum->get_buffer((CORBA::Boolean)true),true); \
1596 (*insert_elt_array)[insert_ind].inner_blob_name = CORBA::string_dup(ARRAY_PIPE); \
1601 (*insert_elt_array)[insert_ctr].value.B(dvsa); \
1602 A &dvsb = (*insert_elt_array)[insert_ctr].value.B(); \
1603 dvsb.replace(max,len,datum->get_buffer((CORBA::Boolean)true),true); \
1604 (*insert_elt_array)[insert_ctr].inner_blob_name = CORBA::string_dup(ARRAY_PIPE); \
1612 if (ext_state.any() == true) \
1615 if (ext_state.test(blobdenamenotset_flag) == true && exceptions_flags.test(blobdenamenotset_flag) == true) \
1616 throw_name_not_set("operator<<"); \
1618 if (ext_state.test(mixing_flag) == true && exceptions_flags.test(mixing_flag) == true) \
1619 throw_mixing("operator>>"); \
1621 if (ext_state.test(notenoughde_flag) == true && exceptions_flags.test(notenoughde_flag) == true) \
1622 throw_too_many("operator<<",false);
1625 #endif /* _DEVICEPIPE_H */