]> git.cworth.org Git - apitrace/blob - trace_file.cpp
0272a5c29767bacb76fed998613113b56b2a6424
[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 ZLibFile::ZLibFile(const std::string &filename,
93                    File::Mode mode)
94     : File(filename, mode),
95       m_gzFile(NULL)
96 {
97 }
98
99 ZLibFile::~ZLibFile()
100 {
101 }
102
103 bool ZLibFile::rawOpen(const std::string &filename, File::Mode mode)
104 {
105     m_gzFile = gzopen(filename.c_str(),
106                       (mode == File::Write) ? "wb" : "rb");
107     return m_gzFile != NULL;
108 }
109
110 bool ZLibFile::rawWrite(const void *buffer, int length)
111 {
112     return gzwrite(m_gzFile, buffer, length) != -1;
113 }
114
115 bool ZLibFile::rawRead(void *buffer, int length)
116 {
117     return gzread(m_gzFile, buffer, length) != -1;
118 }
119
120 int ZLibFile::rawGetc()
121 {
122     return gzgetc(m_gzFile);
123 }
124
125 void ZLibFile::rawClose()
126 {
127     if (m_gzFile) {
128         gzclose(m_gzFile);
129         m_gzFile = NULL;
130     }
131 }
132
133 void ZLibFile::rawFlush()
134 {
135     gzflush(m_gzFile, Z_SYNC_FLUSH);
136 }
137
138 SnappyFile::SnappyFile(const std::string &filename,
139                               File::Mode mode)
140     : File(),
141       m_cache(0),
142       m_cachePtr(0),
143       m_cacheSize(0)
144 {
145     m_compressedCache = new char[SNAPPY_CHUNK_SIZE];
146 }
147
148 SnappyFile::~SnappyFile()
149 {
150     delete [] m_compressedCache;
151 }
152
153 bool SnappyFile::rawOpen(const std::string &filename, File::Mode mode)
154 {
155     std::ios_base::openmode fmode = std::fstream::binary;
156     if (mode == File::Write) {
157         fmode |= (std::fstream::out | std::fstream::trunc);
158         createCache(SNAPPY_CHUNK_SIZE);
159     } else if (mode == File::Read) {
160         fmode |= std::fstream::in;
161     }
162
163     m_stream.open(filename.c_str(), fmode);
164
165     //read in the initial buffer if we're reading
166     if (m_stream.is_open() && mode == File::Read) {
167         flushCache();
168     }
169     return m_stream.is_open();
170 }
171
172 bool SnappyFile::rawWrite(const void *buffer, int length)
173 {
174     if (freeCacheSize() > length) {
175         memcpy(m_cachePtr, buffer, length);
176         m_cachePtr += length;
177     } else if (freeCacheSize() == length) {
178         memcpy(m_cachePtr, buffer, length);
179         m_cachePtr += length;
180         flushCache();
181     } else {
182         int sizeToWrite = length;
183
184         while (sizeToWrite >= freeCacheSize()) {
185             int endSize = freeCacheSize();
186             int offset = length - sizeToWrite;
187             memcpy(m_cachePtr, (char*)buffer + offset, endSize);
188             sizeToWrite -= endSize;
189             m_cachePtr += endSize;
190             flushCache();
191         }
192         if (sizeToWrite) {
193             int offset = length - sizeToWrite;
194             memcpy(m_cachePtr, (char*)buffer + offset, sizeToWrite);
195             m_cachePtr += sizeToWrite;
196         }
197     }
198
199     return true;
200 }
201
202 bool SnappyFile::rawRead(void *buffer, int length)
203 {
204     if (m_stream.eof()) {
205         return false;
206     }
207     if (freeCacheSize() > length) {
208         memcpy(buffer, m_cachePtr, length);
209         m_cachePtr += length;
210     } else if (freeCacheSize() == length) {
211         memcpy(buffer, m_cachePtr, length);
212         m_cachePtr += length;
213         flushCache();
214     } else {
215         int sizeToRead = length;
216         int offset = 0;
217         while (sizeToRead) {
218             int chunkSize = std::min(freeCacheSize(), sizeToRead);
219             offset = length - sizeToRead;
220             memcpy((char*)buffer + offset, m_cachePtr, chunkSize);
221             m_cachePtr += chunkSize;
222             sizeToRead -= chunkSize;
223             if (sizeToRead > 0)
224                 flushCache();
225         }
226     }
227
228     return true;
229 }
230
231 int SnappyFile::rawGetc()
232 {
233     int c = 0;
234     if (!rawRead(&c, 1))
235         return -1;
236     return c;
237 }
238
239 void SnappyFile::rawClose()
240 {
241     flushCache();
242     m_stream.close();
243     delete [] m_cache;
244     m_cache = NULL;
245     m_cachePtr = NULL;
246 }
247
248 void SnappyFile::rawFlush()
249 {
250     m_stream.flush();
251 }
252
253 void SnappyFile::flushCache()
254 {
255     if (m_mode == File::Write) {
256         size_t compressedLength;
257
258         ::snappy::RawCompress(m_cache, SNAPPY_CHUNK_SIZE - freeCacheSize(),
259                               m_compressedCache, &compressedLength);
260
261         m_stream << compressedLength;
262         m_stream.write(m_compressedCache, compressedLength);
263         m_cachePtr = m_cache;
264     } else if (m_mode == File::Read) {
265         if (m_stream.eof())
266             return;
267         //assert(m_cachePtr == m_cache + m_cacheSize);
268         size_t compressedLength;
269         m_stream >> compressedLength;
270         m_stream.read((char*)m_compressedCache, compressedLength);
271         ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
272                                         &m_cacheSize);
273         if (m_cache)
274             delete [] m_cache;
275         createCache(m_cacheSize);
276         ::snappy::RawUncompress(m_compressedCache, compressedLength,
277                                 m_cache);
278     }
279 }
280
281 void SnappyFile::createCache(size_t size)
282 {
283     m_cache = new char[size];
284     m_cachePtr = m_cache;
285     m_cacheSize = size;
286 }