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"