anyscalar.h: move out of line

No reason to believe that inline was helping.
This commit is contained in:
Michael Davidsaver
2018-04-08 15:46:52 -07:00
parent 9ecdb80534
commit 671f9cca4b
3 changed files with 201 additions and 151 deletions

View File

@@ -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
View 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

View File

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