typeCast String <-> boolean
This commit is contained in:
@@ -420,6 +420,16 @@ void handleParseError(int err)
|
||||
|
||||
namespace epics { namespace pvData { namespace detail {
|
||||
|
||||
void parseToPOD(const std::string & in, boolean *out)
|
||||
{
|
||||
if(epicsStrCaseCmp(in.c_str(),"true")==0)
|
||||
*out = 1;
|
||||
else if(epicsStrCaseCmp(in.c_str(),"false")==0)
|
||||
*out = 0;
|
||||
else
|
||||
throw std::runtime_error("parseToPOD: String no match true/false");
|
||||
}
|
||||
|
||||
#define INTFN(T, S) \
|
||||
void parseToPOD(const std::string& in, T *out) { \
|
||||
epics ## S temp; \
|
||||
@@ -428,9 +438,8 @@ void parseToPOD(const std::string& in, T *out) { \
|
||||
else *out = temp; \
|
||||
}
|
||||
|
||||
INTFN(char, Int8);
|
||||
INTFN(int8_t, Int8);
|
||||
INTFN(uint8_t, UInt8);
|
||||
INTFN(int8, Int8);
|
||||
INTFN(uint8, UInt8);
|
||||
INTFN(int16_t, Int16);
|
||||
INTFN(uint16_t, UInt16);
|
||||
INTFN(int32_t, Int32);
|
||||
|
||||
@@ -44,7 +44,7 @@ typedef void (*convertfn)(size_t, void*, const void*);
|
||||
static convertfn converters[pvString+1][pvString+1] =
|
||||
{
|
||||
// to pvBoolean
|
||||
{ &noconvert,
|
||||
{ ©V<epics::pvData::boolean>,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
@@ -55,7 +55,7 @@ static convertfn converters[pvString+1][pvString+1] =
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert
|
||||
&castVTyped<epics::pvData::boolean, String>,
|
||||
},
|
||||
// to pvByte
|
||||
{&noconvert,
|
||||
@@ -198,7 +198,7 @@ static convertfn converters[pvString+1][pvString+1] =
|
||||
&castVTyped<double, String>,
|
||||
},
|
||||
// to pvString
|
||||
{&noconvert,
|
||||
{&castVTyped<String, epics::pvData::boolean>,
|
||||
&castVTyped<String, int8_t>,
|
||||
&castVTyped<String, int16_t>,
|
||||
&castVTyped<String, int32_t>,
|
||||
|
||||
@@ -23,9 +23,9 @@ typedef std::string String;
|
||||
namespace detail {
|
||||
// parseToPOD wraps the epicsParse*() functions in one name
|
||||
// and throws exceptions
|
||||
void parseToPOD(const std::string&, char *out);
|
||||
void parseToPOD(const std::string&, int8_t *out);
|
||||
void parseToPOD(const std::string&, uint8_t *out);
|
||||
void parseToPOD(const std::string&, boolean *out);
|
||||
void parseToPOD(const std::string&, int8 *out);
|
||||
void parseToPOD(const std::string&, uint8 *out);
|
||||
void parseToPOD(const std::string&, int16_t *out);
|
||||
void parseToPOD(const std::string&, uint16_t *out);
|
||||
void parseToPOD(const std::string&, int32_t *out);
|
||||
@@ -43,6 +43,27 @@ namespace detail {
|
||||
template<>
|
||||
struct cast_arg<String> { typedef const String& arg; };
|
||||
|
||||
// Handle mangling of type/value when printing
|
||||
template<typename T>
|
||||
struct print_convolute {
|
||||
static FORCE_INLINE T op(const T& i) { return i; }
|
||||
};
|
||||
// trick std::ostream into treating char's as numbers
|
||||
// by promoting char to int
|
||||
template<>
|
||||
struct print_convolute<int8> {
|
||||
static FORCE_INLINE signed int op(int8 i) { return i; }
|
||||
};
|
||||
template<>
|
||||
struct print_convolute<uint8> {
|
||||
static FORCE_INLINE unsigned int op(uint8 i) { return i; }
|
||||
};
|
||||
// Turn boolean into a string
|
||||
template<>
|
||||
struct print_convolute<boolean> {
|
||||
static FORCE_INLINE String op(boolean i) { return i ? "true" : "false"; }
|
||||
};
|
||||
|
||||
// trick std::ostream into treating char's as numbers
|
||||
// by promoting char to int
|
||||
template<typename T>
|
||||
@@ -75,9 +96,8 @@ namespace detail {
|
||||
template<typename FROM>
|
||||
struct cast_helper<String, FROM, typename meta::not_same_type<String,FROM>::type> {
|
||||
static String op(FROM from) {
|
||||
typedef typename print_cast<FROM>::type ptype;
|
||||
std::ostringstream strm;
|
||||
strm << (ptype)from;
|
||||
strm << print_convolute<FROM>::op(from);
|
||||
if(strm.fail())
|
||||
throw std::runtime_error("Cast to string failed");
|
||||
return strm.str();
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace {
|
||||
|
||||
MAIN(testTypeCast)
|
||||
{
|
||||
testPlan(110);
|
||||
testPlan(122);
|
||||
|
||||
try {
|
||||
|
||||
@@ -313,7 +313,6 @@ try {
|
||||
TEST2(String, "1", int8_t, 1);
|
||||
TEST2(String, "-1", int8_t, -1);
|
||||
TEST2(String, "1", uint8_t, 1);
|
||||
TEST2(String, "-1", char, -1);
|
||||
|
||||
TEST2(String, "127", int32_t, std::numeric_limits<int8_t>::max());
|
||||
TEST2(String, "-128", int32_t, std::numeric_limits<int8_t>::min());
|
||||
@@ -337,6 +336,18 @@ try {
|
||||
|
||||
TEST(double, 1.1e100, String, "1.1E+100");
|
||||
|
||||
// any non-zero value is true
|
||||
TEST(String, "true", epics::pvData::boolean, 100);
|
||||
|
||||
TEST2(String, "true", epics::pvData::boolean, 1);
|
||||
TEST2(String, "false", epics::pvData::boolean, 0);
|
||||
|
||||
// Case insensitive
|
||||
TEST(epics::pvData::boolean, 1, String, "True");
|
||||
TEST(epics::pvData::boolean, 0, String, "False");
|
||||
TEST(epics::pvData::boolean, 1, String, "TRUE");
|
||||
TEST(epics::pvData::boolean, 0, String, "FALSE");
|
||||
|
||||
testDiag("String Parsing");
|
||||
|
||||
TEST(int32_t, 15, String, "0xf");
|
||||
@@ -372,9 +383,15 @@ try {
|
||||
|
||||
FAIL(int8_t, String, "1000");
|
||||
FAIL(int8_t, String, "-1000");
|
||||
;
|
||||
|
||||
FAIL(double, String, "1e+10000000");
|
||||
|
||||
FAIL(epics::pvData::boolean, String, "hello");
|
||||
FAIL(epics::pvData::boolean, String, "1");
|
||||
FAIL(epics::pvData::boolean, String, "0");
|
||||
FAIL(epics::pvData::boolean, String, "T");
|
||||
FAIL(epics::pvData::boolean, String, "F");
|
||||
|
||||
testDiag("Floating point overflows");
|
||||
|
||||
TEST(float, FLT_MAX, double, 1e300);
|
||||
|
||||
Reference in New Issue
Block a user