File indexing completed on 2024-12-29 04:51:01
0001 /* 0002 SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 0006 #include "protobufstreamreader.h" 0007 0008 #include <QDebug> 0009 0010 using namespace KItinerary; 0011 0012 ProtobufStreamReader::ProtobufStreamReader() = default; 0013 0014 ProtobufStreamReader::ProtobufStreamReader(std::string_view data) 0015 : m_data(data) 0016 { 0017 } 0018 0019 ProtobufStreamReader::ProtobufStreamReader(const QByteArray &data) 0020 : m_ownedData(data) 0021 , m_data(std::string_view(data.constData(), data.size())) 0022 { 0023 } 0024 0025 ProtobufStreamReader::~ProtobufStreamReader() = default; 0026 0027 uint64_t ProtobufStreamReader::readVarint() 0028 { 0029 uint64_t result = 0; 0030 int shift = 0; 0031 while (m_cursor < m_data.size()) { 0032 const uint64_t b = m_data[m_cursor++]; 0033 result |= (b & 0b0111'1111) << shift; 0034 if ((b & 0b1000'0000) == 0) { 0035 break; 0036 } 0037 shift += 7; 0038 } 0039 0040 return result; 0041 } 0042 0043 uint64_t ProtobufStreamReader::peekVarint() 0044 { 0045 auto prevCursor = m_cursor; 0046 const auto result = readVarint(); 0047 m_cursor = prevCursor; 0048 return result; 0049 } 0050 0051 quint64 ProtobufStreamReader::fieldNumber() 0052 { 0053 return peekVarint() >> 3; 0054 } 0055 0056 ProtobufStreamReader::WireType ProtobufStreamReader::wireType() 0057 { 0058 return static_cast<WireType>(peekVarint() & 0b111); 0059 } 0060 0061 quint64 ProtobufStreamReader::readVarintField() 0062 { 0063 readVarint(); // skip field number and wire type 0064 return readVarint(); 0065 } 0066 0067 std::string_view ProtobufStreamReader::readLengthDelimitedRecord() 0068 { 0069 if (wireType() != LEN) { 0070 return {}; 0071 } 0072 readVarint(); // skip field number and wire type 0073 const auto len = readVarint(); 0074 if (m_cursor + len <= m_data.size()) { 0075 auto data = m_data.substr(m_cursor, len); 0076 m_cursor += len; 0077 return data; 0078 } 0079 return {}; 0080 } 0081 0082 QString ProtobufStreamReader::readString() 0083 { 0084 const auto data = readLengthDelimitedRecord(); 0085 return QString::fromUtf8(data.data(), data.size()); 0086 } 0087 0088 ProtobufStreamReader ProtobufStreamReader::readSubMessage() 0089 { 0090 return ProtobufStreamReader(readLengthDelimitedRecord()); 0091 } 0092 0093 bool ProtobufStreamReader::atEnd() const 0094 { 0095 return m_cursor >= m_data.size(); 0096 } 0097 0098 void ProtobufStreamReader::skip() 0099 { 0100 switch (wireType()) { 0101 case VARINT: 0102 readVarintField(); 0103 break; 0104 case LEN: 0105 readLengthDelimitedRecord(); 0106 break; 0107 case I64: 0108 case I32: 0109 case SGROUP: 0110 case EGROUP: 0111 qWarning() << "encountered deprecated or unsupported protobuf wire type!" << wireType(); 0112 m_cursor = m_data.size(); 0113 break; 0114 } 0115 } 0116 0117 #include "moc_protobufstreamreader.cpp"