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