File indexing completed on 2025-01-19 05:20:18

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2009-2010 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "bytearraybase64streamencoder.hpp"
0010 
0011 // Okteta core
0012 #include <Okteta/AbstractByteArrayModel>
0013 // KF
0014 #include <KLocalizedString>
0015 // Qt
0016 #include <QTextStream>
0017 
0018 namespace Kasten {
0019 
0020 const char base64EncodeMap[64] = {
0021     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
0022     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
0023     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
0024     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
0025     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
0026     'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
0027     'w', 'x', 'y', 'z', '0', '1', '2', '3',
0028     '4', '5', '6', '7', '8', '9', '+', '/'
0029 };
0030 
0031 static constexpr const char* base64PaddingData[2] = {
0032     "==",
0033     "="
0034 };
0035 static inline constexpr const char* base64Padding(ByteArrayBase64StreamEncoder::InputByteIndex index)
0036 {
0037     return base64PaddingData[static_cast<int>(index) - 1];
0038 }
0039 
0040 ByteArrayBase64StreamEncoder::ByteArrayBase64StreamEncoder()
0041     : AbstractByteArrayStreamEncoder(i18nc("name of the encoding target", "Base64"), QStringLiteral("application/base64"))
0042 {}
0043 
0044 ByteArrayBase64StreamEncoder::~ByteArrayBase64StreamEncoder() = default;
0045 
0046 bool ByteArrayBase64StreamEncoder::encodeDataToStream(QIODevice* device,
0047                                                       const ByteArrayView* byteArrayView,
0048                                                       const Okteta::AbstractByteArrayModel* byteArrayModel,
0049                                                       const Okteta::AddressRange& range)
0050 {
0051     Q_UNUSED(byteArrayView);
0052 
0053     bool success = true;
0054 
0055     // encode
0056     QTextStream textStream(device);
0057 
0058     // prepare
0059     InputByteIndex inputByteIndex = InputByteIndex::First;
0060     int outputGroupsPerLine = 0;
0061     unsigned char bitsFromLastByte;
0062 
0063     for (Okteta::Address i = range.start(); i <= range.end(); ++i) {
0064         const Okteta::Byte byte = byteArrayModel->byte(i);
0065 
0066         switch (inputByteIndex)
0067         {
0068         case InputByteIndex::First:
0069             // bits 7..2
0070             textStream << base64EncodeMap[(byte >> 2)];
0071             // bits 1..0 -> 5..4 for next
0072             bitsFromLastByte = (byte & 0x3) << 4;
0073             inputByteIndex = InputByteIndex::Second;
0074             break;
0075         case InputByteIndex::Second:
0076             // from last and bits 7..4 as 3..0 from this
0077             textStream << base64EncodeMap[(bitsFromLastByte | byte >> 4)];
0078             // bits 3..0 -> 5..2 for next
0079             bitsFromLastByte = (byte & 0xf) << 2;
0080             inputByteIndex = InputByteIndex::Third;
0081             break;
0082         case InputByteIndex::Third:
0083             // from last and bits 7..6 as 1..0 from this
0084             textStream << base64EncodeMap[(bitsFromLastByte | byte >> 6)];
0085             // bits 5..0
0086             textStream << base64EncodeMap[(byte & 0x3F)];
0087             inputByteIndex = InputByteIndex::First;
0088             ++outputGroupsPerLine;
0089             if (outputGroupsPerLine >= maxOutputGroupsPerLine && i < range.end()) {
0090                 textStream << "\r\n";
0091                 outputGroupsPerLine = 0;
0092             }
0093             break;
0094         }
0095     }
0096 
0097     const bool hasBitsLeft = (inputByteIndex != InputByteIndex::First);
0098     if (hasBitsLeft) {
0099         textStream << base64EncodeMap[bitsFromLastByte]
0100                    << base64Padding(inputByteIndex);
0101     }
0102 
0103     return success;
0104 }
0105 
0106 }
0107 
0108 #include "moc_bytearraybase64streamencoder.cpp"