Wayland 协议解析工具代码(Qt 将wayland协议转换为C++接口,我把函数功能也识别进去,更方便通过生成的文件阅读wayland协议)

/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
#include <QDebug>

enum Option {
    ClientHeader,
    ServerHeader,
    ClientCode,
    ServerCode
} option;

bool isServerSide()
{
    return option == ServerHeader || option == ServerCode;
}

bool isHeader()
{
    return option == ClientHeader || option == ServerHeader;
}

QByteArray protocolName;

bool parseOption(const char *str, Option *option)
{
    if (str == QLatin1String("client-header"))
        *option = ClientHeader;
    else if (str == QLatin1String("server-header"))
        *option = ServerHeader;
    else if (str == QLatin1String("client-code"))
        *option = ClientCode;
    else if (str == QLatin1String("server-code"))
        *option = ServerCode;
    else
        return false;

    return true;
}

struct WaylandEnumEntry {
    QByteArray name;
    QByteArray value;
    QByteArray summary;
};

struct WaylandEnum {
    QByteArray name;

    QList<WaylandEnumEntry> entries;
};

struct WaylandArgument {
    QByteArray name;
    QByteArray type;
    QByteArray interface;
    QByteArray summary;
    bool allowNull;
};

struct WaylandEvent {
    bool request;
    QByteArray name;
    QByteArray type;
    QByteArray summary;
    QByteArray describe;
    QList<WaylandArgument> arguments;
};

struct WaylandInterface {
    QByteArray name;
    int version;
    QByteArray summary;
    QByteArray describe;

    QList<WaylandEnum> enums;
    QList<WaylandEvent> events;
    QList<WaylandEvent> requests;
};

QByteArray byteArrayValue(const QXmlStreamReader &xml, const char *name)
{
    if (xml.attributes().hasAttribute(name))
        return xml.attributes().value(name).toUtf8();
    return QByteArray();
}

int intValue(const QXmlStreamReader &xml, const char *name, int defaultValue = 0)
{
    bool ok;
    int result = byteArrayValue(xml, name).toInt(&ok);
    return ok ? result : defaultValue;
}

bool boolValue(const QXmlStreamReader &xml, const char *name)
{
    return byteArrayValue(xml, name) == "true";
}

WaylandEvent readEvent(QXmlStreamReader &xml, bool request)
{
    WaylandEvent event;
    event.request = request;
    event.name = byteArrayValue(xml, "name");
    event.type = byteArrayValue(xml, "type");

    while (xml.readNextStartElement()) {
        if (xml.name() == "arg") {
            WaylandArgument argument;
            argument.name = byteArrayValue(xml, "name");
            argument.type = byteArrayValue(xml, "type");
            argument.interface = byteArrayValue(xml, "interface");
            argument.summary = byteArrayValue(xml, "summary");
            argument.allowNull = boolValue(xml, "allowNull");
            event.arguments << argument;
        } else if (xml.name() == "description") {
            event.summary = byteArrayValue(xml, "summary");
            event.describe = xml.readElementText().toLatin1();
            continue;
        }
        xml.skipCurrentElement();
    }
    return event;
}

WaylandEnum readEnum(QXmlStreamReader &xml)
{
    WaylandEnum result;
    result.name = byteArrayValue(xml, "name");

    while (xml.readNextStartElement()) {
        if (xml.name() == "entry") {
            WaylandEnumEntry entry;
            entry.name = byteArrayValue(xml, "name");
            entry.value = byteArrayValue(xml, "value");
            entry.summary = byteArrayValue(xml, "summary");
            result.entries << entry;
        }

        xml.skipCurrentElement();
    }

    return result;
}

WaylandInterface readInterface(QXmlStreamReader &xml)
{
    WaylandInterface interface;
    interface.name = byteArrayValue(xml, "name");
    interface.version = intValue(xml, "version", 1);

    while (xml.readNextStartElement()) {
        if (xml.name() == "event")
            interface.events << readEvent(xml, false);
        else if (xml.name() == "request")
            interface.requests << readEvent(xml, true);
        else if (xml.name() == "enum")
            interface.enums << readEnum(xml);
        else if (xml.name() == "description") {
            interface.summary = byteArrayValue(xml, "summary");
            interface.describe = xml.readElementText().toLatin1();
            continue;
        } else
            xml.skipCurrentElement();
    }

    return interface;
}

