This is Unofficial EPICS BASE Doxygen Site
osiWireFormat.h
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /*
11  * Author Jeffrey O. Hill
12  * johill@lanl.gov
13  */
14 
15 #ifndef osiWireFormat
16 #define osiWireFormat
17 
18 #include "epicsTypes.h"
19 
20 //
21 // With future CA protocols user defined payload composition will be
22 // supported and we will need to move away from a naturally aligned
23 // protocol (because pad byte overhead will probably be excessive when
24 // maintaining 8 byte natural alignment if the user isnt thinking about
25 // placing like sized elements together).
26 //
27 // Nevertheless, the R3.14 protocol continues to be naturally aligned,
28 // and all of the fields within the DBR_XXXX types are naturally aligned.
29 // Therefore we support here two wire transfer interfaces (naturally
30 // aligned and otherwise) because there are important optimizations
31 // specific to each of them.
32 //
33 // At some point in the future the naturally aligned interfaces might
34 // be eliminated (or unbundled from base) should they be no-longer needed.
35 //
36 
37 template < class T >
38 void WireGet ( const epicsUInt8 * pWireSrc, T & );
39 
40 template < class T >
41 void WireSet ( const T &, epicsUInt8 * pWireDst );
42 
43 template < class T >
44 void AlignedWireGet ( const T &, T & );
45 
46 template < class T >
47 void AlignedWireSet ( const T &, T & );
48 
49 template < class T >
51 public:
52  AlignedWireRef ( T & ref );
53  operator T () const;
54  AlignedWireRef < T > & operator = ( const T & );
55 private:
56  T & _ref;
57  AlignedWireRef ( const AlignedWireRef & );
59 };
60 
61 template < class T >
62 class AlignedWireRef < const T > {
63 public:
64  AlignedWireRef ( const T & ref );
65  operator T () const;
66 private:
67  const T & _ref;
68  AlignedWireRef ( const AlignedWireRef & );
70 };
71 
72 template < class T >
74  _ref ( ref )
75 {
76 }
77 
78 template < class T >
79 inline AlignedWireRef < T > :: operator T () const
80 {
81  T tmp;
82  AlignedWireGet ( _ref, tmp );
83  return tmp;
84 }
85 
86 template < class T >
87 inline AlignedWireRef < T > & AlignedWireRef < T > :: operator = ( const T & src )
88 {
89  AlignedWireSet ( src, _ref );
90  return *this;
91 }
92 
93 template < class T >
95  _ref ( ref )
96 {
97 }
98 
99 template < class T >
100 inline AlignedWireRef < const T > :: operator T () const
101 {
102  T tmp;
103  AlignedWireGet ( _ref, tmp );
104  return tmp;
105 }
106 
107 // may be useful when creating support for little endian
108 inline epicsUInt16 byteSwap ( const epicsUInt16 & src )
109 {
110  return static_cast < epicsUInt16 >
111  ( ( src << 8u ) | ( src >> 8u ) );
112 }
113 
114 // may be useful when creating support for little endian
115 inline epicsUInt32 byteSwap ( const epicsUInt32 & src )
116 {
117  epicsUInt32 tmp0 = byteSwap (
118  static_cast < epicsUInt16 > ( src >> 16u ) );
119  epicsUInt32 tmp1 = byteSwap (
120  static_cast < epicsUInt16 > ( src ) );
121  return static_cast < epicsUInt32 >
122  ( ( tmp1 << 16u ) | tmp0 );
123 }
124 
125 template < class T > union WireAlias;
126 
127 template <>
128 union WireAlias < epicsInt8 > {
131 };
132 
133 template <>
137 };
138 
139 template <>
143 };
144 
145 template <>
149 };
150 
151 //
152 // Missaligned unsigned wire format get/set can be implemented generically
153 // w/o performance penalty. Attempts to improve this on architectures that
154 // dont have alignement requirements will probably get into trouble with
155 // over-aggressive optimization under strict aliasing rules.
156 //
157 
158 template < class T >
159 inline void WireGet ( const epicsUInt8 * pWireSrc, T & dst )
160 {
161  // copy through union here
162  // a) prevents over-aggressive optimization under strict aliasing rules
163  // b) doesnt preclude extra copy operation being optimized away
164  WireAlias < T > tmp;
165  WireGet ( pWireSrc, tmp._u );
166  dst = tmp._o;
167 }
168 
169 template <>
171  const epicsUInt8 * pWireSrc, epicsUInt8 & dst )
172 {
173  dst = pWireSrc[0];
174 }
175 
176 template <>
178  const epicsUInt8 * pWireSrc, epicsUInt16 & dst )
179 {
180  dst = static_cast < epicsUInt16 > (
181  ( pWireSrc[0] << 8u ) | pWireSrc[1] );
182 }
183 
184 template <>
186  const epicsUInt8 * pWireSrc, epicsUInt32 & dst )
187 {
188  dst = static_cast < epicsUInt32 > (
189  ( pWireSrc[0] << 24u ) |
190  ( pWireSrc[1] << 16u ) |
191  ( pWireSrc[2] << 8u ) |
192  pWireSrc[3] );
193 }
194 
195 template < class T >
196 inline void WireSet ( const T & src, epicsUInt8 * pWireDst )
197 {
198  // copy through union here
199  // a) prevents over-aggressive optimization under strict aliasing rules
200  // b) doesnt preclude extra copy operation being optimized away
201  WireAlias < T > tmp;
202  tmp._o = src;
203  WireSet ( tmp._u, pWireDst );
204 }
205 
206 template <>
208  const epicsUInt8 & src, epicsUInt8 * pWireDst )
209 {
210  pWireDst[0] = src;
211 }
212 
213 template <>
215  const epicsUInt16 & src, epicsUInt8 * pWireDst )
216 {
217  pWireDst[0] = static_cast < epicsUInt8 > ( src >> 8u );
218  pWireDst[1] = static_cast < epicsUInt8 > ( src );
219 }
220 
221 template <>
223  const epicsUInt32 & src, epicsUInt8 * pWireDst )
224 {
225  pWireDst[0] = static_cast < epicsUInt8 > ( src >> 24u );
226  pWireDst[1] = static_cast < epicsUInt8 > ( src >> 16u );
227  pWireDst[2] = static_cast < epicsUInt8 > ( src >> 8u );
228  pWireDst[3] = static_cast < epicsUInt8 > ( src );
229 }
230 
231 template < class T >
232 inline void AlignedWireGet ( const T & src, T & dst )
233 {
234  // copy through union here
235  // a) prevents over-aggressive optimization under strict aliasing rules
236  // b) doesnt preclude extra copy operation being optimized away
237  WireAlias < T > srcu, dstu;
238  srcu._o = src;
239  AlignedWireGet ( srcu._u, dstu._u );
240  dst = dstu._o;
241 }
242 
243 template < class T >
244 inline void AlignedWireSet ( const T & src, T & dst )
245 {
246  // copy through union here
247  // a) prevents over-aggressive optimization under strict aliasing rules
248  // b) doesnt preclude extra copy operation being optimized away
249  WireAlias < T > srcu, dstu;
250  srcu._o = src;
251  AlignedWireSet ( srcu._u, dstu._u );
252  dst = dstu._o;
253 }
254 
255 #include "osdWireFormat.h"
256 
257 #endif // osiWireFormat
void AlignedWireSet(const T &, T &)
void WireGet(const epicsUInt8 *pWireSrc, T &)
void WireSet(const T &, epicsUInt8 *pWireDst)
unsigned short epicsUInt16
Definition: epicsTypes.h:41
AlignedWireRef(T &ref)
Definition: osiWireFormat.h:73
unsigned char epicsUInt8
Definition: epicsTypes.h:39
void WireSet< epicsUInt16 >(const epicsUInt16 &src, epicsUInt8 *pWireDst)
void AlignedWireGet(const T &, T &)
unsigned int epicsUInt32
Definition: epicsTypes.h:43
void WireSet< epicsUInt8 >(const epicsUInt8 &src, epicsUInt8 *pWireDst)
void WireSet< epicsUInt32 >(const epicsUInt32 &src, epicsUInt8 *pWireDst)
float epicsFloat32
Definition: epicsTypes.h:48
void WireGet< epicsUInt32 >(const epicsUInt8 *pWireSrc, epicsUInt32 &dst)
char epicsInt8
Definition: epicsTypes.h:38
AlignedWireRef< T > & operator=(const T &)
Definition: osiWireFormat.h:87
short epicsInt16
Definition: epicsTypes.h:40
void WireGet< epicsUInt16 >(const epicsUInt8 *pWireSrc, epicsUInt16 &dst)
int epicsInt32
Definition: epicsTypes.h:42
epicsUInt16 byteSwap(const epicsUInt16 &src)
void WireGet< epicsUInt8 >(const epicsUInt8 *pWireSrc, epicsUInt8 &dst)