]> git.cworth.org Git - apitrace/blobdiff - trace_snappyfile.cpp
Implement scanning/skipping of fragments of the trace
[apitrace] / trace_snappyfile.cpp
index a3481838dd1b23fd02cf4bd248780a156b8b9eb0..443ebe7c5040c131bf7eef72daeb84ace273b98b 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <snappy.h>
 
+#include <iostream>
+
 #include <assert.h>
 #include <string.h>
 
@@ -66,7 +68,9 @@ SnappyFile::SnappyFile(const std::string &filename,
       m_cachePtr(0),
       m_cacheSize(0)
 {
-    m_compressedCache = new char[SNAPPY_CHUNK_SIZE];
+    size_t maxCompressedLength =
+        snappy::MaxCompressedLength(SNAPPY_CHUNK_SIZE);
+    m_compressedCache = new char[maxCompressedLength];
 }
 
 SnappyFile::~SnappyFile()
@@ -135,16 +139,13 @@ bool SnappyFile::rawWrite(const void *buffer, int length)
 
 bool SnappyFile::rawRead(void *buffer, int length)
 {
-    if (m_stream.eof()) {
+    if (endOfData()) {
         return false;
     }
-    if (freeCacheSize() > length) {
-        memcpy(buffer, m_cachePtr, length);
-        m_cachePtr += length;
-    } else if (freeCacheSize() == length) {
+
+    if (freeCacheSize() >= length) {
         memcpy(buffer, m_cachePtr, length);
         m_cachePtr += length;
-        flushCache();
     } else {
         int sizeToRead = length;
         int offset = 0;
@@ -202,9 +203,18 @@ void SnappyFile::flushCache()
         if (m_stream.eof())
             return;
         //assert(m_cachePtr == m_cache + m_cacheSize);
+        m_currentOffset.chunk = m_stream.tellg();
         size_t compressedLength;
         compressedLength = readCompressedLength();
         m_stream.read((char*)m_compressedCache, compressedLength);
+        /*
+         * The reason we peek here is because the last read will
+         * read all the way until the last character, but that will not
+         * trigger m_stream.eof() to be set, so by calling peek
+         * we assure that if we in fact have read the entire stream
+         * then the m_stream.eof() is always set.
+         */
+        m_stream.peek();
         ::snappy::GetUncompressedLength(m_compressedCache, compressedLength,
                                         &m_cacheSize);
         if (m_cache)
@@ -233,3 +243,52 @@ uint32_t SnappyFile::readCompressedLength()
     m_stream.read((char*)&len, sizeof len);
     return len;
 }
+
+bool SnappyFile::supportsOffsets() const
+{
+    return true;
+}
+
+File::Offset SnappyFile::currentOffset()
+{
+    m_currentOffset.offsetInChunk = m_cachePtr - m_cache;
+    return m_currentOffset;
+}
+
+void SnappyFile::setCurrentOffset(const File::Offset &offset)
+{
+    // to remove eof bit
+    m_stream.clear();
+    // seek to the start of a chunk
+    m_stream.seekg(offset.chunk, std::ios::beg);
+    // load the chunk
+    flushCache();
+    assert(m_cacheSize >= offset.offsetInChunk);
+    // seek within our cache to the correct location within the chunk
+    m_cachePtr = m_cache + offset.offsetInChunk;
+
+}
+
+bool SnappyFile::rawSkip(unsigned length)
+{
+    if (endOfData()) {
+        return false;
+    }
+
+    if (freeCacheSize() >= length) {
+        m_cachePtr += length;
+    } else {
+        int sizeToRead = length;
+        while (sizeToRead) {
+            int chunkSize = std::min(freeCacheSize(), sizeToRead);
+            m_cachePtr += chunkSize;
+            sizeToRead -= chunkSize;
+            if (sizeToRead > 0)
+                flushCache();
+            if (!m_cacheSize)
+                break;
+        }
+    }
+
+    return true;
+}