1 /** 2 * Copyright: Copyright (c) 2011 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Oct 1, 2011 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module clang.Util; 8 9 import clang.c.Index; 10 11 import std.conv; 12 import std.stdio; 13 14 immutable(char*)* strToCArray(string[] arr) @safe { 15 import std..string : toStringz; 16 17 if (!arr) 18 return null; 19 20 immutable(char*)[] cArr; 21 cArr.reserve(arr.length); 22 23 foreach (str; arr) 24 cArr ~= str.toStringz; 25 26 return &cArr[0]; 27 } 28 29 /** 30 * Trusted: on the assumption that clang_getCString is implemented by the LLVM 31 * community. Any bugs in them should by now be found. 32 */ 33 string toD(CXString cxString) @trusted { 34 auto cstr = clang_getCString(cxString); 35 auto str = to!(string)(cstr).idup; 36 clang_disposeString(cxString); 37 38 return str; 39 } 40 41 template isCX(T) { 42 enum bool isCX = __traits(hasMember, T, "cx"); 43 } 44 45 template cxName(T) { 46 enum cxName = "CX" ~ T.stringof; 47 } 48 49 U* toCArray(U, T)(T[] arr) @safe { 50 if (!arr) 51 return null; 52 53 static if (is(typeof(T.init.cx))) 54 return arr.map!(e => e.cx).toArray.ptr; 55 56 else 57 return &arr[0]; 58 } 59 60 mixin template CX(string name = "") { 61 static if (name.length == 0) { 62 mixin("private alias CType = " ~ cxName!(typeof(this)) ~ ";"); 63 } else { 64 mixin("private alias CType = CX" ~ name ~ ";"); 65 } 66 67 CType cx; 68 alias cx this; 69 70 /** 71 * Trusted: on the assumption that dispose as implemented by the LLVM 72 * community is good _enough_. Any bugs should by now have been found. 73 */ 74 void dispose() @trusted { 75 enum methodCall = "clang_dispose" ~ typeof(this).stringof ~ "(cx);"; 76 77 static if (false && __traits(compiles, methodCall)) 78 mixin(methodCall); 79 } 80 81 @property bool isValid() @safe pure nothrow const @nogc { 82 return cx !is CType.init; 83 } 84 } 85 86 extern (C) int mkstemps(char*, int); 87 extern (C) int close(int); 88 89 class NamedTempFileException : object.Exception { 90 this(string message, string file = __FILE__, size_t line = __LINE__) { 91 super(message, file, line); 92 } 93 } 94 95 File namedTempFile(string prefix, string suffix) { 96 import std.random; 97 import std.file; 98 import std.path; 99 import std.format; 100 101 void randstr(char[] slice) { 102 for (uint i = 0; i < slice.length; ++i) 103 slice[i] = uniform!("[]")('A', 'Z'); 104 } 105 106 string name = format("%sXXXXXXXXXXXXXXXX%s\0", prefix, suffix); 107 char[] path = buildPath(tempDir(), name).dup; 108 const size_t termAnd6XSize = 7; 109 randstr(path[$ - name.length + prefix.length .. $ - suffix.length - termAnd6XSize]); 110 111 int fd = mkstemps(path.ptr, cast(int) suffix.length); 112 scope (exit) 113 close(fd); 114 115 if (fd == -1) 116 throw new NamedTempFileException("Cannot create \"%s\" temporary file.".format(path)); 117 118 return File(path[0 .. $ - 1], "wb+"); 119 }