diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fd9f918..a8147d3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ endif () # ============ set(XEUS_HEADERS + ${XEUS_INCLUDE_DIR}/xeus/xbase64.hpp ${XEUS_INCLUDE_DIR}/xeus/xbasic_fixed_string.hpp ${XEUS_INCLUDE_DIR}/xeus/xcomm.hpp ${XEUS_INCLUDE_DIR}/xeus/xcontrol_messenger.hpp diff --git a/include/xeus/xbase64.hpp b/include/xeus/xbase64.hpp new file mode 100644 index 00000000..ba0e7b5b --- /dev/null +++ b/include/xeus/xbase64.hpp @@ -0,0 +1,75 @@ +/*************************************************************************** +* Copyright (c) Sylvain Corlay and Johan Mabille and Wolf Vollprecht * +* Copyright (c) QuantStack * +* * +* Distributed under the terms of the BSD 3-Clause License. * +* * +* The full license is in the file LICENSE, distributed with this software. * +****************************************************************************/ + +#ifndef XEUS_BASE64_HPP +#define XEUS_BASE64_HPP + +#include +#include +#include + +namespace xeus +{ + inline std::string base64decode(const std::string& input) + { + std::array T; + T.fill(-1); + for (std::size_t i = 0; i < 64; ++i) + { + T[std::size_t("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i])] = int(i); + } + + std::string output; + int val = 0; + int valb = -8; + for (char c : input) + { + if (T[std::size_t(c)] == -1) + { + break; + } + val = (val << 6) + T[std::size_t(c)]; + valb += 6; + if (valb >= 0) + { + output.push_back(char((val >> valb) & 0xFF)); + valb -= 8; + } + } + return output; + } + + inline std::string base64encode(const std::string& input) + { + std::string output; + int val = 0; + int valb = -6; + for (char sc : input) + { + unsigned char c = static_cast(sc); + val = (val << 8) + c; + valb += 8; + while (valb >= 0) + { + output.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]); + valb -= 6; + } + } + if (valb > -6) + { + output.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]); + } + while (output.size() % 4) + { + output.push_back('='); + } + return output; + } +} +#endif \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 62cf91cb..0d0331d5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,6 +49,7 @@ find_package(doctest REQUIRED) find_package(Threads) set(XEUS_TESTS + test_xbase64.cpp test_xbasic_fixed_string.cpp test_xhash.cpp test_xin_memory_history_manager.cpp diff --git a/test/test_xbase64.cpp b/test/test_xbase64.cpp new file mode 100644 index 00000000..d1ab18bb --- /dev/null +++ b/test/test_xbase64.cpp @@ -0,0 +1,36 @@ +/*************************************************************************** +* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * +* Copyright (c) QuantStack * +* * +* Distributed under the terms of the BSD 3-Clause License. * +* * +* The full license is in the file LICENSE, distributed with this software. * +****************************************************************************/ + +#include "doctest/doctest.h" + +#include "xeus/xbase64.hpp" + +namespace xeus +{ + TEST_SUITE("xbase64") + { + TEST_CASE("base64encode") + { + std::string input = "hello world"; + std::string expected_output = "aGVsbG8gd29ybGQ="; + std::string encoded = base64encode(input); + + REQUIRE(encoded == expected_output); + } + + TEST_CASE("base64decode") + { + std::string input = "aGVsbG8gd29ybGQ="; + std::string expected_output = "hello world"; + std::string decoded = base64decode(input); + + REQUIRE(decoded == expected_output); + } + } +} \ No newline at end of file