Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to write a function for custom data type?

I have an school assignment where we are asked to write our own serialize and deserialize functions in c++.

Consider this simple class

class Hello {
  int Int32;
  float Float;
  vector<int> Array;
};

I am not able to find any way do it. Can anybody just give me rough guidance of how to achieve this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

I’ve put together an outline of what it could look like.

  • I’ve made a class called LEB128 that you can initialize with an integer type.
  • You’ll have to implement the LEB128 encoding/decoding.
  • I’ve commented in the code to explain what it’s doing.
#include <iostream>
#include <type_traits>
#include <vector>

class LEB128 {       
public:
    LEB128() = default;

    // a constructor taking an integer and LEB128 encodes it
    // by putting the encoded data in the `data` member variable:
    template<class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
    LEB128(T v) {
        if constexpr (std::is_signed_v<T>) {
            // implement signed LEB128 here, put data in `data`
        } else {
            // implement unsigned LEB128 here,put data in `data`
        }
    }

    // add one LEB128 object to this object:
    LEB128& operator+=(const LEB128& rhs) {
        data.insert(data.end(), rhs.data.begin(), rhs.data.end());
        return *this;
    }

    // decode the LEB128 encoded data and return it as `T`
    template<class T>
    T to() const {
        // implement decoding the LEB128 encoded data in `data` and return it as
        // type T
        return T{};
    }

    // write a LEB128 to a stream
    friend std::ostream& operator<<(std::ostream& os, const LEB128& l) {
       return os.write(reinterpret_cast<const char*>(l.data.data()), l.data.size());
    }

    // read a LEB128 from a stream
    friend std::istream& operator>>(std::istream& is, LEB128& l) {
        l.data.clear();
        // implement reading LEB128 bytes here and put them in `l.data`
        return is;
    }

private:
    std::vector<uint8_t> data;
};

// concatenate two LEB128's
LEB128 operator+(const LEB128& lhs, const LEB128& rhs) {
    LEB128 rv(lhs);
    rv += rhs;
    return rv;
}

class Hello {
    int32_t Int32;
    float Float;
    std::vector<uint8_t> U8Array;

    // serialize a Hello:
    friend std::ostream& operator<<(std::ostream& os, const Hello& h) {
        // figure out what to do with the `float` - this serializes the integers:
        LEB128 leb = LEB128(h.Int32) + LEB128(h.U8Array.size());
        for(auto val : h.U8Array) leb += LEB128(val);
        return os << leb;
    }

    // deserialize a Hello:
    friend std::istream& operator>>(std::istream& is, Hello& l) {
        LEB128 lebInt32, lebSize;
        if(is >> lebInt32 >> lebSize) {
            l.Int32 = lebInt32.to<int32_t>();
            size_t size = lebSize.to<size_t>();            
            l.U8Array.resize(size);
            LEB128 tmp;
            for(auto& val : l.U8Array) {
                is >> tmp;
                val = tmp.to<uint8_t>();
            }
        }
        return is;
    }
};

Now serializing a Hello could be done like this:

Hello h;
std::ofstream file("Hello.bin");
file << h;

and deserializing:

Hello h;
std::ifstream file("Hello.bin");
file >> h;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading