1 /*
2  *  This file is part of Dune Legacy.
3  *
4  *  Dune Legacy is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  Dune Legacy is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with Dune Legacy.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef OMEMORYSTREAM_H
19 #define OMEMORYSTREAM_H
20 
21 #include "OutputStream.h"
22 #include <stdlib.h>
23 #include <string>
24 
25 class OMemoryStream : public OutputStream
26 {
27 public:
OMemoryStream()28     OMemoryStream()
29      : currentPos(0), bufferSize(0), pBuffer(nullptr) {
30         ;
31     }
32 
~OMemoryStream()33     ~OMemoryStream() {
34         free(pBuffer);
35     }
36 
open()37     void open() {
38         free(pBuffer);
39 
40         currentPos = 0;
41         bufferSize = 4;
42         pBuffer = (char*) malloc(4);
43         if(pBuffer == nullptr) {
44             THROW(OMemoryStream::error, "OMemoryStream::open(): malloc failed!");
45         }
46     }
47 
getData()48     const char* getData() const {
49         return pBuffer;
50     }
51 
getDataLength()52     size_t getDataLength() const {
53         return (bReadOnly == true) ? bufferSize : currentPos;
54     }
55 
flush()56     void flush() {
57         ;
58     }
59 
writeString(const std::string & str)60     void writeString(const std::string& str) {
61         ensureBufferSize(currentPos + str.length() + sizeof(Uint32));
62 
63         writeUint32(str.length());
64 
65         if(!str.empty()) {
66             memcpy(pBuffer + currentPos, str.c_str(), str.length());
67             currentPos += str.length();
68         }
69     }
70 
71 
writeUint8(Uint8 x)72     void writeUint8(Uint8 x) {
73         ensureBufferSize(currentPos + sizeof(Uint8));
74         *((Uint8*) (pBuffer + currentPos)) = x;
75         currentPos += sizeof(Uint8);
76     }
77 
writeUint16(Uint16 x)78     void writeUint16(Uint16 x) {
79         ensureBufferSize(currentPos + sizeof(Uint16));
80         x = SDL_SwapLE16(x);
81         *((Uint16*) (pBuffer + currentPos)) = x;
82         currentPos += sizeof(Uint16);
83     }
84 
writeUint32(Uint32 x)85     void writeUint32(Uint32 x) {
86         ensureBufferSize(currentPos + sizeof(Uint32));
87         x = SDL_SwapLE32(x);
88         *((Uint32*) (pBuffer + currentPos)) = x;
89         currentPos += sizeof(Uint32);
90     }
91 
writeUint64(Uint64 x)92     void writeUint64(Uint64 x) {
93         ensureBufferSize(currentPos + sizeof(Uint64));
94         x = SDL_SwapLE64(x);
95         *((Uint64*) (pBuffer + currentPos)) = x;
96         currentPos += sizeof(Uint64);
97     }
98 
writeBool(bool x)99     void writeBool(bool x) {
100         writeUint8(x == true ? 1 : 0);
101     }
102 
writeFloat(float x)103     void writeFloat(float x) {
104         if(sizeof(float) != sizeof(Uint32)) {
105             THROW(OMemoryStream::error, "OMemoryStream::writeFloat(): sizeof(float) != sizeof(Uint32). Cannot save floats on such systems.");
106         }
107         Uint32 tmp;
108         memcpy(&tmp,&x,sizeof(Uint32)); // workaround for a strange optimization in gcc 4.1
109         writeUint32(tmp);
110     }
111 
ensureBufferSize(size_t minBufferSize)112     void ensureBufferSize(size_t minBufferSize) {
113         if(minBufferSize < bufferSize) {
114             return;
115         }
116 
117         size_t newBufferSize = ((bufferSize * 3) / 2);
118         if(newBufferSize < minBufferSize) {
119             newBufferSize = minBufferSize;
120         }
121 
122         char* pNewBuffer = (char*) realloc(pBuffer, newBufferSize);
123         if(pNewBuffer == nullptr) {
124             THROW(OMemoryStream::error, "OMemoryStream::ensureBufferSize(): realloc failed!");
125         } else {
126             pBuffer = pNewBuffer;
127             bufferSize = newBufferSize;
128         }
129     }
130 
131 private:
132     size_t  currentPos;
133     size_t  bufferSize;
134     char*   pBuffer;
135 };
136 
137 #endif // OMEMORYSTREAM_H
138