summaryrefslogtreecommitdiff
path: root/daemon/unpacker.cpp
blob: e904db89294f670099155b0148b02a85858e0daa (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
#include "unpacker.h"
#include "watchconnector.h"

QByteArray Unpacker::readBytes(int n)
{
    if (checkBad(n)) return QByteArray();
    const char *u = &_buf.constData()[_offset];
    _offset += n;
    return QByteArray(u, n);
}

QString Unpacker::readFixedString(int n)
{
    if (checkBad(n)) return QString();
    const char *u = &_buf.constData()[_offset];
    _offset += n;
    return QString::fromUtf8(u, strnlen(u, n));
}

QUuid Unpacker::readUuid()
{
    if (checkBad(16)) return QString();
    _offset += 16;
    return QUuid::fromRfc4122(_buf.mid(_offset - 16, 16));
}

QMap<int, QVariant> Unpacker::readDict()
{
    QMap<int, QVariant> d;
    if (checkBad(1)) return d;

    const int n = readLE<quint8>();

    for (int i = 0; i < n; i++) {
        if (checkBad(4 + 1 + 2)) return d;
        const int key = readLE<qint32>(); // For some reason, this is little endian.
        const int type = readLE<quint8>();
        const int width = readLE<quint16>();

        switch (type) {
        case WatchConnector::typeBYTES:
            d.insert(key, QVariant::fromValue(readBytes(width)));
            break;
        case WatchConnector::typeSTRING:
            d.insert(key, QVariant::fromValue(readFixedString(width)));
            break;
        case WatchConnector::typeUINT:
            switch (width) {
            case sizeof(quint8):
                d.insert(key, QVariant::fromValue(readLE<quint8>()));
                break;
            case sizeof(quint16):
                d.insert(key, QVariant::fromValue(readLE<quint16>()));
                break;
            case sizeof(quint32):
                d.insert(key, QVariant::fromValue(readLE<quint32>()));
                break;
            default:
                _bad = true;
                return d;
            }

            break;
        case WatchConnector::typeINT:
            switch (width) {
            case sizeof(qint8):
                d.insert(key, QVariant::fromValue(readLE<qint8>()));
                break;
            case sizeof(qint16):
                d.insert(key, QVariant::fromValue(readLE<qint16>()));
                break;
            case sizeof(qint32):
                d.insert(key, QVariant::fromValue(readLE<qint32>()));
                break;
            default:
                _bad = true;
                return d;
            }

            break;
        default:
            _bad = true;
            return d;
        }
    }

    return d;
}