Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

implemented DbPngEntryReader

  • Loading branch information...
commit 0febac0ae4d07c8e2ef738bfe26f0e569878eb6a 1 parent e9ac57d
@albertz authored
Showing with 147 additions and 8 deletions.
  1. +121 −6 DbPng.cpp
  2. +25 −1 DbPng.h
  3. +1 −1  db-push.cpp
View
127 DbPng.cpp
@@ -7,8 +7,7 @@
#include "DbPng.h"
#include "StringUtils.h"
#include "Sha1.h"
-
-#include <sys/mman.h>
+#include <vector>
#include <iostream>
using namespace std;
@@ -29,7 +28,7 @@ Return DbPngEntryWriter::next() {
DbEntryId id;
ASSERT( db->push(id, entry) );
- contentEntries.push_back(id);
+ contentChunkEntries.push_back(id);
continue;
}
else if(reader.scanlines.size() > 0) {
@@ -55,7 +54,7 @@ Return DbPngEntryWriter::next() {
DbEntryId id;
ASSERT( db->push(id, entry) );
- contentEntries.push_back(id);
+ contentDataEntries.push_back(id);
}
for(size_t i = 0; i < blockHeight; ++i)
@@ -68,9 +67,17 @@ Return DbPngEntryWriter::next() {
else if(reader.hasFinishedReading) {
DbEntry entry;
entry.data += (char)DbEntryType_PngContentList;
- for(std::list<DbEntryId>::iterator i = contentEntries.begin(); i != contentEntries.end(); ++i) {
+ for(std::list<DbEntryId>::iterator i = contentChunkEntries.begin(); i != contentChunkEntries.end(); ++i) {
+ if(i->size() > 255)
+ return "we have an ID with len > 255";
+ entry.data += rawString<uint8_t>(i->size());
+ entry.data += *i;
+ }
+ for(std::list<DbEntryId>::iterator i = contentDataEntries.begin(); i != contentDataEntries.end(); ++i) {
+ if(i->size() > 255)
+ return "we have an ID with len > 255";
+ entry.data += rawString<uint8_t>(i->size());
entry.data += *i;
- entry.data += '\0';
}
entry.prepare();
DbEntryId id;
@@ -84,3 +91,111 @@ Return DbPngEntryWriter::next() {
return true;
}
+
+static Return __readPngChunk(PngChunk& chunk, const std::string& data) {
+ if(data.size() < 5)
+ return "chunk entry too small";
+ chunk.type = data.substr(1,4);
+ chunk.data = data.substr(5);
+ return true;
+}
+
+static Return __finishBlock(DbPngEntryReader& png) {
+ if(png.blockList.blockHeight == 0 && png.blockList.blocks.size() == 0)
+ // there was no previos unfinished block. but this is ok
+ return true;
+
+ std::vector<std::string> scanlines(png.blockList.blockHeight);
+ size_t x = 0;
+ for(std::list<std::string>::iterator block = png.blockList.blocks.begin(); block != png.blockList.blocks.end(); ++block) {
+ size_t blockWidth = block->size() / png.blockList.blockHeight;
+ for(short y = 0; y < png.blockList.blockHeight; ++y) {
+ scanlines[y] += block->substr(y * blockWidth, blockWidth);
+ }
+ x += blockWidth;
+ }
+
+ for(short y = 0; y < png.blockList.blockHeight; ++y)
+ png.writer.scanlines.push_back(scanlines[y]);
+
+ return true;
+}
+
+static Return __readBlock(DbPngEntryReader& png, const std::string& data) {
+ size_t offset = 1; // first was the DbEntry type
+ if(data.size() < offset + sizeof(uint16_t))
+ return "block entry too small (before reading x-offset)";
+ uint32_t x = valueFromRaw<uint16_t>(&data[offset]) * PngBlockSize;
+ offset += sizeof(uint16_t);
+
+ if(x == 0) {
+ // new block row start
+ ASSERT( __finishBlock(png) );
+ if(data.size() < offset + sizeof(uint8_t))
+ return "block entry too small (before reading block height)";
+ png.blockList.blockHeight = valueFromRaw<uint8_t>(&data[offset]);
+ offset += sizeof(uint8_t);
+ }
+
+ if(((data.size() - offset) % png.blockList.blockHeight) != 0)
+ return "block entry raw size is not a multiple of blockHeight";
+ size_t blockWidth = (data.size() - offset) / png.blockList.blockHeight;
+
+ png.blockList.scanlineWidth += blockWidth;
+ png.blockList.blocks.push_back( data.substr(offset) );
+
+ return true;
+}
+
+Return DbPngEntryReader::next() {
+ if(!haveContentEntries) {
+ DbEntry entry;
+ ASSERT( db->get(entry, contentId) );
+ if(entry.data.size() == 0)
+ return "content entry list data is empty";
+ if(entry.data[0] != DbEntryType_PngBlock)
+ return "content entry list data is invalid";
+ size_t i = 1;
+ while(i < entry.data.size()) {
+ uint8_t size = entry.data[i];
+ ++i;
+ if(i + size > entry.data.size())
+ return "content entry list data is inconsistent";
+ contentEntries.push_back( DbEntryId(entry.data.substr(i, size)) );
+ i += size;
+ }
+ haveContentEntries = true;
+ return true;
+ }
+
+ if(contentEntries.size() > 0) {
+ DbEntry entry;
+ ASSERT( db->get(entry, contentEntries.front()) );
+ if(entry.data.size() == 0)
+ return "content entry data is empty";
+ switch(entry.data[0]) {
+ case DbEntryType_PngChunk: {
+ PngChunk chunk;
+ ASSERT( __readPngChunk(chunk, entry.data) );
+ writer.chunks.push_back(chunk);
+ break;
+ }
+ case DbEntryType_PngBlock: {
+ writer.hasAllChunks = true; // there wont be any more PngChunk entries
+ ASSERT( __readBlock(*this, entry.data) );
+ break;
+ }
+ default:
+ return "content entry data is invalid";
+ }
+ }
+ if(contentEntries.size() == 0) {
+ ASSERT( __finishBlock(*this) );
+ writer.hasAllChunks = true;
+ writer.hasAllScanlines = true;
+ }
+
+ ASSERT( writer.write() );
+
+ return true;
+}
View
26 DbPng.h
@@ -9,11 +9,14 @@
#include "Png.h"
#include "Db.h"
#include <cstdio>
+#include <string>
+#include <list>
struct DbPngEntryWriter {
PngReader reader;
DbIntf* db;
- std::list<DbEntryId> contentEntries;
+ std::list<DbEntryId> contentChunkEntries;
+ std::list<DbEntryId> contentDataEntries;
DbEntryId contentId;
DbPngEntryWriter(FILE* f, DbIntf* _db) : reader(f), db(_db) {}
@@ -21,4 +24,25 @@ struct DbPngEntryWriter {
operator bool() const { return !reader.hasFinishedReading; }
};
+struct DbPngEntryBlockList {
+ uint8_t blockHeight;
+ size_t scanlineWidth;
+ std::list<std::string> blocks;
+ DbPngEntryBlockList() : scanlineWidth(0), blockHeight(0) {}
+};
+
+struct DbPngEntryReader {
+ PngWriter writer;
+ DbIntf* db;
+ DbEntryId contentId;
+ std::list<DbEntryId> contentEntries;
+ bool haveContentEntries;
+ DbPngEntryBlockList blockList;
+
+ DbPngEntryReader(FILE* f, DbIntf* _db, const DbEntryId& _contentId)
+ : writer(f), db(_db), contentId(_contentId), haveContentEntries(false) {}
+ Return next();
+ operator bool() const { return !writer.hasFinishedWriting; }
+};
+
#endif
View
2  db-push.cpp
@@ -30,7 +30,7 @@ Return _main(const std::string& filename) {
fclose(f);
cout << "content id: " << hexString(dbPngWriter.contentId) << endl;
- cout << "num content entries: " << dbPngWriter.contentEntries.size() << endl;
+ cout << "num content entries: " << dbPngWriter.contentChunkEntries.size() + dbPngWriter.contentDataEntries.size() << endl;
cout << "db stats: push new: " << db.stats.pushNew << endl;
cout << "db stats: push reuse: " << db.stats.pushReuse << endl;
Please sign in to comment.
Something went wrong with that request. Please try again.