QByteArray waylandToCType(const QByteArray &waylandType, const QByteArray &interface)
{
    if (waylandType == "string")
        return "const char *";
    else if (waylandType == "int")
        return "int32_t";
    else if (waylandType == "uint")
        return "uint32_t";
    else if (waylandType == "fixed")
        return "wl_fixed_t";
    else if (waylandType == "fd")
        return "int32_t";
    else if (waylandType == "array")
        return "wl_array *";
    else if (waylandType == "object" || waylandType == "new_id") {
        if (isServerSide())
            return "struct ::wl_resource *";
        if (interface.isEmpty())
            return "struct ::wl_object *";
        return "struct ::" + interface + " *";
    }
    return waylandType;
}

QByteArray waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray)
{
    if (waylandType == "string")
        return "const QString &";
    else if (waylandType == "array")
        return cStyleArray ? "wl_array *" : "const QByteArray &";
    else
        return waylandToCType(waylandType, interface);
}

const WaylandArgument *newIdArgument(const QList<WaylandArgument> &arguments)
{
    for (int i = 0; i < arguments.size(); ++i) {
        if (arguments.at(i).type == "new_id")
            return &arguments.at(i);
    }
    return 0;
}

void printInterfaceDescribe(const WaylandInterface &interface)
{
    if (isHeader()) {
        printf("\t/* |||| %s: event count is %d, request count is %d. \n",
               interface.name.data(), interface.events.size(), interface.requests.size());

        QList<QByteArray> depends;
        depends.append(interface.name);
        for (int i = 0; i < interface.events.size(); ++i)
        {
            const WaylandEvent &e = interface.events.at(i);
            for (int j = 0; j < e.arguments.size(); ++j)
            {
                if (!e.arguments.at(j).interface.trimmed().isEmpty()
                        && !depends.contains(e.arguments.at(j).interface))
                {
                    depends.append(e.arguments.at(j).interface);
                }
            }
        }
        for (int i = 0; i < interface.requests.size(); ++i)
        {
            const WaylandEvent &e = interface.requests.at(i);
            for (int j = 0; j < e.arguments.size(); ++j)
            {
                if (!e.arguments.at(j).interface.trimmed().isEmpty()
                        && !depends.contains(e.arguments.at(j).interface))
                {
                    depends.append(e.arguments.at(j).interface);
                }
            }
        }
        depends.takeFirst();
        printf("\t*  |||| Depend on interface: %s. \n", depends.join(',').data());
        printf("\t* \n");
        QList<QByteArray> summary;
        summary = interface.summary.split('\n');
        for (int i = 0; i < summary.size(); ++i) {
            if (i == 0) {
                printf("\t* Summary: %s\n", summary.at(i).data());
            } else {
                printf("\t* %s\n", summary.at(i).data());
            }
        }

        QList<QByteArray>  describe = interface.describe.split('\n');
        for (int i = 0; i < describe.size(); ++i) {
            printf("\t* %s\n", describe.at(i).data());
        }
        printf("\t*/\n");
    }
}

void printEventDescribe(const WaylandEvent &e)
{
    if (isHeader()) {
        QList<QByteArray> summary;
        summary = e.summary.split('\n');
        printf("\t\t/* |||| %s %s\n", e.name.data(), e.request ? "is a request!":"is a event!");
        printf("\t\t* \n");
        for (int i = 0; i < summary.size(); ++i) {
            if (i == 0) {
                printf("\t\t* Summary: %s\n", summary.at(i).data());
            } else {
                printf("\t\t* %s\n", summary.at(i).data());
            }
        }

        QList<QByteArray>  describe = e.describe.split('\n');
        QByteArray returnArray;
        for (int i = 0; i < e.arguments.size(); ++i) {
            const WaylandArgument &a = e.arguments.at(i);
            if (a.type == "new_id") {
                if (e.request) {
                    if (a.name == "id") {
                        returnArray = "@return (void *) " + a.summary;
                    } else {
                        returnArray = "@return (wl_" + a.name + ") " + a.summary;
                    }
                } else {
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值