1 // This file is part of Visual D 2 // 3 // Visual D integrates the D programming language into Visual Studio 4 // Copyright (c) 2010 by Rainer Schuetze, All Rights Reserved 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt 8 9 module c2d.dgutil; 10 11 import std.string; 12 import std.ascii; 13 import std.utf; 14 import std.path; 15 import std.array; 16 import core.exception; 17 18 ////////////////////////////////////////////////////////////////////////////// 19 20 class SyntaxException : Exception 21 { 22 this(string msg) 23 { 24 super(msg); 25 count++; 26 } 27 28 static int count; 29 } 30 31 void throwException(string msg) 32 { 33 throw new SyntaxException(msg); 34 } 35 36 void throwException(int line, string msg) 37 { 38 throw new SyntaxException(format("(%d): ", line) ~ msg); 39 } 40 41 void assume(T)(T cond, int line = __LINE__, string file = __FILE__) 42 { 43 debug if(!cond) 44 throw new AssertError(file, line); 45 assert(cond); 46 } 47 48 void assume(T)(T cond, string msg, int line = __LINE__, string file = __FILE__) 49 { 50 debug if(!cond) 51 throw new AssertError(msg, file, line); 52 assert(cond); 53 } 54 55 ////////////////////////////////////////////////////////////////////////////// 56 57 string getNameWithoutExt(string fname) 58 { 59 string bname = baseName(fname); 60 string name = stripExtension(bname); 61 if(name.length == 0) 62 name = bname; 63 return name; 64 } 65 66 ////////////////////////////////////////////////////////////////////////////// 67 68 string reindent(string txt, int indent, int tabsize) 69 { 70 string ntxt; 71 size_t pos = 0; 72 for( ; ; ) 73 { 74 ptrdiff_t p = indexOf(txt[pos .. $], '\n'); 75 if(p < 0) 76 break; 77 ntxt ~= txt[pos .. pos + p + 1]; 78 pos += p + 1; 79 int indentation = 0; 80 for(p = pos; p < txt.length; p++) 81 { 82 if(txt[p] == ' ') 83 indentation++; 84 else if(txt[p] == '\t') 85 indentation = tabsize == 0 ? (indentation + 8) & ~7 : ((indentation + tabsize) / tabsize) * tabsize; 86 else 87 break; 88 } 89 indentation += indent; 90 if(indentation < 0) 91 indentation = 0; 92 93 string spaces = replicate("\t", tabsize == 0 ? 0 : indentation / tabsize) 94 ~ replicate(" ", tabsize == 0 ? indentation : indentation % tabsize); 95 ntxt ~= spaces; 96 pos = p; 97 } 98 ntxt ~= txt[pos .. $]; 99 return ntxt; 100 } 101 102 string cpp_string(string txt) 103 { 104 string ntxt; 105 bool escapeNext = false; 106 foreach(dchar ch; txt) 107 { 108 if(escapeNext) 109 { 110 switch(ch) 111 { 112 case '\\': ch = '\\'; break; 113 case 'a': ch = '\a'; break; 114 case 'r': ch = '\r'; break; 115 case 'n': ch = '\n'; break; 116 case 't': ch = '\t'; break; 117 case '"': ch = '\"'; break; 118 case '\'': ch = '\''; break; 119 default: break; 120 } 121 escapeNext = false; 122 } 123 else if(ch == '\\') 124 { 125 escapeNext = true; 126 continue; 127 } 128 ntxt ~= toUTF8((&ch)[0..1]); 129 } 130 return ntxt; 131 } 132 133 string removeDuplicateEmptyLines(string txt) 134 { 135 string ntxt; 136 size_t npos = 0; 137 size_t pos = 0; 138 while(pos < txt.length) 139 { 140 dchar ch = decode(txt, pos); 141 if(ch == '\n') 142 { 143 uint nl = 0; 144 size_t nlpos = pos; // positions after nl 145 size_t lastnlpos = pos; 146 while(pos < txt.length) 147 { 148 ch = decode(txt, pos); 149 if(ch == '\n') 150 { 151 nl++; 152 lastnlpos = pos; 153 } 154 else if(!isWhite(ch)) 155 break; 156 } 157 if(nl > 1) 158 { 159 ntxt ~= txt[npos .. nlpos]; 160 ntxt ~= '\n'; 161 npos = lastnlpos; 162 } 163 } 164 } 165 ntxt ~= txt[npos .. pos]; 166 return ntxt; 167 } 168 169 unittest 170 { 171 string txt; 172 txt = removeDuplicateEmptyLines("abc\n\n\nefg"); 173 assume(txt == "abc\n\nefg"); 174 txt = removeDuplicateEmptyLines("abc\n\nefg"); 175 assume(txt == "abc\n\nefg"); 176 } 177 178 ////////////////////////////////////////////////////////////////////////////// 179 180 unittest 181 { 182 string txt = 183 "\nvoid foo()\n" 184 ~ "{\n" 185 ~ " if(1)\n" 186 ~ "\tx = 0;\n" 187 ~ "}"; 188 string exp = 189 "\n void foo()\n" 190 ~ " {\n" 191 ~ "\tif(1)\n" 192 ~ "\t x = 0;\n" 193 ~ " }"; 194 195 string res = reindent(txt, 4, 8); 196 assume(res == exp); 197 } 198