mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
377 lines
7.6 KiB
C
377 lines
7.6 KiB
C
|
/**
|
||
|
*
|
||
|
* @file MsgBuffer.h
|
||
|
* @author An Tao
|
||
|
*
|
||
|
* Public header file in trantor lib.
|
||
|
*
|
||
|
* Copyright 2018, An Tao. All rights reserved.
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the License file.
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
#include <trantor/utils/NonCopyable.h>
|
||
|
#include <trantor/exports.h>
|
||
|
#include <vector>
|
||
|
#include <string>
|
||
|
#include <algorithm>
|
||
|
#include <stdio.h>
|
||
|
#include <assert.h>
|
||
|
#include <string.h>
|
||
|
#ifdef _WIN32
|
||
|
using ssize_t = long long;
|
||
|
#endif
|
||
|
|
||
|
namespace trantor
|
||
|
{
|
||
|
static constexpr size_t kBufferDefaultLength{2048};
|
||
|
static constexpr char CRLF[]{"\r\n"};
|
||
|
|
||
|
/**
|
||
|
* @brief This class represents a memory buffer used for sending and receiving
|
||
|
* data.
|
||
|
*
|
||
|
*/
|
||
|
class TRANTOR_EXPORT MsgBuffer
|
||
|
{
|
||
|
public:
|
||
|
/**
|
||
|
* @brief Construct a new message buffer instance.
|
||
|
*
|
||
|
* @param len The initial size of the buffer.
|
||
|
*/
|
||
|
MsgBuffer(size_t len = kBufferDefaultLength);
|
||
|
|
||
|
/**
|
||
|
* @brief Get the beginning of the buffer.
|
||
|
*
|
||
|
* @return const char*
|
||
|
*/
|
||
|
const char *peek() const
|
||
|
{
|
||
|
return begin() + head_;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get the end of the buffer where new data can be written.
|
||
|
*
|
||
|
* @return const char*
|
||
|
*/
|
||
|
const char *beginWrite() const
|
||
|
{
|
||
|
return begin() + tail_;
|
||
|
}
|
||
|
char *beginWrite()
|
||
|
{
|
||
|
return begin() + tail_;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get a byte value from the buffer.
|
||
|
*
|
||
|
* @return uint8_t
|
||
|
*/
|
||
|
uint8_t peekInt8() const
|
||
|
{
|
||
|
assert(readableBytes() >= 1);
|
||
|
return *(static_cast<const uint8_t *>((void *)peek()));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Get a unsigned short value from the buffer.
|
||
|
*
|
||
|
* @return uint16_t
|
||
|
*/
|
||
|
uint16_t peekInt16() const;
|
||
|
|
||
|
/**
|
||
|
* @brief Get a unsigned int value from the buffer.
|
||
|
*
|
||
|
* @return uint32_t
|
||
|
*/
|
||
|
uint32_t peekInt32() const;
|
||
|
|
||
|
/**
|
||
|
* @brief Get a unsigned int64 value from the buffer.
|
||
|
*
|
||
|
* @return uint64_t
|
||
|
*/
|
||
|
uint64_t peekInt64() const;
|
||
|
|
||
|
/**
|
||
|
* @brief Get and remove some bytes from the buffer.
|
||
|
*
|
||
|
* @param len
|
||
|
* @return std::string
|
||
|
*/
|
||
|
std::string read(size_t len);
|
||
|
|
||
|
/**
|
||
|
* @brief Get the remove a byte value from the buffer.
|
||
|
*
|
||
|
* @return uint8_t
|
||
|
*/
|
||
|
uint8_t readInt8();
|
||
|
|
||
|
/**
|
||
|
* @brief Get and remove a unsigned short value from the buffer.
|
||
|
*
|
||
|
* @return uint16_t
|
||
|
*/
|
||
|
uint16_t readInt16();
|
||
|
|
||
|
/**
|
||
|
* @brief Get and remove a unsigned int value from the buffer.
|
||
|
*
|
||
|
* @return uint32_t
|
||
|
*/
|
||
|
uint32_t readInt32();
|
||
|
|
||
|
/**
|
||
|
* @brief Get and remove a unsigned int64 value from the buffer.
|
||
|
*
|
||
|
* @return uint64_t
|
||
|
*/
|
||
|
uint64_t readInt64();
|
||
|
|
||
|
/**
|
||
|
* @brief swap the buffer with another.
|
||
|
*
|
||
|
* @param buf
|
||
|
*/
|
||
|
void swap(MsgBuffer &buf) noexcept;
|
||
|
|
||
|
/**
|
||
|
* @brief Return the size of the data in the buffer.
|
||
|
*
|
||
|
* @return size_t
|
||
|
*/
|
||
|
size_t readableBytes() const
|
||
|
{
|
||
|
return tail_ - head_;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Return the size of the empty part in the buffer
|
||
|
*
|
||
|
* @return size_t
|
||
|
*/
|
||
|
size_t writableBytes() const
|
||
|
{
|
||
|
return buffer_.size() - tail_;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Append new data to the buffer.
|
||
|
*
|
||
|
*/
|
||
|
void append(const MsgBuffer &buf);
|
||
|
template <int N>
|
||
|
void append(const char (&buf)[N])
|
||
|
{
|
||
|
assert(strnlen(buf, N) == N - 1);
|
||
|
append(buf, N - 1);
|
||
|
}
|
||
|
void append(const char *buf, size_t len);
|
||
|
void append(const std::string &buf)
|
||
|
{
|
||
|
append(buf.c_str(), buf.length());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Append a byte value to the end of the buffer.
|
||
|
*
|
||
|
* @param b
|
||
|
*/
|
||
|
void appendInt8(const uint8_t b)
|
||
|
{
|
||
|
append(static_cast<const char *>((void *)&b), 1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Append a unsigned short value to the end of the buffer.
|
||
|
*
|
||
|
* @param s
|
||
|
*/
|
||
|
void appendInt16(const uint16_t s);
|
||
|
|
||
|
/**
|
||
|
* @brief Append a unsigned int value to the end of the buffer.
|
||
|
*
|
||
|
* @param i
|
||
|
*/
|
||
|
void appendInt32(const uint32_t i);
|
||
|
|
||
|
/**
|
||
|
* @brief Appaend a unsigned int64 value to the end of the buffer.
|
||
|
*
|
||
|
* @param l
|
||
|
*/
|
||
|
void appendInt64(const uint64_t l);
|
||
|
|
||
|
/**
|
||
|
* @brief Put new data to the beginning of the buffer.
|
||
|
*
|
||
|
* @param buf
|
||
|
* @param len
|
||
|
*/
|
||
|
void addInFront(const char *buf, size_t len);
|
||
|
|
||
|
/**
|
||
|
* @brief Put a byte value to the beginning of the buffer.
|
||
|
*
|
||
|
* @param b
|
||
|
*/
|
||
|
void addInFrontInt8(const uint8_t b)
|
||
|
{
|
||
|
addInFront(static_cast<const char *>((void *)&b), 1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Put a unsigned short value to the beginning of the buffer.
|
||
|
*
|
||
|
* @param s
|
||
|
*/
|
||
|
void addInFrontInt16(const uint16_t s);
|
||
|
|
||
|
/**
|
||
|
* @brief Put a unsigned int value to the beginning of the buffer.
|
||
|
*
|
||
|
* @param i
|
||
|
*/
|
||
|
void addInFrontInt32(const uint32_t i);
|
||
|
|
||
|
/**
|
||
|
* @brief Put a unsigned int64 value to the beginning of the buffer.
|
||
|
*
|
||
|
* @param l
|
||
|
*/
|
||
|
void addInFrontInt64(const uint64_t l);
|
||
|
|
||
|
/**
|
||
|
* @brief Remove all data in the buffer.
|
||
|
*
|
||
|
*/
|
||
|
void retrieveAll();
|
||
|
|
||
|
/**
|
||
|
* @brief Remove some bytes in the buffer.
|
||
|
*
|
||
|
* @param len
|
||
|
*/
|
||
|
void retrieve(size_t len);
|
||
|
|
||
|
/**
|
||
|
* @brief Read data from a file descriptor and put it into the buffer.˝
|
||
|
*
|
||
|
* @param fd The file descriptor. It is usually a socket.
|
||
|
* @param retErrno The error code when reading.
|
||
|
* @return ssize_t The number of bytes read from the file descriptor. -1 is
|
||
|
* returned when an error occurs.
|
||
|
*/
|
||
|
ssize_t readFd(int fd, int *retErrno);
|
||
|
|
||
|
/**
|
||
|
* @brief Remove the data before a certain position from the buffer.
|
||
|
*
|
||
|
* @param end The position.
|
||
|
*/
|
||
|
void retrieveUntil(const char *end)
|
||
|
{
|
||
|
assert(peek() <= end);
|
||
|
assert(end <= beginWrite());
|
||
|
retrieve(end - peek());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Find the position of the buffer where the CRLF is found.
|
||
|
*
|
||
|
* @return const char*
|
||
|
*/
|
||
|
const char *findCRLF() const
|
||
|
{
|
||
|
const char *crlf = std::search(peek(), beginWrite(), CRLF, CRLF + 2);
|
||
|
return crlf == beginWrite() ? NULL : crlf;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Make sure the buffer has enough spaces to write data.
|
||
|
*
|
||
|
* @param len
|
||
|
*/
|
||
|
void ensureWritableBytes(size_t len);
|
||
|
|
||
|
/**
|
||
|
* @brief Move the write pointer forward when the new data has been written
|
||
|
* to the buffer.
|
||
|
*
|
||
|
* @param len
|
||
|
*/
|
||
|
void hasWritten(size_t len)
|
||
|
{
|
||
|
assert(len <= writableBytes());
|
||
|
tail_ += len;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Move the write pointer backward to remove data in the end of the
|
||
|
* buffer.
|
||
|
*
|
||
|
* @param offset
|
||
|
*/
|
||
|
void unwrite(size_t offset)
|
||
|
{
|
||
|
assert(readableBytes() >= offset);
|
||
|
tail_ -= offset;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Access a byte in the buffer.
|
||
|
*
|
||
|
* @param offset
|
||
|
* @return const char&
|
||
|
*/
|
||
|
const char &operator[](size_t offset) const
|
||
|
{
|
||
|
assert(readableBytes() >= offset);
|
||
|
return peek()[offset];
|
||
|
}
|
||
|
char &operator[](size_t offset)
|
||
|
{
|
||
|
assert(readableBytes() >= offset);
|
||
|
return begin()[head_ + offset];
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
size_t head_;
|
||
|
size_t initCap_;
|
||
|
std::vector<char> buffer_;
|
||
|
size_t tail_;
|
||
|
const char *begin() const
|
||
|
{
|
||
|
return &buffer_[0];
|
||
|
}
|
||
|
char *begin()
|
||
|
{
|
||
|
return &buffer_[0];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
inline void swap(MsgBuffer &one, MsgBuffer &two) noexcept
|
||
|
{
|
||
|
one.swap(two);
|
||
|
}
|
||
|
} // namespace trantor
|
||
|
|
||
|
namespace std
|
||
|
{
|
||
|
template <>
|
||
|
inline void swap(trantor::MsgBuffer &one, trantor::MsgBuffer &two) noexcept
|
||
|
{
|
||
|
one.swap(two);
|
||
|
}
|
||
|
} // namespace std
|