00001 #ifndef PACKAGE_H 00002 #define PACKAGE_H 00003 00004 #define USE_ZLIB 00005 00006 #include <stdint.h> 00007 #include <string> 00008 #include <map> 00009 #include <vector> 00010 #include <stack> 00011 00012 #ifdef USE_ZLIB 00013 #include <zlib.h> 00014 #endif 00015 00016 #define MAX_CHUNK_NAME_LENGTH 255 00017 00018 typedef uint32_t len_t; 00019 00020 class package; 00021 00022 class chunk_writer 00023 { 00024 private: 00025 package *pkg; 00026 std::string name; 00027 len_t first_block; 00028 len_t cur_block; 00029 len_t block_len; 00030 #ifdef USE_ZLIB 00031 z_stream zs; 00032 Bytef *z_buffer; 00033 #endif 00034 void raw_write(const void *data, len_t len); 00035 void finish_block(len_t next); 00036 public: 00037 chunk_writer(package *parent, const std::string _name); 00038 ~chunk_writer(); 00039 void write(const void *data, len_t len); 00040 friend class package; 00041 }; 00042 00043 class chunk_reader 00044 { 00045 private: 00046 chunk_reader(package *parent, len_t start); 00047 void init(len_t start); 00048 package *pkg; 00049 len_t next_block; 00050 len_t off, block_left; 00051 #ifdef USE_ZLIB 00052 bool eof; 00053 z_stream zs; 00054 Bytef z_buffer[32768]; 00055 #endif 00056 len_t raw_read(void *data, len_t len); 00057 public: 00058 chunk_reader(package *parent, const std::string _name); 00059 ~chunk_reader(); 00060 len_t read(void *data, len_t len); 00061 void read_all(std::vector<char> &data); 00062 friend class package; 00063 }; 00064 00065 class package 00066 { 00067 public: 00068 package(const char* file, bool writeable, bool empty = false); 00069 ~package(); 00070 chunk_writer* writer(const std::string name); 00071 chunk_reader* reader(const std::string name); 00072 void commit(); 00073 void delete_chunk(const std::string name); 00074 bool has_chunk(const std::string name); 00075 std::vector<std::string> list_chunks(); 00076 void abort(); 00077 void unlink(); 00078 private: 00079 std::string filename; 00080 bool rw; 00081 int fd; 00082 len_t file_len; 00083 int n_users; 00084 bool dirty; 00085 bool aborted; 00086 std::map<std::string, len_t> directory; 00087 std::map<len_t, len_t> free_blocks; 00088 std::stack<len_t> unlinked_blocks; 00089 std::map<len_t, std::pair<len_t, len_t> > block_map; 00090 len_t extend_block(len_t at, len_t size, len_t by); 00091 len_t alloc_block(); 00092 void finish_chunk(const std::string name, len_t at); 00093 void free_chunk(const std::string name); 00094 len_t write_directory(); 00095 void collect_blocks(); 00096 void free_block(len_t at, len_t size); 00097 void seek(len_t to); 00098 void fsck(); 00099 void read_directory(len_t start, uint8_t version); 00100 void trace_chunk(len_t start); 00101 void load(); 00102 friend class chunk_writer; 00103 friend class chunk_reader; 00104 }; 00105 00106 #endif