summaryrefslogtreecommitdiff
path: root/daemon/unpacker.h
blob: 46e6d5773524166b5c3cfb73aed71493a888a002 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#ifndef UNPACKER_H
#define UNPACKER_H

#include <QtEndian>
#include <QByteArray>
#include <QString>
#include <QUuid>
#include <QVariantMap>
#include <QLoggingCategory>

class Unpacker
{
    static QLoggingCategory l;

public:
    Unpacker(const QByteArray &data);

    template <typename T>
    T read();

    template <typename T>
    T readLE();

    QByteArray readBytes(int n);

    QString readFixedString(int n);

    QUuid readUuid();

    QMap<int, QVariant> readDict();

    void skip(int n);

    bool bad() const;

private:
    const uchar * p();
    bool checkBad(int n = 0);

    const QByteArray &_buf;
    int _offset;
    bool _bad;
};

inline Unpacker::Unpacker(const QByteArray &data)
    : _buf(data), _offset(0), _bad(false)
{
}

template <typename T>
inline T Unpacker::read()
{
    if (checkBad(sizeof(T))) return 0;
    const uchar *u = p();
    _offset += sizeof(T);
    return qFromBigEndian<T>(u);
}

template <typename T>
inline T Unpacker::readLE()
{
    if (checkBad(sizeof(T))) return 0;
    const uchar *u = p();
    _offset += sizeof(T);
    return qFromLittleEndian<T>(u);
}

inline void Unpacker::skip(int n)
{
    _offset += n;
    checkBad();
}

inline bool Unpacker::bad() const
{
    return _bad;
}

inline const uchar * Unpacker::p()
{
    return reinterpret_cast<const uchar *>(&_buf.constData()[_offset]);
}

inline bool Unpacker::checkBad(int n)
{
    if (_offset + n > _buf.size()) {
        _bad = true;
    }
    return _bad;
}

#endif // UNPACKER_H