PVData C++  8.0.2
typeCast.h
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 /* Author: Michael Davidsaver */
6 #ifndef PVTYPECAST_H
7 #define PVTYPECAST_H
8 
9 #include <stdexcept>
10 #include <sstream>
11 
12 #include <epicsConvert.h>
13 #include <shareLib.h>
14 
15 #include <pv/pvType.h>
16 #include <pv/pvIntrospect.h>
17 #include <pv/templateMeta.h>
18 
19 
20 namespace epics { namespace pvData {
21 
22 namespace detail {
23  // parseToPOD wraps the epicsParse*() functions in one name
24  // and throws exceptions
25  epicsShareExtern void parseToPOD(const char*, boolean *out);
26  epicsShareExtern void parseToPOD(const char*, int8 *out);
27  epicsShareExtern void parseToPOD(const char*, uint8 *out);
28  epicsShareExtern void parseToPOD(const char*, int16_t *out);
29  epicsShareExtern void parseToPOD(const char*, uint16_t *out);
30  epicsShareExtern void parseToPOD(const char*, int32_t *out);
31  epicsShareExtern void parseToPOD(const char*, uint32_t *out);
32  epicsShareExtern void parseToPOD(const char*, int64_t *out);
33  epicsShareExtern void parseToPOD(const char*, uint64_t *out);
34  epicsShareExtern void parseToPOD(const char*, float *out);
35  epicsShareExtern void parseToPOD(const char*, double *out);
36 
37  static inline void parseToPOD(const std::string& str, boolean *out) { return parseToPOD(str.c_str(), out); }
38  static inline void parseToPOD(const std::string& str, int8 *out) { return parseToPOD(str.c_str(), out); }
39  static inline void parseToPOD(const std::string& str, uint8 *out) { return parseToPOD(str.c_str(), out); }
40  static inline void parseToPOD(const std::string& str, int16_t *out) { return parseToPOD(str.c_str(), out); }
41  static inline void parseToPOD(const std::string& str, uint16_t *out) { return parseToPOD(str.c_str(), out); }
42  static inline void parseToPOD(const std::string& str, int32_t *out) { return parseToPOD(str.c_str(), out); }
43  static inline void parseToPOD(const std::string& str, uint32_t *out) { return parseToPOD(str.c_str(), out); }
44  static inline void parseToPOD(const std::string& str, int64_t *out) { return parseToPOD(str.c_str(), out); }
45  static inline void parseToPOD(const std::string& str, uint64_t *out) { return parseToPOD(str.c_str(), out); }
46  static inline void parseToPOD(const std::string& str, float *out) { return parseToPOD(str.c_str(), out); }
47  static inline void parseToPOD(const std::string& str, double *out) { return parseToPOD(str.c_str(), out); }
48 
49  /* want to pass POD types by value,
50  * and std::string by const reference
51  */
52  template<typename ARG>
53  struct cast_arg { typedef ARG arg; };
54  template<>
55  struct cast_arg<std::string> { typedef const std::string& arg; };
56 
57  // Handle mangling of type/value when printing
58  template<typename T>
59  struct print_convolute {
60  typedef T return_t;
61  static FORCE_INLINE return_t op(const T& i) { return i; }
62  };
63  // trick std::ostream into treating chars as numbers
64  // by promoting char to int
65  template<>
66  struct print_convolute<int8> {
67  typedef signed int return_t;
68  static FORCE_INLINE return_t op(int8 i) { return i; }
69  };
70  template<>
71  struct print_convolute<uint8> {
72  typedef unsigned int return_t;
73  static FORCE_INLINE return_t op(uint8 i) { return i; }
74  };
75  // Turn boolean into a string
76  template<>
77  struct print_convolute<boolean> {
78  typedef const char* return_t;
79  static FORCE_INLINE return_t op(boolean i) { return i ? "true" : "false"; }
80  };
81 
82 
83  // default to C++ type casting
84  template<typename TO, typename FROM, class Enable = void>
85  struct cast_helper {
86  static FORCE_INLINE TO op(FROM from) {
87  return static_cast<TO>(from);
88  }
89  };
90 
91  // special handling when down-casting double to float
92  template<>
93  struct cast_helper<float, double> {
94  static FORCE_INLINE float op(double from) {
95  return epicsConvertDoubleToFloat(from);
96  }
97  };
98 
99  // print POD to string
100  // when std::string!=FROM
101  template<typename FROM>
102  struct cast_helper<std::string, FROM, typename meta::not_same_type<std::string,FROM>::type> {
103  static std::string op(FROM from) {
104  std::ostringstream strm;
105  strm << print_convolute<FROM>::op(from);
106  if(strm.fail())
107  throw std::runtime_error("Cast to string failed");
108  return strm.str();
109  }
110  };
111 
112  // parse POD from string
113  // TO!=std::string
114  template<typename TO>
115  struct cast_helper<TO, std::string, typename meta::not_same_type<TO,std::string>::type> {
116  static FORCE_INLINE TO op(const std::string& from) {
117  TO ret;
118  parseToPOD(from, &ret);
119  return ret;
120  }
121  };
122 
123  // parse POD from C string
124  // TO!=const char*
125  template<typename TO>
126  struct cast_helper<TO, const char*,
127  typename meta::_and<
128  typename meta::not_same_type<TO,const char*>,
129  typename meta::not_same_type<TO,std::string>
130  >::type> {
131  static FORCE_INLINE TO op(const char* from) {
132  TO ret;
133  parseToPOD(from, &ret);
134  return ret;
135  }
136  };
137 
138 } // end detail
139 
140 /** @brief Casting/converting between supported scalar types.
141  *
142  * Supported types: uint8_t, int8_t, uint16_t, int16_t,
143  * uint32_t, int32_t, uint64_t, int64_t,
144  * float, double, std::string, const char* (only FROM)
145  *
146  * As defined in pvType.h
147  *
148  @throws std::runtime_error when the cast is not possible.
149  @throws std::bad_alloc when the cast is not possible.
150  *
151  @section convertg Conversion Guarantees
152  *
153  * Conversions which always produce a correct result.
154  *
155  * - signed integer -> larger signed integer
156  * - unsigned integer -> larger unsigned integer
157  * - integer -> float or double (where sizeof(integer)<sizeof(floating))
158  * - float -> double
159  *
160  * Conversions where out of range inputs always produce
161  * a defined result, but may not be reversible.
162  *
163  * - double -> float. When abs(value) is outside the range
164  * [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX
165  * with the sign preserved.
166  *
167  * Conversions where invalid or out of range inputs result
168  * in an exception.
169  *
170  * - non-std::string -> std::string
171  * - std::string -> non-std::string
172  * - std::string -> std::string (throws only std::bad_alloc)
173  *
174  * Conversions where out of range inputs produce undefined
175  * results.
176  *
177  * - signed integer -> smaller signed integer
178  * - unsigned integer -> smaller unsigned integer
179  * - signed integer <-> unsigned integer
180  * - integer -> float or double (where sizeof(integer)>=sizeof(floating))
181  * - float or double -> integer. The floating point value
182  * is rounded towards zero. However, the result for values
183  * too large to be represented by the integer type
184  * is not defined.
185  *
186  @section stringf std::string formats
187  *
188  * - Numbers beginning with 1-9 are parsed as base-10.
189  * - Numbers beginning with '0x' are parsed as base-16
190  * - Numbers beginning with '0' are parsed as base-8.
191  * - Hex numbers are case insensitive.
192  * - Exponential numbers may use either 'e' or 'E'.
193  */
194 template<typename TO, typename FROM>
195 static FORCE_INLINE TO castUnsafe(const FROM& from)
196 {
197  return detail::cast_helper<TO,FROM>::op(from);
198 }
199 
201 
202 //! Cast value to printable type
203 //! A no-op except for int8 and uint8, which are cast to int
204 //! so that they are printed as numbers std::ostream operators,
205 //! and boolean which is transformed into a const char*
206 template<typename T>
207 static FORCE_INLINE
208 typename detail::print_convolute<T>::return_t
209 print_cast(const T& v) { return detail::print_convolute<T>::op(v); }
210 
211 struct escape;
212 
213 epicsShareFunc
214 std::ostream& operator<<(std::ostream& strm, const escape& Q);
215 
216 //! Helper to print a string with escaping
217 //! @code strm<<'"'<<escape(astring)<<'"' @endcode
218 struct epicsShareClass escape
219 {
220  enum style_t {
221  C, // default
222  CSV, // a la RFC4180
223  };
224 private:
225  const std::string& orig;
226  style_t S;
227 public:
228  escape(const std::string& orig) :orig(orig), S(C) {}
229  ~escape();
230  //! Change escaping style
231  inline escape& style(style_t s) { S = s; return *this; }
232  //! print to string and return. (alloc and copy)
233  std::string str() const;
234 
235  friend
237  std::ostream& operator<<(std::ostream& strm, const escape& Q);
238 };
239 
240 struct maybeQuote {
241  const std::string& s;
242  maybeQuote(const std::string& s) :s(s) {}
243 };
244 
245 epicsShareExtern
246 std::ostream& operator<<(std::ostream& strm, const maybeQuote& q);
247 
248 }} // end namespace
249 
250 #endif // PVTYPECAST_H
#define FORCE_INLINE
Definition: templateMeta.h:20
epicsShareFunc bool yajl_parse_helper(std::istream &src, yajl_handle handle)