KIO

udsentry.cpp
1 /*
2  This file is part of the KDE project
3  SPDX-FileCopyrightText: 2000-2005 David Faure <[email protected]>
4  SPDX-FileCopyrightText: 2007 Norbert Frese <[email protected]>
5  SPDX-FileCopyrightText: 2007 Thiago Macieira <[email protected]>
6  SPDX-FileCopyrightText: 2013-2014 Frank Reininghaus <[email protected]>
7 
8  SPDX-License-Identifier: LGPL-2.0-or-later
9 */
10 
11 #include "udsentry.h"
12 
13 #include <QString>
14 #include <QDataStream>
15 #include <QVector>
16 #include <QDebug>
17 
18 #include <KUser>
19 
20 using namespace KIO;
21 
22 //BEGIN UDSEntryPrivate
23 /* ---------- UDSEntryPrivate ------------ */
24 
25 class KIO::UDSEntryPrivate : public QSharedData
26 {
27 public:
28  void reserve(int size);
29  void insert(uint udsField, const QString &value);
30  void replace(uint udsField, const QString &value);
31  void insert(uint udsField, long long value);
32  void replace(uint udsField, long long value);
33  int count() const;
34  QString stringValue(uint udsField) const;
35  long long numberValue(uint udsField, long long defaultValue = -1) const;
36 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 8)
37  QList<uint> listFields() const;
38 #endif
39  QVector<uint> fields() const;
40  bool contains(uint udsField) const;
41  void clear();
42  void save(QDataStream &s) const;
43  void load(QDataStream &s);
44  void debugUDSEntry(QDebug &stream) const;
49  static QString nameOfUdsField(uint field);
50 
51 private:
52  struct Field
53  {
54  inline Field() {}
55  inline Field(const uint index, const QString &value) : m_str(value), m_index(index) {}
56  inline Field(const uint index, long long value = 0) : m_long(value), m_index(index) {}
57 
58  QString m_str;
59  long long m_long = LLONG_MIN;
60  uint m_index = 0;
61  };
62  std::vector<Field> storage;
63 };
64 
65 void UDSEntryPrivate::reserve(int size)
66 {
67  storage.reserve(size);
68 }
69 
70 void UDSEntryPrivate::insert(uint udsField, const QString &value)
71 {
72  Q_ASSERT(udsField & KIO::UDSEntry::UDS_STRING);
73  Q_ASSERT(std::find_if(storage.cbegin(), storage.cend(),
74  [udsField](const Field &entry) {return entry.m_index == udsField;}) == storage.cend());
75  storage.emplace_back(udsField, value);
76 }
77 
78 void UDSEntryPrivate::replace(uint udsField, const QString &value)
79 {
80  Q_ASSERT(udsField & KIO::UDSEntry::UDS_STRING);
81  auto it = std::find_if(storage.begin(), storage.end(),
82  [udsField](const Field &entry) {return entry.m_index == udsField;});
83  if (it != storage.end()) {
84  it->m_str = value;
85  return;
86  }
87  storage.emplace_back(udsField, value);
88 }
89 
90 void UDSEntryPrivate::insert(uint udsField, long long value)
91 {
92  Q_ASSERT(udsField & KIO::UDSEntry::UDS_NUMBER);
93  Q_ASSERT(std::find_if(storage.cbegin(), storage.cend(),
94  [udsField](const Field &entry) {return entry.m_index == udsField;}) == storage.cend());
95  storage.emplace_back(udsField, value);
96 }
97 
98 void UDSEntryPrivate::replace(uint udsField, long long value)
99 {
100  Q_ASSERT(udsField & KIO::UDSEntry::UDS_NUMBER);
101  auto it = std::find_if(storage.begin(), storage.end(),
102  [udsField](const Field &entry) {return entry.m_index == udsField;});
103  if (it != storage.end()) {
104  it->m_long = value;
105  return;
106  }
107  storage.emplace_back(udsField, value);
108 }
109 
110 int UDSEntryPrivate::count() const
111 {
112  return storage.size();
113 }
114 
115 QString UDSEntryPrivate::stringValue(uint udsField) const
116 {
117  auto it = std::find_if(storage.cbegin(), storage.cend(),
118  [udsField](const Field &entry) {return entry.m_index == udsField;});
119  if (it != storage.cend()) {
120  return it->m_str;
121  }
122  return QString();
123 }
124 
125 long long UDSEntryPrivate::numberValue(uint udsField, long long defaultValue) const
126 {
127  auto it = std::find_if(storage.cbegin(), storage.cend(),
128  [udsField](const Field &entry) {return entry.m_index == udsField;});
129  if (it != storage.cend()) {
130  return it->m_long;
131  }
132  return defaultValue;
133 }
134 
135 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 8)
136 QList<uint> UDSEntryPrivate::listFields() const
137 {
138  QList<uint> res;
139  res.reserve(storage.size());
140  for (const Field &field : storage) {
141  res.append(field.m_index);
142  }
143  return res;
144 }
145 #endif
146 
147 QVector<uint> UDSEntryPrivate::fields() const
148 {
149  QVector<uint> res;
150  res.reserve(storage.size());
151  for (const Field &field : storage) {
152  res.append(field.m_index);
153  }
154  return res;
155 }
156 
157 bool UDSEntryPrivate::contains(uint udsField) const
158 {
159  auto it = std::find_if(storage.cbegin(), storage.cend(),
160  [udsField](const Field &entry) {return entry.m_index == udsField;});
161  return (it != storage.cend());
162 }
163 
164 void UDSEntryPrivate::clear()
165 {
166  storage.clear();
167 }
168 
169 void UDSEntryPrivate::save(QDataStream &s) const
170 {
171  s << static_cast<quint32>(storage.size());
172 
173  for (const Field &field : storage) {
174  uint uds = field.m_index;
175  s << uds;
176 
177  if (uds & KIO::UDSEntry::UDS_STRING) {
178  s << field.m_str;
179  } else if (uds & KIO::UDSEntry::UDS_NUMBER) {
180  s << field.m_long;
181  } else {
182  Q_ASSERT_X(false, "KIO::UDSEntry", "Found a field with an invalid type");
183  }
184  }
185 }
186 
187 void UDSEntryPrivate::load(QDataStream &s)
188 {
189  clear();
190 
191  quint32 size;
192  s >> size;
193  reserve(size);
194 
195  // We cache the loaded strings. Some of them, like, e.g., the user,
196  // will often be the same for many entries in a row. Caching them
197  // permits to use implicit sharing to save memory.
198  static QVector<QString> cachedStrings;
199  if (quint32(cachedStrings.size()) < size) {
200  cachedStrings.resize(size);
201  }
202 
203  for (quint32 i = 0; i < size; ++i) {
204  quint32 uds;
205  s >> uds;
206 
207  if (uds & KIO::UDSEntry::UDS_STRING) {
208  // If the QString is the same like the one we read for the
209  // previous UDSEntry at the i-th position, use an implicitly
210  // shared copy of the same QString to save memory.
211  QString buffer;
212  s >> buffer;
213 
214  if (buffer != cachedStrings.at(i)) {
215  cachedStrings[i] = buffer;
216  }
217 
218  insert(uds, cachedStrings.at(i));
219  } else if (uds & KIO::UDSEntry::UDS_NUMBER) {
220  long long value;
221  s >> value;
222  insert(uds, value);
223  } else {
224  Q_ASSERT_X(false, "KIO::UDSEntry", "Found a field with an invalid type");
225  }
226  }
227 }
228 
229 QString UDSEntryPrivate::nameOfUdsField(uint field)
230 {
231  switch (field) {
232  case UDSEntry::UDS_SIZE:
233  return QStringLiteral("UDS_SIZE");
235  return QStringLiteral("UDS_SIZE_LARGE");
236  case UDSEntry::UDS_USER:
237  return QStringLiteral("UDS_USER");
239  return QStringLiteral("UDS_ICON_NAME");
240  case UDSEntry::UDS_GROUP:
241  return QStringLiteral("UDS_GROUP");
242  case UDSEntry::UDS_NAME:
243  return QStringLiteral("UDS_NAME");
245  return QStringLiteral("UDS_LOCAL_PATH");
247  return QStringLiteral("UDS_HIDDEN");
249  return QStringLiteral("UDS_ACCESS");
251  return QStringLiteral("UDS_MODIFICATION_TIME");
253  return QStringLiteral("UDS_ACCESS_TIME");
255  return QStringLiteral("UDS_CREATION_TIME");
257  return QStringLiteral("UDS_FILE_TYPE");
259  return QStringLiteral("UDS_LINK_DEST");
260  case UDSEntry::UDS_URL:
261  return QStringLiteral("UDS_URL");
263  return QStringLiteral("UDS_MIME_TYPE");
265  return QStringLiteral("UDS_GUESSED_MIME_TYPE");
267  return QStringLiteral("UDS_XML_PROPERTIES");
269  return QStringLiteral("UDS_EXTENDED_ACL");
271  return QStringLiteral("UDS_ACL_STRING");
273  return QStringLiteral("UDS_DEFAULT_ACL_STRING");
275  return QStringLiteral("UDS_DISPLAY_NAME");
277  return QStringLiteral("UDS_TARGET_URL");
279  return QStringLiteral("UDS_DISPLAY_TYPE");
281  return QStringLiteral("UDS_ICON_OVERLAY_NAMES");
283  return QStringLiteral("UDS_COMMENT");
285  return QStringLiteral("UDS_DEVICE_ID");
286  case UDSEntry::UDS_INODE:
287  return QStringLiteral("UDS_INODE");
288  case UDSEntry::UDS_EXTRA:
289  return QStringLiteral("UDS_EXTRA");
291  return QStringLiteral("UDS_EXTRA_END");
292  default:
293  return QStringLiteral("Unknown uds field %1").arg(field);
294  }
295 }
296 
297 void UDSEntryPrivate::debugUDSEntry(QDebug &stream) const
298 {
299  QDebugStateSaver saver(stream);
300  stream.nospace() << "[";
301  for (const Field &field : storage) {
302  stream << " " << nameOfUdsField(field.m_index) << "=";
303  if (field.m_index & KIO::UDSEntry::UDS_STRING) {
304  stream << field.m_str;
305  } else if (field.m_index & KIO::UDSEntry::UDS_NUMBER) {
306  stream << field.m_long;
307  } else {
308  Q_ASSERT_X(false, "KIO::UDSEntry", "Found a field with an invalid type");
309  }
310  }
311  stream << " ]";
312 }
313 //END UDSEntryPrivate
314 
315 //BEGIN UDSEntry
316 /* ---------- UDSEntry ------------ */
317 
318 UDSEntry::UDSEntry()
319  : d(new UDSEntryPrivate())
320 {
321 }
322 
323 // BUG: this API doesn't allow to handle symlinks correctly (we need buff from QT_LSTAT for most things, but buff from QT_STAT for st_mode and st_size)
324 UDSEntry::UDSEntry(const QT_STATBUF &buff, const QString &name)
325  : d(new UDSEntryPrivate())
326 {
327 #ifndef Q_OS_WIN
328  d->reserve(10);
329 #else
330  d->reserve(8);
331 #endif
332  d->insert(UDS_NAME, name);
333  d->insert(UDS_SIZE, buff.st_size);
334  d->insert(UDS_DEVICE_ID, buff.st_dev);
335  d->insert(UDS_INODE, buff.st_ino);
336  d->insert(UDS_FILE_TYPE, buff.st_mode & QT_STAT_MASK); // extract file type
337  d->insert(UDS_ACCESS, buff.st_mode & 07777); // extract permissions
338  d->insert(UDS_MODIFICATION_TIME, buff.st_mtime);
339  d->insert(UDS_ACCESS_TIME, buff.st_atime);
340 #ifndef Q_OS_WIN
341  d->insert(UDS_USER, KUser(buff.st_uid).loginName());
342  d->insert(UDS_GROUP, KUserGroup(buff.st_gid).name());
343 #endif
344 }
345 
346 UDSEntry::UDSEntry(const UDSEntry&) = default;
347 UDSEntry::~UDSEntry() = default;
348 UDSEntry::UDSEntry(UDSEntry&&) = default;
349 UDSEntry& UDSEntry::operator=(const UDSEntry&) = default;
351 
353 {
354  return d->stringValue(field);
355 }
356 
357 long long UDSEntry::numberValue(uint field, long long defaultValue) const
358 {
359  return d->numberValue(field, defaultValue);
360 }
361 
362 bool UDSEntry::isDir() const
363 {
364  return (numberValue(UDS_FILE_TYPE) & QT_STAT_MASK) == QT_STAT_DIR;
365 }
366 
367 bool UDSEntry::isLink() const
368 {
369  return !stringValue(UDS_LINK_DEST).isEmpty();
370 }
371 
372 void UDSEntry::reserve(int size)
373 {
374  d->reserve(size);
375 }
376 
377 void UDSEntry::fastInsert(uint field, const QString &value)
378 {
379  d->insert(field, value);
380 }
381 
382 void UDSEntry::fastInsert(uint field, long long value)
383 {
384  d->insert(field, value);
385 }
386 
387 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 48)
388 void UDSEntry::insert(uint field, const QString &value)
389 {
390  d->replace(field, value);
391 }
392 #endif
393 
394 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 48)
395 void UDSEntry::insert(uint field, long long value)
396 {
397  d->replace(field, value);
398 }
399 #endif
400 
401 void UDSEntry::replace(uint field, const QString &value)
402 {
403  d->replace(field, value);
404 }
405 
406 void UDSEntry::replace(uint field, long long value)
407 {
408  d->replace(field, value);
409 }
410 
411 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 8)
413 {
414  return d->listFields();
415 }
416 #endif
417 
419 {
420  return d->fields();
421 }
422 
423 int UDSEntry::count() const
424 {
425  return d->count();
426 }
427 
428 bool UDSEntry::contains(uint field) const
429 {
430  return d->contains(field);
431 }
432 
434 {
435  d->clear();
436 }
437 //END UDSEntry
438 
439 KIOCORE_EXPORT QDebug operator<<(QDebug stream, const KIO::UDSEntry &entry)
440 {
441  entry.d->debugUDSEntry(stream);
442  return stream;
443 }
444 
445 KIOCORE_EXPORT QDataStream &operator<<(QDataStream &s, const KIO::UDSEntry &a)
446 {
447  a.d->save(s);
448  return s;
449 }
450 
451 KIOCORE_EXPORT QDataStream &operator>>(QDataStream &s, KIO::UDSEntry &a)
452 {
453  a.d->load(s);
454  return s;
455 }
456 
457 KIOCORE_EXPORT bool operator==(const KIO::UDSEntry &entry, const KIO::UDSEntry &other)
458 {
459  if (entry.count() != other.count()) {
460  return false;
461  }
462 
463  const QVector<uint> fields = entry.fields();
464  for (uint field : fields) {
465  if (!other.contains(field)) {
466  return false;
467  }
468 
469  if (field & UDSEntry::UDS_STRING) {
470  if (entry.stringValue(field) != other.stringValue(field)) {
471  return false;
472  }
473  } else {
474  if (entry.numberValue(field) != other.numberValue(field)) {
475  return false;
476  }
477  }
478  }
479 
480  return true;
481 }
482 
483 KIOCORE_EXPORT bool operator!=(const KIO::UDSEntry &entry, const KIO::UDSEntry &other)
484 {
485  return !(entry == other);
486 }
An alternative URL (If different from the caption).
Definition: udsentry.h:277
XML properties, e.g. for WebDAV.
Definition: udsentry.h:285
Indicates that the field is a QString.
Definition: udsentry.h:222
bool isLink() const
Definition: udsentry.cpp:367
This file is a shortcut or mount, pointing to an URL in a different hierarchy.
Definition: udsentry.h:302
void clear()
remove all fields
Definition: udsentry.cpp:433
QString name() const
void append(const T &value)
Device number for this file, used to detect hardlinks.
Definition: udsentry.h:328
Universal Directory Service.
Definition: udsentry.h:77
The access control list serialized into a single string.
Definition: udsentry.h:290
A namespace for KIO globals.
Definition: authinfo.h:21
QList< uint > listFields() const
List all fields.
Definition: udsentry.cpp:412
void reserve(int alloc)
void insert(uint field, const QString &value)
insert field with string value
Definition: udsentry.cpp:388
The default access control list serialized into a single string.
Definition: udsentry.h:293
void reserve(int size)
Calling this function before inserting items into an empty UDSEntry may save time and memory...
Definition: udsentry.cpp:372
File type, part of the mode returned by stat (for a link, this returns the file type of the pointed i...
Definition: udsentry.h:268
bool isDir() const
Definition: udsentry.cpp:362
QDebug & nospace()
A local file path if the ioslave display files sitting on the local filesystem (but in another hierar...
Definition: udsentry.h:253
QVector< uint > fields() const
A vector of fields being present for the current entry.
Definition: udsentry.cpp:418
Treat the file as a hidden file (if set to 1) or as a normal file (if set to 0).
Definition: udsentry.h:256
27 was used by the now removed UDS_NEPOMUK_QUERY
Definition: udsentry.h:324
bool insert(Part *part, qint64 *insertId=nullptr)
User-readable type of file (if not specified, the mimetype&#39;s description is used) ...
Definition: udsentry.h:307
A mime type to be used for displaying only.
Definition: udsentry.h:283
void clear()
User ID of the file owner.
Definition: udsentry.h:235
KDEGAMES_EXPORT QAction * load(const QObject *recvr, const char *slot, QObject *parent)
int count() const
count fields
Definition: udsentry.cpp:423
void append(const T &value)
void resize(int size)
Extra data (used only if you specified Columns/ColumnsTypes) NB: you cannot repeat this entry; use UD...
Definition: udsentry.h:340
long long numberValue(uint field, long long defaultValue=0) const
Definition: udsentry.cpp:357
Extra data (used only if you specified Columns/ColumnsTypes) NB: you cannot repeat this entry; use UD...
Definition: udsentry.h:344
QString loginName() const
bool isEmpty() const const
The last time the file was opened. Required time format: seconds since UNIX epoch.
Definition: udsentry.h:262
QString stringValue(uint field) const
Definition: udsentry.cpp:352
const QList< QKeySequence > & save()
void replace(uint field, const QString &value)
Replace or insert field with string value.
Definition: udsentry.cpp:401
Inode number for this file, used to detect hardlinks.
Definition: udsentry.h:331
const QList< QKeySequence > & replace()
The last time the file was modified. Required time format: seconds since UNIX epoch.
Definition: udsentry.h:260
void reserve(int size)
25 was used by the now removed UDS_NEPOMUK_URI
Definition: udsentry.h:316
bool contains(uint field) const
check existence of a field
Definition: udsentry.cpp:428
void fastInsert(uint field, const QString &value)
insert field with string value, it will assert if the field is already inserted.
Definition: udsentry.cpp:377
~UDSEntry()
Destructor.
const T & at(int i) const const
Indicates that the field is a number (long long)
Definition: udsentry.h:224
Access permissions (part of the mode returned by stat)
Definition: udsentry.h:258
Filename - as displayed in directory listings etc.
Definition: udsentry.h:250
Name of the file where the link points to Allows to check for a symlink (don&#39;t use S_ISLNK !) ...
Definition: udsentry.h:271
The time the file was created. Required time format: seconds since UNIX epoch.
Definition: udsentry.h:264
Group ID of the file owner.
Definition: udsentry.h:240
void reserve(int size)
If set, contains the label to display instead of the &#39;real name&#39; in UDS_NAME.
Definition: udsentry.h:298
Indicates that the entry has extended ACL entries.
Definition: udsentry.h:288
A mime type; the slave should set it if it&#39;s known.
Definition: udsentry.h:279
int size() const const
UDSEntry & operator=(const UDSEntry &)
Copy assignment.
Size of the file.
Definition: udsentry.h:231
Name of the icon, that should be used for displaying.
Definition: udsentry.h:238
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Dec 3 2020 23:01:59 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.