@@ -121,6 +121,7 @@ struct DDF_LoadRecord
121
121
{
122
122
AT_AtomIndex modelid;
123
123
AT_AtomIndex mfname;
124
+ uint32_t mfnameLowerCaseHash;
124
125
DDF_LoadState loadState;
125
126
};
126
127
@@ -166,6 +167,66 @@ static void DDF_UpdateItemHandles(std::vector<DeviceDescription> &descriptions,
166
167
static void DDF_TryCompileAndFixJavascript (QString *expr, const QString &path);
167
168
DeviceDescription DDF_LoadScripts (const DeviceDescription &ddf);
168
169
170
+ /*
171
+ * https://maskray.me/blog/2023-04-12-elf-hash-function
172
+ *
173
+ * PJW hash adapted from musl libc.
174
+ *
175
+ * TODO(mpi): make this a own module U_StringHash()
176
+ */
177
+ static uint32_t DDF_StringHash (const void *s0, unsigned size)
178
+ {
179
+ uint32_t h;
180
+ const unsigned char *s;
181
+
182
+ h = 0 ;
183
+ s = (const unsigned char *)s0;
184
+
185
+ while (size--)
186
+ {
187
+ h = 16 * h + *s++;
188
+ h ^= h >> 24 & 0xF0 ;
189
+ }
190
+ return h & 0xfffffff ;
191
+ }
192
+
193
+ /* ! Helper to create a 32-bit string hash from an atom string.
194
+
195
+ This is mainly used to get a unique number to compare case insensitive manufacturer names.
196
+ For example for "HEIMAN", "heiman" and "Heiman" atoms this function returns the same hash.
197
+ */
198
+ static uint32_t DDF_AtomLowerCaseStringHash (AT_AtomIndex ati)
199
+ {
200
+ unsigned len;
201
+ AT_Atom atom;
202
+ char str[192 ];
203
+
204
+ str[0 ] = ' \0 ' ;
205
+ atom = AT_GetAtomByIndex (ati);
206
+
207
+ if (atom.len == 0 )
208
+ return 0 ;
209
+
210
+ if (sizeof (str) <= atom.len ) // should not happen
211
+ return DDF_StringHash (atom.data , atom.len );
212
+
213
+ for (len = 0 ; len < atom.len ; len++)
214
+ {
215
+ uint8_t ch = atom.data [len];
216
+
217
+ if (ch & 0x80 ) // non ASCII UTF-8 string, don't bother
218
+ return DDF_StringHash (atom.data , atom.len );
219
+
220
+ if (ch >= ' A' && ch <= ' Z' )
221
+ ch += (unsigned char )(' a' - ' A' );
222
+
223
+ str[len] = (char )ch;
224
+ }
225
+
226
+ str[len] = ' \0 ' ;
227
+ return DDF_StringHash (str, len);
228
+ }
229
+
169
230
/* ! Constructor. */
170
231
DeviceDescriptions::DeviceDescriptions (QObject *parent) :
171
232
QObject(parent),
@@ -861,6 +922,7 @@ void DeviceDescriptions::prepare()
861
922
{
862
923
DDF_LoadRecord rec;
863
924
rec.mfname .index = res[i].mfnameAtomIndex ;
925
+ rec.mfnameLowerCaseHash = DDF_AtomLowerCaseStringHash (rec.mfname );
864
926
rec.modelid .index = res[i].modelIdAtomIndex ;
865
927
rec.loadState = DDF_LoadStateScheduled;
866
928
records.push_back (rec);
@@ -1089,6 +1151,8 @@ const DeviceDescription &DeviceDescriptions::get(const Resource *resource, DDF_M
1089
1151
U_ASSERT (modelidAtomIndex != 0 );
1090
1152
U_ASSERT (mfnameAtomIndex != 0 );
1091
1153
1154
+ uint32_t mfnameLowerCaseHash = DDF_AtomLowerCaseStringHash (AT_AtomIndex{mfnameAtomIndex});
1155
+
1092
1156
/*
1093
1157
* Filter matching DDFs, there can be multiple entries for the same modelid and manufacturer name.
1094
1158
* Further sorting for the 'best' match according to attr/ddf_policy is done afterwards.
@@ -1098,7 +1162,7 @@ const DeviceDescription &DeviceDescriptions::get(const Resource *resource, DDF_M
1098
1162
1099
1163
for (;matchedCount < matchedIndices.size ();)
1100
1164
{
1101
- i = std::find_if (i, d->descriptions .end (), [modelidAtomIndex, mfnameAtomIndex](const DeviceDescription &ddf)
1165
+ i = std::find_if (i, d->descriptions .end (), [modelidAtomIndex, mfnameAtomIndex, mfnameLowerCaseHash ](const DeviceDescription &ddf)
1102
1166
{
1103
1167
if (ddf.mfnameAtomIndices .size () != ddf.modelidAtomIndices .size ())
1104
1168
{
@@ -1107,8 +1171,16 @@ const DeviceDescription &DeviceDescriptions::get(const Resource *resource, DDF_M
1107
1171
1108
1172
for (size_t j = 0 ; j < ddf.modelidAtomIndices .size (); j++)
1109
1173
{
1110
- if (ddf.modelidAtomIndices [j] == modelidAtomIndex && ddf.mfnameAtomIndices [j] == mfnameAtomIndex)
1111
- return true ;
1174
+ if (ddf.modelidAtomIndices [j] == modelidAtomIndex)
1175
+ {
1176
+ if (ddf.mfnameAtomIndices [j] == mfnameAtomIndex) // exact manufacturer name match
1177
+ return true ;
1178
+
1179
+ // tolower() manufacturer name match
1180
+ uint32_t mfnameLowerCaseHash2 = DDF_AtomLowerCaseStringHash (AT_AtomIndex{ddf.mfnameAtomIndices [j]});
1181
+ if (mfnameLowerCaseHash == mfnameLowerCaseHash2)
1182
+ return true ;
1183
+ }
1112
1184
}
1113
1185
1114
1186
return false ;
@@ -1378,12 +1450,19 @@ bool DeviceDescriptions::loadDDFAndBundlesFromDisc(const Resource *resource)
1378
1450
return false ;
1379
1451
}
1380
1452
1453
+ uint32_t mfnameLowerCaseHash = DDF_AtomLowerCaseStringHash (AT_AtomIndex{mfnameAtomIndex});
1454
+
1381
1455
for (const DDF_LoadRecord &loadRecord : d->ddfLoadRecords )
1382
1456
{
1383
- if (loadRecord.mfname . index == mfnameAtomIndex && loadRecord.modelid .index == modelidAtomIndex)
1457
+ if (loadRecord.mfnameLowerCaseHash == mfnameLowerCaseHash && loadRecord.modelid .index == modelidAtomIndex)
1384
1458
{
1385
1459
return false ; // been here before
1386
1460
}
1461
+
1462
+ if (loadRecord.mfname .index == mfnameAtomIndex && loadRecord.modelid .index == modelidAtomIndex)
1463
+ {
1464
+ return false ; // been here before, note this check can likely be removed due the lower case check already been hit
1465
+ }
1387
1466
}
1388
1467
1389
1468
DBG_Printf (DBG_DDF, " try load DDF from disc for %s -- %s\n " , mfnameItem->toCString (), modelidItem->toCString ());
@@ -1392,6 +1471,7 @@ bool DeviceDescriptions::loadDDFAndBundlesFromDisc(const Resource *resource)
1392
1471
DDF_LoadRecord loadRecord;
1393
1472
loadRecord.modelid .index = modelidAtomIndex;
1394
1473
loadRecord.mfname .index = mfnameAtomIndex;
1474
+ loadRecord.mfnameLowerCaseHash = mfnameLowerCaseHash;
1395
1475
loadRecord.loadState = DDF_LoadStateScheduled;
1396
1476
d->ddfLoadRecords .push_back (loadRecord);
1397
1477
@@ -2166,6 +2246,7 @@ void DeviceDescriptions::readAllRawJson()
2166
2246
{
2167
2247
AT_AtomIndex mfnameIndex;
2168
2248
AT_AtomIndex modelidIndex;
2249
+ uint32_t mfnameLowerCaseHash = 0 ;
2169
2250
2170
2251
mfnameIndex.index = 0 ;
2171
2252
modelidIndex.index = 0 ;
@@ -2190,6 +2271,10 @@ void DeviceDescriptions::readAllRawJson()
2190
2271
continue ;
2191
2272
}
2192
2273
}
2274
+ else
2275
+ {
2276
+ mfnameLowerCaseHash = DDF_AtomLowerCaseStringHash (mfnameIndex);
2277
+ }
2193
2278
}
2194
2279
2195
2280
{
@@ -2204,12 +2289,12 @@ void DeviceDescriptions::readAllRawJson()
2204
2289
{
2205
2290
if (modelidIndex.index == d->ddfLoadRecords [k].modelid .index )
2206
2291
{
2207
- if (mfnameIndex. index == 0 )
2292
+ if (mfnameLowerCaseHash == 0 )
2208
2293
{
2209
2294
// ignore for now, in worst case we load a DDF to memory which isn't used
2210
2295
U_ASSERT (0 );
2211
2296
}
2212
- else if (mfnameIndex. index != d->ddfLoadRecords [k].mfname . index )
2297
+ else if (mfnameLowerCaseHash != d->ddfLoadRecords [k].mfnameLowerCaseHash )
2213
2298
{
2214
2299
continue ;
2215
2300
}
@@ -2521,14 +2606,16 @@ static int DDF_IsBundleScheduled(DDF_ParseContext *pctx, const char *desc, unsig
2521
2606
if (!foundAtoms)
2522
2607
continue ;
2523
2608
2609
+ uint32_t mfnameLowerCaseHash = DDF_AtomLowerCaseStringHash (mfname_ati);
2610
+
2524
2611
for (size_t j = 0 ; j < ddfLoadRecords.size (); j++)
2525
2612
{
2526
2613
const DDF_LoadRecord &rec = ddfLoadRecords[j];
2527
2614
2528
- if (rec.mfname .index != mfname_ati .index )
2615
+ if (rec.modelid .index != modelid_ati .index )
2529
2616
continue ;
2530
2617
2531
- if (rec.modelid . index != modelid_ati. index )
2618
+ if (rec.mfnameLowerCaseHash != mfnameLowerCaseHash )
2532
2619
continue ;
2533
2620
2534
2621
return 1 ;
@@ -2569,12 +2656,13 @@ void DeviceDescriptions::reloadAllRawJsonAndBundles(const Resource *resource)
2569
2656
const ResourceItem *modelidItem = resource->item (RAttrModelId);
2570
2657
unsigned mfnameAtomIndex = mfnameItem->atomIndex ();
2571
2658
unsigned modelidAtomIndex = modelidItem->atomIndex ();
2659
+ uint32_t mfnameLowerCaseHash = DDF_AtomLowerCaseStringHash (AT_AtomIndex{mfnameAtomIndex});
2572
2660
2573
2661
for (size_t j = 0 ; j < d_ptr2->ddfLoadRecords .size (); j++)
2574
2662
{
2575
2663
DDF_LoadRecord &rec = d_ptr2->ddfLoadRecords [j];
2576
2664
2577
- if (rec.mfname . index != mfnameAtomIndex )
2665
+ if (rec.mfnameLowerCaseHash != mfnameLowerCaseHash )
2578
2666
continue ;
2579
2667
2580
2668
if (rec.modelid .index != modelidAtomIndex)
0 commit comments