Lua: Fix type confusion between signed and unsigned
[lsnes.git] / include / library / filesystem.hpp
blobef7976acc28a757e826e55e253c51e407e9c92aa
1 #ifndef _library__filesystem__hpp__included
2 #define _library__filesystem__hpp__included
4 #include <cstdint>
5 #include <map>
6 #include <string>
7 #include <fstream>
8 #include "threads.hpp"
10 #define CLUSTER_SIZE 8192
11 #define CLUSTERS_PER_SUPER (CLUSTER_SIZE / 4)
12 #define SUPERCLUSTER_SIZE (static_cast<uint64_t>(CLUSTER_SIZE) * CLUSTERS_PER_SUPER)
13 #define FILESYSTEM_SUPERBLOCK 1
14 #define FILESYSTEM_ROOTDIR 2
16 /**
17 * A filesystem.
19 class filesystem
21 public:
22 /**
23 * Create a new filesystem or open existing one, backed by specified file.
25 * Parameters backingfile: The backing file name.
27 filesystem(const std::string& backingfile);
28 /**
29 * Allocate a new file.
31 * Returns: The initial cluster for the new file.
33 uint32_t allocate_cluster();
34 /**
35 * Delete a file.
37 * Parameter cluster: The initial cluster of file to delete.
39 void free_cluster_chain(uint32_t cluster);
40 /**
41 * Read and discard specified amount of data.
43 * Parameter cluster: Cluster to start the read from. Updated to be cluster for following data.
44 * Parameter ptr: The offset in cluster. Updated to be offset for following data.
45 * Parameter length: The length to read.
46 * Returns: The actual amount read. Can only be smaller than length if EOF was seen first.
48 * Note: If this runs off the end of file, cluster will be left pointing to last cluster in file and ptr will be
49 * left at CLUSTER_SIZE.
51 size_t skip_data(uint32_t& cluster, uint32_t& ptr, uint32_t length);
52 /**
53 * Read specified amount of data.
55 * Parameter cluster: Cluster to start the read from. Updated to be cluster for following data.
56 * Parameter ptr: The offset in cluster. Updated to be offset for following data.
57 * Parameter data: The buffer to store the read data to.
58 * Parameter length: The length to read.
59 * Returns: The actual amount read. Can only be smaller than length if EOF was seen first.
61 * Note: If this runs off the end of file, cluster will be left pointing to last cluster in file and ptr will be
62 * left at CLUSTER_SIZE.
64 size_t read_data(uint32_t& cluster, uint32_t& ptr, void* data, uint32_t length);
65 /**
66 * Write specified amount of data.
68 * Parameter cluster: Cluster to start the write from. Update to be cluster for following data.
69 * Parameter ptr: The offset in cluster. Updated to be offset for following data.
70 * Parameter data: The buffer to read the data to write.
71 * Parameter length: The length to write.
72 * Parameter real_cluster: The real cluster the write started from is stored here.
73 * Parameter real_ptr: The real offset the write started from is stored here.
75 * Note: If the write exactly fills the last cluster, ptr will be left as CLUSTER_SIZE.
77 void write_data(uint32_t& cluster, uint32_t& ptr, const void* data, uint32_t length,
78 uint32_t& real_cluster, uint32_t& real_ptr);
79 /**
80 * A reference-counted refernece to a filesystem.
82 class ref
84 public:
85 /**
86 * Create a reference to NULL filesystem.
88 ref()
90 refcnt = NULL;
91 mlock = NULL;
92 fs = NULL;
94 /**
95 * Create/Open a new filesystem and take reference to that.
97 * Parameters backingfile: The backing file.
99 ref(const std::string& backingfile)
101 refcnt = NULL;
102 mlock = NULL;
103 try {
104 refcnt = new unsigned;
105 mlock = new threads::lock;
106 fs = new filesystem(backingfile);
107 } catch(...) {
108 delete refcnt;
109 delete mlock;
110 throw;
112 *refcnt = 1;
115 * Destructor.
117 ~ref()
119 threads::lock* mtodelete = NULL;
120 if(!mlock)
121 return;
123 threads::alock m(*mlock);
124 --*refcnt;
125 if(!*refcnt) {
126 delete fs;
127 delete refcnt;
128 mtodelete = mlock;
131 if(mtodelete)
132 delete mtodelete;
135 * Copy constructor.
137 ref(const ref& r)
139 threads::alock m(*r.mlock);
140 ++*(r.refcnt);
141 refcnt = r.refcnt;
142 mlock = r.mlock;
143 fs = r.fs;
146 * Assignment operator.
148 ref& operator=(const ref& r);
150 * Call allocate_cluster() on underlying filesystem.
152 * Note: See filesystem::allocate_cluster() for description.
154 uint32_t allocate_cluster()
156 threads::alock m(*mlock);
157 return fs->allocate_cluster();
160 * Call free_cluster_chain() on underlying filesystem.
162 * Note: See filesystem::free_cluster_chain() for description.
164 void free_cluster_chain(uint32_t cluster)
166 threads::alock m(*mlock);
167 fs->free_cluster_chain(cluster);
170 * Call skip_data() on underlying filesystem.
172 * Note: See filesystem::skip_data() for description.
174 size_t skip_data(uint32_t& cluster, uint32_t& ptr, uint32_t length)
176 threads::alock m(*mlock);
177 return fs->skip_data(cluster, ptr, length);
180 * Call read_data() on underlying filesystem.
182 * Note: See filesystem::read_data() for description.
184 size_t read_data(uint32_t& cluster, uint32_t& ptr, void* data, uint32_t length)
186 threads::alock m(*mlock);
187 return fs->read_data(cluster, ptr, data, length);
190 * Call write_data() on underlying filesystem.
192 * Note: See filesystem::write_data() for description.
194 void write_data(uint32_t& cluster, uint32_t& ptr, const void* data, uint32_t length,
195 uint32_t& real_cluster, uint32_t& real_ptr)
197 threads::alock m(*mlock);
198 fs->write_data(cluster, ptr, data, length, real_cluster, real_ptr);
200 private:
201 filesystem* fs;
202 unsigned* refcnt;
203 threads::lock* mlock;
205 private:
206 filesystem(const filesystem&);
207 filesystem& operator=(const filesystem&);
208 void link_cluster(uint32_t cluster, uint32_t linkto);
209 struct supercluster
211 unsigned free_clusters;
212 uint32_t clusters[CLUSTERS_PER_SUPER];
213 void load(std::fstream& s, uint32_t index);
214 void save(std::fstream& s, uint32_t index);
216 uint32_t supercluster_count;
217 std::map<uint32_t, supercluster> superclusters;
218 std::fstream backing;
222 #endif