]> git.cworth.org Git - apitrace/blob - trace_file.cpp
10e6565925449f3b820088587cdad1453139dea5
[apitrace] / trace_file.cpp
1 #include "trace_file.hpp"
2
3 #include <assert.h>
4 #include <string.h>
5
6 #include <zlib.h>
7 #include <snappy.h>
8
9 #include <iostream>
10
11 using namespace Trace;
12
13 File::File(const std::string &filename,
14            File::Mode mode)
15     : m_filename(filename),
16       m_mode(mode),
17       m_isOpened(false)
18 {
19     if (!m_filename.empty()) {
20         open(m_filename, m_mode);
21     }
22 }
23
24
25 File::~File()
26 {
27     close();
28 }
29
30 bool File::isOpened() const
31 {
32     return m_isOpened;
33 }
34
35 File::Mode File::mode() const
36 {
37     return m_mode;
38 }
39
40 std::string File::filename() const
41 {
42     return m_filename;
43 }
44
45 bool File::open(const std::string &filename, File::Mode mode)
46 {
47     if (m_isOpened) {
48         close();
49     }
50     m_isOpened = rawOpen(filename, mode);
51     m_mode = mode;
52     return m_isOpened;
53 }
54
55 bool File::write(const void *buffer, int length)
56 {
57     if (!m_isOpened || m_mode != File::Write) {
58         return false;
59     }
60     return rawWrite(buffer, length);
61 }
62
63 bool File::read(void *buffer, int length)
64 {
65     if (!m_isOpened || m_mode != File::Read) {
66         return false;
67     }
68     return rawRead(buffer, length);
69 }
70
71 void File::close()
72 {
73     if (m_isOpened) {
74         rawClose();
75         m_isOpened = false;
76     }
77 }
78
79 void File::flush()
80 {
81     rawFlush();
82 }
83
84 int File::getc()
85 {
86     if (!m_isOpened || m_mode != File::Read) {
87         return 0;
88     }
89     return rawGetc();
90 }
91
92 bool File::isZLibCompressed(const std::string &filename)
93 {
94     std::fstream stream(filename.c_str(),
95                         std::fstream::binary | std::fstream::in);
96     if (!stream.is_open())
97         return false;
98
99     unsigned char byte1, byte2;
100     stream >> byte1;
101     stream >> byte2;
102     stream.close();
103
104     return (byte1 == 0x1f && byte2 == 0x8b);
105 }
106
107 ZLibFile::ZLibFile(const std::string &filename,
108                    File::Mode mode)
109     : File(filename, mode),
110       m_gzFile(NULL)
111 {
112 }
113
114 ZLibFile::~ZLibFile()
115 {
116 }
117
118 bool ZLibFile::rawOpen(const std::string &filename, File::Mode mode)
119 {
120     m_gzFile = gzopen(filename.c_str(),
121                       (mode == File::Write) ? "wb" : "rb");
122     return m_gzFile != NULL;
123 }
124
125 bool ZLibFile::rawWrite(const void *buffer, int length)
126 {
127     return gzwrite(m_gzFile, buffer, length) != -1;
128 }
129
130 bool ZLibFile::rawRead(void *buffer, int length)
131 {
132     return gzread(m_gzFile, buffer, length) != -1;
133 }
134
135 int ZLibFile::rawGetc()
136 {
137     return gzgetc(m_gzFile);
138 }
139
140 void ZLibFile::rawClose()
141 {
142     if (m_gzFile) {
143         gzclose(m_gzFile);
144         m_gzFile = NULL;
145     }
146 }
147
148 void ZLibFile::rawFlush()
149 {
150     gzflush(m_gzFile, Z_SYNC_FLUSH);
151 }
152
153 SnappyFile::SnappyFile(const std::string &filename,
154                               File::Mode mode)
155     : File(),
156       m_cache(0),
157       m_cachePtr(0),
158       m_cacheSize(0)
159 {
160     m_compressedCache = new char[SNAPPY_CHUNK_SIZE];
161 }
162
163 SnappyFile::~SnappyFile()
164 {
165     delete [] m_compressedCache;
166 }
167
168 bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
169 {
170     std::ios_base::openmode fmode = std::fstream::binary;
171     if (mode == File::Write) {
172         fmode |= (std::fstream::out | std::fstream::trunc);
173         createCache(SNAPPY_CHUNK_SIZE);
174     } else if (mode == File::Read) {
175         fmode |= std::fstream::in;
176     }
177
178     m_stream.open(filename.c_str(), fmode);
179
180     //read in the initial buffer if we're reading
181     if (m_stream.is_open() && mode == File::Read) {
182         flushCache();
183     }
184     return m_stream.is_open();
185 }
186
187 bool SnappyFile::rawWrite(const void *buffer, int length)
188 {
189     if (freeCacheSize() > length) {
190         memcpy(m_cachePtr, buffer, length);
191         m_cachePtr += length;
192     } else if (freeCacheSize() == length) {
193         memcpy(m_cachePtr, buffer, length);
194         m_cachePtr += length;
195         flushCache();
196     } else {
197         int sizeToWrite = length;
198
199         while (sizeToWrite >= freeCacheSize()) {
200             int endSize = freeCacheSize();
201             int offset = length - sizeToWrite;
202             memcpy(m_cachePtr, (char*)buffer + offset, endSize);
203             sizeToWrite -= endSize;
204             m_cachePtr += endSize;
205             flushCache();
206         }
207         if (sizeToWrite) {
208             int offset = length - sizeToWrite;
209             memcpy(m_cachePtr, (char*)buffer + offset, sizeToWrite);
210             m_cachePtr += sizeToWrite;
211         }
212     }
213
214     return true;
215 }
216
217 bool SnappyFile::rawRead(void *buffer, int length)
218 {
219     if (m_stream.eof()) {
220         return false;
221     }
222     if (freeCacheSize() > length) {
223         memcpy(buffer, m_cachePtr, length);
224         m_cachePtr += length;
225     } else if (freeCacheSize() == length) {
226         memcpy(buffer, m_cachePtr, length);
227         m_cachePtr += length;
228         flushCache();
229     } else {
230         int sizeToRead = length;
231         int offset = 0;
232         while (sizeToRead) {
233             int chunkSize = std::min(freeCacheSize(), sizeToRead);
234             offset = length - sizeToRead;
235             memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
236             m_cachePtr += chunkSize;
237             sizeToRead -= chunkSize;
238             if (sizeToRead > 0)
239                 flushCache();
240         }
241     }
242
243     return true;
244 }
245
246 int SnappyFile::rawGetc()
247 {
248     int c = 0;
249     if (!rawRead(&c, 1))
250         return -1;
251     return c;
252 }
253
254 void SnappyFile::rawClose()
255 {
256     flushCache();
257     m_stream.close();
258     delete [] m_cache;
259     m_cache = NULL;
260     m_cachePtr = NULL;
261 }
262
263 void SnappyFile::rawFlush()
264 {
265     m_stream.flush();
266 }
267
268 void SnappyFile::flushCache()
269 {
270     if (m_mode == File::Write) {
271         size_t compressedLength;
272
273         ::snappy::RawCompress(m_cache, SNAPPY_CHUNK_SIZE - freeCacheSize(),
274                               m_compressedCache, &compressedLength);
275
276         m_stream << compressedLength;
277         m_stream.write(m_compressedCache, compressedLength);
278         m_cachePtr = m_cache;
279     } else if (m_mode == File::Read) {
280         if (m_stream.eof())
281             return;
282         //assert(m_cachePtr == m_cache + m_cacheSize);
283         size_t compressedLength;
284         m_stream >> compressedLength;
285         m_stream.read((char*)m_compressedCache, compressedLength);
286         ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
287                                         &m_cacheSize);
288         if (m_cache)
289             delete [] m_cache;
290         createCache(m_cacheSize);
291         ::snappy::RawUncompress(m_compressedCache, compressedLength,
292                                 m_cache);
293     }
294 }
295
296 void SnappyFile::createCache(size_t size)
297 {
298     m_cache = new char[size];
299     m_cachePtr = m_cache;
300     m_cacheSize = size;
301 }