File indexing completed on 2024-05-19 05:56:08

0001 /*
0002     This file is part of the Okteta Core library, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2004, 2011 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 "hexadecimalbytecodec.hpp"
0010 
0011 // Qt
0012 #include <QString>
0013 
0014 namespace Okteta {
0015 
0016 static constexpr QChar upperCaseDigits[16] =
0017 {   // '0',        '1',           '2',           '3',
0018     QChar(0x0030), QChar(0x0031), QChar(0x0032), QChar(0x0033),
0019     // '4',        '5',           '6',           '7',
0020     QChar(0x0034), QChar(0x0035), QChar(0x0036), QChar(0x0037),
0021     // '8',        '9',           'A',           'B',
0022     QChar(0x0038), QChar(0x0039), QChar(0x0041), QChar(0x0042),
0023     // 'C',        'D',           'E',           'F'
0024     QChar(0x0043), QChar(0x0044), QChar(0x0045), QChar(0x0046),
0025 };
0026 static constexpr QChar lowerCaseDigits[16] =
0027 {   // '0',        '1',           '2',           '3',
0028     QChar(0x0030), QChar(0x0031), QChar(0x0032), QChar(0x0033),
0029     // '4',        '5',           '6',           '7',
0030     QChar(0x0034), QChar(0x0035), QChar(0x0036), QChar(0x0037),
0031     // '8',        '9',           'a',           'b',
0032     QChar(0x0038), QChar(0x0039), QChar(0x0061), QChar(0x0062),
0033     // 'c',        'd',           'e',           'f'
0034     QChar(0x0063), QChar(0x0064), QChar(0x0065), QChar(0x0066),
0035 };
0036 static constexpr Byte hexadecimalDigitsFilledLimit = 16;
0037 
0038 HexadecimalByteCodec::HexadecimalByteCodec(bool useLowerCaseDigits)
0039     : mDigits(useLowerCaseDigits ? lowerCaseDigits : upperCaseDigits)
0040 {
0041 }
0042 
0043 bool HexadecimalByteCodec::setLowerCaseDigits(bool useLowerCaseDigits)
0044 {
0045     const QChar* const digits = useLowerCaseDigits ? lowerCaseDigits : upperCaseDigits;
0046 
0047     if (digits == mDigits) {
0048         return false;
0049     }
0050 
0051     mDigits = digits;
0052     return true;
0053 }
0054 
0055 bool HexadecimalByteCodec::isLowerCaseDigits() const { return mDigits == lowerCaseDigits; }
0056 
0057 unsigned int HexadecimalByteCodec::encodingWidth() const { return 2; }
0058 Byte HexadecimalByteCodec::digitsFilledLimit() const { return hexadecimalDigitsFilledLimit; }
0059 
0060 void HexadecimalByteCodec::encode(QString* digits, unsigned int pos, Byte byte) const
0061 {
0062     const int minSizeNeeded = pos + 2;
0063     if (digits->size() < minSizeNeeded) {
0064         digits->resize(minSizeNeeded);
0065     }
0066 
0067     (*digits)[pos++] = mDigits[byte >> 4];
0068     (*digits)[pos] = mDigits[byte & 0x0F];
0069 }
0070 
0071 void HexadecimalByteCodec::encodeShort(QString* digits, unsigned int pos, Byte byte) const
0072 {
0073     const int encodingLength = (byte > 0xF) ? 2 : 1;
0074     const int minSizeNeeded = pos + encodingLength;
0075     if (digits->size() < minSizeNeeded) {
0076         digits->resize(minSizeNeeded);
0077     }
0078 
0079     unsigned char digitValue = byte >> 4;
0080 
0081     if (digitValue > 0) {
0082         (*digits)[pos++] = mDigits[digitValue];
0083     }
0084     (*digits)[pos] = mDigits[byte & 0x0F];
0085 }
0086 
0087 static inline constexpr bool isValidBigDigit(unsigned char digit)
0088 {
0089     return ('A' <= digit && digit <= 'F');
0090 }
0091 
0092 static inline constexpr bool isValidSmallDigit(unsigned char digit)
0093 {
0094     return ('a' <= digit && digit <= 'f');
0095 }
0096 
0097 static inline constexpr bool isValidDecimalDigit(unsigned char digit)
0098 {
0099     return ('0' <= digit && digit <= '9');
0100 }
0101 
0102 bool HexadecimalByteCodec::isValidDigit(unsigned char digit) const
0103 {
0104     return isValidDecimalDigit(digit) || isValidBigDigit(digit) || isValidSmallDigit(digit);
0105 }
0106 
0107 bool HexadecimalByteCodec::turnToValue(unsigned char* digit) const
0108 {
0109     if (isValidDecimalDigit(*digit)) {
0110         *digit -= '0';
0111     } else if (isValidBigDigit(*digit)) {
0112         *digit -= 'A' - 10;
0113     } else if (isValidSmallDigit(*digit)) {
0114         *digit -= 'a' - 10;
0115     } else {
0116         return false;
0117     }
0118 
0119     return true;
0120 }
0121 
0122 bool HexadecimalByteCodec::appendDigit(Byte* byte, unsigned char digit) const
0123 {
0124     if (turnToValue(&digit)) {
0125         Byte _byte = *byte;
0126         if (_byte < hexadecimalDigitsFilledLimit) {
0127             _byte <<= 4;
0128             _byte += digit;
0129             *byte = _byte;
0130             return true;
0131         }
0132     }
0133     return false;
0134 }
0135 
0136 void HexadecimalByteCodec::removeLastDigit(Byte* byte) const
0137 {
0138     *byte >>= 4;
0139 }
0140 
0141 }