{"id":15047650,"url":"https://github.com/YexuanXiao/rfc4648-base64","last_synced_at":"2025-10-31T02:31:28.107Z","repository":{"id":256052876,"uuid":"854216429","full_name":"YexuanXiao/rfc4648-base64","owner":"YexuanXiao","description":"Modern C++ base64, base32 and base16 library","archived":false,"fork":false,"pushed_at":"2025-02-10T21:03:28.000Z","size":35,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-10T22:22:00.559Z","etag":null,"topics":["base32","base64","cpp20","modern-cpp","rfc4648"],"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/YexuanXiao.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":"2024-09-08T17:22:46.000Z","updated_at":"2025-02-10T21:03:32.000Z","dependencies_parsed_at":"2025-01-11T01:25:46.447Z","dependency_job_id":"c7496a9b-5620-479c-8abf-54a0ccd45317","html_url":"https://github.com/YexuanXiao/rfc4648-base64","commit_stats":null,"previous_names":["yexuanxiao/base64","yexuanxiao/rfc4648-base64"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YexuanXiao%2Frfc4648-base64","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YexuanXiao%2Frfc4648-base64/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YexuanXiao%2Frfc4648-base64/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YexuanXiao%2Frfc4648-base64/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YexuanXiao","download_url":"https://codeload.github.com/YexuanXiao/rfc4648-base64/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239097845,"owners_count":19581111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["base32","base64","cpp20","modern-cpp","rfc4648"],"created_at":"2024-09-24T21:02:26.756Z","updated_at":"2025-10-31T02:31:22.626Z","avatar_url":"https://github.com/YexuanXiao.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rfc4648/base64/base32/base16-hex\n\nA plain header-only [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648) encoding/decoding library, but with the most modern C++ API design.\n\nThis repository uses NTTP to select encoding/decoding schemes and control padding characters. [Another way](https://github.com/YexuanXiao/rfc4648-afo) is to use function parameters, which allows it to be implemented as [Algorithm Function Objects](https://en.cppreference.com/w/cpp/algorithm/ranges#Algorithm_function_objects) (AFOs).\n\nAll variants of RFC 4648 are supported and the Crockford variant is available.\n\nSupport input from discontinuous multiple buffers.\n\nSupport non-padding for secure base64 url variant.\n\nSupport `constexpr` compile-time caculation.\n\nC++23 required (`std::byteswap`).\n\n## Synopsis\n\n```cpp\n// All functions are constexpr\nenum class rfc4648_kind\n{\n    base64,\n    base64_url,\n    base32,\n    base32_lower,\n    base32_mixed,\n    base32_hex,\n    base32_hex_lower,\n    base32_hex_mixed,\n    base32_crockford,\n    base32_crockford_lower,\n    base32_crockford_mixed,\n    base16,\n    base16_lower,\n    base16_mixed,\n    hex = base16,\n    hex_lower = base16_lower,\n    hex_mixed = base16_mixed\n};\n// All special member functions are trivial and has non-trivial but noexcept default constructor\nclass rfc4648_context;\n//\ntemplate \u003ctypename In, typename Out\u003e\nstruct rfc4648_decode_result\n{\n    In end;\n    Out out;\n    // For rebinding via std::tie\n    operator std::tuple\u003cEnd \u0026, Out \u0026\u003e() \u0026\u0026 noexcept;\n};\n// Encode\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, bool Padding = true, typename In, typename Out\u003e\nOut rfc4648_encode(In begin, In end, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, bool Padding = true, typename R, typename Out\u003e\nOut rfc4648_encode(R\u0026\u0026 r, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, typename In, typename Out\u003e\nOut rfc4648_encode(rfc4648_context\u0026 ctx, In begin, In end, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, typename R, typename Out\u003e\nOut rfc4648_encode(rfc4648_context\u0026 ctx, R\u0026\u0026 r, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, bool Padding = true, typename Out\u003e\nOut rfc4648_encode(rfc4648_context\u0026 ctx, Out first);\n// Decode\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, bool Padding = true, typename In, typename Out\u003e\nrfc4648_decode_result\u003cIn, Out\u003e rfc4648_decode(In begin, In end, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, bool Padding = true, typename R, typename Out\u003e\nrfc4648_decode_result\u003cIn, Out\u003e rfc4648_decode(R\u0026\u0026 r, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, typename In, typename Out\u003e\nrfc4648_decode_result\u003cIn, Out\u003e rfc4648_decode(rfc4648_context\u0026 ctx, In begin, In end, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, typename R, typename Out\u003e\nrfc4648_decode_result\u003cIn, Out\u003e rfc4648_decode(rfc4648_context\u0026 ctx, R\u0026\u0026 r, Out first);\ntemplate \u003crfc4648_kind Kind = rfc4648_kind::base64, bool Padding = true, typename In\u003e\nIn rfc4648_decode(rfc4648_context\u0026 ctx, In begin, In end);\n// Helper functions\ntemplate \u003crfc4648_kind kind = rfc4648_kind::base64\u003e\nstd::size_t rfc4648_encode_length(std::size_t input) noexcept;\ntemplate \u003crfc4648_kind kind = rfc4648_kind::base64\u003e\nstd::size_t rfc4648_decode_length(std::size_t input) noexcept;\n```\n\n`R` must model `std::contiguous_range` , `In` must satisfy *ContinuousIterator* and `Out` must satisfy *OutputIterator*.\n\nLet `n - 1` is the length of the output as specified by RFC 4648.\n\nIf [`begin`, `end`) is not a valid range, or [`first`, `first + n`) is not a valid range, or if [`begin`, `end`) and [`first`, `first + n`) overlap, or if `r` and [`first`, `first + n`) overlap, the behavior is undefined.\n\nIf the template parameter `Padding` is `false` then the padding character `=` is not written.\n\nThe decode functions will return immediately if there are invalid characters (including `=`) within the range [`begin`, `end`), then `rfc4648_decode_result\u003cIn, Out\u003e::end` points to the first invalid character.\n\nThrows any exceptions from increments and dereferences `begin`, `end` or `first`, no other exceptions will be thrown. After an exception is thrown, `ctx` will be in an unspecified state.\n\nThe `rfc4648_encode_length` and `rfc4648_decode_length` functions calculate the maximum number of characters/bytes needed for a given input length. The actual output number will be less than or equal to the returned number.\n\n## Example\n\n```cpp\n#include \"decode.hpp\"\n#include \"encode.hpp\"\n#include \u003ccassert\u003e\n#include \u003cstring\u003e\n#include \u003cstring_view\u003e\n\n#define test_str \"ABCDEFGHIJKLMN\"\n\nint main()\n{\n    std::string_view src1{test_str};\n\n    std::string encoded1;\n    encoded1.resize(bizwen::rfc4648_encode_length(src1.size()));\n    bizwen::rfc4648_encode(src1.begin(), src1.end(), encoded1.begin());\n\n    std::string decoded1;\n    decoded1.resize(src1.size());\n    bizwen::rfc4648_decode(encoded1.begin(), encoded1.end(), decoded1.begin());\n\n    assert(src1 == decoded1);\n\n    std::string_view src2{test_str test_str test_str};\n    std::string encoded2;\n    encoded2.resize(bizwen::rfc4648_encode_length(src2.size()));\n    bizwen::rfc4648_context ctx;\n\n    auto eit = bizwen::rfc4648_encode(ctx, src1.begin(), src1.end(), encoded2.begin());\n    eit = bizwen::rfc4648_encode(ctx, src1.begin(), src1.end(), eit);\n    eit = bizwen::rfc4648_encode(ctx, src1.begin(), src1.end(), eit);\n    // This overload handles remaining bits and outputs the padding characters\n    bizwen::rfc4648_encode(ctx, eit);\n\n    std::string decoded2;\n    decoded2.resize(src2.size());\n    auto [end, dit] = bizwen::rfc4648_decode(ctx, encoded2.begin(), encoded2.begin() + encoded2.size() / 3, decoded2.begin());\n    // If there is an error in decoding, then the assertion fails\n    assert(end == encoded2.begin() + encoded2.size() / 3);\n    std::tie(end, dit) = bizwen::rfc4648_decode(ctx, end, end + encoded2.size() / 3, dit);\n    // If it is the last input data, then the returned end may point to the first padding character\n    // even if the input data is correct\n    std::tie(end, dit) = bizwen::rfc4648_decode(ctx, end, end + (encoded2.size() - encoded2.size() / 3 * 2), dit);\n    // It should not be asserted that the returned end is equal to the input end\n    // This overload is used to check the padding characters\n    end = bizwen::rfc4648_decode(ctx, end, encoded2.end());\n    // The assertion can only be true when the last check is complete\n    assert(end == encoded2.end());\n\n    assert(src2 == decoded2);\n\n    std::string encoded3;\n    encoded3.resize(bizwen::rfc4648_encode_length(src1.size()));\n    bizwen::rfc4648_encode(src1, encoded3.begin());\n\n    std::wstring dest3;\n    dest3.resize(bizwen::rfc4648_encode_length(src1.size()));\n    bizwen::rfc4648_encode((std::byte *)src1.data(), (std::byte *)src1.data() + src1.size(), dest3.begin());\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FYexuanXiao%2Frfc4648-base64","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FYexuanXiao%2Frfc4648-base64","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FYexuanXiao%2Frfc4648-base64/lists"}