1 /*
2 * The Doomsday Engine Project -- libcore
3 *
4 * Copyright © 2004-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
5 *
6 * @par License
7 * LGPL: http://www.gnu.org/licenses/lgpl.html
8 *
9 * <small>This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or (at your
12 * option) any later version. This program is distributed in the hope that it
13 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15 * General Public License for more details. You should have received a copy of
16 * the GNU Lesser General Public License along with this program; if not, see:
17 * http://www.gnu.org/licenses</small>
18 */
19
20 #ifndef LIBDENG2_BLOCK_H
21 #define LIBDENG2_BLOCK_H
22
23 #include "../IByteArray"
24 #include "../IBlock"
25 #include "../ISerializable"
26 #include "../Writer"
27
28 #include <QByteArray>
29
30 namespace de {
31
32 class String;
33 class IIStream;
34
35 /**
36 * Data buffer that implements the byte array interface.
37 *
38 * Note that Block is based on QByteArray, and thus automatically always ensures
39 * that the data is followed by a terminating \0 character (even if one is not
40 * part of the actual Block contents). Therefore it is safe to use it in functions
41 * that assume zero-terminated strings.
42 *
43 * @ingroup data
44 */
45 class DENG2_PUBLIC Block : public QByteArray, public IByteArray, public IBlock,
46 public ISerializable
47 {
48 public:
49 Block(Size initialSize = 0);
50 Block(IByteArray const &array);
51 Block(Block const &other);
52 Block(Block &&moved);
53 Block(QByteArray const &byteArray);
54 Block(char const *nullTerminatedCStr);
55 Block(void const *data, Size length);
56
57 /**
58 * Constructs a block by reading the contents of an input stream. The block
59 * will contain all the data that is available immediately; will not wait
60 * for additional data to become available later.
61 *
62 * @param stream Stream to read from.
63 */
64 Block(IIStream &stream);
65
66 /**
67 * Constructs a block by reading the contents of an input stream in const
68 * mode. The block will contain all the data that is available immediately;
69 * will not wait for additional data to become available later.
70 *
71 * @param stream Stream to read from.
72 */
73 Block(IIStream const &stream);
74
75 /**
76 * Construct a new block and copy its contents from the specified
77 * location at another array.
78 *
79 * @param array Source data.
80 * @param at Offset within source data.
81 * @param count Number of bytes to copy. Also the size of the new block.
82 */
83 Block(IByteArray const &array, Offset at, Size count);
84
85 Byte *data();
86 Byte const *dataConst() const;
87
88 Block &append(Byte b);
89 Block &append(char const *str, int len);
90
91 inline explicit operator bool() const { return !isEmpty(); }
92
93 Block &operator += (char const *nullTerminatedCStr);
94 Block &operator += (QByteArray const &bytes);
95
96 /// Appends a block after this one.
97 Block &operator += (Block const &other);
98
99 /// Appends a byte array after this one.
100 Block &operator += (IByteArray const &byteArray);
101
102 /// Copies the contents of another block.
103 Block &operator = (Block const &other);
104
105 Block &operator = (IByteArray const &byteArray);
106
107 Block compressed(int level = -1) const;
108 Block decompressed() const;
109 Block md5Hash() const;
110 String asHexadecimalText() const;
111
112 // Implements IByteArray.
113 Size size() const;
114 void get(Offset at, Byte *values, Size count) const;
115 void set(Offset at, Byte const *values, Size count);
116
117 // Implements IBlock.
118 void clear();
119 void copyFrom(IByteArray const &array, Offset at, Size count);
120 void resize(Size size);
121 Byte const *data() const;
122
123 // Implements ISerializable.
124 /**
125 * Writes @a block into the destination buffer. Writes the size of the
126 * block in addition to its contents, so a Reader will not need to know
127 * beforehand how large the block is.
128 *
129 * @param block Block to write.
130 *
131 * @return Reference to the Writer.
132 */
133 void operator >> (Writer &to) const;
134
135 void operator << (Reader &from);
136
137 public:
138 static Block join(QList<Block> const &blocks, Block const &sep = Block());
139 };
140
141 template <typename... Args>
md5Hash(Args...args)142 Block md5Hash(Args... args) {
143 Block data;
144 Writer writer(data);
145 writer.writeMultiple(args...);
146 return data.md5Hash();
147 }
148
149 } // namespace de
150
151 #endif // LIBDENG2_BLOCK_H
152