1 module esstool.reader; 2 3 import esstool.arrayutil : count, len; 4 5 @safe unittest 6 { 7 static void main(string[] args) 8 { 9 string[] stringList = new string[0]; 10 LineReader reader = new LineReader("./LICENSE"); // The license <Mozilla Public License v2.0> 11 while (reader.readly()) 12 { 13 stringList = stringList ~ [reader.read()]; 14 } 15 16 assert(stringList == readline("./LICENSE")); 17 } 18 } 19 20 /** 21 * Read all lines in file. 22 * Params: 23 * file = The file input; 24 * Returns: All texts in file input. 25 */ 26 string[] readlines(string file) 27 { 28 import std.container : Array; 29 30 auto arr = new Array!string(); 31 32 LineReader reader = new LineReader(file); 33 while (reader.readly()) 34 { 35 arr.insertBack(reader.read()); 36 } 37 38 return arr.data(); 39 } 40 41 interface IReader 42 { 43 /** 44 * Read raw byte from file. 45 */ 46 public ubyte[] readRaw(); 47 48 /** 49 * Read text from file. 50 */ 51 public string read(); 52 } 53 54 class LineReader : IReader 55 { 56 private ubyte[] bufferedArray; 57 private ubyte[] buffered; 58 59 this(string filePath) 60 { 61 import std.file : read, exists, isFile, FileException; 62 63 if (!exists(filePath) || !isFile(filePath)) 64 { 65 throw new FileException("The file not exits!"); 66 } 67 68 this.bufferedArray = (cast(ubyte[]) read(filePath)); 69 itor(); 70 } 71 72 public bool readly() 73 { 74 return len(this.buffered) > 0 || len(this.bufferedArray) > 0; 75 } 76 77 public ubyte[] readRaw() 78 { 79 const int len = len(buffered); 80 ubyte[] bytes = new ubyte[len]; 81 82 for (int i = 0; i < len; i++) 83 { 84 bytes[i] = buffered[i]; 85 } 86 87 itor(); 88 return bytes; 89 } 90 91 public string read() 92 { 93 import std.conv : to; 94 import esstool.stringbuilder; 95 96 StringBuilder builder = new StringBuilder(); 97 98 foreach (ubyte bt; this.buffered) 99 { 100 builder.append(to!char(bt)); 101 } 102 103 itor(); 104 return builder.asString(); 105 } 106 107 /** 108 * Buffed a new line. 109 */ 110 private void itor() 111 { 112 if (count(this.bufferedArray) > 0) 113 { 114 this.buffered = new ubyte[0]; 115 } 116 117 import std.container : Array; 118 119 auto bytes = Array!ubyte(); 120 int end = -1; 121 122 for (int i = 0; i < len(this.bufferedArray); i++) 123 { 124 ubyte bt = this.bufferedArray[i]; 125 if (this.bufferedArray[i] == 13) 126 { 127 end = i; 128 break; 129 } 130 131 bytes.insertBack(bt); 132 } 133 134 if (end == -1) 135 { 136 this.bufferedArray = new ubyte[0]; 137 } 138 else 139 { 140 this.bufferedArray = this.bufferedArray[end + 2 .. $]; 141 } 142 143 this.buffered = bytes.data(); 144 } 145 }