Move binarystream functions to dedicated namespace

This commit is contained in:
Ilari Liusvaara 2013-12-18 21:50:07 +02:00
parent 99b526335c
commit 6256506884
3 changed files with 290 additions and 100 deletions

View file

@ -9,63 +9,250 @@
#include <functional>
#include <stdexcept>
struct binary_output_stream
namespace binarystream
{
/**
* Output binary stream.
*/
struct output
{
public:
binary_output_stream();
binary_output_stream(std::ostream& s);
/**
* Create a new output binary stream outputting to internal buffer.
*/
output();
/**
* Create a new output binary stream outputting to given output stream.
*
* Parameter s: The stream to output to.
*/
output(std::ostream& s);
/**
* Output a byte to stream (1 byte).
*
* Parameter byte: The byte to output.
*/
void byte(uint8_t byte);
/**
* Output a number to stream.
*
* Parameter number: The number to output.
*/
void number(uint64_t number);
/**
* Count number of bytes needed to store given number.
*
* Parameter number: The number to query.
* Return: The number of bytes needed.
*/
size_t numberbytes(uint64_t number);
/**
* Output a 32-bit number to stream (4 byte).
*
* Parameter number: The number to output.
*/
void number32(uint32_t number);
/**
* Output a string with explicit length indication to the stream.
*
* This takes space for one number + number of bytes in the string.
*
* Parameter string: The number to output.
*/
void string(const std::string& string);
/**
* Output a string without length indication to the stream.
*
* This takes space for number of bytes in the string.
*
* Parameter string: The number to output.
*/
void string_implicit(const std::string& string);
/**
* Output a octet string without length indication to the stream.
*
* This takes space for number of bytes in the sequence.
*
* Parameter blob: The octet string to output.
*/
void blob_implicit(const std::vector<char>& blob);
/**
* Output a octet string without length indication to the stream.
*
* This takes space for number of bytes in the sequence.
*
* Parameter buf: The input buffer to read the octet string from.
* Parameter bufsize: The size of buffer in bytes.
*/
void raw(const void* buf, size_t bufsize);
void extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty = false);
void extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty,
/**
* Output a extension substream into stream.
*
* Parameter tag: Tag identifying the extension member type.
* Parameter fn: Function writing the contents of the extension substream.
* Parameter even_empty: If true, the member is written even if empty (otherwise it is elided).
*/
void extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty = false);
/**
* Output a extension substream with known size into stream.
*
* In exchange for having to know the size of the payload, this is faster to write as it avoids buffering.
*
* Parameter tag: Tag identifying the extension member type.
* Parameter fn: Function writing the contents of the extension substream.
* Parameter even_empty: If true, the member is written even if empty (otherwise it is elided).
* Parameter size_precognition: The known size of the payload.
*/
void extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty,
size_t size_precognition);
/**
* Output explicit extension tag.
*
* This has to be followed by writing size bytes, forming the payload.
*
* Parameter tag: The Tag identifying the extension member type.
* Parameter size: Size of the payload.
*/
void write_extension_tag(uint32_t tag, uint64_t size);
/**
* Get the output stream contents.
*
* The output stream has to use internal buffer for this to work.
*
* Returns: The internal buffer contents.
*/
std::string get();
private:
std::ostream& strm;
std::ostringstream buf;
};
struct binary_input_stream
/**
* Input binary stream.
*/
struct input
{
public:
/**
* Extension tag handler.
*/
struct binary_tag_handler
{
/**
* The extension tag to activate on.
*/
uint32_t tag;
std::function<void(binary_input_stream& s)> fn;
/**
* Handler function for the tag.
*
* Parameter s: The substream of extension.
*/
std::function<void(input& s)> fn;
};
binary_input_stream(std::istream& s);
binary_input_stream(binary_input_stream& s, uint64_t len);
/**
* Create a new top-level input stream, reading from specified stream.
*/
input(std::istream& s);
/**
* Create a new input substream, under specified top-level stream and with specified length.
*
* Parameter s: The top-level stream.
* Parameter len: Amount of payload in extension stream.
*/
input(input& s, uint64_t len);
/**
* Read a byte.
*
* Returns: The read byte.
*/
uint8_t byte();
/**
* Read a number.
*
* Returns: The read number.
*/
uint64_t number();
/**
* Read a 32-bit number.
*
* Returns: The read number.
*/
uint32_t number32();
/**
* Read a string with explicit length indication.
*
* Returns: The read string.
*/
std::string string();
/**
* Read a string without explicit length indication, quitting when reaching end of extension substream.
*
* Can be only used in extension substreams.
*
* Returns: The read string.
*/
std::string string_implicit();
/**
* Read a octet string without explicit length indication, quitting when reaching end of extension substream.
*
* Can be only used in extension substreams.
*
* Parameter blob: Store the read octet string here.
*/
void blob_implicit(std::vector<char>& blob);
/**
* Read a octet string of specified length.
*
* Parameter buf: Buffer to store the octet string to.
* Parameter bufsize: The amount of data to read.
*/
void raw(void* buf, size_t bufsize);
void extension(std::function<void(uint32_t tag, binary_input_stream& s)> fn);
/**
* Read extension substreams.
*
* This reads substreams until the end of stream.
*
* Parameter fn: Function handling the read extension substream.
* Parameter tag: The type tag of read substream.
* Parameter s: The substream with contents of extension substream.
*/
void extension(std::function<void(uint32_t tag, input& s)> fn);
/**
* Read extension substreams.
*
* This reads substreams until the end of stream.
*
* Parameter funcs: Table of functions to call for each known extension type.
* Parameter default_hdlr: Handler for unknown types (parameters as in other ::extension()).
*/
void extension(std::initializer_list<binary_tag_handler> funcs,
std::function<void(uint32_t tag, binary_input_stream& s)> default_hdlr);
std::function<void(uint32_t tag, input& s)> default_hdlr);
/**
* Get number of bytes left in substream.
*
* Can only be used for substreams.
*
* Returns: Number of bytes left.
*/
uint64_t get_left()
{
if(!parent)
throw std::logic_error("binary_input_stream::get_left() can only be used in substreams");
throw std::logic_error("binarystream::input::get_left() can only be used in substreams");
return left;
}
private:
bool read(char* buf, size_t size, bool allow_none = false);
void flush();
binary_input_stream* parent;
input* parent;
std::istream& strm;
uint64_t left;
};
void binary_null_default(uint32_t tag, binary_input_stream& s);
/**
* Do nothing. Handy as second parameter for two-parameter output::extension() if the table enumerates all non-
* ignored types.
*/
void null_default(uint32_t tag, input& s);
}
#endif

