diff options
Diffstat (limited to 'src/common/Encoding')
-rw-r--r-- | src/common/Encoding/Base32.cpp | 54 | ||||
-rw-r--r-- | src/common/Encoding/Base32.h | 38 | ||||
-rw-r--r-- | src/common/Encoding/Base64.cpp | 57 | ||||
-rw-r--r-- | src/common/Encoding/Base64.h | 38 | ||||
-rw-r--r-- | src/common/Encoding/BaseEncoding.h | 160 |
5 files changed, 347 insertions, 0 deletions
diff --git a/src/common/Encoding/Base32.cpp b/src/common/Encoding/Base32.cpp new file mode 100644 index 00000000000..6866536848c --- /dev/null +++ b/src/common/Encoding/Base32.cpp @@ -0,0 +1,54 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Base32.h" +#include "BaseEncoding.h" +#include "Errors.h" + +struct B32Impl +{ + static constexpr std::size_t BITS_PER_CHAR = 5; + + static constexpr char PADDING = '='; + static constexpr char Encode(uint8 v) + { + ASSERT(v < 0x20); + if (v < 26) return 'A'+v; + else return '2' + (v-26); + } + + static constexpr uint8 DECODE_ERROR = 0xff; + static constexpr uint8 Decode(uint8 v) + { + if (v == '0') return Decode('O'); + if (v == '1') return Decode('l'); + if (('A' <= v) && (v <= 'Z')) return (v-'A'); + if (('a' <= v) && (v <= 'z')) return (v-'a'); + if (('2' <= v) && (v <= '8')) return (v-'2')+26; + return DECODE_ERROR; + } +}; + +/*static*/ std::string Trinity::Encoding::Base32::Encode(std::vector<uint8> const& data) +{ + return Trinity::Impl::GenericBaseEncoding<B32Impl>::Encode(data); +} + +/*static*/ Optional<std::vector<uint8>> Trinity::Encoding::Base32::Decode(std::string const& data) +{ + return Trinity::Impl::GenericBaseEncoding<B32Impl>::Decode(data); +} diff --git a/src/common/Encoding/Base32.h b/src/common/Encoding/Base32.h new file mode 100644 index 00000000000..23705ddfebb --- /dev/null +++ b/src/common/Encoding/Base32.h @@ -0,0 +1,38 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_BASE32_H +#define TRINITY_BASE32_H + +#include "Define.h" +#include "Optional.h" +#include <string> +#include <vector> + +namespace Trinity +{ +namespace Encoding +{ +struct TC_COMMON_API Base32 +{ + static std::string Encode(std::vector<uint8> const& data); + static Optional<std::vector<uint8>> Decode(std::string const& data); +}; +} +} + +#endif diff --git a/src/common/Encoding/Base64.cpp b/src/common/Encoding/Base64.cpp new file mode 100644 index 00000000000..1b1860375e8 --- /dev/null +++ b/src/common/Encoding/Base64.cpp @@ -0,0 +1,57 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Base64.h" +#include "BaseEncoding.h" +#include "Errors.h" + +struct B64Impl +{ + static constexpr std::size_t BITS_PER_CHAR = 6; + + static constexpr char PADDING = '='; + static constexpr char Encode(uint8 v) + { + ASSERT(v < 0x40); + if (v < 26) return 'A' + v; + if (v < 52) return 'a' + (v - 26); + if (v < 62) return '0' + (v - 52); + if (v == 62) return '+'; + else return '/'; + } + + static constexpr uint8 DECODE_ERROR = 0xff; + static constexpr uint8 Decode(uint8 v) + { + if (('A' <= v) && (v <= 'Z')) return (v - 'A'); + if (('a' <= v) && (v <= 'z')) return (v - 'a') + 26; + if (('0' <= v) && (v <= '9')) return (v - '0') + 52; + if (v == '+') return 62; + if (v == '/') return 63; + return DECODE_ERROR; + } +}; + +/*static*/ std::string Trinity::Encoding::Base64::Encode(std::vector<uint8> const& data) +{ + return Trinity::Impl::GenericBaseEncoding<B64Impl>::Encode(data); +} + +/*static*/ Optional<std::vector<uint8>> Trinity::Encoding::Base64::Decode(std::string const& data) +{ + return Trinity::Impl::GenericBaseEncoding<B64Impl>::Decode(data); +} diff --git a/src/common/Encoding/Base64.h b/src/common/Encoding/Base64.h new file mode 100644 index 00000000000..43ef5da65e4 --- /dev/null +++ b/src/common/Encoding/Base64.h @@ -0,0 +1,38 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_BASE64_H +#define TRINITY_BASE64_H + +#include "Define.h" +#include "Optional.h" +#include <string> +#include <vector> + +namespace Trinity +{ +namespace Encoding +{ +struct TC_COMMON_API Base64 +{ + static std::string Encode(std::vector<uint8> const& data); + static Optional<std::vector<uint8>> Decode(std::string const& data); +}; +} +} + +#endif diff --git a/src/common/Encoding/BaseEncoding.h b/src/common/Encoding/BaseEncoding.h new file mode 100644 index 00000000000..123720c6ce2 --- /dev/null +++ b/src/common/Encoding/BaseEncoding.h @@ -0,0 +1,160 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITY_BASE_ENCODING_HPP +#define TRINITY_BASE_ENCODING_HPP + +#include "advstd.h" +#include "Define.h" +#include "Optional.h" +#include <string> +#include <vector> + +namespace Trinity +{ +namespace Impl +{ +template <typename Encoding> +struct GenericBaseEncoding +{ + static constexpr std::size_t BITS_PER_CHAR = Encoding::BITS_PER_CHAR; + static constexpr std::size_t PAD_TO = advstd::lcm(8u, BITS_PER_CHAR); + + static_assert(BITS_PER_CHAR < 8, "Encoding parameters are invalid"); + + static constexpr uint8 DECODE_ERROR = Encoding::DECODE_ERROR; + static constexpr char PADDING = Encoding::PADDING; + + static constexpr std::size_t EncodedSize(std::size_t size) + { + size *= 8; // bits in input + if (size % PAD_TO) // pad to boundary + size += (PAD_TO - (size % PAD_TO)); + return (size / BITS_PER_CHAR); + } + + static constexpr std::size_t DecodedSize(std::size_t size) + { + size *= BITS_PER_CHAR; // bits in input + if (size % PAD_TO) // pad to boundary + size += (PAD_TO - (size % PAD_TO)); + return (size / 8); + } + + static std::string Encode(std::vector<uint8> const& data) + { + auto it = data.begin(), end = data.end(); + if (it == end) + return ""; + + std::string s; + s.reserve(EncodedSize(data.size())); + + uint8 bitsLeft = 8; // in current byte + do + { + uint8 thisC = 0; + if (bitsLeft >= BITS_PER_CHAR) + { + bitsLeft -= BITS_PER_CHAR; + thisC = ((*it >> bitsLeft) & ((1 << BITS_PER_CHAR)-1)); + if (!bitsLeft) + { + ++it; + bitsLeft = 8; + } + } + else + { + thisC = (*it & ((1 << bitsLeft) - 1)) << (BITS_PER_CHAR - bitsLeft); + bitsLeft += (8 - BITS_PER_CHAR); + if ((++it) != end) + thisC |= (*it >> bitsLeft); + } + s.append(1, Encoding::Encode(thisC)); + } while (it != end); + + while (bitsLeft != 8) + { + if (bitsLeft > BITS_PER_CHAR) + bitsLeft -= BITS_PER_CHAR; + else + bitsLeft += (8 - BITS_PER_CHAR); + s.append(1, PADDING); + } + + return s; + } + + static Optional<std::vector<uint8>> Decode(std::string const& data) + { + auto it = data.begin(), end = data.end(); + if (it == end) + return std::vector<uint8>(); + + std::vector<uint8> v; + v.reserve(DecodedSize(data.size())); + + uint8 currentByte = 0; + uint8 bitsLeft = 8; // in current byte + while ((it != end) && (*it != PADDING)) + { + uint8 cur = Encoding::Decode(*(it++)); + if (cur == DECODE_ERROR) + return {}; + + if (bitsLeft > BITS_PER_CHAR) + { + bitsLeft -= BITS_PER_CHAR; + currentByte |= (cur << bitsLeft); + } + else + { + bitsLeft = BITS_PER_CHAR - bitsLeft; // in encoded char + currentByte |= (cur >> bitsLeft); + v.push_back(currentByte); + currentByte = (cur & ((1 << bitsLeft) - 1)); + bitsLeft = 8 - bitsLeft; // in byte again + currentByte <<= bitsLeft; + } + } + + if (currentByte) + return {}; // decode error, trailing non-zero bits + + // process padding + while ((it != end) && (*it == PADDING) && (bitsLeft != 8)) + { + if (bitsLeft > BITS_PER_CHAR) + bitsLeft -= BITS_PER_CHAR; + else + bitsLeft += (8 - BITS_PER_CHAR); + ++it; + } + + // ok, all padding should be consumed, and we should be at end of string + if (it == end) + return v; + + // anything else is an error + return {}; + } +}; +} +} + +#endif |