summaryrefslogtreecommitdiff
path: root/src/hir/serialise_lowlevel.hpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-10-18 21:17:13 +0800
committerJohn Hodge <tpg@mutabah.net>2016-10-18 21:17:13 +0800
commit1daa57b7cfd4dc609502f28eeaecdad4cb43b3d4 (patch)
tree4a66d171abd4c41cdc1f4c585f4fe1b793d66968 /src/hir/serialise_lowlevel.hpp
parentce853ffc73fc2cc743bf2b03cfd1e0d4130ffd30 (diff)
downloadmrust-1daa57b7cfd4dc609502f28eeaecdad4cb43b3d4.tar.gz
HIR Serialise - Compress (now requires boost, sorry)
Diffstat (limited to 'src/hir/serialise_lowlevel.hpp')
-rw-r--r--src/hir/serialise_lowlevel.hpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/hir/serialise_lowlevel.hpp b/src/hir/serialise_lowlevel.hpp
new file mode 100644
index 00000000..34464683
--- /dev/null
+++ b/src/hir/serialise_lowlevel.hpp
@@ -0,0 +1,247 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * hir/serialise_lowlevel.hpp
+ * - HIR (De)Serialisation low-level "protocol"
+ */
+#pragma once
+
+#include <boost/iostreams/filtering_stream.hpp>
+#include <fstream>
+
+namespace HIR {
+namespace serialise {
+
+class Writer
+{
+ ::std::ofstream m_backing;
+ ::boost::iostreams::filtering_ostream m_os;
+public:
+ Writer(const ::std::string& path);
+ Writer(const Writer&) = delete;
+ Writer(Writer&&) = delete;
+
+ void write(const void* data, size_t count);
+
+ void write_u8(uint8_t v) {
+ write(reinterpret_cast<const char*>(&v), 1);
+ }
+ void write_u16(uint16_t v) {
+ uint8_t buf[] = { static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8) };
+ this->write(buf, 2);
+ }
+ void write_u32(uint32_t v) {
+ uint8_t buf[] = {
+ static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8),
+ static_cast<uint8_t>(v >> 16), static_cast<uint8_t>(v >> 24) };
+ this->write(buf, 4);
+ }
+ void write_u64(uint64_t v) {
+ uint8_t buf[] = {
+ static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8), static_cast<uint8_t>(v >> 16), static_cast<uint8_t>(v >> 24),
+ static_cast<uint8_t>(v >> 32), static_cast<uint8_t>(v >> 40), static_cast<uint8_t>(v >> 48), static_cast<uint8_t>(v >> 56)
+ };
+ this->write(buf, 8);
+ }
+ // Variable-length encoded u64 (for array sizes)
+ void write_u64c(uint64_t v) {
+ if( v < (1<<7) ) {
+ write_u8(v);
+ }
+ else if( v < (1<<(6+16)) ) {
+ uint8_t buf[] = {
+ static_cast<uint8_t>(0x80 + (v >> 16)), // 0x80 -- 0xBF
+ static_cast<uint8_t>(v >> 8),
+ static_cast<uint8_t>(v & 0xFF)
+ };
+ this->write(buf, sizeof buf);
+ }
+ else if( v < (1ul << (5 + 32)) ) {
+ uint8_t buf[] = {
+ static_cast<uint8_t>(0xC0 + (v >> 32)), // 0xC0 -- 0xDF
+ static_cast<uint8_t>(v >> 24),
+ static_cast<uint8_t>(v >> 16),
+ static_cast<uint8_t>(v >> 8),
+ static_cast<uint8_t>(v)
+ };
+ this->write(buf, sizeof buf);
+ }
+ else {
+ uint8_t buf[] = {
+ 0xFF,
+ static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8), static_cast<uint8_t>(v >> 16), static_cast<uint8_t>(v >> 24),
+ static_cast<uint8_t>(v >> 32), static_cast<uint8_t>(v >> 40), static_cast<uint8_t>(v >> 48), static_cast<uint8_t>(v >> 56)
+ };
+ this->write(buf, sizeof buf);
+ }
+ }
+ void write_i64c(int64_t v) {
+ // Convert from 2's completement
+ bool sign = (v < 0);
+ uint64_t va = (v < 0 ? -v : v);
+ va <<= 1;
+ va |= (sign ? 1 : 0);
+ write_u64c(va);
+ }
+ void write_double(double v) {
+ // - Just raw-writes the double
+ this->write(&v, sizeof v);
+ }
+ void write_tag(unsigned int t) {
+ assert(t < 256);
+ write_u8( static_cast<uint8_t>(t) );
+ }
+ void write_count(size_t c) {
+ //DEBUG("c = " << c);
+ if(c < 0xFE) {
+ write_u8( static_cast<uint8_t>(c) );
+ }
+ else if( c == ~0u ) {
+ write_u8( 0xFF );
+ }
+ else {
+ assert(c < (1u<<16));
+ write_u8( 0xFE );
+ write_u16( static_cast<uint16_t>(c) );
+ }
+ }
+ void write_string(const ::std::string& v) {
+ if(v.size() < 128) {
+ write_u8( static_cast<uint8_t>(v.size()) );
+ }
+ else {
+ assert(v.size() < (1u<<(16+7)));
+ write_u8( static_cast<uint8_t>(128 + (v.size() >> 16)) );
+ write_u16( static_cast<uint16_t>(v.size() & 0xFFFF) );
+ }
+ this->write(v.data(), v.size());
+ }
+ void write_bool(bool v) {
+ write_u8(v ? 0xFF : 0x00);
+ }
+};
+
+
+class Reader
+{
+ ::std::ifstream m_backing;
+ ::boost::iostreams::filtering_istream m_is;
+public:
+ Reader(const ::std::string& path);
+ Reader(const Writer&) = delete;
+ Reader(Writer&&) = delete;
+
+ void read(void* dst, size_t count);
+
+ uint8_t read_u8() {
+ uint8_t v;
+ read(&v, sizeof v);
+ return v;
+ }
+ uint16_t read_u16() {
+ uint8_t buf[2];
+ read(buf, sizeof buf);
+ return static_cast<uint16_t>(buf[0]) | (static_cast<uint16_t>(buf[1]) << 8);
+ }
+ uint32_t read_u32() {
+ uint8_t buf[4];
+ read(buf, sizeof buf);
+ return static_cast<uint32_t>(buf[0])
+ | (static_cast<uint32_t>(buf[1]) << 8)
+ | (static_cast<uint32_t>(buf[2]) << 16)
+ | (static_cast<uint32_t>(buf[3]) << 24)
+ ;
+ }
+ uint64_t read_u64() {
+ uint8_t buf[8];
+ read(buf, sizeof buf);
+ return static_cast<uint64_t>(buf[0])
+ | (static_cast<uint64_t>(buf[1]) << 8)
+ | (static_cast<uint64_t>(buf[2]) << 16)
+ | (static_cast<uint64_t>(buf[3]) << 24)
+ | (static_cast<uint64_t>(buf[4]) << 32)
+ | (static_cast<uint64_t>(buf[5]) << 40)
+ | (static_cast<uint64_t>(buf[6]) << 48)
+ | (static_cast<uint64_t>(buf[7]) << 56)
+ ;
+ }
+ // Variable-length encoded u64 (for array sizes)
+ uint64_t read_u64c() {
+ auto v = read_u8();
+ if( v < (1<<7) ) {
+ return static_cast<uint64_t>(v);
+ }
+ else if( v < 0xC0 ) {
+ uint64_t rv = static_cast<uint64_t>(v & 0x3F) << 16;
+ rv |= static_cast<uint64_t>(read_u8()) << 8;
+ rv |= static_cast<uint64_t>(read_u8());
+ return rv;
+ }
+ else if( v < 0xFF ) {
+ uint64_t rv = static_cast<uint64_t>(v & 0x3F) << 32;
+ rv |= static_cast<uint64_t>(read_u8()) << 24;
+ rv |= static_cast<uint64_t>(read_u8()) << 16;
+ rv |= static_cast<uint64_t>(read_u8()) << 8;
+ rv |= static_cast<uint64_t>(read_u8());
+ return rv;
+ }
+ else {
+ return read_u64();
+ }
+ }
+ int64_t read_i64c() {
+ uint64_t va = read_u64c();
+ bool sign = (va & 0x1) != 0;
+ va >>= 1;
+
+ if( va == 0 && sign ) {
+ return INT64_MIN;
+ }
+ else if( sign ) {
+ return -static_cast<int64_t>(va);
+ }
+ else {
+ return -static_cast<uint64_t>(va);
+ }
+ }
+ double read_double() {
+ double v;
+ read(reinterpret_cast<char*>(&v), sizeof v);
+ return v;
+ }
+ unsigned int read_tag() {
+ return static_cast<unsigned int>( read_u8() );
+ }
+ size_t read_count() {
+ auto v = read_u8();
+ if( v < 0xFE ) {
+ return v;
+ }
+ else if( v == 0xFE ) {
+ return read_u16( );
+ }
+ else /*if( v == 0xFF )*/ {
+ return ~0u;
+ }
+ }
+ ::std::string read_string() {
+ size_t len = read_u8();
+ if( len < 128 ) {
+ }
+ else {
+ len = (len & 0x7F) << 16;
+ len |= read_u16();
+ }
+ ::std::string rv(len, '\0');
+ read( const_cast<char*>(rv.data()), len);
+ return rv;
+ }
+ bool read_bool() {
+ return read_u8() != 0x00;
+ }
+};
+
+} // namespace serialise
+} // namespace HIR
+