This is Unofficial EPICS BASE Doxygen Site
parseToPOD.cpp
Go to the documentation of this file.
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 #include <ctype.h>
6 #include <stdio.h>
7 #include <errno.h>
8 #include <float.h>
9 #include <limits.h>
10 
11 #include <epicsVersion.h>
12 
13 #include <epicsMath.h>
14 #include <epicsStdlib.h>
15 #include <epicsString.h>
16 #include <epicsConvert.h>
17 
18 #define epicsExportSharedSymbols
19 #include "pv/typeCast.h"
20 
21 using std::string;
22 
23 // need to use "long long" when sizeof(int)==sizeof(long)
24 #if (ULONG_MAX == 0xfffffffful) || defined(_WIN32) || defined(__rtems__) || defined(__APPLE__)
25 #define NEED_LONGLONG
26 #endif
27 
28 /* do we need long long? */
29 #ifdef NEED_LONGLONG
30 static int
31 epicsParseLongLong(const char *str, long long *to, int base, char **units)
32 {
33  int c;
34  char *endp;
35  long long value;
36 
37  while ((c = *str) && isspace(c))
38  ++str;
39 
40  errno = 0;
41  value = strtoll(str, &endp, base);
42 
43  if (endp == str)
44  return S_stdlib_noConversion;
45  if (errno == EINVAL) /* Not universally supported */
46  return S_stdlib_badBase;
47  if (errno == ERANGE)
48  return S_stdlib_overflow;
49 
50  while ((c = *endp) && isspace(c))
51  ++endp;
52  if (c && !units)
53  return S_stdlib_extraneous;
54 
55  *to = value;
56  if (units)
57  *units = endp;
58  return 0;
59 }
60 
61 static int
62 epicsParseULongLong(const char *str, unsigned long long *to, int base, char **units)
63 {
64  int c;
65  char *endp;
66  unsigned long long value;
67 
68  while ((c = *str) && isspace(c))
69  ++str;
70 
71  errno = 0;
72  value = strtoull(str, &endp, base);
73 
74  if (endp == str)
75  return S_stdlib_noConversion;
76  if (errno == EINVAL) /* Not universally supported */
77  return S_stdlib_badBase;
78  if (errno == ERANGE)
79  return S_stdlib_overflow;
80 
81  while ((c = *endp) && isspace(c))
82  ++endp;
83  if (c && !units)
84  return S_stdlib_extraneous;
85 
86  *to = value;
87  if (units)
88  *units = endp;
89  return 0;
90 }
91 #endif
92 
93 static
94 void handleParseError(int err)
95 {
96  switch(err) {
97  case 0: break;
98  case S_stdlib_noConversion: throw std::runtime_error("parseToPOD: No digits to convert");
99  case S_stdlib_extraneous: throw std::runtime_error("parseToPOD: Extraneous characters");
100  case S_stdlib_underflow: throw std::runtime_error("parseToPOD: Too small to represent");
101  case S_stdlib_overflow: throw std::runtime_error("parseToPOD: Too large to represent");
102  case S_stdlib_badBase: throw std::runtime_error("parseToPOD: Number base not supported");
103  default:
104  throw std::runtime_error("parseToPOD: unknown error");
105  }
106 }
107 
108 namespace epics { namespace pvData { namespace detail {
109 
110 void parseToPOD(const char* in, boolean *out)
111 {
112  if(epicsStrCaseCmp(in,"true")==0)
113  *out = 1;
114  else if(epicsStrCaseCmp(in,"false")==0)
115  *out = 0;
116  else
117  throw std::runtime_error("parseToPOD: string no match true/false");
118 }
119 
120 #define INTFN(T, S) \
121 void parseToPOD(const char* in, T *out) { \
122  epics ## S temp; \
123  int err = epicsParse ## S (in, &temp, 0, NULL); \
124  if(err) handleParseError(err); \
125  else *out = temp; \
126 }
127 
128 INTFN(int8, Int8);
129 INTFN(uint8, UInt8);
130 INTFN(int16_t, Int16);
131 INTFN(uint16_t, UInt16);
132 INTFN(int32_t, Int32);
133 INTFN(uint32_t, UInt32);
134 
135 void parseToPOD(const char* in, int64_t *out) {
136 #ifdef NEED_LONGLONG
137  int err = epicsParseLongLong(in, out, 0, NULL);
138 #else
139  int err = epicsParseLong(in, out, 0, NULL);
140 #endif
141  if(err) handleParseError(err);
142 }
143 
144 void parseToPOD(const char* in, uint64_t *out) {
145 #ifdef NEED_LONGLONG
146  int err = epicsParseULongLong(in, out, 0, NULL);
147 #else
148  int err = epicsParseULong(in, out, 0, NULL);
149 #endif
150  if(err) handleParseError(err);
151 }
152 
153 void parseToPOD(const char* in, float *out) {
154  int err = epicsParseFloat(in, out, NULL);
155  if(err) handleParseError(err);
156 }
157 
158 void parseToPOD(const char* in, double *out) {
159  int err = epicsParseDouble(in, out, NULL);
160  if(err) handleParseError(err);
161 #if defined(vxWorks)
162  /* vxWorks strtod returns [-]epicsINF when it should return ERANGE error.
163  * If [-]epicsINF is returned and the first char is a digit we translate
164  * this into an ERANGE error
165  */
166  else if (*out == epicsINF || *out == -epicsINF) {
167  const char* s = in;
168  int c;
169 
170  /* skip spaces and the sign */
171  do {
172  c = *s++;
173  } while (isspace(c));
174 
175  if (c == '-' || c == '+')
176  c = *s++;
177 
178  if (isdigit(c))
179  handleParseError(S_stdlib_overflow);
180  }
181 #endif
182 }
183 
184 }}}
int8_t int8
Definition: pvType.h:75
Definition: link.h:174
#define S_stdlib_underflow
Definition: epicsStdlib.h:29
#define S_stdlib_badBase
Definition: epicsStdlib.h:31
#define S_stdlib_noConversion
Definition: epicsStdlib.h:27
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
#define NULL
Definition: catime.c:38
#define str(v)
LIBCOM_API int epicsParseFloat(const char *str, float *to, char **units)
Definition: epicsStdlib.c:318
int epicsStrCaseCmp(const char *s1, const char *s2)
Definition: epicsString.c:191
#define S_stdlib_extraneous
Definition: epicsStdlib.h:28
#define strtoll
Definition: osdStrtod.h:27
LIBCOM_API int epicsParseULong(const char *str, unsigned long *to, int base, char **units)
Definition: epicsStdlib.c:56
void parseToPOD(const char *in, boolean *out)
Definition: parseToPOD.cpp:110
LIBCOM_API int epicsParseDouble(const char *str, double *to, char **units)
Definition: epicsStdlib.c:149
LIBCOM_API int epicsParseLong(const char *str, long *to, int base, char **units)
Definition: epicsStdlib.c:25
#define S_stdlib_overflow
Definition: epicsStdlib.h:30
#define strtoull
Definition: osdStrtod.h:28
int * base
Definition: flex.c:92
uint8_t uint8
Definition: pvType.h:91
float epicsINF
Definition: epicsMath.cpp:36