/****************************************************************************
**
** 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 {
Wayland 协议解析工具代码(Qt 将wayland协议转换为C++接口,我把函数功能也识别进去,更方便通过生成的文件阅读wayland协议)
最新推荐文章于 2024-02-26 10:56:50 发布