View file

@ -83,7 +83,7 @@ void write_linefile(zip_writer& w, const std::string& member, const std::string&
namespace
{
void binary_read_movie(binary_input_stream& in, controller_frame_vector& v)
void binary_read_movie(binarystream::input& in, controller_frame_vector& v)
{
uint64_t stride = v.get_stride();
uint64_t pageframes = v.get_frames_per_page();
@ -100,7 +100,7 @@ namespace
v.resize(vsize);
}
void binary_write_movie(binary_output_stream& out, controller_frame_vector& v)
void binary_write_movie(binarystream::output& out, controller_frame_vector& v)
{
uint64_t pages = v.get_page_count();
uint64_t stride = v.get_stride();
@ -519,7 +519,7 @@ moviefile::brief_info::brief_info(const std::string& filename)
void moviefile::brief_info::binary_io(std::istream& _stream)
{
binary_input_stream in(_stream);
binarystream::input in(_stream);
sysregion = in.string();
//Discard the settings.
while(in.byte()) {
@ -527,17 +527,17 @@ void moviefile::brief_info::binary_io(std::istream& _stream)
in.string();
}
in.extension({
{TAG_CORE_VERSION, [this](binary_input_stream& s) {
{TAG_CORE_VERSION, [this](binarystream::input& s) {
this->corename = s.string_implicit();
}},{TAG_PROJECT_ID, [this](binary_input_stream& s) {
}},{TAG_PROJECT_ID, [this](binarystream::input& s) {
this->projectid = s.string_implicit();
}},{TAG_SAVESTATE, [this](binary_input_stream& s) {
}},{TAG_SAVESTATE, [this](binarystream::input& s) {
this->current_frame = s.number();
}},{TAG_RRDATA, [this](binary_input_stream& s) {
}},{TAG_RRDATA, [this](binarystream::input& s) {
std::vector<char> c_rrdata;
s.blob_implicit(c_rrdata);
this->rerecords = rrdata.count(c_rrdata);
}},{TAG_ROMHASH, [this](binary_input_stream& s) {
}},{TAG_ROMHASH, [this](binarystream::input& s) {
uint8_t n = s.byte();
std::string h = s.string_implicit();
if(n > 2 * ROM_SLOT_COUNT)
@ -546,14 +546,14 @@ void moviefile::brief_info::binary_io(std::istream& _stream)
this->hashxml[n >> 1] = h;
else
this->hash[n >> 1] = h;
}},{TAG_ROMHINT, [this](binary_input_stream& s) {
}},{TAG_ROMHINT, [this](binarystream::input& s) {
uint8_t n = s.byte();
std::string h = s.string_implicit();
if(n > ROM_SLOT_COUNT)
return;
this->hint[n] = h;
}}
}, binary_null_default);
}, binarystream::null_default);
}
moviefile::moviefile() throw(std::bad_alloc)
@ -799,49 +799,49 @@ Following need to be saved:
*/
void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runtime_error)
{
binary_output_stream out(_stream);
binarystream::output out(_stream);
out.string(gametype->get_name());
write_settings<binary_output_stream>(out, settings, gametype->get_type().get_settings(),
[](binary_output_stream& s, const std::string& name, const std::string& value) -> void {
write_settings<binarystream::output>(out, settings, gametype->get_type().get_settings(),
[](binarystream::output& s, const std::string& name, const std::string& value) -> void {
s.byte(0x01);
s.string(name);
s.string(value);
});
out.byte(0x00);
out.extension(TAG_MOVIE_TIME, [this](binary_output_stream& s) {
out.extension(TAG_MOVIE_TIME, [this](binarystream::output& s) {
s.number(this->movie_rtc_second);
s.number(this->movie_rtc_subsecond);
});
out.extension(TAG_PROJECT_ID, [this](binary_output_stream& s) {
out.extension(TAG_PROJECT_ID, [this](binarystream::output& s) {
s.string_implicit(this->projectid);
});
out.extension(TAG_CORE_VERSION, [this](binary_output_stream& s) {
out.extension(TAG_CORE_VERSION, [this](binarystream::output& s) {
this->coreversion = this->gametype->get_type().get_core_identifier();
s.string_implicit(this->coreversion);
});
for(unsigned i = 0; i < ROM_SLOT_COUNT; i++) {
out.extension(TAG_ROMHASH, [this, i](binary_output_stream& s) {
out.extension(TAG_ROMHASH, [this, i](binarystream::output& s) {
if(!this->romimg_sha256[i].length()) return;
s.byte(2 * i);
s.string_implicit(this->romimg_sha256[i]);
});
out.extension(TAG_ROMHASH, [this, i](binary_output_stream& s) {
out.extension(TAG_ROMHASH, [this, i](binarystream::output& s) {
if(!this->romxml_sha256[i].length()) return;
s.byte(2 * i + 1);
s.string_implicit(this->romxml_sha256[i]);
});
out.extension(TAG_ROMHINT, [this, i](binary_output_stream& s) {
out.extension(TAG_ROMHINT, [this, i](binarystream::output& s) {
if(!this->namehint[i].length()) return;
s.byte(i);
s.string_implicit(this->namehint[i]);
});
}
out.extension(TAG_RRDATA, [this](binary_output_stream& s) {
out.extension(TAG_RRDATA, [this](binarystream::output& s) {
uint64_t count;
std::vector<char> rrd;
count = rrdata.write(rrd);
@ -849,16 +849,16 @@ void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runt
});
for(auto i : movie_sram)
out.extension(TAG_MOVIE_SRAM, [&i](binary_output_stream& s) {
out.extension(TAG_MOVIE_SRAM, [&i](binarystream::output& s) {
s.string(i.first);
s.blob_implicit(i.second);
});
out.extension(TAG_ANCHOR_SAVE, [this](binary_output_stream& s) {
out.extension(TAG_ANCHOR_SAVE, [this](binarystream::output& s) {
s.blob_implicit(this->anchor_savestate);
});
if(is_savestate) {
out.extension(TAG_SAVESTATE, [this](binary_output_stream& s) {
out.extension(TAG_SAVESTATE, [this](binarystream::output& s) {
s.number(this->save_frame);
s.number(this->lagged_frames);
s.number(this->rtc_second);
@ -872,47 +872,47 @@ void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runt
out.numberbytes(rtc_subsecond) + out.numberbytes(pollcounters.size()) +
4 * pollcounters.size() + 1 + savestate.size());
out.extension(TAG_HOSTMEMORY, [this](binary_output_stream& s) {
out.extension(TAG_HOSTMEMORY, [this](binarystream::output& s) {
s.blob_implicit(this->host_memory);
});
out.extension(TAG_SCREENSHOT, [this](binary_output_stream& s) {
out.extension(TAG_SCREENSHOT, [this](binarystream::output& s) {
s.blob_implicit(this->screenshot);
}, true, screenshot.size());
for(auto i : sram) {
out.extension(TAG_SAVE_SRAM, [&i](binary_output_stream& s) {
out.extension(TAG_SAVE_SRAM, [&i](binarystream::output& s) {
s.string(i.first);
s.blob_implicit(i.second);
});
}
}
out.extension(TAG_GAMENAME, [this](binary_output_stream& s) {
out.extension(TAG_GAMENAME, [this](binarystream::output& s) {
s.string_implicit(this->gamename);
});
for(auto i : subtitles)
out.extension(TAG_SUBTITLE, [&i](binary_output_stream& s) {
out.extension(TAG_SUBTITLE, [&i](binarystream::output& s) {
s.number(i.first.get_frame());
s.number(i.first.get_length());
s.string_implicit(i.second);
});
for(auto i : authors)
out.extension(TAG_AUTHOR, [&i](binary_output_stream& s) {
out.extension(TAG_AUTHOR, [&i](binarystream::output& s) {
s.string(i.first);
s.string_implicit(i.second);
});
for(auto i : active_macros)
out.extension(TAG_MACRO, [&i](binary_output_stream& s) {
out.extension(TAG_MACRO, [&i](binarystream::output& s) {
s.number(i.second);
s.string_implicit(i.first);
});
for(auto i : ramcontent) {
out.extension(TAG_RAMCONTENT, [&i](binary_output_stream& s) {
out.extension(TAG_RAMCONTENT, [&i](binarystream::output& s) {
s.string(i.first);
s.blob_implicit(i.second);
});
@ -923,7 +923,7 @@ void moviefile::binary_io(std::ostream& _stream) throw(std::bad_alloc, std::runt
void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::bad_alloc, std::runtime_error)
{
binary_input_stream in(_stream);
binarystream::input in(_stream);
std::string tmp = in.string();
try {
gametype = &romtype.lookup_sysregion(tmp);
@ -941,35 +941,35 @@ void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::
input.clear(ports);
in.extension({
{TAG_ANCHOR_SAVE, [this](binary_input_stream& s) {
{TAG_ANCHOR_SAVE, [this](binarystream::input& s) {
s.blob_implicit(this->anchor_savestate);
}},{TAG_AUTHOR, [this](binary_input_stream& s) {
}},{TAG_AUTHOR, [this](binarystream::input& s) {
std::string a = s.string();
std::string b = s.string_implicit();
this->authors.push_back(std::make_pair(a, b));
}},{TAG_CORE_VERSION, [this](binary_input_stream& s) {
}},{TAG_CORE_VERSION, [this](binarystream::input& s) {
this->coreversion = s.string_implicit();
}},{TAG_GAMENAME, [this](binary_input_stream& s) {
}},{TAG_GAMENAME, [this](binarystream::input& s) {
this->gamename = s.string_implicit();
}},{TAG_HOSTMEMORY, [this](binary_input_stream& s) {
}},{TAG_HOSTMEMORY, [this](binarystream::input& s) {
s.blob_implicit(this->host_memory);
}},{TAG_MACRO, [this](binary_input_stream& s) {
}},{TAG_MACRO, [this](binarystream::input& s) {
uint64_t n = s.number();
this->active_macros[s.string_implicit()] = n;
}},{TAG_MOVIE, [this](binary_input_stream& s) {
}},{TAG_MOVIE, [this](binarystream::input& s) {
binary_read_movie(s, input);
}},{TAG_MOVIE_SRAM, [this](binary_input_stream& s) {
}},{TAG_MOVIE_SRAM, [this](binarystream::input& s) {
std::string a = s.string();
s.blob_implicit(this->movie_sram[a]);
}},{TAG_RAMCONTENT, [this](binary_input_stream& s) {
}},{TAG_RAMCONTENT, [this](binarystream::input& s) {
std::string a = s.string();
s.blob_implicit(this->ramcontent[a]);
}},{TAG_MOVIE_TIME, [this](binary_input_stream& s) {
}},{TAG_MOVIE_TIME, [this](binarystream::input& s) {
this->movie_rtc_second = s.number();
this->movie_rtc_subsecond = s.number();
}},{TAG_PROJECT_ID, [this](binary_input_stream& s) {
}},{TAG_PROJECT_ID, [this](binarystream::input& s) {
this->projectid = s.string_implicit();
}},{TAG_ROMHASH, [this](binary_input_stream& s) {
}},{TAG_ROMHASH, [this](binarystream::input& s) {
uint8_t n = s.byte();
std::string h = s.string_implicit();
if(n > 2 * ROM_SLOT_COUNT)
@ -978,19 +978,19 @@ void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::
romxml_sha256[n >> 1] = h;
else
romimg_sha256[n >> 1] = h;
}},{TAG_ROMHINT, [this](binary_input_stream& s) {
}},{TAG_ROMHINT, [this](binarystream::input& s) {
uint8_t n = s.byte();
std::string h = s.string_implicit();
if(n > ROM_SLOT_COUNT)
return;
namehint[n] = h;
}},{TAG_RRDATA, [this](binary_input_stream& s) {
}},{TAG_RRDATA, [this](binarystream::input& s) {
s.blob_implicit(this->c_rrdata);
this->rerecords = (stringfmt() << rrdata.count(c_rrdata)).str();
}},{TAG_SAVE_SRAM, [this](binary_input_stream& s) {
}},{TAG_SAVE_SRAM, [this](binarystream::input& s) {
std::string a = s.string();
s.blob_implicit(this->sram[a]);
}},{TAG_SAVESTATE, [this](binary_input_stream& s) {
}},{TAG_SAVESTATE, [this](binarystream::input& s) {
this->is_savestate = true;
this->save_frame = s.number();
this->lagged_frames = s.number();
@ -1001,15 +1001,15 @@ void moviefile::binary_io(std::istream& _stream, core_type& romtype) throw(std::
i = s.number32();
this->poll_flag = (s.byte() != 0);
s.blob_implicit(this->savestate);
}},{TAG_SCREENSHOT, [this](binary_input_stream& s) {
}},{TAG_SCREENSHOT, [this](binarystream::input& s) {
s.blob_implicit(this->screenshot);
}},{TAG_SUBTITLE, [this](binary_input_stream& s) {
}},{TAG_SUBTITLE, [this](binarystream::input& s) {
uint64_t f = s.number();
uint64_t l = s.number();
std::string x = s.string_implicit();
this->subtitles[moviefile_subtiming(f, l)] = x;
}}
}, binary_null_default);
}, binarystream::null_default);
}
uint64_t moviefile::get_frame_count() throw()

View file

@ -6,24 +6,26 @@
#include <iterator>
#include <map>
namespace binarystream
{
const uint32_t TAG_ = 0xaddb2d86;
binary_output_stream::binary_output_stream()
output::output()
: strm(buf)
{
}
binary_output_stream::binary_output_stream(std::ostream& s)
output::output(std::ostream& s)
: strm(s)
{
}
void binary_output_stream::byte(uint8_t byte)
void output::byte(uint8_t byte)
{
strm.write(reinterpret_cast<char*>(&byte), 1);
}
void binary_output_stream::number(uint64_t number)
void output::number(uint64_t number)
{
char data[10];
size_t len = 0;
@ -35,7 +37,7 @@ void binary_output_stream::number(uint64_t number)
strm.write(data, len);
}
size_t binary_output_stream::numberbytes(uint64_t number)
size_t output::numberbytes(uint64_t number)
{
size_t o = 0;
do {
@ -45,44 +47,44 @@ size_t binary_output_stream::numberbytes(uint64_t number)
return o;
}
void binary_output_stream::number32(uint32_t number)
void output::number32(uint32_t number)
{
char data[4];
write32ube(data, number);
strm.write(data, 4);
}
void binary_output_stream::string(const std::string& string)
void output::string(const std::string& string)
{
number(string.length());
std::copy(string.begin(), string.end(), std::ostream_iterator<char>(strm));
}
void binary_output_stream::string_implicit(const std::string& string)
void output::string_implicit(const std::string& string)
{
std::copy(string.begin(), string.end(), std::ostream_iterator<char>(strm));
}
void binary_output_stream::blob_implicit(const std::vector<char>& blob)
void output::blob_implicit(const std::vector<char>& blob)
{
strm.write(&blob[0], blob.size());
}
void binary_output_stream::raw(const void* buf, size_t bufsize)
void output::raw(const void* buf, size_t bufsize)
{
strm.write(reinterpret_cast<const char*>(buf), bufsize);
}
void binary_output_stream::write_extension_tag(uint32_t tag, uint64_t size)
void output::write_extension_tag(uint32_t tag, uint64_t size)
{
number32(TAG_);
number32(tag);
number(size);
}
void binary_output_stream::extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty)
void output::extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty)
{
binary_output_stream tmp;
output tmp;
fn(tmp);
std::string str = tmp.get();
if(!even_empty && !str.length())
@ -92,7 +94,7 @@ void binary_output_stream::extension(uint32_t tag, std::function<void(binary_out
string(str);
}
void binary_output_stream::extension(uint32_t tag, std::function<void(binary_output_stream&)> fn, bool even_empty,
void output::extension(uint32_t tag, std::function<void(output&)> fn, bool even_empty,
size_t size_precognition)
{
if(!even_empty && !size_precognition)
@ -104,21 +106,21 @@ void binary_output_stream::extension(uint32_t tag, std::function<void(binary_out
}
std::string binary_output_stream::get()
std::string output::get()
{
if(&strm != &buf)
throw std::logic_error("Get can only be used without explicit sink");
return buf.str();
}
uint8_t binary_input_stream::byte()
uint8_t input::byte()
{
char byte;
read(&byte, 1);
return byte;
}
uint64_t binary_input_stream::number()
uint64_t input::number()
{
uint64_t s = 0;
int sh = 0;
@ -131,14 +133,14 @@ uint64_t binary_input_stream::number()
return s;
}
uint32_t binary_input_stream::number32()
uint32_t input::number32()
{
char c[4];
read(c, 4);
return read32ube(c);
}
std::string binary_input_stream::string()
std::string input::string()
{
size_t sz = number();
std::vector<char> _r;
@ -148,10 +150,10 @@ std::string binary_input_stream::string()
return r;
}
std::string binary_input_stream::string_implicit()
std::string input::string_implicit()
{
if(!parent)
throw std::logic_error("binary_input_stream::string_implicit() can only be used in substreams");
throw std::logic_error("binarystream::input::string_implicit() can only be used in substreams");
std::vector<char> _r;
_r.resize(left);
read(&_r[0], left);
@ -159,40 +161,40 @@ std::string binary_input_stream::string_implicit()
return r;
}
void binary_input_stream::blob_implicit(std::vector<char>& blob)
void input::blob_implicit(std::vector<char>& blob)
{
if(!parent)
throw std::logic_error("binary_input_stream::string_implicit() can only be used in substreams");
throw std::logic_error("binarystream::input::string_implicit() can only be used in substreams");
blob.resize(left);
read(&blob[0], left);
}
binary_input_stream::binary_input_stream(std::istream& s)
input::input(std::istream& s)
: strm(s), left(0), parent(NULL)
{
}
binary_input_stream::binary_input_stream(binary_input_stream& s, uint64_t len)
input::input(input& s, uint64_t len)
: strm(s.strm), left(len), parent(&s)
{
if(parent->parent && left > parent->left)
throw std::runtime_error("Substream length greater than its parent");
}
void binary_input_stream::raw(void* buf, size_t bufsize)
void input::raw(void* buf, size_t bufsize)
{
read(reinterpret_cast<char*>(buf), bufsize);
}
void binary_input_stream::extension(std::function<void(uint32_t tag, binary_input_stream& s)> fn)
void input::extension(std::function<void(uint32_t tag, input& s)> fn)
{
extension({}, fn);
}
void binary_input_stream::extension(std::initializer_list<binary_tag_handler> funcs,
std::function<void(uint32_t tag, binary_input_stream& s)> default_hdlr)
void input::extension(std::initializer_list<binary_tag_handler> funcs,
std::function<void(uint32_t tag, input& s)> default_hdlr)
{
std::map<uint32_t, std::function<void(binary_input_stream& s)>> fn;
std::map<uint32_t, std::function<void(input& s)>> fn;
for(auto i : funcs)
fn[i.tag] = i.fn;
while(!parent || left > 0) {
@ -204,7 +206,7 @@ void binary_input_stream::extension(std::initializer_list<binary_tag_handler> fu
throw std::runtime_error("Binary file packet structure desync");
uint32_t tag = number32();
uint64_t size = number();
binary_input_stream ss(*this, size);
input ss(*this, size);
if(fn.count(tag))
fn[tag](ss);
else
@ -213,16 +215,16 @@ void binary_input_stream::extension(std::initializer_list<binary_tag_handler> fu
}
}
void binary_input_stream::flush()
void input::flush()
{
if(!parent)
throw std::logic_error("binary_input_stream::flush() can only be used in substreams");
throw std::logic_error("binarystream::input::flush() can only be used in substreams");
char buf[256];
while(left)
read(buf, min(left, (uint64_t)256));
}
bool binary_input_stream::read(char* buf, size_t size, bool allow_none)
bool input::read(char* buf, size_t size, bool allow_none)
{
if(parent) {
if(left == 0 && allow_none)
@ -242,7 +244,8 @@ bool binary_input_stream::read(char* buf, size_t size, bool allow_none)
return true;
}
void binary_null_default(uint32_t tag, binary_input_stream& s)
void null_default(uint32_t tag, input& s)
{
//no-op
}
}