XB Library: xb::extend

The xb::extend template function is used to convert element data into a variable of required type. The element is first converted to a type that is compatible with the requested type (whose size is the size of the data), then converted to the requested type.


Interface:

namespace xb {
    template <typename T>
    bool extend (const xb::element & e, T & v);
};

Default implementation tries to byte-wise copy content of the element into the variable. When there is more data that can fit into the variable then only sizeof (T) bytes is copies and the function returns true. Otherwise the function returns false and the remaining bytes (if present) in the variable are set to zero.

The return value is true on overflow or precission loss, false otherwise.

Specialized versions are provided for following data types:

Note that there is no specialization for unsigned integers. The default implementation is sufficient. The default implementation also work correctly for arrays of char or wchar_t (but not for pointers to these types).

For example: Using the xb::extend can 1 byte-long signed integral value be converted to variable of signed integral type of any lenght. An overloaded version of xb::extend is required for all data types that are stored in xb::values that should be convertible back.

User specialization:

Specialize the xb::extend function if you have implemented a data type for which the default implementation is not sufficient.

Specialize the xb::extend function also if you have implemented two (or more) data types where one can always be converted to the other, larger, type and you want to have this conversion done automaticaly when reading value of the xb::node.

Examples:

#include <xb/xb_extend.hpp>

// ...

class myTypeLong { /* ... */ };
class myTypeShort { /* ... */ };

// ...

namespace xb {
    template <>
    bool extend <myTypeShort> (const xb::element & e, myTypeShort & v) {
        if (e.size () == sizeof (myTypeLong)) {
            myTypeLong temp;
            std::memcpy (&temp, e.data (), sizeof temp);
            v = temp;

            return myTypeLong (v) != temp; // true if conversion is not "perfect"

        } else
        if (e.size () == sizeof (myTypeShort)) {
            std::memcpy (&v, e.data (), sizeof v);

        } else
            throw std::bad_cast (); // Invalid data

        return false;
    };

    template <>
    bool extend <myTypeLong> (const xb::element & e, myTypeLong & v) {
        if (e.size () == sizeof (myTypeLong)) {
            std::memcpy (&v, e.data (), sizeof v);

        } else
        if (e.size () == sizeof (myTypeShort)) {
            myTypeShort temp;
            std::memcpy (&temp, e.data (), sizeof temp);
            v = temp;

        } else
            throw std::bad_cast (); // Invalid data

        return false;
    };
};

// ...

Note that part of this example code could be rewritten using extend_helper_assign () template function. See xb_extend.hpp for details regarding this function. Also note that this example assumes that the myTypes are byte-copyable and that casting to "longer" type is always lossless.

Remarks:

Note that you will also need to overload the xb::compact function to be able to correctly assign the types to XB values.


[index]