the ReceivedFrame class has been split into a InBuffer base class to make it easier to store messages without having to construct a full frame, this commit adds the newly introduced classes

This commit is contained in:
Emiel Bruijntjes 2020-08-14 12:20:58 +02:00
parent b03cc6ff1c
commit 92d21c5ddd
3 changed files with 386 additions and 0 deletions

143
include/amqpcpp/inbuffer.h Normal file
View File

@ -0,0 +1,143 @@
/**
* InBuffer.h
*
* The InBuffer class is a wrapper around a data buffer and that adds
* some safety checks so that the rest of the library can safely read
* from it.
*
* This is a class that is used internally by the AMQP library. As a user
* of this library, you normally do not have to instantiate it. However,
* if you do want to store or safe messages yourself, it sometimes can
* be useful to implement it.
*
* @copyright 2014 - 2020 Copernica BV
*/
/**
* Include guard
*/
#pragma once
/**
* Dependencies
*/
#include <cstdint>
/**
* Set up namespace
*/
namespace AMQP {
/**
* Forward declarations
*/
class Buffer;
/**
* Class definition
*/
class InBuffer
{
protected:
/**
* The buffer we are reading from
* @var Buffer
*/
const Buffer &_buffer;
/**
* Number of bytes already processed
* @var uint32_t
*/
uint32_t _skip = 0;
public:
/**
* Constructor
* @param buffer Binary buffer
*/
InBuffer(const Buffer &buffer) : _buffer(buffer) {}
/**
* Destructor
*/
virtual ~InBuffer() {}
/**
* Read the next uint8_t from the buffer
* @return uint8_t value read
*/
uint8_t nextUint8();
/**
* Read the next int8_t from the buffer
* @return int8_t value read
*/
int8_t nextInt8();
/**
* Read the next uint16_t from the buffer
* @return uint16_t value read
*/
uint16_t nextUint16();
/**
* Read the next int16_t from the buffer
* @return int16_t value read
*/
int16_t nextInt16();
/**
* Read the next uint32_t from the buffer
* @return uint32_t value read
*/
uint32_t nextUint32();
/**
* Read the next int32_t from the buffer
* @return int32_t value read
*/
int32_t nextInt32();
/**
* Read the next uint64_t from the buffer
* @return uint64_t value read
*/
uint64_t nextUint64();
/**
* Read the next int64_t from the buffer
* @return int64_t value read
*/
int64_t nextInt64();
/**
* Read a float from the buffer
* @return float float read from buffer.
*/
float nextFloat();
/**
* Read a double from the buffer
* @return double double read from buffer
*/
double nextDouble();
/**
* Get a pointer to the next binary buffer of a certain size
* @param size
* @return char*
*/
const char *nextData(uint32_t size);
/**
* The checker may access private data
*/
friend class BufferCheck;
};
/**
* End of namespace
*/
}

61
src/buffercheck.h Normal file
View File

@ -0,0 +1,61 @@
/**
* BufferCheck.h
*
* Class that checks incoming frames for their size
*
* @copyright 2014 - 2020 Copernica BV
*/
/**
* Set up namespace
*/
namespace AMQP {
/**
* Internal helper class that checks if there is enough room left in the buffer
*/
class BufferCheck
{
private:
/**
* The frame
* @var InBuffer
*/
InBuffer *_frame;
/**
* The size that is checked
* @var size_t
*/
size_t _size;
public:
/**
* Constructor
* @param frame
* @param size
*/
BufferCheck(InBuffer *frame, size_t size) : _frame(frame), _size(size)
{
// no problem is there are still enough bytes left
if (frame->_buffer.size() - frame->_skip >= size) return;
// frame buffer is too small
throw ProtocolException("frame out of range");
}
/**
* Destructor
*/
virtual ~BufferCheck()
{
// update the number of bytes to skip
_frame->_skip += (uint32_t)_size;
}
};
/**
* End namespace
*/
}

182
src/inbuffer.cpp Normal file
View File

