1 /++ 2 This module contains contains some misc. functions. (The name says that) 3 +/ 4 module utils.misc; 5 6 import std.stdio; 7 import std.datetime; 8 9 ///`integer is a `long` on 64 bit systems, and `int` on 32 bit systems 10 alias integer = ptrdiff_t; 11 ///`uinteger` is a `ulong` on 64 bit systems, and `uint` on 32 bit systems 12 alias uinteger = size_t; 13 14 ///Reads a file into an array of string 15 ///Throws exception on failure 16 string[] fileToArray(string fname){ 17 try{ 18 File f = File(fname,"r"); 19 string[] r; 20 string line; 21 integer i=0; 22 r.length=0; 23 while (!f.eof()){ 24 if (i+1>=r.length){ 25 r.length+=5; 26 } 27 line=f.readln; 28 if (line.length>0 && line[line.length-1]=='\n'){ 29 line.length--; 30 } 31 r[i]=line; 32 i++; 33 } 34 f.close; 35 r.length = i; 36 return r; 37 }catch (Exception e){ 38 throw e; 39 } 40 } 41 42 /// Writes an array of string to a file 43 /// Throws exception on failure 44 void arrayToFile(string[] array, string fname){ 45 try{ 46 File f = File(fname,"w"); 47 uinteger i; 48 for (i=0;i<array.length;i++){ 49 f.write(array[i],'\n'); 50 } 51 f.close; 52 }catch (Exception e){ 53 throw e; 54 } 55 } 56 57 /// Returns true if an aray has an element, false if no 58 bool hasElement(T)(T[] array, T element){ 59 bool r = false; 60 foreach(cur; array){ 61 if (cur == element){ 62 r = true; 63 break; 64 } 65 } 66 return r; 67 } 68 /// 69 unittest{ 70 assert([0, 1, 2].hasElement(2) == true); 71 assert([0, 1, 2].hasElement(4) == false); 72 } 73 /// Returns true if array contains all elements provided in an array, else, false 74 bool hasElement(T)(T[] array, T[] elements){ 75 bool r = true; 76 elements = elements.dup; 77 // go through the list and match as many elements as possible 78 for (uinteger i = 0; i < elements.length; i ++){ 79 // check if it exists in array 80 uinteger index = array.indexOf(elements[i]); 81 if (index == -1){ 82 r = false; 83 break; 84 } 85 } 86 return r; 87 } 88 /// 89 unittest{ 90 assert([0, 1, 2].hasElement([2, 0, 1]) == true); 91 assert([0, 1, 2].hasElement([2, 0, 1, 1, 0, 2]) == true); // it works different-ly from `LinkedList.hasElements` 92 assert([0, 1, 2].hasElement([1, 2]) == true); 93 assert([0, 1, 2].hasElement([2, 4]) == false); 94 } 95 /// Returns true if all elements in array match with another array's elements. 96 /// Index, and the number of times the element is present in each array doesn't matter 97 /// 98 /// `toMatch` is the array to perform the check on 99 /// `elements` is the array containing the elements that will be compared against 100 bool matchElements(T)(T[] toMatch, T[] elements){ 101 bool r = true; 102 foreach(currentToMatch; toMatch){ 103 if (!elements.hasElement(currentToMatch)){ 104 r = false; 105 break; 106 } 107 } 108 return r; 109 } 110 /// 111 unittest{ 112 assert("Hello".matchElements("aeloH") == true); 113 assert("abcd".matchElements("cda") == false); 114 } 115 116 /// Returns the index of an element in an array, negative one if not found 117 integer indexOf(T)(T[] array, T element){ 118 integer i; 119 for (i = 0; i < array.length; i++){ 120 if (array[i] == element){ 121 break; 122 } 123 } 124 //check if it was not found, and the loop just ended 125 if (i >= array.length || array[i] != element){ 126 i = -1; 127 } 128 return i; 129 } 130 /// 131 unittest{ 132 assert([0, 1, 2].indexOf(1) == 1); 133 assert([0, 1, 2].indexOf(4) == -1); 134 } 135 136 /// Removes element(s) from an array, and returns the modified array; 137 T[] deleteElement(T)(T[] dat, uinteger pos, uinteger count=1){ 138 T[] ar1, ar2; 139 ar1 = dat[0..pos]; 140 ar2 = dat[pos+count..dat.length]; 141 return ar1~ar2; 142 } 143 /// 144 unittest{ 145 assert([0, 1, 2].deleteElement(1) == [0, 2]); 146 assert([0, 1, 2].deleteElement(0, 2) == [2]); 147 } 148 149 /// Inserts an array into another array, returns the result; 150 T[] insertElement(T)(T[] dat, T[] ins, uinteger pos){ 151 T[] ar1, ar2; 152 ar1 = dat[0..pos]; 153 ar2 = dat[pos..dat.length]; 154 return ar1~ins~ar2; 155 } 156 /// 157 unittest{ 158 assert([0, 2].insertElement([1, 1], 1) == [0, 1, 1, 2]); 159 assert([2].insertElement([0, 1], 0) == [0, 1, 2]); 160 } 161 /// Inserts an element into an array 162 T[] insertElement(T)(T[] dat, T ins, uinteger pos){ 163 T[] ar1, ar2; 164 ar1 = dat[0..pos]; 165 ar2 = dat[pos..dat.length]; 166 return ar1~[ins]~ar2; 167 } 168 /// 169 unittest{ 170 assert([0, 2].insertElement(1, 1) == [0, 1, 2]); 171 assert([2].insertElement(1, 0) == [1, 2]); 172 } 173 174 /// returns the reverse of an array 175 T[] reverseArray(T)(T[] s){ 176 integer i, writePos = 0; 177 T[] r; 178 r.length = s.length; 179 180 for (i = s.length-1; writePos < r.length; i--){ 181 r[writePos] = s[i]; 182 writePos ++; 183 } 184 return r; 185 } 186 /// 187 unittest{ 188 assert([1, 2, 3, 4].reverseArray == [4, 3, 2, 1]); 189 } 190 191 /// Returns true if a string is a number, with a decimal point, or without 192 bool isNum(string s){ 193 bool r=true; 194 uinteger i; 195 bool hasDecimalPoint = false; 196 for (i=0;i<s.length;i++){ 197 if (!"0123456789".hasElement(s[i])){ 198 if (s[i] == '.' && !hasDecimalPoint){ 199 hasDecimalPoint = true; 200 }else{ 201 r = false; 202 break; 203 } 204 } 205 } 206 return r; 207 } 208 /// 209 unittest{ 210 assert("32".isNum == true); 211 assert("32.2".isNum == true); 212 assert("32.2.4".isNum == false); 213 assert("5.a".isNum == false); 214 assert("thisIsAVar_1234".isNum == false); 215 } 216 217 /// Returns a string with all uppercase alphabets converted into lowercase 218 string lowercase(string s){ 219 string tmstr; 220 ubyte tmbt; 221 ubyte diff = 'a' - 'A'; 222 for (integer i=0;i<s.length;i++){ 223 tmbt = cast(ubyte) s[i]; 224 if (tmbt>='A' && tmbt<='Z'){ 225 tmbt += diff; 226 tmstr ~= cast(char) tmbt; 227 }else{ 228 tmstr ~= s[i]; 229 } 230 } 231 232 return tmstr; 233 } 234 /// 235 unittest{ 236 assert("ABcD".lowercase == "abcd"); 237 assert("abYZ".lowercase == "abyz"); 238 } 239 240 /// returns true if all characters in a string are alphabets, uppercase, lowercase, or both 241 bool isAlphabet(string s){ 242 uinteger i; 243 bool r=true; 244 for (i=0;i<s.length;i++){ 245 if ((s[i] < 'a' || s[i] > 'z') && (s[i]<'A' || s[i] > 'Z')){ 246 r = false; 247 break; 248 } 249 } 250 return r; 251 } 252 /// 253 unittest{ 254 assert("aBcDEf".isAlphabet == true); 255 assert("ABCd_".isAlphabet == false); 256 assert("ABC12".isAlphabet == false); 257 } 258 259 /// generates a markdown table for some data. 260 /// 261 /// `headings` is the headings for each column. Left-to-Right 262 /// `data` contains each row's data. All rows must be same length 263 string[] makeTable(T)(string[] headings, T[][] data){ 264 assert(headings.length > 0, "cannot make table with no headings"); 265 assert(data.length > 0, "cannot make table with no data"); 266 assert(headings.length == data[0].length, "headings.length does not equal data.length "~to!string(headings.length)~"!="~ 267 to!string(data[0].length)); 268 import utils.lists; 269 // stores the data in string 270 string[][] sData; 271 // convert it all to string 272 static if (is (T == string)){ 273 sData = data; 274 }else{ 275 sData.length = data.length; 276 foreach (rowNum, row; data){ 277 sData[rowNum].length = row.length; 278 foreach (cellNum, cell; row){ 279 sData[rowNum][cellNum] = to!string(cell); 280 } 281 } 282 } 283 // now make the table 284 LinkedList!string table = new LinkedList!string; 285 // add headings 286 { 287 string line; 288 string alignment; 289 line = headings[0]; 290 alignment = "---"; 291 for (uinteger i = 1; i < headings.length; i ++){ 292 line ~= " | "~headings[i]; 293 alignment ~= " | ---"; 294 } 295 table.append([line, alignment]); 296 } 297 // now begin with the data 298 foreach (row; sData){ 299 string line/* = row[0]*/; 300 foreach (cell; row){ 301 line ~= cell~" | "; 302 } 303 line.length -= 3; 304 table.append (line); 305 } 306 string[] r = table.toArray; 307 .destroy(table); 308 return r; 309 }