1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
/**
* Numeric field types for AMQP
*
* @copyright 2014 - 2023 Copernica BV
*/
/**
* Include guard
*/
#pragma once
/**
* Dependencies
*/
#include <memory>
#include <type_traits>
#include "inbuffer.h"
#include "outbuffer.h"
#include "field.h"
#include <ostream>
/**
* Set up namespace
*/
namespace AMQP {
/**
* Template for numeric field types
*/
template<
typename T,
char F,
typename = typename std::enable_if<std::is_arithmetic<T>::value, T>
>
class NumericField : public Field
{
private:
/**
* Field value
*/
T _value;
public:
using Type = T;
/**
* Default constructor, assign 0
*/
NumericField() : _value(0) {}
/**
* Construct numeric field from
* one of numeric types
*
* @param value field value
*/
NumericField(T value) : _value(value) {}
/**
* Parse based on incoming buffer
* @param frame
*/
NumericField(InBuffer &frame)
{
// The Microsoft Visual Studio compiler thinks that there is an issue
// with the following code, so we temporarily disable a specific warning
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4244)
#endif
if (std::is_same<int8_t, typename std::remove_cv<T>::type>::value) _value = frame.nextInt8();
else if (std::is_same<int16_t, typename std::remove_cv<T>::type>::value) _value = frame.nextInt16();
else if (std::is_same<int32_t, typename std::remove_cv<T>::type>::value) _value = frame.nextInt32();
else if (std::is_same<int64_t, typename std::remove_cv<T>::type>::value) _value = frame.nextInt64();
else if (std::is_same<uint8_t, typename std::remove_cv<T>::type>::value) _value = frame.nextUint8();
else if (std::is_same<uint16_t, typename std::remove_cv<T>::type>::value) _value = frame.nextUint16();
else if (std::is_same<uint32_t, typename std::remove_cv<T>::type>::value) _value = frame.nextUint32();
else if (std::is_same<uint64_t, typename std::remove_cv<T>::type>::value) _value = frame.nextUint64();
else if (std::is_same<float, typename std::remove_cv<T>::type>::value) _value = frame.nextFloat();
else if (std::is_same<double, typename std::remove_cv<T>::type>::value) _value = frame.nextDouble();
// re-enable the warning
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
}
/**
* Destructor
*/
virtual ~NumericField() {}
/**
* Create a new instance of this object
* @return unique_ptr
*/
virtual std::unique_ptr<Field> clone() const override
{
// create a new copy of ourselves and return it
return std::unique_ptr<Field>(new NumericField(_value));
}
/**
* Assign a new value
*
* @param value new value for field
* @return NumericField
*/
NumericField& operator=(T value)
{
_value = value;
return *this;
};
/**
* Clear the field
* @return NumericField
*/
NumericField& clear()
{
_value = 0;
return *this;
}
/**
* Get the value
* @return mixed
*/
operator uint8_t () const override { return (uint8_t)_value; }
operator uint16_t() const override { return (uint16_t)_value; }
operator uint32_t() const override { return (uint32_t)_value; }
operator uint64_t() const override { return (uint64_t)_value; }
operator int8_t () const override { return (int8_t)_value; }
operator int16_t () const override { return (int16_t)_value; }
operator int32_t () const override { return (int32_t)_value; }
operator int64_t () const override { return (int64_t)_value; }
operator float () const override { return (float)_value; }
operator double () const override { return (double)_value; }
/**
* Get the value
* @return mixed
*/
T value() const
{
// return internal value
return _value;
}
/**
* We are an integer field
*
* @return true, because we are an integer
*/
bool isInteger() const override
{
return std::is_integral<T>::value;
}
/**
* Get the size this field will take when
* encoded in the AMQP wire-frame format
* @return size_t
*/
virtual size_t size() const override
{
// numeric types have no extra storage requirements
return sizeof(_value);
}
/**
* Write encoded payload to the given buffer.
* @param buffer OutBuffer to write to
*/
virtual void fill(OutBuffer& buffer) const override
{
// store converted value
T value = _value;
// write to buffer
// adding a value takes care of host to network byte order
buffer.add(value);
}
/**
* Get the type ID that is used to identify this type of
* field in a field table
*/
virtual char typeID() const override
{
return F;
}
/**
* Output the object to a stream
* @param std::ostream
*/
virtual void output(std::ostream &stream) const override
{
// show
stream << "numeric(" << value() << ")";
}
};
/**
* Concrete numeric types for AMQP
*/
typedef NumericField<int8_t, 'b'> Octet;
typedef NumericField<uint8_t, 'B'> UOctet;
typedef NumericField<int16_t, 'U'> Short;
typedef NumericField<uint16_t, 'u'> UShort;
typedef NumericField<int32_t, 'I'> Long;
typedef NumericField<uint32_t, 'i'> ULong;
typedef NumericField<int64_t, 'L'> LongLong;
typedef NumericField<uint64_t, 'l'> ULongLong;
typedef NumericField<uint64_t, 'T'> Timestamp;
/**
* Concrete floating-point types for AMQP
*/
typedef NumericField<float, 'f'> Float;
typedef NumericField<double, 'd'> Double;
/**
* end namespace
*/
}
|