{"id":19797885,"url":"https://github.com/podgorskiy/bfio","last_synced_at":"2026-06-16T14:32:09.688Z","repository":{"id":83552901,"uuid":"99750473","full_name":"podgorskiy/bfio","owner":"podgorskiy","description":"One-header library for defining writing and reading procedures of C/C++ objects to/from specific binary formats.","archived":false,"fork":false,"pushed_at":"2018-04-19T08:38:50.000Z","size":40,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-28T16:35:41.935Z","etag":null,"topics":["binary","binary-data","cpp","raw","serialization","serialization-library","serializer"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/podgorskiy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-09T01:08:08.000Z","updated_at":"2018-12-14T08:42:51.000Z","dependencies_parsed_at":"2023-07-07T18:32:12.332Z","dependency_job_id":null,"html_url":"https://github.com/podgorskiy/bfio","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/podgorskiy/bfio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Fbfio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Fbfio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Fbfio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Fbfio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/podgorskiy","download_url":"https://codeload.github.com/podgorskiy/bfio/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/podgorskiy%2Fbfio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34410780,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["binary","binary-data","cpp","raw","serialization","serialization-library","serializer"],"created_at":"2024-11-12T07:27:15.452Z","updated_at":"2026-06-16T14:32:09.671Z","avatar_url":"https://github.com/podgorskiy.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bfio - Binary formats I/O. \n\n[![Build Status](https://travis-ci.org/podgorskiy/bfio.svg?branch=master)](https://travis-ci.org/podgorskiy/bfio)\n\n**bfio** is a small, one header only library for serialization/deserialization of C/C++ objects.\n\nGoals:\n\n* Serialize/Deserialize C/C++ objects into/from existing binary formats. For example, you can define readers/writers for zip-archive headers, PE headers, ELF headers, etc..\n* Provide API that defines readers/writers simultaneously, so that you do not need to write code for serialization and deserialization separately, but allowing to do so if needed.\n* Provide API similar to [boost serialization library](https://www.boost.org/doc/libs/1_67_0/libs/serialization/doc/)\n* File I/O API agnostic and allowing reading/writing to memory buffers.\n\n*Why not [boost serialization library](https://www.boost.org/doc/libs/1_67_0/libs/serialization/doc/) or [Cereal](https://uscilab.github.io/cereal/) or others?*\n\n\\- The goal is not just to serialize/deserialize objects, but write and read specific (existing) binary formats.\n\nBelow presented a very simple show case for reading/writing TGA headers, you can find full example [here](https://github.com/podgorskiy/bfio/blob/master/examples/example_3.cpp).\n\nFor more complex examples see [streams example](https://github.com/podgorskiy/bfio/blob/master/examples/example_1.cpp) and  [reading zip archive](https://github.com/podgorskiy/bfio/blob/master/examples/example_2.cpp) example.\n\n# Showcase. Truevision TGA header\n\nThe detailed description of the format can be found at [wiki](https://en.wikipedia.org/wiki/Truevision_TGA)\n\nThe main header has the following structure:\n\n| Field no. | Length | Field name | Description|\n| --------- | ------ | ---------- | ---------- |\n| 1         | 1 byte | ID length  | Length of the image ID field |\n| 2         | 1 byte | Color map type | Whether a color map is included |\n| 3         | 1 byte | Image type | Compression and color types|\n| 4         | 5 bytes| Color map specification | Describes the color map |\n| 5         |10 bytes| Image specification |Image dimensions and format |\n\nColor map has the following structure:\n\n| Length | Field name | Description|\n| ------ | ---------- | ---------- |\n| 2 byte | First entry index  | Index of first color map entry that is included in the file |\n| 2 byte | Color map length | Number of entries of the color map that are included in the file |\n| 1 byte | Color map entry size | Number of bits per pixel|\n\nImage specification has the following structure:\n\n| Length | Field name | Description|\n| ------ | ---------- | ---------- |\n| 2 byte | X-origin  | absolute coordinate of lower-left corner for displays where origin is at the lower left |\n| 2 byte | Y-origin | as for X-origin |\n| 2 byte | Image width | width in pixels |\n| 2 byte | Image height | height in pixels |\n| 1 byte | Pixel depth | bits per pixel |\n| 1 byte | Image descriptor | bits 3-0 give the alpha channel depth, bits 5-4 give direction|\n\nLet's say, we have defined structures for main header, color-map, and image specification: \n\n```cpp\nstruct ColorMapSpecificatuion\n{\n    uint16_t firstEntryIndex;\n    uint16_t colorMapLength;\n    uint8_t colorMapEntrySize;\n};\n\nstruct ImageSpecificatuion\n{\n    uint16_t xOrigin;\n    uint16_t yOrigin;\n    uint16_t width;\n    uint16_t height;\n    uint8_t pixelDepth;\n    uint8_t imageDescriptor;\n};\n\nstruct MainTGAHeader\n{\n    uint8_t IDLength;\n    uint8_t colorMapType;\n    uint8_t imageType;\n    ColorMapSpecificatuion colormap;\n    ImageSpecificatuion imageSpec;\n};\n```\n\nThen, we should define serialization functions for each type:\n(Syntax is heavily inspired by [boost serialization library](https://www.boost.org/doc/libs/1_67_0/libs/serialization/doc/).)\n\n```cpp\nnamespace bfio\n{\n    template\u003cclass RW\u003e\n    inline void Serialize(RW\u0026 io, ColorMapSpecificatuion\u0026 x)\n    {\n        io \u0026 x.firstEntryIndex;\n        io \u0026 x.colorMapLength;\n        io \u0026 x.colorMapEntrySize;\n    }\n    template\u003cclass RW\u003e\n    inline void Serialize(RW\u0026 io, ImageSpecificatuion\u0026 x)\n    {\n        io \u0026 x.xOrigin;\n        io \u0026 x.yOrigin;\n        io \u0026 x.width;\n        io \u0026 x.height;\n        io \u0026 x.pixelDepth;\n        io \u0026 x.imageDescriptor;\n    }\n    template\u003cclass RW\u003e\n    inline void Serialize(RW\u0026 io, MainTGAHeader\u0026 x)\n    {\n        io \u0026 x.IDLength;\n        io \u0026 x.colorMapType;\n        io \u0026 x.imageType;\n        io \u0026 x.colormap;\n        io \u0026 x.imageSpec;\n    }\n}\n```\nIn the case shown above, the template functions define serialization process for both, reading and writing.\n\nNow we can use them as follows:\n\n```cpp\nint main()\n{\n    // Reading image header\n    FILE* f = fopen(\"test.tga\", \"rb\");\n    bfio::CFileStream stream(f);\n\n    printf(\"Tga header size: %d\\n\", (int)bfio::SizeOf\u003cMainTGAHeader\u003e());\n\n    MainTGAHeader tgaHeader;\n\n    stream \u003e\u003e tgaHeader;\n\n    printf(\"Image info:\\nColormap: %s\\nImage type: %d\\nImage width %d\\nImage height: %d\\nPixel depth: %d\\n\"\n        ,tgaHeader.colorMapType == 0 ? \"No colormap\" : \"Has colormap\"\n        ,tgaHeader.imageType\n        ,tgaHeader.imageSpec.width\n        ,tgaHeader.imageSpec.height\n        ,tgaHeader.imageSpec.pixelDepth);\n\n    fclose(f);\n\n    // Writing image header\n    FILE* fout = fopen(\"header.bin\", \"wb\");\n\n    bfio::CFileStream outstream(fout);\n    outstream \u003c\u003c tgaHeader;\n    fclose(fout);\n\n    return 0;\n}\n\n```\n\n# Features.\n\n* Provides default serialization functions for some standard containers. \nTo enable containers, you need to define one of those:\n  * *BFIO_INCLUDE_VECTOR* for *std::vector*\n  * *BFIO_INCLUDE_STRING* for *std::string*\n  * *BFIO_INCLUDE_MAP* for *std::map*\n  * *BFIO_INCLUDE_SET* for *std::set*\n  * *BFIO_INCLUDE_LIST* for *std::list*\n* Has support for glm. To enable define *BFIO_INCLUDE_GLM*\n* Has *SizeOf* function that can return size of the object to be serialized, with optimizations on it is optimized to ilined constant.\n* Has predefined streams:\n  * *CFileStream* for working with C files\n  * *StaticMemoryStream* for working with preallocated memory buffer\n  * *DynamicMemoryStream* for working with dynamically growing memory buffer\n* Allows defining custom streams for working with any I/O API.\n\n# Installation.\n\nIt is a one-header library, no installation is needed. Add the path to the *bfio/include* to your search paths for headers. CMakeLists.txt is mainly for building examples are tests.\nHowever, you can install the library on the system by running:\n\n```\nmkdir build\ncd build\ncmake ../\nmake install\n```\n\n# Reference\n\n## How to write serialization functions?\n\nThere are two ways:\n\n * Write a generic serialization function for both, writing and reading.\n * Write distinct functions for writing and for reading\n \nTypically, the first option is preferred. The second option is used when you need to do some additional manipulations that are different for reading and writing.\n\nTo write a generic function, create in **bfio** namespace a template function *Serialize* of the form:\n\n```cpp\nnamespace bfio\n{\n    template\u003ctypename Stream, AccessType direction\u003e\n    inline void Serialize(Accessor\u003cStream, direction\u003e\u0026 w, MyData\u0026 x)\n}\n```\n\nWhere *MyData* - is the type for which the serialization function is written. \n\nThe function should take a reference to the template *bfio::Accessor\u003ctypename Stream, enum Direction\u003e* object and a non-const reference to your type.\n\nUsing operator *\u0026* of the *bfio::Accessor*, you can specify which members and in which order should be serialized/deserialized.\n\nYou can write generic functions, which are templates with arguments *Stream* and *Direction* or you can create a specialization for particular direction (Reading or Writing) or specific stream types.\n\n### Example:\n\nStructure:\n\n```cpp\nstruct MyData\n{\n    std::map\u003cint, std::string\u003e m;\n    std::string str;\n    std::vector\u003cstd::pair\u003cstd::string, float\u003e \u003e v;\n\n    int a[10];\n};\n```\n\nSerialization function:\n\n```cpp\nnamespace bfio\n{\n    template\u003ctypename Stream, AccessType direction\u003e\n    inline void Serialize(Accessor\u003cStream, direction\u003e\u0026 w, MyData\u0026 x)\n    {\n        w \u0026 x.m;\n        w \u0026 x.str;\n        w \u0026 x.v;\n        w \u0026 x.a;\n    }\n}\n```\n\nOr in shortened form:\n\n```cpp\nnamespace bfio\n{\n    template\u003ctypename A\u003e\n    inline void Serialize(A\u0026 w, MyData\u0026 x)\n    {\n        w \u0026 x.m;\n        w \u0026 x.str;\n        w \u0026 x.v;\n        w \u0026 x.a;\n    }\n}\n```\n\n\nThe second way is to specify functions for reading/writing separately. To do so, you need to specify *bfio::Accessor* with template arguments of:\n\n * Stream type. Intended to be a template argument. However, you can create a specialization for particular stream types.\n * Direction. *bfio::AccessType::Reading* or *bfio::AccessType::Writing*\n\nExample:\n\n```cpp\nnamespace bfio\n{\n    template\u003ctypename Stream\u003e\n    inline void Serialize(Accessor\u003cStream, Writing\u003e\u0026 w, MyData\u0026 x)\n    {\n        printf(\"Hello from writer!\");\n        w \u0026 x.m;\n        w \u0026 x.str;\n        w \u0026 x.v;\n        w \u0026 x.a;\n    }\n\n    template\u003ctypename Stream\u003e\n    inline void Serialize(Accessor\u003cStream, Reading\u003e\u0026 r, MyData\u0026 x)\n    {\n        printf(\"Hello from reader!\");\n        r \u0026 x.m;\n        r \u0026 x.str;\n        r \u0026 x.v;\n        r \u0026 x.a;\n    }\n}\n```\n\n## How to use streams?\n\nStreams are classes derived from *bfio::Stream* class and implement the following functions:\n\n```cpp\n    bool Write(const void* src, size_t size);\n    bool Read(void* dst, size_t size);\n```\n\nClass *bfio::Stream* defines operators *\u003c\u003c* and *\u003e\u003e* for serialization and deserialization. \nThere are three default streams:\n\n* *CFileStream* - for access to fread and fwrite from standard c library.\n* *StaticMemoryStream* - for reading/writing to the preallocated memory buffer.\n* *DynamicMemoryStream* - for reading/writing to dynamic, growing memory buffer.\n\nYou can create your streams by subclassing from *bfio::Stream*.\n\n*CFileStream*  as an example:\n\n```cpp\n    class CFileStream : public Stream\u003cCFileStream\u003e\n    {\n    public:\n        CFileStream(FILE* f) : file(f)\n        {};\n\n        bool Write(const void* src, size_t size)\n        {\n            return fwrite(src, size, 1, file) == size;\n        }\n        bool Read(void* dst, size_t size)\n        {\n            return fread(dst, size, 1, file) == size;\n        }\n\n    private:\n        FILE* file;\n    };\n```\n\n### *CFileStream*\n\n*CFileStream* is a small wrapper for reading/writing using fread and fwrite functions from C standard library.\n\nUseage:\n\n```cpp\n    FILE* f = fopen(\"test.bin\", \"wb\");\n    CFileStream(f) \u003c\u003c mydata;\n    fcolse(f);\n```\n\n### *StaticMemoryStream*\n\nThis stream type takes a pointer to preallocated memory buffer and size of the buffer in its constructor. This stream does not copy data from the buffer and does not delete it. You should use this stream with caution and make sure the stream is not used after the memory is freed. \n\nUsage:\n\n```cpp\n    char* data = new char[512];\n    bfio::StaticMemoryStream stearm(data, 512);\n    stearm \u003c\u003c mydata;\n```\n\nIt won't read/write beyond the buffer boundaries, the access operators (\u003c\u003c,  \u003e\u003e) will return false for this case.\n\nProvides additional member functions:\n\n* *size_t StaticMemoryStream::GetSize() const* Returns size of the buffer associated with the stream.\n* *char* StaticMemoryStream::Data()* Returns pointer to the buffer.\n* *const char* StaticMemoryStream::DataConst() const* Return const pointer to the buffer.\n* *void StaticMemoryStream::Seek(size_t position)* Sets internal offset pointer to the given position.\n* *size_t StaticMemoryStream::Tell() const* Returns internal offset pointer.\n    \n\n### *DynamicMemoryStream*\n\nThis stream creates internal memory buffer that can grow. If in constructor specified a pointer to a memory block and size, this memory buffer will be copied to the internal buffer and thus can be freed after the construction of the *DynamicMemoryStream*.\n\nInternal buffer grows when the data to be written goes beyond the internal buffer size.\n\nUsage:\n\n```cpp\n    char* data = new char[512];\n    bfio::StaticMemoryStream stearm(data, 512);\n    stearm \u003c\u003c mydata;\n```\n\nProvides all member functions of *StaticMemoryStream* plus additional member function:\n\n* *bool StaticMemoryStream::Resize(size_t newSize)* Chanes the size of internal buffer.\n\nFor more references see [examples](https://github.com/podgorskiy/bfio/tree/master/examples)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpodgorskiy%2Fbfio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpodgorskiy%2Fbfio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpodgorskiy%2Fbfio/lists"}