summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/package.h
diff options
context:
space:
mode:
authorAdam Borowski <kilobyte@angband.pl>2010-08-20 02:12:53 +0200
committerAdam Borowski <kilobyte@angband.pl>2010-08-20 02:12:53 +0200
commitb25ec0a923318fd601619cd0bd89a9c262ef74e1 (patch)
tree38d077a4e21a31ffa6ea0da77978e4e4ccd4adb1 /crawl-ref/source/package.h
parenta290ba3a83431e38b1d54ed611e7892e38e0fdfd (diff)
downloadcrawl-ref-b25ec0a923318fd601619cd0bd89a9c262ef74e1.tar.gz
crawl-ref-b25ec0a923318fd601619cd0bd89a9c262ef74e1.zip
The transactional save packager.
Diffstat (limited to 'crawl-ref/source/package.h')
-rw-r--r--crawl-ref/source/package.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/crawl-ref/source/package.h b/crawl-ref/source/package.h
new file mode 100644
index 0000000000..9ff525c49c
--- /dev/null
+++ b/crawl-ref/source/package.h
@@ -0,0 +1,96 @@
+#ifndef PACKAGE_H
+#define PACKAGE_H
+
+#define USE_ZLIB
+
+#include <stdint.h>
+#include <string>
+#include <map>
+#include <vector>
+#include <stack>
+
+#ifdef USE_ZLIB
+#include <zlib.h>
+#endif
+
+typedef uint32_t len_t;
+
+class package;
+
+class chunk_writer
+{
+private:
+ chunk_writer(package *parent, const std::string _name);
+ package *pkg;
+ std::string name;
+ len_t first_block;
+ len_t cur_block;
+ len_t block_len;
+#ifdef USE_ZLIB
+ z_stream zs;
+ Bytef *z_buffer;
+#endif
+ void raw_write(const void *data, len_t len);
+ void finish_block(len_t next);
+public:
+ ~chunk_writer();
+ void write(const void *data, len_t len);
+ friend class package;
+};
+
+class chunk_reader
+{
+private:
+ chunk_reader(package *parent, len_t start);
+ package *pkg;
+ len_t next_block;
+ len_t off, block_left;
+#ifdef USE_ZLIB
+ bool eof;
+ z_stream zs;
+ Bytef z_buffer[32768];
+#endif
+ len_t raw_read(void *data, len_t len);
+public:
+ ~chunk_reader();
+ len_t read(void *data, len_t len);
+ friend class package;
+};
+
+class package
+{
+public:
+ package(const char* file, bool writeable, bool empty = false);
+ ~package();
+ chunk_writer* writer(const std::string name);
+ chunk_reader* reader(const std::string name);
+ void commit();
+ void delete_chunk(const std::string name);
+ bool has_chunk(const std::string name);
+ std::vector<std::string> list_chunks();
+private:
+ bool rw;
+ int fd;
+ len_t file_len;
+ int n_users;
+ bool dirty;
+ std::map<std::string, len_t> directory;
+ std::map<len_t, len_t> free_blocks;
+ std::stack<len_t> unlinked_blocks;
+ std::map<len_t, std::pair<len_t, len_t> > block_map;
+ len_t extend_block(len_t at, len_t size, len_t by);
+ len_t alloc_block();
+ void finish_chunk(const std::string name, len_t at);
+ void free_chunk(const std::string name);
+ len_t write_directory();
+ void collect_blocks();
+ void free_block(len_t at, len_t size);
+ void seek(len_t to);
+ void fsck();
+ void read_directory(len_t start);
+ void trace_chunk(len_t start);
+ friend class chunk_writer;
+ friend class chunk_reader;
+};
+
+#endif