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