caseUnsafeV use switch instead of jump table
Change from jump table to switch. reduces code size (~1k of 30k for rtems/mvme3100). use indexed loop to help gcc vectorizer. Helpfully won't fail to compile w/ gcc 4.1 (vxworks 6.6/6.7)
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <epicsConvert.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
@@ -18,7 +20,7 @@ using std::string;
|
||||
|
||||
namespace {
|
||||
|
||||
static void noconvert(size_t, void*, const void*)
|
||||
static void noconvert()
|
||||
{
|
||||
throw std::runtime_error("castUnsafeV: Conversion not supported");
|
||||
}
|
||||
@@ -31,12 +33,10 @@ static void castVTyped(size_t count, void *draw, const void *sraw)
|
||||
|
||||
//std::transform(src, src+count, dest, castUnsafe<TO,FROM>);
|
||||
|
||||
const FROM *last = src+count;
|
||||
try {
|
||||
while (src != last) {
|
||||
*dest = castUnsafe<TO,FROM>(*src);
|
||||
++dest; ++src;
|
||||
}
|
||||
for(size_t i=0; i<count; i++) {
|
||||
dest[i] = castUnsafe<TO,FROM>(src[i]);
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
// do not report index for scalars (or arrays with one element)
|
||||
if (count > 1)
|
||||
@@ -59,182 +59,11 @@ static void copyV(size_t count, void *draw, const void *sraw)
|
||||
std::copy(src, src+count, dest);
|
||||
}
|
||||
|
||||
typedef void (*convertfn)(size_t, void*, const void*);
|
||||
|
||||
/* lookup table of converter functions.
|
||||
* first dimension is TO, second is FROM
|
||||
*/
|
||||
static convertfn converters[pvString+1][pvString+1] =
|
||||
template<int N>
|
||||
static void copyMem(size_t count, void *draw, const void *sraw)
|
||||
{
|
||||
// to pvBoolean
|
||||
{ ©V<epics::pvData::boolean>,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&castVTyped<epics::pvData::boolean, string>,
|
||||
},
|
||||
// to pvByte
|
||||
{&noconvert,
|
||||
©V<int8_t>,
|
||||
&castVTyped<int8_t, int16_t>,
|
||||
&castVTyped<int8_t, int32_t>,
|
||||
&castVTyped<int8_t, int64_t>,
|
||||
&castVTyped<int8_t, uint8_t>,
|
||||
&castVTyped<int8_t, uint16_t>,
|
||||
&castVTyped<int8_t, uint32_t>,
|
||||
&castVTyped<int8_t, uint64_t>,
|
||||
&castVTyped<int8_t, float>,
|
||||
&castVTyped<int8_t, double>,
|
||||
&castVTyped<int8_t, string>,
|
||||
},
|
||||
// to pvShort
|
||||
{&noconvert,
|
||||
&castVTyped<int16_t, int8_t>,
|
||||
©V<int16_t>,
|
||||
&castVTyped<int16_t, int32_t>,
|
||||
&castVTyped<int16_t, int64_t>,
|
||||
&castVTyped<int16_t, uint8_t>,
|
||||
&castVTyped<int16_t, uint16_t>,
|
||||
&castVTyped<int16_t, uint32_t>,
|
||||
&castVTyped<int16_t, uint64_t>,
|
||||
&castVTyped<int16_t, float>,
|
||||
&castVTyped<int16_t, double>,
|
||||
&castVTyped<int16_t, string>,
|
||||
},
|
||||
// to pvInt
|
||||
{&noconvert,
|
||||
&castVTyped<int32_t, int8_t>,
|
||||
&castVTyped<int32_t, int16_t>,
|
||||
©V<int32_t>,
|
||||
&castVTyped<int32_t, int64_t>,
|
||||
&castVTyped<int32_t, uint8_t>,
|
||||
&castVTyped<int32_t, uint16_t>,
|
||||
&castVTyped<int32_t, uint32_t>,
|
||||
&castVTyped<int32_t, uint64_t>,
|
||||
&castVTyped<int32_t, float>,
|
||||
&castVTyped<int32_t, double>,
|
||||
&castVTyped<int32_t, string>,
|
||||
},
|
||||
// to pvLong
|
||||
{&noconvert,
|
||||
&castVTyped<int64_t, int8_t>,
|
||||
&castVTyped<int64_t, int16_t>,
|
||||
&castVTyped<int64_t, int32_t>,
|
||||
©V<int64_t>,
|
||||
&castVTyped<int64_t, uint8_t>,
|
||||
&castVTyped<int64_t, uint16_t>,
|
||||
&castVTyped<int64_t, uint32_t>,
|
||||
&castVTyped<int64_t, uint64_t>,
|
||||
&castVTyped<int64_t, float>,
|
||||
&castVTyped<int64_t, double>,
|
||||
&castVTyped<int64_t, string>,
|
||||
},
|
||||
// to pvUByte
|
||||
{&noconvert,
|
||||
&castVTyped<uint8_t, int8_t>,
|
||||
&castVTyped<uint8_t, int16_t>,
|
||||
&castVTyped<uint8_t, int32_t>,
|
||||
&castVTyped<uint8_t, uint64_t>,
|
||||
©V<uint8_t>,
|
||||
&castVTyped<uint8_t, uint16_t>,
|
||||
&castVTyped<uint8_t, uint32_t>,
|
||||
&castVTyped<uint8_t, uint64_t>,
|
||||
&castVTyped<uint8_t, float>,
|
||||
&castVTyped<uint8_t, double>,
|
||||
&castVTyped<uint8_t, string>,
|
||||
},
|
||||
// to pvUShort
|
||||
{&noconvert,
|
||||
&castVTyped<uint16_t, int8_t>,
|
||||
&castVTyped<uint16_t, int16_t>,
|
||||
&castVTyped<uint16_t, int32_t>,
|
||||
&castVTyped<uint16_t, uint64_t>,
|
||||
&castVTyped<uint16_t, uint8_t>,
|
||||
©V<uint16_t>,
|
||||
&castVTyped<uint16_t, uint32_t>,
|
||||
&castVTyped<uint16_t, uint64_t>,
|
||||
&castVTyped<uint16_t, float>,
|
||||
&castVTyped<uint16_t, double>,
|
||||
&castVTyped<uint16_t, string>,
|
||||
},
|
||||
// to pvUInt
|
||||
{&noconvert,
|
||||
&castVTyped<uint32_t, int8_t>,
|
||||
&castVTyped<uint32_t, int16_t>,
|
||||
&castVTyped<uint32_t, int32_t>,
|
||||
&castVTyped<uint32_t, uint64_t>,
|
||||
&castVTyped<uint32_t, uint8_t>,
|
||||
&castVTyped<uint32_t, uint16_t>,
|
||||
©V<uint32_t>,
|
||||
&castVTyped<uint32_t, uint64_t>,
|
||||
&castVTyped<uint32_t, float>,
|
||||
&castVTyped<uint32_t, double>,
|
||||
&castVTyped<uint32_t, string>,
|
||||
},
|
||||
// to pvULong
|
||||
{&noconvert,
|
||||
&castVTyped<uint64_t, int8_t>,
|
||||
&castVTyped<uint64_t, int16_t>,
|
||||
&castVTyped<uint64_t, int32_t>,
|
||||
&castVTyped<uint64_t, uint64_t>,
|
||||
&castVTyped<uint64_t, uint8_t>,
|
||||
&castVTyped<uint64_t, uint16_t>,
|
||||
&castVTyped<uint64_t, uint32_t>,
|
||||
©V<uint64_t>,
|
||||
&castVTyped<uint64_t, float>,
|
||||
&castVTyped<uint64_t, double>,
|
||||
&castVTyped<uint64_t, string>,
|
||||
},
|
||||
// to pvFloat
|
||||
{&noconvert,
|
||||
&castVTyped<float, int8_t>,
|
||||
&castVTyped<float, int16_t>,
|
||||
&castVTyped<float, int32_t>,
|
||||
&castVTyped<float, uint64_t>,
|
||||
&castVTyped<float, uint8_t>,
|
||||
&castVTyped<float, uint16_t>,
|
||||
&castVTyped<float, uint32_t>,
|
||||
&castVTyped<float, uint64_t>,
|
||||
©V<float>,
|
||||
&castVTyped<float, double>,
|
||||
&castVTyped<float, string>,
|
||||
},
|
||||
// to pvDouble
|
||||
{&noconvert,
|
||||
&castVTyped<double, int8_t>,
|
||||
&castVTyped<double, int16_t>,
|
||||
&castVTyped<double, int32_t>,
|
||||
&castVTyped<double, uint64_t>,
|
||||
&castVTyped<double, uint8_t>,
|
||||
&castVTyped<double, uint16_t>,
|
||||
&castVTyped<double, uint32_t>,
|
||||
&castVTyped<double, uint64_t>,
|
||||
&castVTyped<double, float>,
|
||||
©V<double>,
|
||||
&castVTyped<double, string>,
|
||||
},
|
||||
// to pvString
|
||||
{&castVTyped<string, epics::pvData::boolean>,
|
||||
&castVTyped<string, int8_t>,
|
||||
&castVTyped<string, int16_t>,
|
||||
&castVTyped<string, int32_t>,
|
||||
&castVTyped<string, uint64_t>,
|
||||
&castVTyped<string, uint8_t>,
|
||||
&castVTyped<string, uint16_t>,
|
||||
&castVTyped<string, uint32_t>,
|
||||
&castVTyped<string, uint64_t>,
|
||||
&castVTyped<string, float>,
|
||||
&castVTyped<string, double>,
|
||||
©V<string>,
|
||||
},
|
||||
};
|
||||
memcpy(draw, sraw, count*N);
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
@@ -242,12 +71,207 @@ namespace epics { namespace pvData {
|
||||
|
||||
void castUnsafeV(size_t count, ScalarType to, void *dest, ScalarType from, const void *src)
|
||||
{
|
||||
unsigned int ito=to, ifrom=from;
|
||||
#define COPYMEM(N) copyMem<N>(count, dest, src)
|
||||
#define CAST(TO, FROM) castVTyped<TO, FROM>(count, dest, src)
|
||||
|
||||
if(ito>pvString || ifrom>pvString)
|
||||
throw std::runtime_error("castUnsafeV: Invalid types");
|
||||
switch(to) {
|
||||
case pvBoolean:
|
||||
switch(from) {
|
||||
case pvBoolean: COPYMEM(1); return;
|
||||
case pvString: CAST(boolean, std::string); return;
|
||||
default: noconvert(); return;
|
||||
}
|
||||
break;
|
||||
|
||||
converters[ito][ifrom](count, dest, src);
|
||||
case pvByte:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte:
|
||||
case pvUByte: COPYMEM(1); return;
|
||||
case pvShort: CAST(int8, int16); return;
|
||||
case pvUShort: CAST(int8, uint16); return;
|
||||
case pvInt: CAST(int8, int32); return;
|
||||
case pvUInt: CAST(int8, uint32); return;
|
||||
case pvLong: CAST(int8, int64); return;
|
||||
case pvULong: CAST(int8, uint64); return;
|
||||
case pvFloat: CAST(int8, float); return;
|
||||
case pvDouble: CAST(int8, double); return;
|
||||
case pvString: CAST(int8, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvUByte:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte:
|
||||
case pvUByte: COPYMEM(1); return;
|
||||
case pvShort: CAST(uint8, int16); return;
|
||||
case pvUShort: CAST(uint8, uint16); return;
|
||||
case pvInt: CAST(uint8, int32); return;
|
||||
case pvUInt: CAST(uint8, uint32); return;
|
||||
case pvLong: CAST(uint8, int64); return;
|
||||
case pvULong: CAST(uint8, uint64); return;
|
||||
case pvFloat: CAST(uint8, float); return;
|
||||
case pvDouble: CAST(uint8, double); return;
|
||||
case pvString: CAST(uint8, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvShort:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(int16, int8); return;
|
||||
case pvUByte: CAST(int16, uint8); return;
|
||||
case pvShort:
|
||||
case pvUShort: COPYMEM(2); return;
|
||||
case pvInt: CAST(int16, int32); return;
|
||||
case pvUInt: CAST(int16, uint32); return;
|
||||
case pvLong: CAST(int16, int64); return;
|
||||
case pvULong: CAST(int16, uint64); return;
|
||||
case pvFloat: CAST(int16, float); return;
|
||||
case pvDouble: CAST(int16, double); return;
|
||||
case pvString: CAST(int16, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvUShort:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(uint16, int8); return;
|
||||
case pvUByte: CAST(uint16, uint8); return;
|
||||
case pvShort:
|
||||
case pvUShort: COPYMEM(2); return;
|
||||
case pvInt: CAST(uint16, int32); return;
|
||||
case pvUInt: CAST(uint16, uint32); return;
|
||||
case pvLong: CAST(uint16, int64); return;
|
||||
case pvULong: CAST(uint16, uint64); return;
|
||||
case pvFloat: CAST(uint16, float); return;
|
||||
case pvDouble: CAST(uint16, double); return;
|
||||
case pvString: CAST(uint16, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvInt:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(int32, int8); return;
|
||||
case pvUByte: CAST(int32, uint8); return;
|
||||
case pvShort: CAST(int32, int16); return;
|
||||
case pvUShort: CAST(int32, uint16); return;
|
||||
case pvInt:
|
||||
case pvUInt: COPYMEM(4); return;
|
||||
case pvLong: CAST(int32, int64); return;
|
||||
case pvULong: CAST(int32, uint64); return;
|
||||
case pvFloat: CAST(int32, float); return;
|
||||
case pvDouble: CAST(int32, double); return;
|
||||
case pvString: CAST(int32, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvUInt:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(uint32, int8); return;
|
||||
case pvUByte: CAST(uint32, uint8); return;
|
||||
case pvShort: CAST(uint32, int16); return;
|
||||
case pvUShort: CAST(uint32, uint16); return;
|
||||
case pvInt:
|
||||
case pvUInt: COPYMEM(4); return;
|
||||
case pvLong: CAST(uint32, int64); return;
|
||||
case pvULong: CAST(uint32, uint64); return;
|
||||
case pvFloat: CAST(uint32, float); return;
|
||||
case pvDouble: CAST(uint32, double); return;
|
||||
case pvString: CAST(uint32, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvLong:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(int64, int8); return;
|
||||
case pvUByte: CAST(int64, uint8); return;
|
||||
case pvShort: CAST(int64, int16); return;
|
||||
case pvUShort: CAST(int64, uint16); return;
|
||||
case pvInt: CAST(int64, int32); return;
|
||||
case pvUInt: CAST(int64, uint32); return;
|
||||
case pvLong:
|
||||
case pvULong: COPYMEM(8); return;
|
||||
case pvFloat: CAST(int64, float); return;
|
||||
case pvDouble: CAST(int64, double); return;
|
||||
case pvString: CAST(int64, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvULong:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(uint64, int8); return;
|
||||
case pvUByte: CAST(uint64, uint8); return;
|
||||
case pvShort: CAST(uint64, int16); return;
|
||||
case pvUShort: CAST(uint64, uint16); return;
|
||||
case pvInt: CAST(uint64, int32); return;
|
||||
case pvUInt: CAST(uint64, uint32); return;
|
||||
case pvLong:
|
||||
case pvULong: COPYMEM(8); return;
|
||||
case pvFloat: CAST(uint64, float); return;
|
||||
case pvDouble: CAST(uint64, double); return;
|
||||
case pvString: CAST(uint64, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvFloat:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(float, int8); return;
|
||||
case pvUByte: CAST(float, uint8); return;
|
||||
case pvShort: CAST(float, int16); return;
|
||||
case pvUShort: CAST(float, uint16); return;
|
||||
case pvInt: CAST(float, int32); return;
|
||||
case pvUInt: CAST(float, uint32); return;
|
||||
case pvLong: CAST(float, int64); return;
|
||||
case pvULong: CAST(float, uint64); return;
|
||||
case pvFloat: COPYMEM(4); return;
|
||||
case pvDouble: CAST(float, double); return;
|
||||
case pvString: CAST(float, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvDouble:
|
||||
switch(from) {
|
||||
case pvBoolean: noconvert(); return;
|
||||
case pvByte: CAST(double, int8); return;
|
||||
case pvUByte: CAST(double, uint8); return;
|
||||
case pvShort: CAST(double, int16); return;
|
||||
case pvUShort: CAST(double, uint16); return;
|
||||
case pvInt: CAST(double, int32); return;
|
||||
case pvUInt: CAST(double, uint32); return;
|
||||
case pvLong: CAST(double, int64); return;
|
||||
case pvULong: CAST(double, uint64); return;
|
||||
case pvFloat: CAST(double, float); return;
|
||||
case pvDouble: COPYMEM(8); return;
|
||||
case pvString: CAST(double, std::string); return;
|
||||
}
|
||||
break;
|
||||
|
||||
case pvString:
|
||||
switch(from) {
|
||||
case pvBoolean: CAST(std::string, boolean); return;
|
||||
case pvByte: CAST(std::string, int8); return;
|
||||
case pvUByte: CAST(std::string, uint8); return;
|
||||
case pvShort: CAST(std::string, int16); return;
|
||||
case pvUShort: CAST(std::string, uint16); return;
|
||||
case pvInt: CAST(std::string, int32); return;
|
||||
case pvUInt: CAST(std::string, uint32); return;
|
||||
case pvLong: CAST(std::string, int64); return;
|
||||
case pvULong: CAST(std::string, uint64); return;
|
||||
case pvFloat: CAST(std::string, float); return;
|
||||
case pvDouble: CAST(std::string, double); return;
|
||||
case pvString: copyV<std::string>(count, dest, src); return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
THROW_EXCEPTION2(std::logic_error, "Undefined cast");
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user