typeCast String <-> boolean

This commit is contained in:
Michael Davidsaver
2013-10-29 17:56:36 -04:00
parent 14dc098761
commit 9cd7008efe
4 changed files with 60 additions and 14 deletions

View File

@@ -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);

View File

@@ -44,7 +44,7 @@ typedef void (*convertfn)(size_t, void*, const void*);
static convertfn converters[pvString+1][pvString+1] =
{
// to pvBoolean
{ &noconvert,
{ &copyV<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>,

View File

@@ -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();

View File

@@ -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);