Beispiel #1
0
QVariant Message::parseValue(QIODevice &data, const quint8 wireType,
                             const Types::ScalarType scalarType,
                             const QString &tagPath) const
{
    // A small sanity check. In this case, the wireType will take precedence.
    if ((scalarType != Types::Unknown) &&
        (wireType != Types::LengthDelimeted) &&
        (wireType != Types::getWireType(scalarType))) {
        qWarning() << tagPath << "wire type" << wireType << "does not match "
            "expected wire type" << Types::getWireType(scalarType) << "for "
            "scalar type" << scalarType;
    }

    switch (wireType) {
    case Types::Varint: // int32, int64, uint32, uint64, sint32, sint64, bool, enum.
        switch (scalarType) {
        case Types::Int32:      return parseStandardVarint(data);
        case Types::Int64:      return parseStandardVarint(data);
        case Types::Uint32:     return parseUnsignedVarint(data);
        case Types::Uint64:     return parseUnsignedVarint(data);
        case Types::Sint32:     return parseSignedVarint(data);
        case Types::Sint64:     return parseSignedVarint(data);
        case Types::Bool:       return parseStandardVarint(data);
        case Types::Enumerator: return parseStandardVarint(data);
        default:                return parseStandardVarint(data);
        }
        break;
    case Types::SixtyFourBit: // fixed64, sfixed64, double.
        switch (scalarType) {
        case Types::Fixed64:  return parseFixedNumber<quint64>(data);
        case Types::Sfixed64: return parseFixedNumber<qint64>(data);
        case Types::Double:   return parseFixedNumber<double>(data);
        default:              return data.read(8); // The raw 8-byte sequence.
        }
        break;
    case Types::LengthDelimeted: // string, bytes, embedded messages, packed repeated fields.
        return parseLengthDelimitedValue(data, scalarType, tagPath);
    case Types::StartGroup: // deprecated.
        return parse(data, tagPath + pathSeparator);
    case Types::EndGroup: // deprecated.
        return QVariant(); // Caller will need to end the group started previously.
    case Types::ThirtyTwoBit: // fixed32, sfixed32, float.
        switch (scalarType) {
        case Types::Fixed32:  return parseFixedNumber<quint32>(data);
        case Types::Sfixed32: return parseFixedNumber<qint32>(data);
        case Types::Float:    return parseFixedNumber<float>(data);
        default:              return data.read(4); // The raw 4-byte sequence.
        }
        break;
    }
    qWarning() << "invalid wireType:" << wireType << "(tagPath:" << tagPath << ')';
    return QVariant();
}
Beispiel #2
0
QPair<quint32, quint8> Message::parseTagAndType(QIODevice &data) const
{
    QVariant tagAndType = parseUnsignedVarint(data);
    return tagAndType.isValid()
        ? QPair<quint32, quint8>(tagAndType.toULongLong() >> 3, tagAndType.toULongLong() & 0x07)
        : QPair<quint32, quint8>(0, 0);
}
Beispiel #3
0
QVariant parseStandardVarint(QIODevice &data)
{
    const QVariant variant = parseUnsignedVarint(data);
    if (!variant.isValid()) {
        return QVariant();
    }
    return static_cast<qint64>(variant.toULongLong());
}
Beispiel #4
0
QVariant parseSignedVarint(QIODevice &data)
{
    const QVariant variant = parseUnsignedVarint(data);
    if (!variant.isValid()) {
        return QVariant();
    }
    const quint64 result = variant.toULongLong();
    return static_cast<qint64>(result >> 1) * ((result & 0x1) ? -1 : 1) + ((result & 0x1) ? -1 : 0);
}
Beispiel #5
0
QVariant Message::readLengthDelimitedValue(QIODevice &data) const
{
    // Note: We're assuming length-delimited values use unsigned varints for lengths.
    // I haven't found any Protocl Buffers documentation to support / dispute this.
    const QVariant length = parseUnsignedVarint(data);
    if (!length.isValid()) {
        qWarning() << "failed to read prefix-delimited length";
        return QVariant();
    }
    const QByteArray value = data.read(length.toULongLong());
    return (value.length() == length.toInt()) ? value : QVariant();
}
Beispiel #6
0
QVariantList parseUnsignedVarints(QIODevice &data, int maxItems)
{
    QVariantList list;
    for (; (maxItems < 0) || (list.size() < maxItems);) {
        const QVariant item = parseUnsignedVarint(data);
        if (item.isValid()) {
            list << item;
        } else {
            maxItems = 0;
        }
    }
    return list;
}
Beispiel #7
0
QVariant parseUnsignedVarint(QByteArray data)
{
    QBuffer buffer(&data);
    buffer.open(QIODevice::ReadOnly);
    return parseUnsignedVarint(buffer);
}