| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 #ifndef COMMUNICATION_H | 1 #ifndef COMMUNICATION_H |
| 2 #define COMMUNICATION_H | 2 #define COMMUNICATION_H |
| 3 | 3 |
| 4 #include <memory> | |
| 4 #include <sstream> | 5 #include <sstream> |
| 6 #include <stdexcept> | |
| 5 #include <stdint.h> | 7 #include <stdint.h> |
| 6 #include <string> | 8 #include <string> |
| 7 #include <vector> | 9 #include <vector> |
| 8 #include <Windows.h> | 10 #include <Windows.h> |
| 9 | 11 |
| 10 namespace Communication | 12 namespace Communication |
| 11 { | 13 { |
| 12 extern const std::wstring pipeName; | 14 extern const std::wstring pipeName; |
| 13 const int bufferSize = 1024; | 15 const int bufferSize = 1024; |
| 14 | 16 |
| 15 enum ValueType {TYPE_STRING, TYPE_WSTRING, TYPE_INT64, TYPE_INT32, TYPE_BOOL}; | 17 enum {TYPE_STRING, TYPE_WSTRING, TYPE_INT64, TYPE_INT32, TYPE_BOOL}; |
| 18 typedef int32_t ValueType; | |
| 19 typedef uint32_t SizeType; | |
| 16 | 20 |
| 17 class InputBuffer | 21 class InputBuffer |
| 18 { | 22 { |
| 19 public: | 23 public: |
| 20 InputBuffer(const std::string& data) : buffer(data) {} | 24 InputBuffer(const std::string& data) : buffer(data), hasType(false) {} |
| 21 InputBuffer& operator>>(std::string& value) { return ReadString(value, TYPE_ STRING); } | 25 InputBuffer& operator>>(std::string& value) { return ReadString(value, TYPE_ STRING); } |
| 22 InputBuffer& operator>>(std::wstring& value) { return ReadString(value, TYPE _WSTRING); } | 26 InputBuffer& operator>>(std::wstring& value) { return ReadString(value, TYPE _WSTRING); } |
| 23 InputBuffer& operator>>(int64_t& value) { return Read(value, TYPE_INT64); } | 27 InputBuffer& operator>>(int64_t& value) { return Read(value, TYPE_INT64); } |
| 24 InputBuffer& operator>>(int32_t& value) { return Read(value, TYPE_INT32); } | 28 InputBuffer& operator>>(int32_t& value) { return Read(value, TYPE_INT32); } |
| 25 InputBuffer& operator>>(bool& value) { return Read(value, TYPE_BOOL); } | 29 InputBuffer& operator>>(bool& value) { return Read(value, TYPE_BOOL); } |
| 26 private: | 30 private: |
| 27 std::istringstream buffer; | 31 std::istringstream buffer; |
| 32 ValueType currentType; | |
| 33 bool hasType; | |
| 34 | |
| 35 void CheckType(ValueType expectedType) | |
| 36 { | |
| 37 if (!hasType) | |
| 38 ReadBinary(currentType); | |
| 39 | |
| 40 if (currentType != expectedType) | |
| 41 { | |
| 42 // Make sure we don't attempt to read the type again | |
| 43 hasType = true; | |
| 44 throw new std::runtime_error("Unexpected type found in input buffer"); | |
| 45 } | |
| 46 else | |
| 47 hasType = false; | |
| 48 } | |
| 28 | 49 |
| 29 template<class T> | 50 template<class T> |
| 30 InputBuffer& ReadString(T& value, ValueType expectedType) | 51 InputBuffer& ReadString(T& value, ValueType expectedType) |
|
Felix Dahlke
2013/06/03 11:25:41
I'd just call this "ReadArray", since it would wor
Wladimir Palant
2013/06/03 11:53:00
Nope - this is expecting std::base_string rather t
| |
| 31 { | 52 { |
| 32 int32_t type; | 53 CheckType(expectedType); |
|
Felix Dahlke
2013/06/03 11:25:41
Should be ValueType, not int32_t I guess?
Wladimir Palant
2013/06/03 11:53:00
I'm not sure whether the internal representation o
Felix Dahlke
2013/06/03 12:02:09
Fair enough. But I'd want a typedef then :)
| |
| 33 ReadBinary(type); | |
| 34 if (type != expectedType) | |
| 35 throw new std::runtime_error("Unexpected type found in input buffer"); | |
| 36 | 54 |
| 37 uint32_t length; | 55 SizeType length; |
|
Felix Dahlke
2013/06/03 11:25:41
Would prefer a typedef for this.
| |
| 38 ReadBinary(length); | 56 ReadBinary(length); |
| 39 | 57 |
| 40 std::auto_ptr<T::value_type> data(new T::value_type[length]); | 58 std::auto_ptr<T::value_type> data(new T::value_type[length]); |
| 41 buffer.read(reinterpret_cast<char*>(data.get()), sizeof(T::value_type) * l ength); | 59 buffer.read(reinterpret_cast<char*>(data.get()), sizeof(T::value_type) * l ength); |
| 42 if (buffer.fail()) | 60 if (buffer.fail()) |
| 43 throw new std::runtime_error("Unexpected end of input buffer"); | 61 throw new std::runtime_error("Unexpected end of input buffer"); |
| 44 | 62 |
| 45 value.assign(data.get(), length); | 63 value.assign(data.get(), length); |
|
Felix Dahlke
2013/06/03 11:25:41
Based on some quick searching, only std::basic_str
Wladimir Palant
2013/06/03 11:53:00
See above - this function is used both for std::st
Felix Dahlke
2013/06/03 12:02:09
I thought basic_string was a base class, but it's
| |
| 46 return *this; | 64 return *this; |
| 47 } | 65 } |
| 48 | 66 |
| 49 template<class T> | 67 template<class T> |
| 50 InputBuffer& Read(T& value, ValueType expectedType) | 68 InputBuffer& Read(T& value, ValueType expectedType) |
| 51 { | 69 { |
| 52 int32_t type; | 70 CheckType(expectedType); |
|
Felix Dahlke
2013/06/03 11:25:41
Like above, I think this should be ValueType
| |
| 53 ReadBinary(type); | |
| 54 if (type != expectedType) | |
| 55 throw new std::runtime_error("Unexpected type found in input buffer"); | |
| 56 | |
| 57 ReadBinary(value); | 71 ReadBinary(value); |
| 58 return *this; | 72 return *this; |
| 59 } | 73 } |
| 60 | 74 |
| 61 template<class T> | 75 template<class T> |
| 62 void ReadBinary(T& value) | 76 void ReadBinary(T& value) |
| 63 { | 77 { |
| 64 buffer.read(reinterpret_cast<char*>(&value), sizeof(T)); | 78 buffer.read(reinterpret_cast<char*>(&value), sizeof(T)); |
| 65 if (buffer.fail()) | 79 if (buffer.fail()) |
| 66 throw new std::runtime_error("Unexpected end of input buffer"); | 80 throw new std::runtime_error("Unexpected end of input buffer"); |
| 67 } | 81 } |
| 68 }; | 82 }; |
| 69 | 83 |
| 70 class OutputBuffer | 84 class OutputBuffer |
| 71 { | 85 { |
| 72 public: | 86 public: |
| 73 OutputBuffer() {} | 87 OutputBuffer() {} |
| 74 | 88 |
| 75 // Explicit copy constructor to allow returning OutputBuffer by value | 89 // Explicit copy constructor to allow returning OutputBuffer by value |
|
Felix Dahlke
2013/06/03 11:25:41
I find this kind of obvious :P
Wladimir Palant
2013/06/03 11:53:00
It wasn't to me :)
| |
| 76 OutputBuffer(const OutputBuffer& copy) : buffer(copy.buffer.str()) {} | 90 OutputBuffer(const OutputBuffer& copy) : buffer(copy.buffer.str()) {} |
|
Felix Dahlke
2013/06/03 11:25:41
We should implement the copy assign operator as we
Wladimir Palant
2013/06/03 11:53:00
I think I'm fine with copy assignment failing - I
Felix Dahlke
2013/06/03 12:02:09
Assignment won't fail if the copy assignment opera
| |
| 77 | 91 |
| 78 std::string Get() | 92 std::string Get() |
| 79 { | 93 { |
| 80 return buffer.str(); | 94 return buffer.str(); |
| 81 } | 95 } |
| 82 OutputBuffer& operator<<(const std::string& value) { return WriteString(valu e, TYPE_STRING); } | 96 OutputBuffer& operator<<(const std::string& value) { return WriteString(valu e, TYPE_STRING); } |
| 83 OutputBuffer& operator<<(const std::wstring& value) { return WriteString(val ue, TYPE_WSTRING); } | 97 OutputBuffer& operator<<(const std::wstring& value) { return WriteString(val ue, TYPE_WSTRING); } |
| 84 OutputBuffer& operator<<(int64_t value) { return Write(value, TYPE_INT64); } | 98 OutputBuffer& operator<<(int64_t value) { return Write(value, TYPE_INT64); } |
| 85 OutputBuffer& operator<<(int32_t value) { return Write(value, TYPE_INT32); } | 99 OutputBuffer& operator<<(int32_t value) { return Write(value, TYPE_INT32); } |
| 86 OutputBuffer& operator<<(bool value) { return Write(value, TYPE_BOOL); } | 100 OutputBuffer& operator<<(bool value) { return Write(value, TYPE_BOOL); } |
| 87 private: | 101 private: |
| 88 std::ostringstream buffer; | 102 std::ostringstream buffer; |
| 89 | 103 |
| 104 // Disallow copying | |
| 105 const OutputBuffer& operator=(const OutputBuffer&); | |
| 106 | |
| 90 template<class T> | 107 template<class T> |
| 91 OutputBuffer& WriteString(const T& value, int32_t type) | 108 OutputBuffer& WriteString(const T& value, ValueType type) |
|
Felix Dahlke
2013/06/03 11:25:41
Should be ValueType instead of int32_t I guess.
| |
| 92 { | 109 { |
| 93 WriteBinary(type); | 110 WriteBinary(type); |
| 94 | 111 |
| 95 uint32_t length = value.size(); | 112 SizeType length = value.size(); |
| 96 WriteBinary(length); | 113 WriteBinary(length); |
| 97 | 114 |
| 98 buffer.write(reinterpret_cast<const char*>(value.c_str()), sizeof(T::value _type) * length); | 115 buffer.write(reinterpret_cast<const char*>(value.c_str()), sizeof(T::value _type) * length); |
|
Felix Dahlke
2013/06/03 11:25:41
AFAIK, only std::basic_string has c_str(). So no n
Wladimir Palant
2013/06/03 11:53:00
See above - both std::string and std::wstring are
| |
| 99 if (buffer.fail()) | 116 if (buffer.fail()) |
| 100 throw new std::runtime_error("Unexpected error writing to output buffer" ); | 117 throw new std::runtime_error("Unexpected error writing to output buffer" ); |
| 101 | 118 |
| 102 return *this; | 119 return *this; |
| 103 } | 120 } |
| 104 | 121 |
| 105 template<class T> | 122 template<class T> |
| 106 OutputBuffer& Write(const T value, int32_t type) | 123 OutputBuffer& Write(const T value, ValueType type) |
|
Felix Dahlke
2013/06/03 11:25:41
Should be ValueType instead of int32_t I think. Al
|
Felix Dahlke
2013/06/03 12:23:54
Shouldn't value be passed by reference?
Wladimir Palant
2013/06/03 12:25:55
Given that this function is meant for primitive ty
Felix Dahlke
2013/06/04 06:41:38
Right, didn't think of that. Won't hurt, but it wo
|
| 107 { | 124 { |
| 108 WriteBinary(type); | 125 WriteBinary(type); |
| 109 WriteBinary(value); | 126 WriteBinary(value); |
| 110 return *this; | 127 return *this; |
| 111 } | 128 } |
| 112 | 129 |
| 113 template<class T> | 130 template<class T> |
| 114 void WriteBinary(const T& value) | 131 void WriteBinary(const T& value) |
| 115 { | 132 { |
| 116 buffer.write(reinterpret_cast<const char*>(&value), sizeof(T)); | 133 buffer.write(reinterpret_cast<const char*>(&value), sizeof(T)); |
| 117 if (buffer.fail()) | 134 if (buffer.fail()) |
| 118 throw new std::runtime_error("Unexpected error writing to output buffer" ); | 135 throw new std::runtime_error("Unexpected error writing to output buffer" ); |
| 119 } | 136 } |
| 120 }; | 137 }; |
| 121 | 138 |
| 122 InputBuffer ReadMessage(HANDLE pipe); | 139 class PipeConnectionError : public std::runtime_error |
| 123 void WriteMessage(HANDLE pipe, OutputBuffer& message); | 140 { |
| 141 public: | |
| 142 PipeConnectionError(); | |
| 143 }; | |
| 144 | |
| 145 class Pipe | |
| 146 { | |
| 147 public: | |
| 148 enum Mode {MODE_CREATE, MODE_CONNECT}; | |
| 149 | |
| 150 Pipe(const std::wstring& name, Mode mode); | |
| 151 ~Pipe(); | |
| 152 | |
| 153 InputBuffer ReadMessage(); | |
| 154 void WriteMessage(OutputBuffer& message); | |
| 155 | |
| 156 protected: | |
| 157 HANDLE pipe; | |
| 158 }; | |
| 124 } | 159 } |
| 125 | 160 |
| 126 #endif | 161 #endif |
| LEFT | RIGHT |