From ad3b95741e8cdefe3ac678b7947c8fc43e14e1c0 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Fri, 24 Apr 2015 10:46:44 +0200 Subject: [PATCH] various trics and changes so that windows compilers, and 32bit systems will not complain about stuff --- include/booleanset.h | 2 +- include/connection.h | 4 +- include/connectionimpl.h | 2 +- include/decimalfield.h | 2 +- include/endian.h | 93 +++++++++++++++++++++++++++++++++++++++- include/envelope.h | 2 +- include/numericfield.h | 51 ++++++++++------------ src/channelimpl.cpp | 26 +++++------ src/connectionimpl.cpp | 6 +-- src/messageimpl.h | 10 ++++- src/receivedframe.cpp | 4 +- 11 files changed, 146 insertions(+), 56 deletions(-) diff --git a/include/booleanset.h b/include/booleanset.h index b527048..00e870c 100644 --- a/include/booleanset.h +++ b/include/booleanset.h @@ -110,7 +110,7 @@ public: if (index > 7) return false; // magic bit manipulation... - return (bool)((1 << index) & _byte); + return 0 != ((1 << index) & _byte); } /** diff --git a/include/connection.h b/include/connection.h index 2de2d9e..599ff01 100644 --- a/include/connection.h +++ b/include/connection.h @@ -106,7 +106,7 @@ public: * @param size size of the buffer to decode * @return number of bytes that were processed */ - size_t parse(const char *buffer, size_t size) + uint64_t parse(const char *buffer, size_t size) { return _implementation.parse(ByteBuffer(buffer, size)); } @@ -129,7 +129,7 @@ public: * @param buffer buffer to decode * @return number of bytes that were processed */ - size_t parse(const Buffer &buffer) + uint64_t parse(const Buffer &buffer) { return _implementation.parse(buffer); } diff --git a/include/connectionimpl.h b/include/connectionimpl.h index 7283e03..b3ceeb8 100644 --- a/include/connectionimpl.h +++ b/include/connectionimpl.h @@ -253,7 +253,7 @@ public: * @param buffer buffer to decode * @return number of bytes that were processed */ - size_t parse(const Buffer &buffer); + uint64_t parse(const Buffer &buffer); /** * Close the connection diff --git a/include/decimalfield.h b/include/decimalfield.h index 75a8ab0..67ac372 100644 --- a/include/decimalfield.h +++ b/include/decimalfield.h @@ -136,7 +136,7 @@ public: */ operator float() const { - return _number / pow(10, _places); + return static_cast(_number / pow(10, _places)); } /** diff --git a/include/endian.h b/include/endian.h index 3eaac1d..bcc4e0e 100644 --- a/include/endian.h +++ b/include/endian.h @@ -5,6 +5,18 @@ * and big endian byte orders. This header file adds the missing macros * * @author madmongo1 + * + * And we have also copied code from the "portable_endian.h" file by + * Mathias Panzenböck. His license: + * + * "License": Public Domain + * I, Mathias Panzenböck, place this file hereby into the public + * domain. Use it at your own risk for whatever you like. In case + * there are jurisdictions that don't support putting things in the + * public domain you can also consider it to be "dual licensed" + * under the BSD, MIT and Apache licenses, if you want to. This + * code is trivial anyway. Consider it an example on how to get the + * endian conversion functions on different platforms. */ /** @@ -39,10 +51,87 @@ #define be64toh(x) OSSwapBigToHostInt64(x) #define le64toh(x) OSSwapLittleToHostInt64(x) -// not on apple +/** + * And on Windows systems weird things are going on as well + */ +#elif (defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)) && !defined(__CYGWIN__) + +#include +#pragma comment(lib,"Ws2_32.lib") +//# include + +#if BYTE_ORDER == LITTLE_ENDIAN + +#define htobe16(x) htons(x) +#define htole16(x) (x) +#define be16toh(x) ntohs(x) +#define le16toh(x) (x) + +#define htobe32(x) htonl(x) +#define htole32(x) (x) +#define be32toh(x) ntohl(x) +#define le32toh(x) (x) + +#define htobe64(x) htonll(x) +#define htole64(x) (x) +#define be64toh(x) ntohll(x) +#define le64toh(x) (x) + +#elif BYTE_ORDER == BIG_ENDIAN + +/* that would be xbox 360 */ +#define htobe16(x) (x) +#define htole16(x) __builtin_bswap16(x) +#define be16toh(x) (x) +#define le16toh(x) __builtin_bswap16(x) + +#define htobe32(x) (x) +#define htole32(x) __builtin_bswap32(x) +#define be32toh(x) (x) +#define le32toh(x) __builtin_bswap32(x) + +#define htobe64(x) (x) +#define htole64(x) __builtin_bswap64(x) +#define be64toh(x) (x) +#define le64toh(x) __builtin_bswap64(x) + #else -// non-apple systems have their own endian header file +#error byte order not supported + +#endif + +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#define __PDP_ENDIAN PDP_ENDIAN + +/** + * OpenBSD handling + */ +#elif defined(__OpenBSD__) + +#include + +/** + * NetBSD handling + */ +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +#include +#define be16toh(x) betoh16(x) +#define le16toh(x) letoh16(x) +#define be32toh(x) betoh32(x) +#define le32toh(x) letoh32(x) +#define be64toh(x) betoh64(x) +#define le64toh(x) letoh64(x) + +/** + * Not on apple, and not on windows + */ +#else + +// this is the normal linux way of doing things #include // end of "#if defined(__APPLE__)" diff --git a/include/envelope.h b/include/envelope.h index b1cdf6a..48aef96 100644 --- a/include/envelope.h +++ b/include/envelope.h @@ -91,7 +91,7 @@ public: */ std::string message() const { - return std::string(_body, _bodySize); + return std::string(_body, static_cast(_bodySize)); } }; diff --git a/include/numericfield.h b/include/numericfield.h index 3cd4c93..04518b9 100644 --- a/include/numericfield.h +++ b/include/numericfield.h @@ -47,26 +47,28 @@ public: */ NumericField(ReceivedFrame &frame) { - // copy the data from the buffer into the field - if (!std::is_floating_point::value) - { - // convert value based on internal storage size - switch (sizeof(T)) - { - case 1: _value = frame.nextUint8(); break; - case 2: _value = frame.nextUint16(); break; - case 4: _value = frame.nextUint32(); break; - case 8: _value = frame.nextUint64(); break; - } - } - else - { - switch (sizeof(T)) - { - case 4: _value = frame.nextFloat(); break; - case 8: _value = frame.nextDouble(); break; - } - } +// 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::type>::value) _value = frame.nextInt8(); + else if (std::is_same::type>::value) _value = frame.nextInt16(); + else if (std::is_same::type>::value) _value = frame.nextInt32(); + else if (std::is_same::type>::value) _value = frame.nextInt64(); + else if (std::is_same::type>::value) _value = frame.nextUint8(); + else if (std::is_same::type>::value) _value = frame.nextUint16(); + else if (std::is_same::type>::value) _value = frame.nextUint32(); + else if (std::is_same::type>::value) _value = frame.nextUint64(); + else if (std::is_same::type>::value) _value = frame.nextFloat(); + else if (std::is_same::type>::value) _value = frame.nextDouble(); + +// re-enable the warning +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif } /** @@ -126,15 +128,6 @@ public: return sizeof(_value); } - /** - * Get the maximum allowed value for this field - * @return mixed - */ - constexpr static T max() - { - return std::numeric_limits::max(); - } - /** * Write encoded payload to the given buffer. * @param buffer OutBuffer to write to diff --git a/src/channelimpl.cpp b/src/channelimpl.cpp index 8ab04f8..867ae78 100644 --- a/src/channelimpl.cpp +++ b/src/channelimpl.cpp @@ -225,7 +225,7 @@ Deferred &ChannelImpl::declareExchange(const std::string &name, ExchangeType typ if (type == ExchangeType::headers)exchangeType = "headers"; // send declare exchange frame - return push(ExchangeDeclareFrame(_id, name, exchangeType, flags & passive, flags & durable, false, arguments)); + return push(ExchangeDeclareFrame(_id, name, exchangeType, (flags & passive) != 0, (flags & durable) != 0, false, arguments)); } /** @@ -274,7 +274,7 @@ Deferred &ChannelImpl::unbindExchange(const std::string &source, const std::stri Deferred &ChannelImpl::removeExchange(const std::string &name, int flags) { // send delete exchange frame - return push(ExchangeDeleteFrame(_id, name, flags & ifunused, false)); + return push(ExchangeDeleteFrame(_id, name, (flags & ifunused) != 0, false)); } /** @@ -289,7 +289,7 @@ Deferred &ChannelImpl::removeExchange(const std::string &name, int flags) DeferredQueue &ChannelImpl::declareQueue(const std::string &name, int flags, const Table &arguments) { // the frame to send - QueueDeclareFrame frame(_id, name, flags & passive, flags & durable, flags & exclusive, flags & autodelete, false, arguments); + QueueDeclareFrame frame(_id, name, (flags & passive) != 0, (flags & durable) != 0, (flags & exclusive) != 0, (flags & autodelete) != 0, false, arguments); // send the queuedeclareframe auto result = std::make_shared(!send(frame)); @@ -388,7 +388,7 @@ DeferredDelete &ChannelImpl::purgeQueue(const std::string &name) DeferredDelete &ChannelImpl::removeQueue(const std::string &name, int flags) { // the frame to send - QueueDeleteFrame frame(_id, name, flags & ifunused, flags & ifempty, false); + QueueDeleteFrame frame(_id, name, (flags & ifunused) != 0, (flags & ifempty) != 0, false); // send the frame, and create deferred object auto deferred = std::make_shared(!send(frame)); @@ -431,17 +431,17 @@ bool ChannelImpl::publish(const std::string &exchange, const std::string &routin // the max payload size is the max frame size minus the bytes for headers and trailer uint32_t maxpayload = _connection->maxPayload(); - uint32_t bytessent = 0; + uint64_t bytessent = 0; // the buffer const char *data = envelope.body(); - uint32_t bytesleft = envelope.bodySize(); + uint64_t bytesleft = envelope.bodySize(); // split up the body in multiple frames depending on the max frame size while (bytesleft > 0) { // size of this chunk - uint32_t chunksize = std::min(maxpayload, bytesleft); + uint64_t chunksize = std::min(static_cast(maxpayload), bytesleft); // send out a body frame if (!send(BodyFrame(_id, data + bytessent, chunksize))) return false; @@ -497,7 +497,7 @@ Deferred &ChannelImpl::setQos(uint16_t prefetchCount, bool global) DeferredConsumer& ChannelImpl::consume(const std::string &queue, const std::string &tag, int flags, const Table &arguments) { // the frame to send - BasicConsumeFrame frame(_id, queue, tag, flags & nolocal, flags & noack, flags & exclusive, false, arguments); + BasicConsumeFrame frame(_id, queue, tag, (flags & nolocal) != 0, (flags & noack) != 0, (flags & exclusive) != 0, false, arguments); // send the frame, and create deferred object auto deferred = std::make_shared(this, !send(frame)); @@ -576,7 +576,7 @@ DeferredCancel &ChannelImpl::cancel(const std::string &tag) DeferredGet &ChannelImpl::get(const std::string &queue, int flags) { // the get frame to send - BasicGetFrame frame(_id, queue, flags & noack); + BasicGetFrame frame(_id, queue, (flags & noack) != 0); // send the frame, and create deferred object auto deferred = std::make_shared(this, !send(frame)); @@ -597,7 +597,7 @@ DeferredGet &ChannelImpl::get(const std::string &queue, int flags) bool ChannelImpl::ack(uint64_t deliveryTag, int flags) { // send an ack frame - return send(BasicAckFrame(_id, deliveryTag, flags & multiple)); + return send(BasicAckFrame(_id, deliveryTag, (flags & multiple) != 0)); } /** @@ -612,12 +612,12 @@ bool ChannelImpl::reject(uint64_t deliveryTag, int flags) if (flags & multiple) { // send a nack frame - return send(BasicNackFrame(_id, deliveryTag, true, flags & requeue)); + return send(BasicNackFrame(_id, deliveryTag, true, (flags & requeue) != 0)); } else { // send a reject frame - return send(BasicRejectFrame(_id, deliveryTag, flags & requeue)); + return send(BasicRejectFrame(_id, deliveryTag, (flags & requeue) != 0)); } } @@ -631,7 +631,7 @@ bool ChannelImpl::reject(uint64_t deliveryTag, int flags) Deferred &ChannelImpl::recover(int flags) { // send a nack frame - return push(BasicRecoverFrame(_id, flags & requeue)); + return push(BasicRecoverFrame(_id, (flags & requeue) != 0)); } /** diff --git a/src/connectionimpl.cpp b/src/connectionimpl.cpp index b41c07c..ddaf289 100644 --- a/src/connectionimpl.cpp +++ b/src/connectionimpl.cpp @@ -104,13 +104,13 @@ void ConnectionImpl::remove(const ChannelImpl *channel) * @param buffer buffer to decode * @return number of bytes that were processed */ -size_t ConnectionImpl::parse(const Buffer &buffer) +uint64_t ConnectionImpl::parse(const Buffer &buffer) { // do not parse if already in an error state if (_state == state_closed) return 0; // number of bytes processed - size_t processed = 0; + uint64_t processed = 0; // create a monitor object that checks if the connection still exists Monitor monitor(this); @@ -130,7 +130,7 @@ size_t ConnectionImpl::parse(const Buffer &buffer) receivedFrame.process(this); // number of bytes processed - size_t bytes = receivedFrame.totalSize(); + uint64_t bytes = receivedFrame.totalSize(); // add bytes processed += bytes; diff --git a/src/messageimpl.h b/src/messageimpl.h index f9f839a..b4f1708 100644 --- a/src/messageimpl.h +++ b/src/messageimpl.h @@ -81,15 +81,21 @@ public: } else { + // we're going to allocated memory, but that should be a size_t, not a uint64_t + size_t memory = static_cast(_bodySize); + + // prevent truncation + if (memory < _bodySize) throw std::runtime_error("message is too big for this system"); + // it does not yet fit, do we have to allocate? - if (!_body) _body = new char[_bodySize]; + if (!_body) _body = new char[memory]; _selfAllocated = true; // prevent that size is too big if (size > _bodySize - _received) size = _bodySize - _received; // append data - memcpy((char *)(_body + _received), buffer, size); + memcpy(static_cast(const_cast(_body) + _received), buffer, static_cast(size)); // we have more data now _received += size; diff --git a/src/receivedframe.cpp b/src/receivedframe.cpp index 68998b5..96f6d68 100644 --- a/src/receivedframe.cpp +++ b/src/receivedframe.cpp @@ -104,7 +104,9 @@ ReceivedFrame::ReceivedFrame(const Buffer &buffer, uint32_t max) : _buffer(buffe else { // frame is not yet valid - _type = _channel = _payloadSize = 0; + _type = 0; + _channel = 0; + _payloadSize = 0; } }