diff options
Diffstat (limited to '')
-rw-r--r-- | src/network/packet.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/network/packet.h b/src/network/packet.h new file mode 100644 index 000000000..6d84cfbac --- /dev/null +++ b/src/network/packet.h @@ -0,0 +1,192 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <vector> +#include "common/common_types.h" + +namespace Network { + +/// A class for serialize data for network transfer. It also handles endianess +class Packet { + /// A bool-like type that cannot be converted to integer or pointer types + typedef bool (Packet::*BoolType)(std::size_t); + +public: + Packet(); + ~Packet(); + + /** + * Append data to the end of the packet + * @param data Pointer to the sequence of bytes to append + * @param size_in_bytes Number of bytes to append + */ + void Append(const void* data, std::size_t size_in_bytes); + + /** + * Reads data from the current read position of the packet + * @param out_data Pointer where the data should get written to + * @param size_in_bytes Number of bytes to read + */ + void Read(void* out_data, std::size_t size_in_bytes); + + /** + * Clear the packet + * After calling Clear, the packet is empty. + */ + void Clear(); + + /** + * Ignores bytes while reading + * @param length THe number of bytes to ignore + */ + void IgnoreBytes(u32 length); + + /** + * Get a pointer to the data contained in the packet + * @return Pointer to the data + */ + const void* GetData() const; + + /** + * This function returns the number of bytes pointed to by + * what getData returns. + * @return Data size, in bytes + */ + std::size_t GetDataSize() const; + + /** + * This function is useful to know if there is some data + * left to be read, without actually reading it. + * @return True if all data was read, false otherwise + */ + bool EndOfPacket() const; + /** + * Test the validity of the packet, for reading + * This operator allows to test the packet as a boolean + * variable, to check if a reading operation was successful. + * + * A packet will be in an invalid state if it has no more + * data to read. + * + * This behaviour is the same as standard C++ streams. + * + * Usage example: + * @code + * float x; + * packet >> x; + * if (packet) + * { + * // ok, x was extracted successfully + * } + * + * // -- or -- + * + * float x; + * if (packet >> x) + * { + * // ok, x was extracted successfully + * } + * @endcode + * + * Don't focus on the return type, it's equivalent to bool but + * it disallows unwanted implicit conversions to integer or + * pointer types. + * + * @return True if last data extraction from packet was successful + */ + operator BoolType() const; + + /// Overloads of operator >> to read data from the packet + Packet& operator>>(bool& out_data); + Packet& operator>>(s8& out_data); + Packet& operator>>(u8& out_data); + Packet& operator>>(s16& out_data); + Packet& operator>>(u16& out_data); + Packet& operator>>(s32& out_data); + Packet& operator>>(u32& out_data); + Packet& operator>>(float& out_data); + Packet& operator>>(double& out_data); + Packet& operator>>(char* out_data); + Packet& operator>>(std::string& out_data); + template <typename T> + Packet& operator>>(std::vector<T>& out_data); + template <typename T, std::size_t S> + Packet& operator>>(std::array<T, S>& out_data); + + /// Overloads of operator << to write data into the packet + Packet& operator<<(bool in_data); + Packet& operator<<(s8 in_data); + Packet& operator<<(u8 in_data); + Packet& operator<<(s16 in_data); + Packet& operator<<(u16 in_data); + Packet& operator<<(s32 in_data); + Packet& operator<<(u32 in_data); + Packet& operator<<(float in_data); + Packet& operator<<(double in_data); + Packet& operator<<(const char* in_data); + Packet& operator<<(const std::string& in_data); + template <typename T> + Packet& operator<<(const std::vector<T>& in_data); + template <typename T, std::size_t S> + Packet& operator<<(const std::array<T, S>& data); + +private: + /// Disallow comparisons between packets + bool operator==(const Packet& right) const; + bool operator!=(const Packet& right) const; + + /** + * Check if the packet can extract a given number of bytes + * This function updates accordingly the state of the packet. + * @param size Size to check + * @return True if size bytes can be read from the packet + */ + bool CheckSize(std::size_t size); + + // Member data + std::vector<char> data; ///< Data stored in the packet + std::size_t read_pos; ///< Current reading position in the packet + bool is_valid; ///< Reading state of the packet +}; + +template <typename T> +Packet& Packet::operator>>(std::vector<T>& out_data) { + for (u32 i = 0; i < out_data.size(); ++i) { + T character = 0; + *this >> character; + out_data[i] = character; + } + return *this; +} + +template <typename T, std::size_t S> +Packet& Packet::operator>>(std::array<T, S>& out_data) { + for (u32 i = 0; i < out_data.size(); ++i) { + T character = 0; + *this >> character; + out_data[i] = character; + } + return *this; +} + +template <typename T> +Packet& Packet::operator<<(const std::vector<T>& in_data) { + for (u32 i = 0; i < in_data.size(); ++i) { + *this << in_data[i]; + } + return *this; +} + +template <typename T, std::size_t S> +Packet& Packet::operator<<(const std::array<T, S>& in_data) { + for (u32 i = 0; i < in_data.size(); ++i) { + *this << in_data[i]; + } + return *this; +} + +} // namespace Network |