anyscalar.h: move out of line
No reason to believe that inline was helping.
This commit is contained in:
@@ -37,3 +37,4 @@ LIBSRCS += parseToPOD.cpp
|
||||
LIBSRCS += pvUnitTest.cpp
|
||||
LIBSRCS += debugPtr.cpp
|
||||
LIBSRCS += reftrack.cpp
|
||||
LIBSRCS += anyscalar.cpp
|
||||
|
||||
161
src/misc/anyscalar.cpp
Normal file
161
src/misc/anyscalar.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
|
||||
#include <epicsAssert.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <shareLib.h>
|
||||
|
||||
#include "pv/anyscalar.h"
|
||||
|
||||
namespace epics {namespace pvData {
|
||||
|
||||
AnyScalar::AnyScalar(ScalarType type, const void *buf)
|
||||
{
|
||||
if(type==pvString) {
|
||||
new (_wrap.blob) std::string(*static_cast<const std::string*>(buf));
|
||||
|
||||
} else {
|
||||
memcpy(_wrap.blob, buf, ScalarTypeFunc::elementSize(type));
|
||||
}
|
||||
|
||||
_stype = type;
|
||||
}
|
||||
|
||||
AnyScalar::AnyScalar(const AnyScalar& o)
|
||||
:_stype(o._stype)
|
||||
{
|
||||
if(o._stype==pvString) {
|
||||
new (_wrap.blob) std::string(o._as<std::string>());
|
||||
} else if(o._stype!=(ScalarType)-1) {
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
}
|
||||
}
|
||||
|
||||
#if __cplusplus>=201103L
|
||||
AnyScalar::AnyScalar(AnyScalar&& o)
|
||||
:_stype(o._stype)
|
||||
{
|
||||
typedef std::string string;
|
||||
if(o._stype==pvString) {
|
||||
new (_wrap.blob) std::string();
|
||||
_as<std::string>() = std::move(o._as<std::string>());
|
||||
o._as<string>().~string();
|
||||
} else if(o._stype!=(ScalarType)-1) {
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
}
|
||||
o._stype = (ScalarType)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void AnyScalar::clear() {
|
||||
if(_stype==pvString) {
|
||||
typedef std::string string;
|
||||
_as<string>().~string();
|
||||
}
|
||||
// other types need no cleanup
|
||||
_stype = (ScalarType)-1;
|
||||
}
|
||||
|
||||
void AnyScalar::swap(AnyScalar& o) {
|
||||
typedef std::string string;
|
||||
switch((int)_stype) {
|
||||
case -1:
|
||||
switch((int)o._stype) {
|
||||
case -1:
|
||||
// nil <-> nil
|
||||
break;
|
||||
case pvString:
|
||||
// nil <-> string
|
||||
new (_wrap.blob) std::string();
|
||||
_as<std::string>().swap(o._as<std::string>());
|
||||
o._as<std::string>().~string();
|
||||
break;
|
||||
default:
|
||||
// nil <-> non-string
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case pvString:
|
||||
switch((int)o._stype) {
|
||||
case -1:
|
||||
// string <-> nil
|
||||
new (o._wrap.blob) std::string();
|
||||
_as<std::string>().swap(o._as<std::string>());
|
||||
_as<std::string>().~string();
|
||||
break;
|
||||
case pvString:
|
||||
// string <-> string
|
||||
_as<std::string>().swap(o._as<std::string>());
|
||||
break;
|
||||
default: {
|
||||
// string <-> non-string
|
||||
std::string temp;
|
||||
temp.swap(_as<std::string>());
|
||||
|
||||
_as<std::string>().~string();
|
||||
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
|
||||
new (o._wrap.blob) std::string();
|
||||
temp.swap(o._as<std::string>());
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch((int)o._stype) {
|
||||
case -1:
|
||||
// non-string <-> nil
|
||||
memcpy(o._wrap.blob, _wrap.blob, sizeof(_largest_blob));
|
||||
break;
|
||||
case pvString: {
|
||||
// non-string <-> string
|
||||
std::string temp;
|
||||
temp.swap(o._as<std::string>());
|
||||
|
||||
o._as<std::string>().~string();
|
||||
|
||||
memcpy(o._wrap.blob, _wrap.blob, sizeof(_largest_blob));
|
||||
|
||||
new (_wrap.blob) std::string();
|
||||
temp.swap(_as<std::string>());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// non-string <-> non-string
|
||||
_largest_blob temp;
|
||||
memcpy(&temp, _wrap.blob, sizeof(_largest_blob));
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
memcpy(o._wrap.blob, &temp, sizeof(_largest_blob));
|
||||
// std::swap(o._wrap.blob, _wrap.blob); // gcc <=4.3 doesn't like this
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
std::swap(_stype, o._stype);
|
||||
}
|
||||
const void* AnyScalar::bufferUnsafe() const {
|
||||
if(_stype==pvString) {
|
||||
return as<std::string>().c_str();
|
||||
} else {
|
||||
return _wrap.blob;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& strm, const AnyScalar& v)
|
||||
{
|
||||
switch(v.type()) {
|
||||
#define CASE(BASETYPE, PVATYPE, DBFTYPE, PVACODE) case pv ## PVACODE: strm<<v._as<PVATYPE>(); break;
|
||||
#define CASE_REAL_INT64
|
||||
#define CASE_STRING
|
||||
#include "pv/typemap.h"
|
||||
#undef CASE
|
||||
#undef CASE_REAL_INT64
|
||||
#undef CASE_STRING
|
||||
default:
|
||||
strm<<"(nil)"; break;
|
||||
}
|
||||
return strm;
|
||||
}
|
||||
|
||||
}} // namespace epics::pvData
|
||||
@@ -48,7 +48,7 @@ constexpr size_t cmax(size_t A, size_t B) {
|
||||
assert(A.ref<double>()==5.0); // throws AnyScalar::bad_cast
|
||||
@endcode
|
||||
*/
|
||||
class AnyScalar {
|
||||
class epicsShareClass AnyScalar {
|
||||
public:
|
||||
struct bad_cast : public std::exception {
|
||||
#if __cplusplus>=201103L
|
||||
@@ -95,8 +95,11 @@ private:
|
||||
return *reinterpret_cast<const T*>(_wrap.blob);
|
||||
}
|
||||
public:
|
||||
//! Construct empty
|
||||
//! @post empty()==true
|
||||
AnyScalar() : _stype((ScalarType)-1) {}
|
||||
|
||||
//! Construct from provided value.
|
||||
template<typename T>
|
||||
explicit AnyScalar(T v)
|
||||
{
|
||||
@@ -112,59 +115,31 @@ public:
|
||||
_stype = (ScalarType)ScalarTypeID<TT>::value;
|
||||
}
|
||||
|
||||
AnyScalar(ScalarType type, const void *buf)
|
||||
{
|
||||
if(type==pvString) {
|
||||
new (_wrap.blob) std::string(*static_cast<const std::string*>(buf));
|
||||
//! Construct from un-typed pointer.
|
||||
//! Caller is responsible to ensure that buf actually points to the provided type
|
||||
AnyScalar(ScalarType type, const void *buf);
|
||||
|
||||
} else {
|
||||
memcpy(_wrap.blob, buf, ScalarTypeFunc::elementSize(type));
|
||||
}
|
||||
|
||||
_stype = type;
|
||||
}
|
||||
|
||||
AnyScalar(const AnyScalar& o)
|
||||
:_stype(o._stype)
|
||||
{
|
||||
if(o._stype==pvString) {
|
||||
new (_wrap.blob) std::string(o._as<std::string>());
|
||||
} else if(o._stype!=(ScalarType)-1) {
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
}
|
||||
}
|
||||
AnyScalar(const AnyScalar& o);
|
||||
|
||||
#if __cplusplus>=201103L
|
||||
AnyScalar(AnyScalar&& o)
|
||||
:_stype(o._stype)
|
||||
{
|
||||
typedef std::string string;
|
||||
if(o._stype==pvString) {
|
||||
new (_wrap.blob) std::string();
|
||||
_as<std::string>() = std::move(o._as<std::string>());
|
||||
o._as<string>().~string();
|
||||
} else if(o._stype!=(ScalarType)-1) {
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
}
|
||||
o._stype = (ScalarType)-1;
|
||||
}
|
||||
AnyScalar(AnyScalar&& o);
|
||||
#endif
|
||||
|
||||
~AnyScalar() {clear();}
|
||||
inline ~AnyScalar() {clear();}
|
||||
|
||||
AnyScalar& operator=(const AnyScalar& o) {
|
||||
inline AnyScalar& operator=(const AnyScalar& o) {
|
||||
AnyScalar(o).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
AnyScalar& operator=(T v) {
|
||||
inline AnyScalar& operator=(T v) {
|
||||
AnyScalar(v).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus>=201103L
|
||||
AnyScalar& operator=(AnyScalar&& o) {
|
||||
inline AnyScalar& operator=(AnyScalar&& o) {
|
||||
clear();
|
||||
swap(o);
|
||||
return *this;
|
||||
@@ -174,101 +149,17 @@ public:
|
||||
//! Reset internal state.
|
||||
//! Added after 7.0.0
|
||||
//! @post empty()==true
|
||||
void clear() {
|
||||
if(_stype==pvString) {
|
||||
typedef std::string string;
|
||||
_as<string>().~string();
|
||||
}
|
||||
// other types need no cleanup
|
||||
_stype = (ScalarType)-1;
|
||||
}
|
||||
void clear();
|
||||
|
||||
void swap(AnyScalar& o) {
|
||||
typedef std::string string;
|
||||
switch((int)_stype) {
|
||||
case -1:
|
||||
switch((int)o._stype) {
|
||||
case -1:
|
||||
// nil <-> nil
|
||||
break;
|
||||
case pvString:
|
||||
// nil <-> string
|
||||
new (_wrap.blob) std::string();
|
||||
_as<std::string>().swap(o._as<std::string>());
|
||||
o._as<std::string>().~string();
|
||||
break;
|
||||
default:
|
||||
// nil <-> non-string
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case pvString:
|
||||
switch((int)o._stype) {
|
||||
case -1:
|
||||
// string <-> nil
|
||||
new (o._wrap.blob) std::string();
|
||||
_as<std::string>().swap(o._as<std::string>());
|
||||
_as<std::string>().~string();
|
||||
break;
|
||||
case pvString:
|
||||
// string <-> string
|
||||
_as<std::string>().swap(o._as<std::string>());
|
||||
break;
|
||||
default: {
|
||||
// string <-> non-string
|
||||
std::string temp;
|
||||
temp.swap(_as<std::string>());
|
||||
|
||||
_as<std::string>().~string();
|
||||
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
|
||||
new (o._wrap.blob) std::string();
|
||||
temp.swap(o._as<std::string>());
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch((int)o._stype) {
|
||||
case -1:
|
||||
// non-string <-> nil
|
||||
memcpy(o._wrap.blob, _wrap.blob, sizeof(_largest_blob));
|
||||
break;
|
||||
case pvString: {
|
||||
// non-string <-> string
|
||||
std::string temp;
|
||||
temp.swap(o._as<std::string>());
|
||||
|
||||
o._as<std::string>().~string();
|
||||
|
||||
memcpy(o._wrap.blob, _wrap.blob, sizeof(_largest_blob));
|
||||
|
||||
new (_wrap.blob) std::string();
|
||||
temp.swap(_as<std::string>());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// non-string <-> non-string
|
||||
_largest_blob temp;
|
||||
memcpy(&temp, _wrap.blob, sizeof(_largest_blob));
|
||||
memcpy(_wrap.blob, o._wrap.blob, sizeof(_largest_blob));
|
||||
memcpy(o._wrap.blob, &temp, sizeof(_largest_blob));
|
||||
// std::swap(o._wrap.blob, _wrap.blob); // gcc <=4.3 doesn't like this
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
std::swap(_stype, o._stype);
|
||||
}
|
||||
void swap(AnyScalar& o);
|
||||
|
||||
//! Type code of contained value. Or (ScalarType)-1 is empty.
|
||||
inline ScalarType type() const {
|
||||
return _stype;
|
||||
}
|
||||
|
||||
void* unsafe() { return _wrap.blob; }
|
||||
const void* unsafe() const { return _wrap.blob; }
|
||||
inline void* unsafe() { return _wrap.blob; }
|
||||
inline const void* unsafe() const { return _wrap.blob; }
|
||||
|
||||
inline bool empty() const { return _stype==(ScalarType)-1; }
|
||||
|
||||
@@ -283,16 +174,18 @@ public:
|
||||
|
||||
//! Provide read-only access to underlying buffer.
|
||||
//! For a string this is std::string::c_str().
|
||||
const void* bufferUnsafe() const {
|
||||
if(_stype==pvString) {
|
||||
return as<std::string>().c_str();
|
||||
} else {
|
||||
return _wrap.blob;
|
||||
}
|
||||
}
|
||||
const void* bufferUnsafe() const;
|
||||
|
||||
/** Return reference to wrapped value */
|
||||
/** Return typed reference to wrapped value. Non-const reference allows value modification
|
||||
*
|
||||
@code
|
||||
AnyScalar v(42);
|
||||
v.ref<uint32>() = 42;
|
||||
assert(v.ref<uint32>() = 43);
|
||||
@endcode
|
||||
*/
|
||||
template<typename T>
|
||||
inline
|
||||
// T -> strip_const -> map to storage type -> add reference
|
||||
typename detail::any_storage_type<typename meta::strip_const<T>::type>::type&
|
||||
ref() {
|
||||
@@ -304,7 +197,15 @@ public:
|
||||
return reinterpret_cast<TT&>(_wrap.blob);
|
||||
}
|
||||
|
||||
/** Return typed reference to wrapped value. Const reference does not allow modification.
|
||||
*
|
||||
@code
|
||||
AnyScalar v(42);
|
||||
assert(v.ref<uint32>() = 42);
|
||||
@endcode
|
||||
*/
|
||||
template<typename T>
|
||||
inline
|
||||
// T -> strip_const -> map to storage type -> add const reference
|
||||
typename meta::decorate_const<typename detail::any_storage_type<typename meta::strip_const<T>::type>::type>::type&
|
||||
ref() const {
|
||||
@@ -318,6 +219,7 @@ public:
|
||||
|
||||
/** copy out wrapped value, with a value conversion. */
|
||||
template<typename T>
|
||||
inline
|
||||
T as() const {
|
||||
typedef typename meta::strip_const<T>::type T2;
|
||||
typedef typename detail::any_storage_type<T2>::type TT;
|
||||
@@ -334,22 +236,8 @@ private:
|
||||
friend std::ostream& operator<<(std::ostream& strm, const AnyScalar& v);
|
||||
};
|
||||
|
||||
inline
|
||||
std::ostream& operator<<(std::ostream& strm, const AnyScalar& v)
|
||||
{
|
||||
switch(v.type()) {
|
||||
#define CASE(BASETYPE, PVATYPE, DBFTYPE, PVACODE) case pv ## PVACODE: strm<<v._as<PVATYPE>(); break;
|
||||
#define CASE_REAL_INT64
|
||||
#define CASE_STRING
|
||||
#include "pv/typemap.h"
|
||||
#undef CASE
|
||||
#undef CASE_REAL_INT64
|
||||
#undef CASE_STRING
|
||||
default:
|
||||
strm<<"(nil)"; break;
|
||||
}
|
||||
return strm;
|
||||
}
|
||||
epicsShareExtern
|
||||
std::ostream& operator<<(std::ostream& strm, const AnyScalar& v);
|
||||
|
||||
}} // namespace epics::pvData
|
||||
|
||||
|
||||
Reference in New Issue
Block a user