1 module clang.util; 2 3 4 version (Windows) { 5 extern(C) private int _mktemp_s(char* nameTemplate, size_t sizeInChars) nothrow @safe @nogc; 6 } 7 8 9 /** 10 Makes a member variable lazy so that it's only computed if necessary. 11 Very hacky, uses undefined behaviour by casting const away as if 12 it were using C++'s `mutable`. 13 */ 14 mixin template Lazy(alias memberVariable) { 15 16 import std.format: format; 17 18 private enum id = __traits(identifier, memberVariable); 19 static assert(id[0] == '_', 20 "`" ~ id ~ "` does not start with an underscore"); 21 22 private enum initVar = id ~ `Init`; 23 mixin(`bool `, initVar, `;`); 24 25 private enum str = q{ 26 ref %s()() @property const scope return { 27 import std.traits: Unqual; 28 if(!%s) { 29 () @trusted { cast(bool) %s = true; }(); 30 () @trusted { cast(Unqual!(typeof(%s))) %s = %s; }(); 31 } 32 return %s; 33 } 34 }.format( 35 id[1..$], 36 initVar, 37 initVar, 38 id, id, id ~ `Create`, 39 id, 40 ) 41 ; 42 43 //pragma(msg, str); 44 mixin(str); 45 } 46 47 48 /** 49 Returns a suitable temporary file name 50 */ 51 string getTempFileName() @trusted { 52 import std.file: tempDir; 53 import std.path: buildPath; 54 55 const pattern = "libclangXXXXXX\0"; 56 57 version (Posix) { 58 import core.sys.posix.stdlib: mkstemp; 59 char[] tmpnamBuf = buildPath(tempDir, pattern).dup; 60 mkstemp(&tmpnamBuf[0]); 61 return tmpnamBuf.idup; 62 } else version (Windows) { 63 char[] tmpnamBuf = pattern.dup; 64 _mktemp_s(&tmpnamBuf[0], tmpnamBuf.length); 65 return buildPath(tempDir, tmpnamBuf.idup); 66 } 67 }