00001
00003 #ifndef SST_XDR_H
00004 #define SST_XDR_H
00005
00006 #include <QIODevice>
00007
00008 #include "os.h"
00009
00010 class QByteArray;
00011
00012
00013 namespace SST {
00014
00019 class XdrStream : public QObject
00020 {
00021 public:
00022 enum Status {
00023 Ok = 0,
00024 ReadPastEnd,
00025 ReadCorruptData,
00026 IOError,
00027 };
00028
00029 private:
00030 QIODevice *dev;
00031 Status st;
00032
00033 static char zeros[4];
00034
00035 public:
00038 XdrStream();
00039
00043 XdrStream(QIODevice *d);
00044
00047 XdrStream(QByteArray *a, QIODevice::OpenMode mode);
00048
00050 XdrStream(const QByteArray &a);
00051
00052
00054
00056 inline QIODevice *device() { return dev; }
00057
00059 void setDevice(QIODevice *d);
00060
00061
00063
00065 inline Status status() const { return st; }
00066
00068 inline void setStatus(Status st) { this->st = st; }
00069
00071 inline void resetStatus() { setStatus(Ok); }
00072
00073
00075
00077 inline bool atEnd() { return dev->atEnd(); }
00078
00081 inline void readRawData(void *buf, int len) {
00082 if (dev->read((char*)buf, len) < len)
00083 setStatus(ReadPastEnd);
00084 }
00085
00089 inline void skipRawData(int len) {
00090 if (!dev->seek(dev->pos() + len))
00091 setStatus(IOError);
00092 }
00093
00096 inline void writeRawData(const void *buf, int len) {
00097 if (dev->write((const char*)buf, len) < len)
00098 setStatus(IOError);
00099 }
00100
00101
00103
00107 void readPadData(void *buf, int len);
00108
00110 void skipPadData(int len);
00111
00115 void writePadData(const void *buf, int len);
00116
00117
00119
00127 void readBytes(char *&s, qint32 &len);
00128
00132 void writeBytes(const char *s, qint32 len);
00133
00135 inline XdrStream &operator<<(bool b) {
00136 qint32 v = htonl(b);
00137 writeRawData(&v, 4);
00138 return *this;
00139 }
00140
00142 inline XdrStream &operator<<(qint8 i) {
00143 qint32 v = htonl(i);
00144 writeRawData(&v, 4);
00145 return *this;
00146 }
00147
00149 inline XdrStream &operator<<(qint16 i) {
00150 qint32 v = htonl(i);
00151 writeRawData(&v, 4);
00152 return *this;
00153 }
00154
00156 inline XdrStream &operator<<(qint32 i) {
00157 qint32 v = htonl(i);
00158 writeRawData(&v, 4);
00159 return *this;
00160 }
00161
00163 inline XdrStream &operator<<(qint64 i) {
00164 qint32 v[2] = { htonl(i >> 32), htonl(i) };
00165 Q_ASSERT(sizeof(v) == 8);
00166 writeRawData(&v, 8);
00167 return *this;
00168 }
00169
00171 inline XdrStream &operator<<(quint8 i) {
00172 return *this << (qint8)i;
00173 }
00174
00176 inline XdrStream &operator<<(quint16 i) {
00177 return *this << (qint16)i;
00178 }
00179
00181 inline XdrStream &operator<<(quint32 i) {
00182 return *this << (qint32)i;
00183 }
00184
00186 inline XdrStream &operator<<(quint64 i) {
00187 return *this << (qint64)i;
00188 }
00189
00191 inline XdrStream &operator<<(float f) {
00192 Q_ASSERT(sizeof(f) == 4);
00193 return *this << *(qint32*)&f;
00194 }
00195
00197 inline XdrStream &operator<<(double f) {
00198 Q_ASSERT(sizeof(f) == 8);
00199 return *this << *(qint64*)&f;
00200 }
00201
00202
00204
00206 inline XdrStream &operator>>(bool &b) {
00207 qint32 v;
00208 readRawData(&v, 4);
00209 b = (v != 0);
00210 return *this;
00211 }
00212
00214 inline XdrStream &operator>>(qint8 &i) {
00215 qint32 v;
00216 readRawData(&v, 4);
00217 i = ntohl(v);
00218 return *this;
00219 }
00220
00222 inline XdrStream &operator>>(qint16 &i) {
00223 qint32 v;
00224 readRawData(&v, 4);
00225 i = ntohl(v);
00226 return *this;
00227 }
00228
00230 inline XdrStream &operator>>(qint32 &i) {
00231 qint32 v;
00232 readRawData(&v, 4);
00233 i = ntohl(v);
00234 return *this;
00235 }
00236
00238 inline XdrStream &operator>>(qint64 &i) {
00239 quint32 v[2];
00240 Q_ASSERT(sizeof(v) == 8);
00241 readRawData(&v, 8);
00242 i = ((quint64)(quint32)ntohl(v[0]) << 32) |
00243 (quint32)ntohl(v[1]);
00244 return *this;
00245 }
00246
00248 inline XdrStream &operator>>(quint8 &i) {
00249 return *this >> *(qint8*)&i;
00250 }
00251
00253 inline XdrStream &operator>>(quint16 &i) {
00254 return *this >> *(qint16*)&i;
00255 }
00256
00258 inline XdrStream &operator>>(quint32 &i) {
00259 return *this >> *(qint32*)&i;
00260 }
00261
00263 inline XdrStream &operator>>(quint64 &i) {
00264 return *this >> *(qint64*)&i;
00265 }
00266
00268 inline XdrStream &operator>>(float &f) {
00269 Q_ASSERT(sizeof(f) == 4);
00270 return *this >> *(qint32*)&f;
00271 }
00272
00274 inline XdrStream &operator>>(double &f) {
00275 Q_ASSERT(sizeof(f) == 8);
00276 return *this >> *(qint64*)&f;
00277 }
00278
00280 XdrStream &operator>>(QByteArray &a);
00281
00283 XdrStream &operator<<(const QByteArray &a);
00284
00286 XdrStream &operator<<(const QString &s);
00287
00289 XdrStream &operator>>(QString &s);
00290
00291
00294 QString errorString();
00295 };
00296
00297
00298
00299 template<class T>
00300 void xdrEncodeVector(XdrStream &xs, const QList<T> &l, int len)
00301 {
00302 Q_ASSERT(l.size() == len);
00303 for (int i = 0; i < len; i++) {
00304 if (xs.status() != xs.Ok)
00305 return;
00306 xs << l.at(i);
00307 }
00308 }
00309
00310 template<class T>
00311 void xdrDecodeVector(XdrStream &xs, QList<T> &l, int len)
00312 {
00313 l.clear();
00314 for (int i = 0; i < len; i++) {
00315 if (xs.status() != xs.Ok)
00316 return;
00317 T v;
00318 xs >> v;
00319 l.append(v);
00320 }
00321 }
00322
00323 template<class T>
00324 void xdrEncodeArray(XdrStream &xs, const QList<T> &l, quint32 maxlen)
00325 {
00326 quint32 len = l.size();
00327 Q_ASSERT(len <= maxlen);
00328 xs << len;
00329 for (quint32 i = 0; i < len; i++) {
00330 if (xs.status() != xs.Ok)
00331 return;
00332 xs << l.at(i);
00333 }
00334 }
00335
00336 template<class T>
00337 void xdrDecodeArray(XdrStream &xs, QList<T> &l, quint32 maxlen)
00338 {
00339 quint32 len;
00340 xs >> len;
00341 if (len > maxlen)
00342 return xs.setStatus(xs.ReadCorruptData);
00343 l.clear();
00344 for (quint32 i = 0; i < len; i++) {
00345 if (xs.status() != xs.Ok)
00346 return;
00347 T v;
00348 xs >> v;
00349 l.append(v);
00350 }
00351 }
00352
00353
00354
00355 inline void xdrEncodeVector(XdrStream &xs, const QByteArray &v, int len)
00356 {
00357 Q_ASSERT(v.size() == len);
00358 xs.writeRawData(v.constData(), len);
00359 }
00360
00361 inline void xdrDecodeVector(XdrStream &xs, QByteArray &v, int len)
00362 {
00363 v.resize(len);
00364 xs.readRawData(v.data(), len);
00365 }
00366
00367 inline void xdrEncodeArray(XdrStream &xs, const QByteArray &v, quint32 maxlen)
00368 {
00369 Q_ASSERT((quint32)v.size() <= maxlen);
00370 xs << v;
00371 }
00372
00373 inline void xdrDecodeArray(XdrStream &xs, QByteArray &v, quint32 maxlen)
00374 {
00375 xs >> v;
00376 if ((quint32)v.size() > maxlen)
00377 return xs.setStatus(xs.ReadCorruptData);
00378 }
00379
00380
00381
00390 template<class T> class XdrPointer
00391 {
00392 private:
00393 T *i;
00394
00395 public:
00396 inline XdrPointer() : i(0) { }
00397 inline XdrPointer(const T &o) : i(new T(o)) { }
00398 inline XdrPointer(const XdrPointer<T> &o)
00399 : i(o.i ? new T(*o.i) : 0) { }
00400
00401 inline ~XdrPointer() { if (i) delete i; }
00402
00403 inline bool isNull() const { return i == 0; }
00404 inline void clear() { if (i) { delete i; i = 0; } }
00405 inline T& alloc() { if (!i) i = new T; return *i; }
00406
00407 inline XdrPointer<T> &operator=(const XdrPointer<T> &o)
00408 { clear(); if (o.i) i = new T(*o.i); }
00409 inline XdrPointer<T> &operator=(T *o)
00410 { clear(); if (o) i = new T(o); }
00411
00412 inline T* operator->() const { return i; }
00413 inline T& operator*() const { return *i; }
00414 inline operator T*() const { return i; }
00415 };
00416
00417 template<class T>
00418 inline XdrStream &operator<<(XdrStream &xs, const XdrPointer<T> &p)
00419 { if (p) { xs << true << *p; } else { xs << false; }; return xs; }
00420 template<class T>
00421 inline XdrStream &operator>>(XdrStream &xs, XdrPointer<T> &p)
00422 { bool f; xs >> f; if (f) { xs >> p.alloc(); } else p.clear();
00423 return xs; }
00424
00425
00435 template<class T> class XdrOption
00436 {
00437 private:
00438 T *i;
00439 QByteArray enc;
00440
00441 public:
00442 inline XdrOption() : i(NULL) { }
00443 inline XdrOption(const T &o) : i(new T(o)) { }
00444 inline XdrOption(const XdrOption<T> &o)
00445 : i(o.i ? new T(*o.i) : NULL), enc(o.enc) { }
00446
00447 inline ~XdrOption() { if (i) { delete i; i = NULL; } }
00448
00450 inline bool isNull() const { return i == NULL; }
00451
00453 inline bool isEmpty() const { return i == NULL && enc.isEmpty(); }
00454
00455
00456 inline T& alloc() { enc.clear(); if (!i) i = new T; return *i; }
00457 inline void clear() { enc.clear(); if (i) { delete i; i = NULL; } }
00458
00459
00460 inline QByteArray getEncoded() const { return enc; }
00461 inline void setEncoded(const QByteArray &e)
00462 { clear(); enc = e; }
00463
00464 inline XdrOption<T> &operator=(const XdrOption<T> &o)
00465 { clear(); if (o.i) i = new T(*o.i); enc = o.enc;
00466 return *this; }
00467 inline XdrOption<T> &operator=(T *o)
00468 { clear(); if (o) i = new T(o); return *this; }
00469
00470 inline T* operator->() const { return i; }
00471 inline T& operator*() const { return *i; }
00472 inline operator T*() const { return i; }
00473 };
00474
00475 template<class T>
00476 XdrStream &operator<<(XdrStream &xs, const XdrOption<T> &o)
00477 {
00478 if (!o.isNull()) {
00479 QByteArray buf;
00480 XdrStream bxs(&buf, QIODevice::WriteOnly);
00481 bxs << *o;
00482 xs << buf;
00483 } else
00484 xs << o.getEncoded();
00485 return xs;
00486 }
00487
00488 template<class T>
00489 XdrStream &operator>>(XdrStream &xs, XdrOption<T> &o)
00490 {
00491 QByteArray buf;
00492 xs >> buf;
00493 if (buf.isEmpty()) {
00494 o.clear();
00495 return xs;
00496 }
00497 XdrStream bxs(&buf, QIODevice::ReadOnly);
00498 bxs >> o.alloc();
00499 if (bxs.status() != bxs.Ok)
00500 o.setEncoded(buf);
00501 return xs;
00502 }
00503
00504 }
00505
00506 #endif // SST_XDR_H