1 /** 2 Reading files without the D runtime. 3 4 Copyright: Guillaume Piolat 2015-2016. 5 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 6 */ 7 module dplug.core.file; 8 9 import core.stdc.stdio; 10 11 import dplug.core.nogc; 12 13 nothrow: 14 @nogc: 15 16 /// Replacement for `std.file.read`. 17 /// Returns: File contents, allocated with malloc. `null` on error. 18 /// Note: the result file gets an additional terminal zero after the slice, so that 19 /// it can be converted to a C string at no cost. 20 // FUTURE: this should be depreciated in favor of take a char*, this is confusing 21 ubyte[] readFile(const(char)[] fileNameZ) 22 { 23 // assuming that fileNameZ is zero-terminated, since it will in practice be 24 // a static string 25 FILE* file = fopen(assumeZeroTerminated(fileNameZ), "rb".ptr); 26 if (file) 27 { 28 scope(exit) fclose(file); 29 30 // finds the size of the file 31 fseek(file, 0, SEEK_END); 32 long size = ftell(file); 33 fseek(file, 0, SEEK_SET); 34 35 // Is this too large to read? 36 // Refuse to read more than 1gb file (if it happens, it's probably a bug). 37 if (size > 1024*1024*1024) 38 return null; 39 40 // Read whole file in a mallocated slice 41 ubyte[] fileBytes = mallocSliceNoInit!ubyte(cast(int)size + 1); // room for one additional '\0' byte 42 size_t remaining = cast(size_t)size; 43 44 ubyte* p = fileBytes.ptr; 45 46 while (remaining > 0) 47 { 48 size_t bytesRead = fread(p, 1, remaining, file); 49 if (bytesRead == 0) 50 { 51 freeSlice(fileBytes); 52 return null; 53 } 54 p += bytesRead; 55 remaining -= bytesRead; 56 } 57 58 fileBytes[cast(size_t)size] = 0; 59 60 return fileBytes[0..cast(size_t)size]; 61 } 62 else 63 return null; 64 } 65 ubyte[] readFile(const(char)* fileNameZ) 66 { 67 import core.stdc.string: strlen; 68 return readFile(fileNameZ[0..strlen(fileNameZ)]); 69 } 70 71 72 /// Replacement for `std.file.write`. 73 /// Returns: `false` on error. 74 bool writeFile(const(char)[] fileNameZ, const(ubyte)[] bytes) 75 { 76 // assuming that fileNameZ is zero-terminated, since it will in practice be 77 // a static string 78 FILE* file = fopen(assumeZeroTerminated(fileNameZ), "wb".ptr); 79 if (file) 80 { 81 scope(exit) fclose(file); 82 83 size_t n = fwrite(bytes.ptr, 1, bytes.length, file); 84 return n == bytes.length; 85 } 86 else 87 return false; 88 }