LCOV - code coverage report
Current view: top level - core/core/string - SPBase64.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 248 260 95.4 %
Date: 2024-05-12 00:16:13 Functions: 69 69 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #include "SPString.h"
      25             : 
      26             : namespace STAPPLER_VERSIONIZED stappler::base64 {
      27             : 
      28             : using Reader = BytesViewNetwork;
      29             : 
      30             : // Mapping from 6 bit pattern to ASCII character.
      31             : static const char * base64EncodeLookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      32             : 
      33             : // Definition for "masked-out" areas of the base64DecodeLookup mapping
      34             : #define xx 65
      35             : 
      36             : static unsigned char base64DecodeLookup[256] = {
      37             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      38             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      39             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, 62, xx, 63,
      40             :     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
      41             :     xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
      42             :     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, 63,
      43             :     xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
      44             :     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
      45             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      46             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      47             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      48             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      49             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      50             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      51             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      52             :     xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
      53             : };
      54             : 
      55             : // Fundamental sizes of the binary and base64 encode/decode units in bytes
      56             : constexpr int BinaryUnit = 3;
      57             : constexpr int Base64Unit = 4;
      58             : 
      59        5225 : size_t encodeSize(size_t l) { return ((l / BinaryUnit) + ((l % BinaryUnit) ? 1 : 0)) * Base64Unit; }
      60         300 : size_t decodeSize(size_t l) { return ((l+Base64Unit-1) / Base64Unit) * BinaryUnit; }
      61             : 
      62             : template <typename Callback>
      63        1150 : static void make_encode(const CoderSource &data, const Callback &cb) {
      64        1150 :         Reader inputBuffer(data.data(), data.size());
      65        1150 :         auto length = inputBuffer.size();
      66             : 
      67        1150 :         size_t i = 0;
      68      131704 :         for (; i + BinaryUnit - 1 < length; i += BinaryUnit) {
      69             :                 // Inner loop: turn 48 bytes into 64 base64 characters
      70      130554 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
      71      130554 :                 cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
      72      130554 :                 cb(base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) | ((inputBuffer[i + 2] & 0xC0) >> 6)]);
      73      130554 :                 cb(base64EncodeLookup[inputBuffer[i + 2] & 0x3F]);
      74             :         }
      75             : 
      76        1150 :         if (i + 1 < length) {
      77             :                 // Handle the single '=' case
      78         494 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
      79         494 :                 cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
      80         494 :                 cb(base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]);
      81         494 :                 cb('=');
      82         656 :         } else if (i < length) {
      83             :                 // Handle the double '=' case
      84         259 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
      85         259 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]);
      86         259 :                 cb('=');
      87         259 :                 cb('=');
      88             :         }
      89        1150 : }
      90             : 
      91             : template <typename Callback>
      92        3050 : static void make_decode(const CoderSource &data, const Callback &cb) {
      93        3050 :         StringView inputBuffer((char *)data.data(), data.size());
      94        3050 :         auto length = inputBuffer.size();
      95             : 
      96        3050 :         size_t i = 0;
      97      222456 :         while (i < length) {
      98             :                 // Accumulate 4 valid characters (ignore everything else)
      99             :                 unsigned char accumulated[Base64Unit];
     100      219406 :                 size_t accumulateIndex = 0;
     101      884709 :                 while (i < length) {
     102      882475 :                         unsigned char decode = base64DecodeLookup[(unsigned char)inputBuffer[i++]];
     103      882475 :                         if (decode != xx) {
     104      874397 :                                 accumulated[accumulateIndex] = decode;
     105      874397 :                                 accumulateIndex++;
     106      874397 :                                 if (accumulateIndex == Base64Unit) {
     107      217172 :                                         break;
     108             :                                 }
     109             :                         }
     110             :                 }
     111             : 
     112      219406 :                 if(accumulateIndex >= 2)
     113      219381 :                         cb((accumulated[0] << 2) | (accumulated[1] >> 4));
     114      219406 :                 if(accumulateIndex >= 3)
     115      218463 :                         cb((accumulated[1] << 4) | (accumulated[2] >> 2));
     116      219406 :                 if(accumulateIndex >= 4)
     117      217172 :                         cb((accumulated[2] << 6) | accumulated[3]);
     118             :         }
     119        3050 : }
     120             : 
     121             : #undef xx
     122             : 
     123         125 : typename memory::PoolInterface::StringType __encode_pool(const CoderSource &source) {
     124         125 :         typename memory::PoolInterface::StringType output;
     125         125 :         output.reserve(encodeSize(source.size()));
     126         125 :         make_encode(source, [&] (const char &c) {
     127        2500 :                 output.push_back(c);
     128        2500 :         });
     129         125 :         return output;
     130           0 : }
     131         500 : typename memory::StandartInterface::StringType __encode_std(const CoderSource &source) {
     132         500 :         typename memory::StandartInterface::StringType output;
     133         500 :         output.reserve(encodeSize(source.size()));
     134         500 :         make_encode(source, [&] (const char &c) {
     135      234300 :                 output.push_back(c);
     136      234300 :         });
     137         500 :         return output;
     138           0 : }
     139             : 
     140             : template <>
     141         125 : auto encode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::StringType {
     142         125 :         return __encode_pool(source);
     143             : }
     144             : 
     145             : template <>
     146         500 : auto encode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::StringType {
     147         500 :         return __encode_std(source);
     148             : }
     149             : 
     150          25 : void encode(std::basic_ostream<char> &stream, const CoderSource &source) {
     151          25 :         make_encode(source, [&] (const char &c) {
     152         600 :                 stream << c;
     153         600 :         });
     154          25 : }
     155             : 
     156         450 : void encode(const Callback<void(char)> &cb, const CoderSource &source) {
     157         450 :         make_encode(source, cb);
     158         450 : }
     159             : 
     160          50 : size_t encode(char *buf, size_t bsize, const CoderSource &source) {
     161          50 :         size_t accum = 0;
     162          50 :         if (bsize < encodeSize(source.size())) {
     163          25 :                 make_encode(source, [&] (const char &c) {
     164         600 :                         if (accum < bsize) {
     165         250 :                                 buf[accum++] = c;
     166             :                         }
     167         600 :                 });
     168             :         } else {
     169          25 :                 make_encode(source, [&] (const char &c) {
     170         600 :                         buf[accum++] = c;
     171         600 :                 });
     172             :         }
     173          50 :         return accum;
     174             : }
     175             : 
     176        1125 : typename memory::PoolInterface::BytesType __decode_pool(const CoderSource &source) {
     177        1125 :         typename memory::PoolInterface::BytesType output;
     178        1125 :         output.reserve(encodeSize(source.size()));
     179        1125 :         make_decode(source, [&] (const uint8_t &c) {
     180       33150 :                 output.emplace_back(c);
     181       33150 :         });
     182        1125 :         return output;
     183           0 : }
     184        1575 : typename memory::StandartInterface::BytesType __decode_std(const CoderSource &source) {
     185        1575 :         typename memory::StandartInterface::BytesType output;
     186        1575 :         output.reserve(encodeSize(source.size()));
     187        1575 :         make_decode(source, [&] (const uint8_t &c) {
     188      541491 :                 output.emplace_back(c);
     189      541491 :         });
     190        1575 :         return output;
     191           0 : }
     192          50 : void decode(std::basic_ostream<char> &stream, const CoderSource &source) {
     193          50 :         make_decode(source, [&] (const uint8_t &c) {
     194         800 :                 stream << char(c);
     195         800 :         });
     196          50 : }
     197             : 
     198         200 : void decode(const Callback<void(uint8_t)> &cb, const CoderSource &source) {
     199         200 :         make_decode(source, cb);
     200         200 : }
     201             : 
     202         100 : size_t decode(uint8_t *buf, size_t bsize, const CoderSource &source) {
     203         100 :         size_t accum = 0;
     204         100 :         if (bsize < decodeSize(source.size())) {
     205          50 :                 make_decode(source, [&] (const uint8_t &c) {
     206         800 :                         if (accum < bsize) {
     207         500 :                                 buf[accum++] = c;
     208             :                         }
     209         800 :                 });
     210             :         } else {
     211          50 :                 make_decode(source, [&] (const uint8_t &c) {
     212         800 :                         buf[accum++] = c;
     213         800 :                 });
     214             :         }
     215         100 :         return accum;
     216             : }
     217             : 
     218             : }
     219             : 
     220             : namespace STAPPLER_VERSIONIZED stappler::base64url {
     221             : 
     222             : using Reader = BytesViewNetwork;
     223             : 
     224             : // Mapping from 6 bit pattern to ASCII character.
     225             : static const char * base64EncodeLookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
     226             : 
     227             : // Fundamental sizes of the binary and base64 encode/decode units in bytes
     228             : constexpr int BinaryUnit = 3;
     229             : constexpr int Base64Unit = 4;
     230             : 
     231             : template <typename Callback>
     232        6775 : static void make_encode(const CoderSource &data, const Callback &cb) {
     233        6775 :         Reader inputBuffer(data.data(), data.size());
     234        6775 :         auto length = inputBuffer.size();
     235             : 
     236        6775 :         size_t i = 0;
     237       60730 :         for (; i + BinaryUnit - 1 < length; i += BinaryUnit) {
     238             :                 // Inner loop: turn 48 bytes into 64 base64 characters
     239       53955 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
     240       53955 :                 cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
     241       53955 :                 cb(base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) | ((inputBuffer[i + 2] & 0xC0) >> 6)]);
     242       53955 :                 cb(base64EncodeLookup[inputBuffer[i + 2] & 0x3F]);
     243             :         }
     244             : 
     245        6775 :         if (i + 1 < length) {
     246             :                 // Handle the single '=' case
     247         541 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
     248         541 :                 cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
     249         541 :                 cb(base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]);
     250        6234 :         } else if (i < length) {
     251             :                 // Handle the double '=' case
     252         879 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
     253         879 :                 cb(base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]);
     254             :         }
     255        6775 : }
     256             : 
     257         675 : typename memory::PoolInterface::StringType __encode_pool(const CoderSource &source) {
     258         675 :         typename memory::PoolInterface::StringType output;
     259         675 :         output.reserve(encodeSize(source.size()));
     260         675 :         make_encode(source, [&] (const char &c) {
     261       21825 :                 output.push_back(c);
     262       21825 :         });
     263         675 :         return output;
     264           0 : }
     265        1125 : typename memory::StandartInterface::StringType __encode_std(const CoderSource &source) {
     266        1125 :         typename memory::StandartInterface::StringType output;
     267        1125 :         output.reserve(encodeSize(source.size()));
     268        1125 :         make_encode(source, [&] (const char &c) {
     269      117751 :                 output.push_back(c);
     270      117751 :         });
     271        1125 :         return output;
     272           0 : }
     273             : 
     274             : template <>
     275         675 : auto encode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::StringType {
     276         675 :         return __encode_pool(source);
     277             : }
     278             : 
     279             : template <>
     280        1125 : auto encode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::StringType {
     281        1125 :         return __encode_std(source);
     282             : }
     283             : 
     284          25 : void encode(std::basic_ostream<char> &stream, const CoderSource &source) {
     285          25 :         make_encode(source, [&] (const char &c) {
     286         550 :                 stream << c;
     287         550 :         });
     288          25 : }
     289             : 
     290        4900 : void encode(const Callback<void(char)> &cb, const CoderSource &source) {
     291        4900 :         make_encode(source, cb);
     292        4900 : }
     293             : 
     294          50 : size_t encode(char *buf, size_t bsize, const CoderSource &source) {
     295          50 :         size_t accum = 0;
     296          50 :         if (bsize < encodeSize(source.size())) {
     297          25 :                 make_encode(source, [&] (const char &c) {
     298         550 :                         if (accum < bsize) {
     299         250 :                                 buf[accum++] = c;
     300             :                         }
     301         550 :                 });
     302             :         } else {
     303          25 :                 make_encode(source, [&] (const char &c) {
     304         550 :                         buf[accum++] = c;
     305         550 :                 });
     306             :         }
     307          50 :         return accum;
     308             : }
     309             : 
     310             : }
     311             : 
     312             : namespace STAPPLER_VERSIONIZED stappler::base16 {
     313             : 
     314             : using Reader = BytesViewNetwork;
     315             : 
     316             : static const char* s_hexTable_lower[256] = {
     317             :     "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11",
     318             :     "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23",
     319             :     "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35",
     320             :     "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47",
     321             :     "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
     322             :     "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b",
     323             :     "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d",
     324             :     "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
     325             :     "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1",
     326             :     "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3",
     327             :     "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5",
     328             :     "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
     329             :     "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
     330             :     "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb",
     331             :     "fc", "fd", "fe", "ff"
     332             : };
     333             : 
     334             : static const char* s_hexTable_upper[256] = {
     335             :         "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11",
     336             :         "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23",
     337             :         "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31", "32", "33", "34", "35",
     338             :         "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45", "46", "47",
     339             :         "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
     340             :         "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B",
     341             :         "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D",
     342             :         "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
     343             :         "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1",
     344             :         "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3",
     345             :         "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5",
     346             :         "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
     347             :         "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9",
     348             :         "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB",
     349             :         "FC", "FD", "FE", "FF"
     350             : };
     351             : 
     352             : static uint8_t s_decTable[256] = {
     353             :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     354             :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
     355             :         0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     356             :         0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     357             :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     358             :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     359             :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     360             :         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     361             : };
     362             : 
     363          25 : size_t encodeSize(size_t length) { return length * 2; }
     364          25 : size_t decodeSize(size_t length) { return length / 2; }
     365             : 
     366         100 : const char *charToHex(const char &c, bool upper) {
     367         100 :         return upper ?  s_hexTable_upper[reinterpret_cast<const uint8_t &>(c)] : s_hexTable_lower[reinterpret_cast<const uint8_t &>(c)];
     368             : }
     369             : 
     370        3250 : uint8_t hexToChar(const char &c) {
     371        3250 :         return s_decTable[reinterpret_cast<const uint8_t &>(c)];
     372             : }
     373             : 
     374        1625 : uint8_t hexToChar(const char &c, const char &d) {
     375        1625 :         return (hexToChar(c) << 4) | hexToChar(d);
     376             : }
     377             : 
     378             : 
     379             : template <>
     380          25 : auto encode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::StringType {
     381          25 :         Reader inputBuffer(source.data(), source.size());
     382          25 :         const auto length = inputBuffer.size();
     383             : 
     384          25 :         memory::PoolInterface::StringType output; output.resize(length * 2);
     385         225 :         for (size_t i = 0; i < length; ++i) {
     386         200 :                 memcpy(output.data() + i * 2, s_hexTable_lower[inputBuffer[i]], 2);
     387             :         }
     388          50 :     return output;
     389           0 : }
     390             : 
     391             : template <>
     392         177 : auto encode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::StringType {
     393         177 :         Reader inputBuffer(source.data(), source.size());
     394         177 :         const auto length = inputBuffer.size();
     395             : 
     396         177 :         memory::StandartInterface::StringType output; output.reserve(length * 2);
     397        5047 :     for (size_t i = 0; i < length; ++i) {
     398        4870 :         output.append(s_hexTable_lower[inputBuffer[i]], 2);
     399             :     }
     400             : 
     401         354 :     return output;
     402           0 : }
     403             : 
     404          25 : void encode(std::basic_ostream<char> &stream, const CoderSource &source) {
     405          25 :         const auto length = source.size();
     406         425 :     for (size_t i = 0; i < length; ++i) {
     407         400 :         stream << s_hexTable_lower[source[i]];
     408             :     }
     409          25 : }
     410          25 : void encode(const Callback<void(char)> &cb, const CoderSource &source) {
     411          25 :         const auto length = source.size();
     412         425 :     for (size_t i = 0; i < length; ++i) {
     413         400 :         auto &t = s_hexTable_lower[source[i]];
     414         400 :         cb(t[0]);
     415         400 :         cb(t[1]);
     416             :     }
     417          25 : }
     418       17337 : size_t encode(char *buf, size_t bsize, const CoderSource &source) {
     419       17337 :         Reader inputBuffer(source.data(), source.size());
     420       17334 :         const auto length = inputBuffer.size();
     421             : 
     422       17334 :         size_t bytes = 0;
     423      156194 :     for (size_t i = 0; i < length; ++i) {
     424      138871 :         if (bytes + 2 <= bsize) {
     425      138871 :                 memcpy(buf + i * 2, s_hexTable_lower[inputBuffer[i]], 2);
     426      138860 :                 bytes += 2;
     427             :         } else {
     428           0 :                 break;
     429             :         }
     430             :     }
     431       17323 :     return bytes;
     432             : }
     433             : 
     434             : template <>
     435          25 : auto decode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::BytesType {
     436          25 :         const auto length = source.size();
     437          25 :         memory::PoolInterface::BytesType outputBuffer; outputBuffer.reserve(length / 2);
     438         425 :         for (size_t i = 0; i < length; i += 2) {
     439         400 :                 outputBuffer.push_back(
     440         400 :                                 (s_decTable[source[i]] << 4)
     441         400 :                                         | s_decTable[source[i + 1]]);
     442             :         }
     443          25 :         return outputBuffer;
     444           0 : }
     445             : 
     446             : template <>
     447        1175 : auto decode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::BytesType {
     448        1175 :         const auto length = source.size();
     449        1175 :         memory::StandartInterface::BytesType outputBuffer; outputBuffer.reserve(length / 2);
     450       61400 :         for (size_t i = 0; i < length; i += 2) {
     451       60225 :                 outputBuffer.push_back(
     452       60225 :                                 (s_decTable[source[i]] << 4)
     453       60225 :                                         | s_decTable[source[i + 1]]);
     454             :         }
     455        1175 :         return outputBuffer;
     456           0 : }
     457             : 
     458          25 : void decode(std::basic_ostream<char> &stream, const CoderSource &source) {
     459          25 :         const auto length = source.size();
     460             : 
     461         425 :         for (size_t i = 0; i < length; i += 2) {
     462             :                 stream << char(
     463         400 :                                 (s_decTable[source[i]] << 4)
     464         400 :                                         | s_decTable[source[i + 1]]);
     465             :         }
     466          25 : }
     467          25 : void decode(const Callback<void(uint8_t)> &cb, const CoderSource &source) {
     468          25 :         const auto length = source.size();
     469             : 
     470         425 :                 for (size_t i = 0; i < length; i += 2) {
     471         400 :                         cb(uint8_t(
     472         400 :                                         (s_decTable[source[i]] << 4)
     473         400 :                                                 | s_decTable[source[i + 1]]));
     474             :                 }
     475          25 : }
     476          25 : size_t decode(uint8_t *buf, size_t bsize, const CoderSource &source) {
     477          25 :         const auto length = source.size();
     478             : 
     479          25 :         size_t bytes = 0;
     480         425 :         for (size_t i = 0; i < length; i += 2) {
     481         400 :                 if (bytes + 1 <= bsize) {
     482         400 :                         buf[bytes] = uint8_t(
     483         400 :                                         (s_decTable[source[i]] << 4)
     484         400 :                                                 | s_decTable[source[i + 1]]);
     485         400 :                         ++ bytes;
     486             :                 } else {
     487           0 :                         break;
     488             :                 }
     489             :         }
     490          25 :         return bytes;
     491             : }
     492             : 
     493             : }

Generated by: LCOV version 1.14