File indexing completed on 2024-05-05 17:57:58

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