9#include "ksycocadict_p.h"
10#include "ksycocaentry.h"
11#include "sycocadebug.h"
23 , length(_key.length())
25 , key(keyStr.unicode())
32 const QChar *
const key;
37class KSycocaDictPrivate
52 qint32 offsetForKey(
const QString &key)
const;
55 quint32 hashKey(
const QString &key)
const;
57 std::vector<std::unique_ptr<string_entry>> m_stringentries;
60 quint32 hashTableSize;
64KSycocaDict::KSycocaDict()
65 : d(new KSycocaDictPrivate)
69KSycocaDict::KSycocaDict(
QDataStream *str,
int offset)
70 : d(new KSycocaDictPrivate)
77 str->
device()->seek(offset);
78 (*str) >> test1 >> test2;
79 if ((test1 > 0x000fffff) || (test2 > 1024)) {
86 str->
device()->seek(offset);
87 (*str) >> d->hashTableSize;
88 (*str) >> d->hashList;
89 d->offset = str->
device()->pos();
92KSycocaDict::~KSycocaDict() =
default;
103 d->m_stringentries.push_back(std::make_unique<string_entry>(key, payload));
106void KSycocaDict::remove(
const QString &key)
112 auto it = std::find_if(d->m_stringentries.begin(), d->m_stringentries.end(), [&key](
const std::unique_ptr<string_entry> &entry) {
113 return entry->keyStr == key;
116 if (it != d->m_stringentries.end()) {
117 d->m_stringentries.erase(it);
119 qCDebug(SYCOCA) <<
"key not found:" << key;
123int KSycocaDict::find_string(
const QString &key)
const
128 qint32 offset = d->offsetForKey(key);
142 d->stream->device()->seek(offset);
146 (*d->stream) >> offset;
151 (*d->stream) >> dupkey;
164 qint32 offset = d->offsetForKey(key);
171 offsetList.
append(offset);
178 d->stream->device()->seek(offset);
182 (*d->stream) >> offset;
187 (*d->stream) >> dupkey;
190 offsetList.
append(offset);
196uint KSycocaDict::count()
const
202 return d->m_stringentries.
size();
205void KSycocaDict::clear()
210uint KSycocaDictPrivate::hashKey(
const QString &key)
const
215 for (
int i = 0; i < hashList.
count(); i++) {
216 int pos = hashList[i];
219 }
else if (pos < 0) {
222 h = ((h * 13) + (key[len - pos].cell() % 29)) & 0x3ffffff;
227 h = ((h * 13) + (key[pos].cell() % 29)) & 0x3ffffff;
249static int calcDiversity(std::vector<std::unique_ptr<string_entry>> *stringlist,
int inPos, uint sz)
262 for (
const auto &entryPtr : *stringlist) {
263 const int rpos = entryPtr->length - pos;
265 const uint hash = ((entryPtr->hash * 13) + (entryPtr->key[rpos].cell() % 29)) & 0x3ffffff;
266 matrix.setBit(hash % sz,
true);
273 for (
const auto &entryPtr : *stringlist) {
274 if (pos < entryPtr->length) {
275 const uint hash = ((entryPtr->hash * 13) + (entryPtr->key[pos].cell() % 29)) & 0x3ffffff;
276 matrix.setBit(hash % sz,
true);
282 return matrix.count(
true);
287static void addDiversity(std::vector<std::unique_ptr<string_entry>> *stringlist,
int pos)
295 for (
auto &entryPtr : *stringlist) {
296 const int rpos = entryPtr->length - pos;
298 entryPtr->hash = ((entryPtr->hash * 13) + (entryPtr->key[rpos].cell() % 29)) & 0x3fffffff;
303 for (
auto &entryPtr : *stringlist) {
304 if (pos < entryPtr->length) {
305 entryPtr->hash = ((entryPtr->hash * 13) + (entryPtr->key[pos].cell() % 29)) & 0x3fffffff;
314 d->hashTableSize = 0;
316 str << d->hashTableSize;
329 for (
auto &entryPtr : d->m_stringentries) {
331 if (entryPtr->length > maxLength) {
332 maxLength = entryPtr->length;
341 unsigned int sz = count() * 4 + 1;
342 while (!(((sz % 3) && (sz % 5) && (sz % 7) && (sz % 11) && (sz % 13)))) {
375 for (
int pos = -maxLength; pos <= maxLength; ++pos) {
377 if (oldvec[pos + maxLength] < mindiv) {
378 oldvec[pos + maxLength] = 0;
382 const int diversity = calcDiversity(&(d->m_stringentries), pos, sz);
383 if (diversity > maxDiv) {
387 oldvec[pos + maxLength] = diversity;
393 mindiv = (3 * divsum) / (4 * divnum);
396 if (maxDiv <= lastDiv) {
401 addDiversity(&(d->m_stringentries), maxPos);
402 d->hashList.append(maxPos);
405 for (
auto &entryPtr : d->m_stringentries) {
406 entryPtr->hash = d->hashKey(entryPtr->keyStr);
410 d->hashTableSize = sz;
414 struct hashtable_entry {
417 qint64 duplicate_offset;
420 hashtable_entry *hashTable =
new hashtable_entry[sz];
423 for (
unsigned int i = 0; i < sz; i++) {
424 hashTable[i].entry =
nullptr;
425 hashTable[i].duplicates =
nullptr;
429 for (
const auto &entryPtr : d->m_stringentries) {
431 const int hash = entryPtr->hash % sz;
432 if (!hashTable[hash].entry) {
434 hashTable[hash].entry = entryPtr.get();
436 if (!hashTable[hash].duplicates) {
439 hashTable[hash].duplicates->append(hashTable[hash].entry);
440 hashTable[hash].duplicate_offset = 0;
442 hashTable[hash].duplicates->append(entryPtr.get());
446 str << d->hashTableSize;
455 for (
int pass = 1; pass <= 2; pass++) {
458 for (uint i = 0; i < d->hashTableSize; i++) {
460 if (!hashTable[i].entry) {
462 }
else if (!hashTable[i].duplicates) {
463 tmpid = hashTable[i].entry->payload->offset();
465 tmpid = -hashTable[i].duplicate_offset;
473 for (uint i = 0; i < d->hashTableSize; i++) {
476 hashTable[i].duplicate_offset = str.
device()->
pos();
480 for (string_entry *dup : std::as_const(*dups)) {
481 const qint32 offset = dup->payload->offset();
483 const QString storageId = dup->payload->storageId();
484 qCDebug(SYCOCA) <<
"about to assert! dict=" <<
this <<
"storageId=" << storageId << dup->payload.
data();
485 if (dup->payload->isType(KST_KService)) {
487 qCDebug(SYCOCA) << service->storageId() << service->entryPath();
492 QByteArray(
"entry offset is 0, save() was not called on " + dup->payload->storageId().toLatin1()
493 +
" entryPath=" + dup->payload->entryPath().toLatin1())
506 for (uint i = 0; i < d->hashTableSize; i++) {
507 delete hashTable[i].duplicates;
512qint32 KSycocaDictPrivate::offsetForKey(
const QString &key)
const
514 if (!stream || !offset) {
515 qCWarning(SYCOCA) <<
"No ksycoca database available! Tried running" << KBUILDSYCOCA_EXENAME <<
"?";
519 if (hashTableSize == 0) {
524 const uint hash = hashKey(key) % hashTableSize;
527 const qint64 off = offset +
sizeof(qint32) * hash;
532 (*stream) >> retOffset;
Represents an installed application.
static void flagError()
A read error occurs.
const char * constData() const const
QIODevice * device() const const
virtual qint64 pos() const const
virtual bool seek(qint64 pos)
void append(QList< T > &&value)
qsizetype count() const const
qsizetype size() const const
bool isEmpty() const const
qsizetype length() const const