1 /** 2 * ae.sys.dataio 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.sys.dataio; 15 16 import ae.sys.data; 17 18 // ************************************************************************ 19 20 static import std.stream; 21 22 Data readStreamData(std.stream.Stream s) 23 { 24 auto size = s.size - s.position; 25 assert(size < size_t.max); 26 auto data = Data(cast(size_t)size); 27 s.readExact(data.mptr, data.length); 28 return data; 29 } 30 31 Data readData(string filename) 32 { 33 scope file = new std.stream.File(filename); 34 scope(exit) file.close(); 35 return readStreamData(file); 36 } 37 38 // ************************************************************************ 39 40 static import std.stdio; 41 42 Data readFileData(ref std.stdio.File f) 43 { 44 Data buf = Data(1024*1024); 45 Data result; 46 while (!f.eof()) 47 result ~= f.rawRead(cast(ubyte[])buf.mcontents); 48 buf.deleteContents(); 49 return result; 50 } 51 52 // ************************************************************************ 53 54 /// Wrapper for Data class, allowing an object to be swapped to disk 55 /// and automatically retreived as required. 56 57 final class SwappedData 58 { 59 import std.file; 60 import std.string; 61 debug(SwappedData) import ae.sys.log; 62 63 private: 64 Data _data; 65 string fileName; 66 const(char)* cFileName; 67 68 static const MIN_SIZE = 4096; // minimum size to swap out 69 70 debug(SwappedData) static Logger log; 71 72 public: 73 this(string fileName) 74 { 75 debug(SwappedData) { if (log is null) log = new FileAndConsoleLogger("SwappedData"); log(fileName ~ " - Creating"); } 76 this.fileName = fileName; 77 cFileName = fileName.toStringz(); 78 if (exists(fileName)) 79 remove(fileName); 80 } 81 82 void unload() 83 { 84 if (!_data.empty && _data.length >= MIN_SIZE) 85 { 86 debug(SwappedData) log(fileName ~ " - Unloading"); 87 write(fileName, _data.contents); 88 _data.clear(); 89 } 90 } 91 92 bool isLoaded() 93 { 94 return !exists(fileName); 95 } 96 97 // Getter 98 Data data() 99 { 100 if (!_data.length) 101 { 102 debug(SwappedData) log(fileName ~ " - Reloading"); 103 if (!exists(fileName)) 104 return Data(); 105 _data = readData(fileName); 106 remove(fileName); 107 } 108 return _data; 109 } 110 111 // Setter 112 void data(Data data) 113 { 114 debug(SwappedData) log(fileName ~ " - Setting"); 115 if (exists(fileName)) 116 remove(fileName); 117 _data = data; 118 } 119 120 size_t length() 121 { 122 if (!_data.empty) 123 return _data.length; 124 else 125 if (exists(fileName)) 126 return cast(size_t)getSize(fileName); 127 else 128 return 0; 129 } 130 131 ~this() 132 { 133 // Can't allocate in destructors. 134 135 //debug(SwappedData) log(fileName ~ " - Destroying"); 136 /*if (exists(fileName)) 137 { 138 debug(SwappedData) log(fileName ~ " - Deleting"); 139 remove(fileName); 140 }*/ 141 core.stdc.stdio.remove(cFileName); 142 } 143 }