|
@@ -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
|