1 /*****************************************************************************/
2 /* */
3 /* CONT.CC */
4 /* */
5 /* (C) 1993-95 Ullrich von Bassewitz */
6 /* Zwehrenbuehlstrasse 33 */
7 /* D-72070 Tuebingen */
8 /* EMail: uz@ibb.schwaben.com */
9 /* */
10 /*****************************************************************************/
11
12
13
14 // $Id$
15 //
16 // $Log$
17 //
18 //
19
20
21
22 #include <stdio.h>
23 #include <sys/stat.h>
24
25 #include "streamid.h"
26 #include "cont.h"
27
28
29
30 // Register class Container
31 LINK(Container, ID_Container);
32
33
34
35 /*****************************************************************************/
36 /* class Container */
37 /*****************************************************************************/
38
39
40
Container(const Container & C)41 Container::Container (const Container& C)
42 {
43 if (C.Data == NULL) {
44 // Other container is empty
45 Data = NULL;
46 Size = 0;
47 } else {
48 // Second container is not empty
49 Size = C.Size;
50 Data = new char [Size];
51 memcpy (Data, C.Data, Size);
52 }
53 }
54
55
56
~Container()57 Container::~Container ()
58 {
59 FreeData ();
60 }
61
62
63
Load(Stream & S)64 void Container::Load (Stream& S)
65 {
66 // Get Size of Data
67 S >> Size;
68
69 // Maybe, size is 0
70 if (Size == 0) {
71 Data = NULL;
72 } else {
73 Data = new char [Size];
74 S.Read (Data, Size);
75 }
76 }
77
78
79
Store(Stream & S) const80 void Container::Store (Stream& S) const
81 {
82 S << Size;
83 S.Write (Data, Size);
84 }
85
86
87
StreamableID() const88 u16 Container::StreamableID () const
89 {
90 return ID_Container;
91 }
92
93
94
Build()95 Streamable* Container::Build ()
96 {
97 return new Container (Empty);
98 }
99
100
101
FreeData()102 void Container::FreeData ()
103 {
104 delete [] Data;
105 Data = NULL;
106 Size = 0L;
107 }
108
109
110
GetData()111 void* Container::GetData ()
112 // Don't inline this function - it's needed in this module for correct linking
113 {
114 return Data;
115 }
116
117
118
GetData() const119 const void* Container::GetData () const
120 // Don't inline this function - it's needed in this module for correct linking
121 {
122 return Data;
123 }
124
125
126
RetrieveData()127 void* Container::RetrieveData ()
128 // Return the current data and empty the container. After this call,
129 // the calling function is responsible for managing/deleting the data.
130 {
131 void* D = Data;
132 Data = NULL;
133 Size = 0;
134 return D;
135 }
136
137
138
PutData(void * DataPtr,u32 DataSize)139 void Container::PutData (void* DataPtr, u32 DataSize)
140 {
141 // Free old data
142 FreeData ();
143
144 // Get control of new data
145 Data = DataPtr;
146 Size = DataSize;
147 }
148
149
150
CopyFrom(void * DataPtr,u32 DataSize)151 Container& Container::CopyFrom (void* DataPtr, u32 DataSize)
152 // Free the current data, create a new data block, copy given data
153 {
154 // If compiled under DOS: Check for maximum block size
155 #ifdef DOS
156 CHECK (DataSize < 0xFFF0L);
157 #endif
158
159 // Free the current data
160 FreeData ();
161
162 // Create a new data block and copy the given data
163 Data = memcpy (new unsigned char [DataSize], DataPtr, DataSize);
164
165 // Remember the size
166 Size = DataSize;
167
168 // Return a reference to this
169 return *this;
170 }
171
172
173
StoreData(const String & Filename) const174 int Container::StoreData (const String& Filename) const
175 {
176 FILE* F;
177
178 // If compiled under DOS: Honor the maximum data size for fwrite
179 #ifdef DOS
180 CHECK (Size < 0xFFF0L);
181 #endif
182
183 // Create a new file for writing
184 if ((F = fopen (Filename.GetStr (), "wb")) == NULL) {
185 // Cannot open file
186 return 0;
187 }
188
189 // Write the container data to the file
190 fwrite (Data, (size_t) Size, 1, F);
191
192 // Close the file, return success
193 fclose (F);
194 return 1;
195 }
196
197
198
LoadData(const String & Filename)199 int Container::LoadData (const String& Filename)
200 {
201 FILE* F;
202 u32 FileSize;
203
204 // Get the size of the file
205 struct stat StatBuf;
206 if (stat (Filename.GetStr (), &StatBuf) != 0) {
207 // No file
208 return 0;
209 }
210 FileSize = StatBuf.st_size;
211
212 // When running under DOS, check for enough memory as new is not
213 // able to handle requests > 0xFFF0 bytes.
214 #ifdef DOS
215 if (FileSize > 0xFFF0) {
216 // File is too big.
217 return 0;
218 }
219 #endif
220
221
222 // Try to open the file for reading
223 if ((F = fopen (Filename.GetStr (), "rb")) == NULL) {
224 // Error
225 return 0;
226 }
227
228 // Now as chances are good to access the file, we drop any old data
229 // and allocate memory for the new data
230 FreeData ();
231 if (FileSize > 0) {
232 Size = (u32) FileSize;
233 Data = new char [FileSize];
234
235 // Now read in the file data
236 (void) fread (Data, (size_t) Size, 1, F);
237 }
238
239 // Close the file, ignore errors (don't know how to handle them)
240 fclose (F);
241
242 // Return success
243 return 1;
244 }
245
246
247
operator =(const Container & rhs)248 Container& Container::operator = (const Container &rhs)
249 {
250 // Beware of C = C
251 if (&rhs != this) {
252 // Free current data
253 FreeData ();
254
255 // Get data from right hand side
256 if (rhs.Data == NULL) {
257 Data = NULL;
258 Size = 0;
259 } else {
260 Size = rhs.Size;
261 Data = new char [Size];
262 memcpy (Data, rhs.Data, Size);
263 }
264 }
265 return *this;
266 }
267
268
269
270
271