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 U* toCArray(U, T)(T[] arr) @safe {
42     if (!arr)
43         return null;
44 
45     static if (is(typeof(T.init.cx)))
46         return arr.map!(e => e.cx).toArray.ptr;
47 
48     else
49         return &arr[0];
50 }
51 
52 template isCX(T) {
53     enum bool isCX = __traits(hasMember, T, "cx");
54 }
55 
56 template cxName(T) {
57     enum cxName = "CX" ~ T.stringof;
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     /** Trusted: on the assumption that dispose as implemented by the LLVM
71      * community is good _enough_. Any bugs should by now have been found.
72      */
73     void dispose() @trusted {
74         if (cx is CType.init)
75             return;
76 
77         static if (name.length == 0)
78             enum methodName = "clang_dispose" ~ typeof(this).stringof;
79         else
80             enum methodName = "clang_dispose" ~ name;
81         enum methodCall = methodName ~ "(cx);";
82 
83         static if (__traits(hasMember, clang.c.Index, methodName))
84             mixin(methodCall);
85         else
86             pragma(msg,
87                     "info: (this is not an error or problem, just a note to dextool developers) clang dispose not found: "
88                     ~ methodName);
89 
90         cx = CType.init;
91     }
92 
93     @property bool isValid() @safe pure nothrow const @nogc {
94         return cx !is CType.init;
95     }
96 }