QEdidParser: optimize the hardcoded EDID vendor table

Instead of using an array of fixed-length strings for the vendor names,
use qOffsetStringArray instead. This removes the need of using the
longest vendor name length as the size of the fixed-length strings,
which results in a massive waste of space. This saves 150KB of
(readonly) data.

Details: there are 2555 entries, each one hardcoded to be 78 byte long,
for a total of 199290 bytes. However the vendor names themselves amount
only to 50658 bytes.

Making all this data optional on desktop Linux (where the vendor data is
present anyhow on the system, in /usr/share/) is left for a future
change.

Change-Id: I17007865e741e3dab15dd2ab2feffbce4664fb37
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Giuseppe D'Angelo 2024-12-18 22:51:57 +01:00
parent 8d0283ad2c
commit 6844c70ae9
3 changed files with 7746 additions and 2493 deletions

View File

@ -124,20 +124,20 @@ bool QEdidParser::parse(const QByteArray &blob)
if (manufacturer.isEmpty()) {
// Find the manufacturer from the vendor lookup table
const auto compareVendorId = [](const VendorTable &vendor, const char *str)
const auto compareVendorId = [](const QEdidVendorId &vendor, const char *str)
{
return strncmp(vendor.id, str, 3) < 0;
};
const auto b = std::begin(q_edidVendorTable);
const auto e = std::end(q_edidVendorTable);
const auto b = std::begin(q_edidVendorIds);
const auto e = std::end(q_edidVendorIds);
auto it = std::lower_bound(b,
e,
pnpId,
compareVendorId);
if (it != e && strncmp(it->id, pnpId, 3) == 0)
manufacturer = QString::fromUtf8(it->name);
manufacturer = QString::fromUtf8(q_edidVendorNames + q_edidVendorNamesOffsets[it - b]);
}
// If we don't know the manufacturer, fallback to PNP ID

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,14 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import urllib.request
import sys
# The original source for this data used to be
# 'https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids'
# which is discontinued. For now there seems to be a fork at:
url = 'https://github.com/vcrhonek/hwdata/raw/master/pnp.ids'
# REUSE-IgnoreStart
copyright = """
// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
copyright = """// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
# REUSE-IgnoreEnd
@ -37,43 +37,89 @@ header = """
//
#include <QtCore/private/qglobal_p.h>
#include <QtCore/qtypes.h>
#include <iterator>
QT_BEGIN_NAMESPACE
"""
struct VendorTable {
vendorIdHeader = """struct QEdidVendorId {
const char id[4];
const char name[%d];
};
static const VendorTable q_edidVendorTable[] = {"""
static constexpr QEdidVendorId q_edidVendorIds[] = {"""
footer = """};
vendorIdFooter = """};
"""
vendorNameHeader = """static constexpr char q_edidVendorNames[] = {"""
vendorNameFooter = """};
"""
vendorNameOffsetHeader = """static constexpr %s q_edidVendorNamesOffsets[] = {"""
vendorNameOffsetFooter = """};
"""
footer = """static_assert(std::size(q_edidVendorIds) == std::size(q_edidVendorNamesOffsets));
QT_END_NAMESPACE
#endif // QEDIDVENDORTABLE_P_H"""
# Actual script begins here
vendors = {}
max_vendor_length = 0
vendorNameTotalLength = 0
response = urllib.request.urlopen(url)
data = response.read().decode('utf-8')
for line in data.split('\n'):
l = line.split()
if line.startswith('#'):
continue
elif len(l) == 0:
elif len(line) == 0:
continue
else:
pnp_id = l[0].upper()
vendors[pnp_id] = ' '.join(l[1:])
if len(vendors[pnp_id]) > max_vendor_length:
max_vendor_length = len(vendors[pnp_id])
l = line.split('\t', 1)
if len(l) == 0:
continue
pnp_id = l[0].upper()
if len(pnp_id) != 3:
sys.exit("Id '%s' is non-conforming" % pnp_id)
vendors[pnp_id] = l[1]
vendorNameTotalLength += len(l[1]) + 1
sortedVendorKeys = sorted(vendors.keys())
print(copyright)
print(notice)
print(header % (max_vendor_length + 1))
for pnp_id in sorted(vendors.keys()):
print(' { "%s", "%s" },' % (pnp_id, vendors[pnp_id]))
print(header)
print(vendorIdHeader)
print(*[(' { "%s" }' % pnp_id) for pnp_id in sortedVendorKeys], sep=",\n")
print(vendorIdFooter)
print(vendorNameHeader)
print(*[(' "%s\\0"' % vendors[pnp_id]) for pnp_id in sortedVendorKeys], sep="\n")
print(vendorNameFooter)
if vendorNameTotalLength < 2**16:
print(vendorNameOffsetHeader % "quint16")
elif vendorNameTotalLength < 2**32:
print(vendorNameOffsetHeader % "quint32")
else:
sys.exit("Vendor name table is too big")
currentOffset = 0
for pnp_id in sortedVendorKeys:
vendor = vendors[pnp_id]
print(' %d,' % currentOffset)
currentOffset += len(vendor) + 1
print(vendorNameOffsetFooter)
print(footer)