Oops from previous commit
[lsnes.git] / include / library / binarystream.hpp
blob2e9940d5525d1bb043b2d1b506d88bbe5d14b1fd
1 #ifndef _library__binarystream__hpp__included__
2 #define _library__binarystream__hpp__included__
4 #include <iostream>
5 #include <sstream>
6 #include <cstdint>
7 #include <string>
8 #include <vector>
9 #include <functional>
10 #include <stdexcept>
12 namespace binarystream
14 /**
15 * Output binary stream.
17 struct output
19 public:
20 /**
21 * Create a new output binary stream outputting to internal buffer.
23 output();
24 /**
25 * Create a new output binary stream outputting to given output stream.
27 * Parameter s: The stream to output to.
29 output(int s);
30 /**
31 * Output a byte to stream (1 byte).
33 * Parameter byte: The byte to output.
35 void byte(uint8_t byte);
36 /**
37 * Output a number to stream.
39 * Parameter number: The number to output.
41 void number(uint64_t number);
42 /**
43 * Count number of bytes needed to store given number.
45 * Parameter number: The number to query.
46 * Return: The number of bytes needed.
48 size_t numberbytes(uint64_t number);
49 /**
50 * Count number of bytes needed to store given string.
52 * Parameter string: The string to query.
53 * Return: The number of bytes needed.
55 size_t stringbytes(const std::string& string);
56 /**
57 * Output a 32-bit number to stream (4 byte).
59 * Parameter number: The number to output.
61 void number32(uint32_t number);
62 /**
63 * Output a string with explicit length indication to the stream.
65 * This takes space for one number + number of bytes in the string.
67 * Parameter string: The number to output.
69 void string(const std::string& string);
70 /**
71 * Output a string without length indication to the stream.
73 * This takes space for number of bytes in the string.
75 * Parameter string: The number to output.
77 void string_implicit(const std::string& string);
78 /**
79 * Output a octet string without length indication to the stream.
81 * This takes space for number of bytes in the sequence.
83 * Parameter blob: The octet string to output.
85 void blob_implicit(const std::vector<char>& blob);
86 /**
87 * Output a octet string without length indication to the stream.
89 * This takes space for number of bytes in the sequence.
91 * Parameter buf: The input buffer to read the octet string from.
92 * Parameter bufsize: The size of buffer in bytes.
94 void raw(const void* buf, size_t bufsize);
95 /**
96 * Output a extension substream into stream.
98 * Parameter tag: Tag identifying the extension member type.
99 * Parameter fn: Function writing the contents of the extension substream.
100 * Parameter even_empty: If true, the member is written even if empty (otherwise it is elided).
102 void extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty = false);
104 * Output a extension substream with known size into stream.
106 * In exchange for having to know the size of the payload, this is faster to write as it avoids buffering.
108 * Parameter tag: Tag identifying the extension member type.
109 * Parameter fn: Function writing the contents of the extension substream.
110 * Parameter even_empty: If true, the member is written even if empty (otherwise it is elided).
111 * Parameter size_precognition: The known size of the payload.
113 void extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty,
114 size_t size_precognition);
116 * Output explicit extension tag.
118 * This has to be followed by writing size bytes, forming the payload.
120 * Parameter tag: The Tag identifying the extension member type.
121 * Parameter size: Size of the payload.
123 void write_extension_tag(uint32_t tag, uint64_t size);
125 * Get the output stream contents.
127 * The output stream has to use internal buffer for this to work.
129 * Returns: The internal buffer contents.
131 std::string get();
132 private:
133 inline void write(const char* buf, size_t size);
134 int strm;
135 std::vector<char> buf;
139 * Input binary stream.
141 struct input
143 public:
145 * Extension tag handler.
147 struct binary_tag_handler
150 * The extension tag to activate on.
152 uint32_t tag;
154 * Handler function for the tag.
156 * Parameter s: The substream of extension.
158 std::function<void(input& s)> fn;
161 * Create a new top-level input stream, reading from specified stream.
163 input(int s);
165 * Create a new input substream, under specified top-level stream and with specified length.
167 * Parameter s: The top-level stream.
168 * Parameter len: Amount of payload in extension stream.
170 input(input& s, uint64_t len);
172 * Read a byte.
174 * Returns: The read byte.
176 uint8_t byte();
178 * Read a number.
180 * Returns: The read number.
182 uint64_t number();
184 * Read a 32-bit number.
186 * Returns: The read number.
188 uint32_t number32();
190 * Read a string with explicit length indication.
192 * Returns: The read string.
194 std::string string();
196 * Read a string without explicit length indication, quitting when reaching end of extension substream.
198 * Can be only used in extension substreams.
200 * Returns: The read string.
202 std::string string_implicit();
204 * Read a octet string without explicit length indication, quitting when reaching end of extension substream.
206 * Can be only used in extension substreams.
208 * Parameter blob: Store the read octet string here.
210 void blob_implicit(std::vector<char>& blob);
212 * Read a octet string of specified length.
214 * Parameter buf: Buffer to store the octet string to.
215 * Parameter bufsize: The amount of data to read.
217 void raw(void* buf, size_t bufsize);
219 * Read extension substreams.
221 * This reads substreams until the end of stream.
223 * Parameter fn: Function handling the read extension substream.
224 * Parameter tag: The type tag of read substream.
225 * Parameter s: The substream with contents of extension substream.
227 void extension(std::function<void(uint32_t tag, input& s)> fn);
229 * Read extension substreams.
231 * This reads substreams until the end of stream.
233 * Parameter funcs: Table of functions to call for each known extension type.
234 * Parameter default_hdlr: Handler for unknown types (parameters as in other ::extension()).
236 void extension(std::initializer_list<binary_tag_handler> funcs,
237 std::function<void(uint32_t tag, input& s)> default_hdlr);
239 * Get number of bytes left in substream.
241 * Can only be used for substreams.
243 * Returns: Number of bytes left.
245 uint64_t get_left()
247 if(!parent)
248 throw std::logic_error("binarystream::input::get_left() can only be used in substreams");
249 return left;
251 private:
252 bool read(char* buf, size_t size, bool allow_none = false);
253 void flush();
254 input* parent;
255 int strm;
256 uint64_t left;
260 * Do nothing. Handy as second parameter for two-parameter output::extension() if the table enumerates all non-
261 * ignored types.
263 void null_default(uint32_t tag, input& s);
266 #endif