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 }