@ -0,0 +1,182 @@
/**
* InBuffer.cpp
*
* Implementation of the InBuffer class
*
* @copyright 2014 - 2020 Copernica BV
*/
#include "includes.h"
#include "buffercheck.h"
/**
* Set up namespace
*/
namespace AMQP {
/**
* Read the next uint8 from the buffer
* @param char* buffer buffer to read from
* @return uint8_t value read
*/
uint8_t InBuffer::nextUint8()
{
// check if there is enough size
BufferCheck check(this, 1);
// get a byte
return _buffer.byte(_skip);
}
/**
* Read the next int8 from the buffer
* @param char* buffer buffer to read from
* @return int8_t value read
*/
int8_t InBuffer::nextInt8()
{
// check if there is enough size
BufferCheck check(this, 1);
// get a byte
return (int8_t)_buffer.byte(_skip);
}
/**
* Read the next uint16_t from the buffer
* @return uint16_t value read
*/
uint16_t InBuffer::nextUint16()
{
// check if there is enough size
BufferCheck check(this, sizeof(uint16_t));
// get two bytes, and convert to host-byte-order
uint16_t value;
_buffer.copy(_skip, sizeof(uint16_t), &value);
return be16toh(value);
}
/**
* Read the next int16_t from the buffer
* @return int16_t value read
*/
int16_t InBuffer::nextInt16()
{
// check if there is enough size
BufferCheck check(this, sizeof(int16_t));
// get two bytes, and convert to host-byte-order
int16_t value;
_buffer.copy(_skip, sizeof(int16_t), &value);
return be16toh(value);
}
/**
* Read the next uint32_t from the buffer
* @return uint32_t value read
*/
uint32_t InBuffer::nextUint32()
{
// check if there is enough size
BufferCheck check(this, sizeof(uint32_t));
// get four bytes, and convert to host-byte-order
uint32_t value;
_buffer.copy(_skip, sizeof(uint32_t), &value);
return be32toh(value);
}
/**
* Read the next int32_t from the buffer
* @return uint32_t value read
*/
int32_t InBuffer::nextInt32()
{
// check if there is enough size
BufferCheck check(this, sizeof(int32_t));
// get four bytes, and convert to host-byte-order
int32_t value;
_buffer.copy(_skip, sizeof(int32_t), &value);
return be32toh(value);
}
/**
* Read the next uint64_t from the buffer
* @return uint64_t value read
*/
uint64_t InBuffer::nextUint64()
{
// check if there is enough size
BufferCheck check(this, sizeof(uint64_t));
// get eight bytes, and convert to host-byte-order
uint64_t value;
_buffer.copy(_skip, sizeof(uint64_t), &value);
return be64toh(value);
}
/**
* Read the next uint64_t from the buffer
* @return uint64_t value read
*/
int64_t InBuffer::nextInt64()
{
// check if there is enough size
BufferCheck check(this, sizeof(int64_t));
// get eight bytes, and convert to host-byte-order
int64_t value;
_buffer.copy(_skip, sizeof(int64_t), &value);
return be64toh(value);
}
/**
* Read a float from the buffer
* @return float float read from buffer.
*/
float InBuffer::nextFloat()
{
// check if there is enough size
BufferCheck check(this, sizeof(float));
// get four bytes
float value;
_buffer.copy(_skip, sizeof(float), &value);
return value;
}
/**
* Read a double from the buffer
* @return double double read from buffer
*/
double InBuffer::nextDouble()
{
// check if there is enough size
BufferCheck check(this, sizeof(double));
// get eight bytes, and convert to host-byte-order
double value;
_buffer.copy(_skip, sizeof(double), &value);
return value;
}
/**
* Get a pointer to the next binary buffer of a certain size
* @param size
* @return char*
*/
const char *InBuffer::nextData(uint32_t size)
{
// check if there is enough size
BufferCheck check(this, size);
// get the data
return _buffer.data(_skip, size);
}
/**
* End of namespace
*/
}