typeCast.h: allow cast from C string to numeric w/o copy
also re-enable compile test of string to int64 which was disabled for some reason...
This commit is contained in:
@@ -507,20 +507,20 @@ void handleParseError(int err)
|
||||
|
||||
namespace epics { namespace pvData { namespace detail {
|
||||
|
||||
void parseToPOD(const string & in, boolean *out)
|
||||
void parseToPOD(const char* in, boolean *out)
|
||||
{
|
||||
if(epicsStrCaseCmp(in.c_str(),"true")==0)
|
||||
if(epicsStrCaseCmp(in,"true")==0)
|
||||
*out = 1;
|
||||
else if(epicsStrCaseCmp(in.c_str(),"false")==0)
|
||||
else if(epicsStrCaseCmp(in,"false")==0)
|
||||
*out = 0;
|
||||
else
|
||||
throw std::runtime_error("parseToPOD: string no match true/false");
|
||||
}
|
||||
|
||||
#define INTFN(T, S) \
|
||||
void parseToPOD(const string& in, T *out) { \
|
||||
void parseToPOD(const char* in, T *out) { \
|
||||
epics ## S temp; \
|
||||
int err = epicsParse ## S (in.c_str(), &temp, 0, NULL); \
|
||||
int err = epicsParse ## S (in, &temp, 0, NULL); \
|
||||
if(err) handleParseError(err); \
|
||||
else *out = temp; \
|
||||
}
|
||||
@@ -532,31 +532,31 @@ INTFN(uint16_t, UInt16);
|
||||
INTFN(int32_t, Int32);
|
||||
INTFN(uint32_t, UInt32);
|
||||
|
||||
void parseToPOD(const string& in, int64_t *out) {
|
||||
void parseToPOD(const char* in, int64_t *out) {
|
||||
#ifdef NEED_LONGLONG
|
||||
int err = epicsParseLongLong(in.c_str(), out, 0, NULL);
|
||||
int err = epicsParseLongLong(in, out, 0, NULL);
|
||||
#else
|
||||
int err = epicsParseLong(in.c_str(), out, 0, NULL);
|
||||
int err = epicsParseLong(in, out, 0, NULL);
|
||||
#endif
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const string& in, uint64_t *out) {
|
||||
void parseToPOD(const char* in, uint64_t *out) {
|
||||
#ifdef NEED_LONGLONG
|
||||
int err = epicsParseULongLong(in.c_str(), out, 0, NULL);
|
||||
int err = epicsParseULongLong(in, out, 0, NULL);
|
||||
#else
|
||||
int err = epicsParseULong(in.c_str(), out, 0, NULL);
|
||||
int err = epicsParseULong(in, out, 0, NULL);
|
||||
#endif
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const string& in, float *out) {
|
||||
int err = epicsParseFloat(in.c_str(), out, NULL);
|
||||
void parseToPOD(const char* in, float *out) {
|
||||
int err = epicsParseFloat(in, out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const string& in, double *out) {
|
||||
int err = epicsParseDouble(in.c_str(), out, NULL);
|
||||
void parseToPOD(const char* in, double *out) {
|
||||
int err = epicsParseDouble(in, out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
#if defined(vxWorks)
|
||||
/* vxWorks strtod returns [-]epicsINF when it should return ERANGE error.
|
||||
@@ -564,7 +564,7 @@ void parseToPOD(const string& in, double *out) {
|
||||
* this into an ERANGE error
|
||||
*/
|
||||
else if (*out == epicsINF || *out == -epicsINF) {
|
||||
const char* s = in.c_str();
|
||||
const char* s = in;
|
||||
int c;
|
||||
|
||||
/* skip spaces and the sign */
|
||||
|
||||
@@ -22,17 +22,29 @@ namespace epics { namespace pvData {
|
||||
namespace detail {
|
||||
// parseToPOD wraps the epicsParse*() functions in one name
|
||||
// and throws exceptions
|
||||
epicsShareExtern void parseToPOD(const std::string&, boolean *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int8 *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint8 *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int16_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint16_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int32_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint32_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, int64_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, uint64_t *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, float *out);
|
||||
epicsShareExtern void parseToPOD(const std::string&, double *out);
|
||||
epicsShareExtern void parseToPOD(const char*, boolean *out);
|
||||
epicsShareExtern void parseToPOD(const char*, int8 *out);
|
||||
epicsShareExtern void parseToPOD(const char*, uint8 *out);
|
||||
epicsShareExtern void parseToPOD(const char*, int16_t *out);
|
||||
epicsShareExtern void parseToPOD(const char*, uint16_t *out);
|
||||
epicsShareExtern void parseToPOD(const char*, int32_t *out);
|
||||
epicsShareExtern void parseToPOD(const char*, uint32_t *out);
|
||||
epicsShareExtern void parseToPOD(const char*, int64_t *out);
|
||||
epicsShareExtern void parseToPOD(const char*, uint64_t *out);
|
||||
epicsShareExtern void parseToPOD(const char*, float *out);
|
||||
epicsShareExtern void parseToPOD(const char*, double *out);
|
||||
|
||||
static inline void parseToPOD(const std::string& str, boolean *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, int8 *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, uint8 *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, int16_t *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, uint16_t *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, int32_t *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, uint32_t *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, int64_t *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, uint64_t *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, float *out) { return parseToPOD(str.c_str(), out); }
|
||||
static inline void parseToPOD(const std::string& str, double *out) { return parseToPOD(str.c_str(), out); }
|
||||
|
||||
/* want to pass POD types by value,
|
||||
* and std::string by const reference
|
||||
@@ -108,13 +120,28 @@ namespace detail {
|
||||
}
|
||||
};
|
||||
|
||||
// parse POD from C string
|
||||
// TO!=const char*
|
||||
template<typename TO>
|
||||
struct cast_helper<TO, const char*,
|
||||
typename meta::_and<
|
||||
typename meta::not_same_type<TO,const char*>,
|
||||
typename meta::not_same_type<TO,std::string>
|
||||
>::type> {
|
||||
static FORCE_INLINE TO op(const char* from) {
|
||||
TO ret;
|
||||
parseToPOD(from, &ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} // end detail
|
||||
|
||||
/** @brief Casting/converting between supported scalar types.
|
||||
*
|
||||
* Supported types: uint8_t, int8_t, uint16_t, int16_t,
|
||||
* uint32_t, int32_t, uint64_t, int64_t,
|
||||
* float, double, std::string
|
||||
* float, double, std::string, const char* (only FROM)
|
||||
*
|
||||
* As defined in pvType.h
|
||||
*
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace {
|
||||
|
||||
MAIN(testTypeCast)
|
||||
{
|
||||
testPlan(123);
|
||||
testPlan(124);
|
||||
|
||||
try {
|
||||
|
||||
@@ -138,10 +138,12 @@ try {
|
||||
float xfloat=0.0;
|
||||
double xdouble=0.0;
|
||||
string xstring("0");
|
||||
const char* xcstring = "0";
|
||||
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
typedef string string_t;
|
||||
typedef const char* cstring_t;
|
||||
|
||||
// force all possibilities to be compiled
|
||||
#define CHECK(M, N) x## M = ::epics::pvData::castUnsafe<M ##_t>(x## N); \
|
||||
@@ -158,6 +160,7 @@ try {
|
||||
CHECK(int8, float);
|
||||
CHECK(int8, double);
|
||||
CHECK(int8, string);
|
||||
CHECK(int8, cstring);
|
||||
|
||||
CHECK(uint8, int8);
|
||||
CHECK(uint8, uint8);
|
||||
@@ -170,6 +173,7 @@ try {
|
||||
CHECK(uint8, float);
|
||||
CHECK(uint8, double);
|
||||
CHECK(uint8, string);
|
||||
CHECK(uint8, cstring);
|
||||
|
||||
CHECK(int16, int8);
|
||||
CHECK(int16, uint8);
|
||||
@@ -182,6 +186,7 @@ try {
|
||||
CHECK(int16, float);
|
||||
CHECK(int16, double);
|
||||
CHECK(int16, string);
|
||||
CHECK(int16, cstring);
|
||||
|
||||
CHECK(uint16, int8);
|
||||
CHECK(uint16, uint8);
|
||||
@@ -194,6 +199,7 @@ try {
|
||||
CHECK(uint16, float);
|
||||
CHECK(uint16, double);
|
||||
CHECK(uint16, string);
|
||||
CHECK(uint16, cstring);
|
||||
|
||||
CHECK(int32, int8);
|
||||
CHECK(int32, uint8);
|
||||
@@ -206,6 +212,7 @@ try {
|
||||
CHECK(int32, float);
|
||||
CHECK(int32, double);
|
||||
CHECK(int32, string);
|
||||
CHECK(int32, cstring);
|
||||
|
||||
CHECK(uint32, int8);
|
||||
CHECK(uint32, uint8);
|
||||
@@ -218,6 +225,7 @@ try {
|
||||
CHECK(uint32, float);
|
||||
CHECK(uint32, double);
|
||||
CHECK(uint32, string);
|
||||
CHECK(uint32, cstring);
|
||||
|
||||
CHECK(int64, int8);
|
||||
CHECK(int64, uint8);
|
||||
@@ -229,7 +237,8 @@ try {
|
||||
CHECK(int64, uint64);
|
||||
CHECK(int64, float);
|
||||
CHECK(int64, double);
|
||||
//CHECK(int64, string);
|
||||
CHECK(int64, string);
|
||||
CHECK(int64, cstring);
|
||||
|
||||
CHECK(uint64, int8);
|
||||
CHECK(uint64, uint8);
|
||||
@@ -241,7 +250,8 @@ try {
|
||||
CHECK(uint64, uint64);
|
||||
CHECK(uint64, float);
|
||||
CHECK(uint64, double);
|
||||
//CHECK(uint64, string);
|
||||
CHECK(uint64, string);
|
||||
CHECK(uint64, cstring);
|
||||
|
||||
CHECK(float, int8);
|
||||
CHECK(float, uint8);
|
||||
@@ -254,6 +264,7 @@ try {
|
||||
CHECK(float, float);
|
||||
CHECK(float, double);
|
||||
CHECK(float, string);
|
||||
CHECK(float, cstring);
|
||||
|
||||
CHECK(double, int8);
|
||||
CHECK(double, uint8);
|
||||
@@ -266,6 +277,7 @@ try {
|
||||
CHECK(double, float);
|
||||
CHECK(double, double);
|
||||
CHECK(double, string);
|
||||
CHECK(double, cstring);
|
||||
|
||||
CHECK(string, int8);
|
||||
CHECK(string, uint8);
|
||||
@@ -278,6 +290,9 @@ try {
|
||||
CHECK(string, float);
|
||||
CHECK(string, double);
|
||||
CHECK(string, string);
|
||||
CHECK(string, cstring);
|
||||
|
||||
// cast to const char* not supported
|
||||
#undef CHECK
|
||||
|
||||
testDiag("Integer signed <=> unsigned");
|
||||
@@ -344,6 +359,7 @@ try {
|
||||
TEST2(string, "1.1e-100", double, 1.1e-100);
|
||||
|
||||
TEST(double, 1.1e100, string, "1.1E+100");
|
||||
TEST(double, 1.1e100, const char*, "1.1E+100");
|
||||
|
||||
// any non-zero value is true
|
||||
TEST(string, "true", epics::pvData::boolean, 100);
|
||||
|
||||
Reference in New Issue
Block a user