============================ How-To work with binary data ============================ C++ effectively has three ways for dealing with binary data: #. The old way was to treat things as a ``char *``, which generally reflects the fact that ``char`` is one byte in size. Unfortunately, this is messy e.g. when using literals, not only because ``char`` may be signed or unsigned. #. The other old way was to use ``void *`` everywhere, which correctly documents that binary data is essentially untyped -- but introduces the problem that, being untyped, it is conceptually impossible to increment such a pointer, because one cannot know by how much to increment the underlying memory address. #. The C++17 way, which is to use ``std::byte``. Sadly, this type is not uniformly available. In order to deal with this a little better, liberate introduces a very simple type of its own, :cpp:type:`liberate::types::byte`. Depending on whether it is available, this is defined as ``std::byte`` -- or as a fallback, ``uint8_t``. In either case, it is designed to be unsigned and available. The `liberate/types/byte.h` header also introduces ``_b`` literals: .. sourcecode:: cpp :linenos: :dedent: :caption: Using byte literals #include using namespace liberate::types::literals; auto a = 'A'_b; // => std::byte with value 0x65 auto b = 0x65_b; // => same auto c = 123456_b; // => std::byte with value (123456 % 256) auto d = "hello"_b; // => std::vector