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