File indexing completed on 2024-11-24 04:45:06

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "kitinerary_export.h"
0010 
0011 #include <QByteArray>
0012 
0013 #include <cstdint>
0014 
0015 class QIODevice;
0016 
0017 namespace KItinerary {
0018 
0019 /** BER/DER/X.690 encoding classes and functions. */
0020 namespace BER {
0021 
0022 /**
0023  * An element in BER/DER/X.690 encoding.
0024  * Implicitly this is also kinda implementing a QByteArrayRef, as this works without copying
0025  * the underlying data.
0026  */
0027 class KITINERARY_EXPORT Element
0028 {
0029 public:
0030     Element();
0031     explicit Element(const QByteArray &data, int offset = 0, int size = -1);
0032     ~Element();
0033 
0034     /** Returns @c true if this element has a valid structure and can be read from. */
0035     bool isValid() const;
0036 
0037     /** Type, "right-aligned" in the returned 32bit value. */
0038     uint32_t type() const;
0039 
0040     /** Size of the entire element (type, size and content). */
0041     int size() const;
0042     /** Raw data of this element.
0043      *  Typically only needed when copying/writing this element somewhere.
0044      */
0045     const char* rawData() const;
0046 
0047     /** Size of the value part of this element.
0048      *  This is excluding a possible variable length end marker.
0049      */
0050     int contentSize() const;
0051     /** Raw content data. */
0052     const uint8_t* contentData() const;
0053 
0054     /** Convenience method to access typed content. */
0055     template <typename T>
0056     inline const T* contentAt(int offset = 0) const
0057     {
0058         if (offset < 0 || (int)sizeof(T) > contentSize() - offset) {
0059             return nullptr;
0060         }
0061         return reinterpret_cast<const T*>(contentData() + offset);
0062     }
0063 
0064     /** First child element, for nested types. */
0065     Element first() const;
0066     /** Next child element, for nested types. */
0067     Element next() const;
0068     /** Returns the first child element of the given @p type. */
0069     Element find(uint32_t type) const;
0070 
0071     /** Writes the given size in BER encoding to @p out. */
0072     static void writeSize(QIODevice *out, int size);
0073 
0074 private:
0075     int typeSize() const;
0076     int lengthSize() const;
0077     int contentOffset() const;
0078 
0079     QByteArray m_data;
0080     int m_offset = -1;
0081     int m_dataSize = -1;
0082 };
0083 
0084 template <uint32_t TagValue>
0085 class TypedElement : public Element
0086 {
0087 public:
0088     using Element::Element;
0089     inline bool isValid() const
0090     {
0091         return Element::isValid() && type() == TagValue;
0092     }
0093 };
0094 
0095 }
0096 }
0097