1 /**************************************************************************** 2 ** 3 ** DQt - D bindings for the Qt Toolkit 4 ** 5 ** GNU Lesser General Public License Usage 6 ** This file may be used under the terms of the GNU Lesser 7 ** General Public License version 3 as published by the Free Software 8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 9 ** packaging of this file. Please review the following information to 10 ** ensure the GNU Lesser General Public License version 3 requirements 11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 12 ** 13 ****************************************************************************/ 14 module qt.core.datastream; 15 extern(C++): 16 17 import qt.config; 18 import qt.helpers; 19 version(QT_NO_DATASTREAM){}else 20 { 21 import qt.core.bytearray; 22 import qt.core.global; 23 import qt.core.iodevice; 24 import qt.core.scopedpointer; 25 import qt.core.sysinfo; 26 } 27 28 /+ #ifdef Status 29 #error qdatastream.h must be included before any header file that defines Status 30 #endif 31 32 33 class qfloat16; 34 class QByteArray; 35 class QIODevice; 36 37 template <typename T> class QList; 38 template <typename T> class QVector; 39 template <typename T> class QSet; 40 template <class Key, class T> class QHash; 41 template <class Key, class T> class QMap; +/ 42 43 version(QT_NO_DATASTREAM){}else 44 { 45 extern(C++, class) struct QDataStreamPrivate; 46 /+ namespace QtPrivate { 47 class StreamStateSaver; 48 } +/ 49 extern(C++, class) struct /+ Q_CORE_EXPORT +/ QDataStream 50 { 51 public: 52 enum Version { 53 Qt_1_0 = 1, 54 Qt_2_0 = 2, 55 Qt_2_1 = 3, 56 Qt_3_0 = 4, 57 Qt_3_1 = 5, 58 Qt_3_3 = 6, 59 Qt_4_0 = 7, 60 Qt_4_1 = Version.Qt_4_0, 61 Qt_4_2 = 8, 62 Qt_4_3 = 9, 63 Qt_4_4 = 10, 64 Qt_4_5 = 11, 65 Qt_4_6 = 12, 66 Qt_4_7 = Version.Qt_4_6, 67 Qt_4_8 = Version.Qt_4_7, 68 Qt_4_9 = Version.Qt_4_8, 69 Qt_5_0 = 13, 70 Qt_5_1 = 14, 71 Qt_5_2 = 15, 72 Qt_5_3 = Version.Qt_5_2, 73 Qt_5_4 = 16, 74 Qt_5_5 = Version.Qt_5_4, 75 Qt_5_6 = 17, 76 Qt_5_7 = Version.Qt_5_6, 77 Qt_5_8 = Version.Qt_5_7, 78 Qt_5_9 = Version.Qt_5_8, 79 Qt_5_10 = Version.Qt_5_9, 80 Qt_5_11 = Version.Qt_5_10, 81 Qt_5_12 = 18, 82 Qt_5_13 = 19, 83 Qt_5_14 = Version.Qt_5_13, 84 /+ #if QT_VERSION >= 0x050f00 +/ 85 Qt_5_15 = Version.Qt_5_14, 86 Qt_DefaultCompiledVersion = Version.Qt_5_15 87 /+ #elif QT_VERSION >= 0x060000 88 Qt_6_0 = Qt_5_15, 89 Qt_DefaultCompiledVersion = Qt_6_0 90 #else 91 Qt_DefaultCompiledVersion = Qt_5_14 92 #endif 93 #if QT_VERSION >= 0x060100 94 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion 95 #endif +/ 96 } 97 98 enum ByteOrder { 99 BigEndian = QSysInfo.Endian.BigEndian, 100 LittleEndian = QSysInfo.Endian.LittleEndian 101 } 102 103 enum Status { 104 Ok, 105 ReadPastEnd, 106 ReadCorruptData, 107 WriteFailed 108 } 109 110 enum FloatingPointPrecision { 111 SinglePrecision, 112 DoublePrecision 113 } 114 115 @disable this(); 116 pragma(mangle, defaultConstructorMangling(__traits(identifier, typeof(this)))) 117 ref typeof(this) rawConstructor(); 118 static typeof(this) create() 119 { 120 typeof(this) r = typeof(this).init; 121 r.rawConstructor(); 122 return r; 123 } 124 125 /+ explicit +/this(QIODevice ); 126 this(QByteArray* , QIODevice.OpenMode flags); 127 this(ref const(QByteArray) ); 128 ~this(); 129 130 pragma(inline, true) QIODevice device() const 131 { return cast(QIODevice)dev; } 132 void setDevice(QIODevice ); 133 /+ #if QT_DEPRECATED_SINCE(5, 13) +/ 134 /+ QT_DEPRECATED_X("Use QDataStream::setDevice(nullptr) instead") +/ 135 void unsetDevice(); 136 /+ #endif +/ 137 138 bool atEnd() const; 139 140 Status status() const; 141 void setStatus(Status status); 142 void resetStatus(); 143 144 FloatingPointPrecision floatingPointPrecision() const; 145 void setFloatingPointPrecision(FloatingPointPrecision precision); 146 147 pragma(inline, true) ByteOrder byteOrder() const 148 /+pragma(inline, true) QDataStream.ByteOrder byteOrder() const+/ 149 { return byteorder; } 150 void setByteOrder(ByteOrder); 151 152 pragma(inline, true) int version_() const 153 { return ver; } 154 pragma(inline, true) void setVersion(int v) 155 { ver = v; } 156 157 /+ref QDataStream operator >>(ref qint8 i);+/ 158 /+pragma(inline, true) ref QDataStream operator >>(ref quint8 i) 159 { return this >> reinterpret_cast!(ref qint8)(i); }+/ 160 /+ref QDataStream operator >>(ref qint16 i);+/ 161 /+pragma(inline, true) ref QDataStream operator >>(ref quint16 i) 162 { return this >> reinterpret_cast!(ref qint16)(i); }+/ 163 /+ref QDataStream operator >>(ref qint32 i);+/ 164 /+pragma(inline, true) ref QDataStream operator >>(ref quint32 i) 165 { return this >> reinterpret_cast!(ref qint32)(i); }+/ 166 /+ref QDataStream operator >>(ref qint64 i);+/ 167 /+pragma(inline, true) ref QDataStream operator >>(ref quint64 i) 168 { return this >> reinterpret_cast!(ref qint64)(i); }+/ 169 /+ref QDataStream operator >>(ref /+ std:: +/nullptr_t ptr) { ptr = null; return this; }+/ 170 171 /+ref QDataStream operator >>(ref bool i);+/ 172 /+ref QDataStream operator >>(ref qfloat16 f);+/ 173 /+ref QDataStream operator >>(ref float f);+/ 174 /+ref QDataStream operator >>(ref double f);+/ 175 /+ref QDataStream operator >>(ref char* str);+/ 176 177 /+ref QDataStream operator <<(qint8 i);+/ 178 /+pragma(inline, true) ref QDataStream operator <<(quint8 i) 179 { return this << qint8(i); }+/ 180 /+ref QDataStream operator <<(qint16 i);+/ 181 /+pragma(inline, true) ref QDataStream operator <<(quint16 i) 182 { return this << qint16(i); }+/ 183 /+ref QDataStream operator <<(qint32 i);+/ 184 /+pragma(inline, true) ref QDataStream operator <<(quint32 i) 185 { return this << qint32(i); }+/ 186 /+ref QDataStream operator <<(qint64 i);+/ 187 /+pragma(inline, true) ref QDataStream operator <<(quint64 i) 188 { return this << qint64(i); }+/ 189 /+ref QDataStream operator <<(/+ std:: +/nullptr_t) { return this; }+/ 190 /+ref QDataStream operator <<(bool i);+/ 191 /+ref QDataStream operator <<(qfloat16 f);+/ 192 /+ref QDataStream operator <<(float f);+/ 193 /+ref QDataStream operator <<(double f);+/ 194 /+ref QDataStream operator <<(const(char)* str);+/ 195 196 ref QDataStream readBytes(ref char* , ref uint len); 197 int readRawData(char* , int len); 198 199 ref QDataStream writeBytes(const(char)* , uint len); 200 int writeRawData(const(char)* , int len); 201 202 int skipRawData(int len); 203 204 void startTransaction(); 205 bool commitTransaction(); 206 void rollbackTransaction(); 207 void abortTransaction(); 208 209 private: 210 /+ Q_DISABLE_COPY(QDataStream) +/ 211 @disable this(this); 212 /+this(ref const(QDataStream));+//+ref QDataStream operator =(ref const(QDataStream));+/ 213 QScopedPointer!(QDataStreamPrivate) d; 214 215 QIODevice dev; 216 bool owndev; 217 bool noswap; 218 ByteOrder byteorder; 219 int ver; 220 Status q_status; 221 222 int readBlock(char* data, int len); 223 /+ friend class QtPrivate::StreamStateSaver; +/ 224 } 225 226 /+ namespace QtPrivate { 227 228 class StreamStateSaver 229 { 230 public: 231 inline StreamStateSaver(QDataStream *s) : stream(s), oldStatus(s->status()) 232 { 233 if (!stream->dev || !stream->dev->isTransactionStarted()) 234 stream->resetStatus(); 235 } 236 inline ~StreamStateSaver() 237 { 238 if (oldStatus != QDataStream::Ok) { 239 stream->resetStatus(); 240 stream->setStatus(oldStatus); 241 } 242 } 243 244 private: 245 QDataStream *stream; 246 QDataStream::Status oldStatus; 247 }; 248 249 template <typename Container> 250 QDataStream &readArrayBasedContainer(QDataStream &s, Container &c) 251 { 252 StreamStateSaver stateSaver(&s); 253 254 c.clear(); 255 quint32 n; 256 s >> n; 257 c.reserve(n); 258 for (quint32 i = 0; i < n; ++i) { 259 typename Container::value_type t; 260 s >> t; 261 if (s.status() != QDataStream::Ok) { 262 c.clear(); 263 break; 264 } 265 c.append(t); 266 } 267 268 return s; 269 } 270 271 template <typename Container> 272 QDataStream &readListBasedContainer(QDataStream &s, Container &c) 273 { 274 StreamStateSaver stateSaver(&s); 275 276 c.clear(); 277 quint32 n; 278 s >> n; 279 for (quint32 i = 0; i < n; ++i) { 280 typename Container::value_type t; 281 s >> t; 282 if (s.status() != QDataStream::Ok) { 283 c.clear(); 284 break; 285 } 286 c << t; 287 } 288 289 return s; 290 } 291 292 template <typename T> 293 struct MultiContainer { using type = T; }; 294 template <typename K, typename V> 295 struct MultiContainer<QMap<K, V>> { using type = QMultiMap<K, V>; }; 296 template <typename K, typename V> 297 struct MultiContainer<QHash<K, V>> { using type = QMultiHash<K, V>; }; 298 299 template <typename Container> 300 QDataStream &readAssociativeContainer(QDataStream &s, Container &c) 301 { 302 StreamStateSaver stateSaver(&s); 303 304 c.clear(); 305 quint32 n; 306 s >> n; 307 for (quint32 i = 0; i < n; ++i) { 308 typename Container::key_type k; 309 typename Container::mapped_type t; 310 s >> k >> t; 311 if (s.status() != QDataStream::Ok) { 312 c.clear(); 313 break; 314 } 315 static_cast<typename MultiContainer<Container>::type &>(c).insert(k, t); 316 } 317 318 return s; 319 } 320 321 template <typename Container> 322 QDataStream &writeSequentialContainer(QDataStream &s, const Container &c) 323 { 324 s << quint32(c.size()); 325 for (const typename Container::value_type &t : c) 326 s << t; 327 328 return s; 329 } 330 331 template <typename Container> 332 QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c) 333 { 334 s << quint32(c.size()); 335 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && QT_DEPRECATED_SINCE(5, 15) 336 // Deserialization should occur in the reverse order. 337 // Otherwise, value() will return the least recently inserted 338 // value instead of the most recently inserted one. 339 auto it = c.constEnd(); 340 auto begin = c.constBegin(); 341 while (it != begin) { 342 QT_WARNING_PUSH 343 QT_WARNING_DISABLE_DEPRECATED 344 --it; 345 QT_WARNING_POP 346 s << it.key() << it.value(); 347 } 348 #else 349 auto it = c.constBegin(); 350 auto end = c.constEnd(); 351 while (it != end) { 352 const auto rangeStart = it++; 353 while (it != end && rangeStart.key() == it.key()) 354 ++it; 355 const qint64 last = std::distance(rangeStart, it) - 1; 356 for (qint64 i = last; i >= 0; --i) { 357 auto next = std::next(rangeStart, i); 358 s << next.key() << next.value(); 359 } 360 } 361 #endif 362 363 return s; 364 } 365 366 } // QtPrivate namespace 367 368 /***************************************************************************** 369 QDataStream inline functions 370 *****************************************************************************/ 371 372 template <typename Enum> 373 inline QDataStream &operator<<(QDataStream &s, QFlags<Enum> e) 374 { return s << e.i; } 375 376 template <typename Enum> 377 inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e) 378 { return s >> e.i; } 379 380 template <typename T> 381 typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type& 382 operator<<(QDataStream &s, const T &t) 383 { return s << static_cast<typename std::underlying_type<T>::type>(t); } 384 385 template <typename T> 386 typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type& 387 operator>>(QDataStream &s, T &t) 388 { return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); } 389 390 template <typename T> 391 inline QDataStream &operator>>(QDataStream &s, QList<T> &l) 392 { 393 return QtPrivate::readArrayBasedContainer(s, l); 394 } 395 396 template <typename T> 397 inline QDataStream &operator<<(QDataStream &s, const QList<T> &l) 398 { 399 return QtPrivate::writeSequentialContainer(s, l); 400 } 401 402 template<typename T> 403 inline QDataStream &operator>>(QDataStream &s, QVector<T> &v) 404 { 405 return QtPrivate::readArrayBasedContainer(s, v); 406 } 407 408 template<typename T> 409 inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v) 410 { 411 return QtPrivate::writeSequentialContainer(s, v); 412 } 413 414 template <typename T> 415 inline QDataStream &operator>>(QDataStream &s, QSet<T> &set) 416 { 417 return QtPrivate::readListBasedContainer(s, set); 418 } 419 420 template <typename T> 421 inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set) 422 { 423 return QtPrivate::writeSequentialContainer(s, set); 424 } 425 426 template <class Key, class T> 427 inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash) 428 { 429 return QtPrivate::readAssociativeContainer(s, hash); 430 } 431 432 template <class Key, class T> 433 inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash) 434 { 435 return QtPrivate::writeAssociativeContainer(s, hash); 436 } 437 438 template <class Key, class T> 439 inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map) 440 { 441 return QtPrivate::readAssociativeContainer(s, map); 442 } 443 444 template <class Key, class T> 445 inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map) 446 { 447 return QtPrivate::writeAssociativeContainer(s, map); 448 } 449 450 #ifndef QT_NO_DATASTREAM 451 template <class T1, class T2> 452 inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p) 453 { 454 s >> p.first >> p.second; 455 return s; 456 } 457 458 template <class T1, class T2> 459 inline QDataStream& operator<<(QDataStream& s, const QPair<T1, T2>& p) 460 { 461 s << p.first << p.second; 462 return s; 463 } 464 #endif +/ 465 466 } 467 468 version(QT_NO_DATASTREAM) 469 { 470 extern(C++, class) struct QDataStream; 471 } 472 473