1 module libssh.mix;
2 
3 package:
4 
5 import std.array : appender;
6 import std.algorithm : map;
7 import std.string : lineSplitter, strip, startsWith;
8 import std.range : put;
9 
10 string appendToAllLines(string lines, string suffix, string g_prefix, string g_suffix)
11 {
12     auto buf = appender!string;
13 
14     if (g_prefix.length)
15     {
16         put(buf, g_prefix);
17         put(buf, "\n");
18     }
19 
20     foreach (line; lines.lineSplitter.map!strip)
21     {
22         if (line.startsWith("//")) // comment
23         {
24             put(buf, line);
25         }
26         else if (line.startsWith("%")) // not append
27         {
28             put(buf, line[1..$]);
29         }
30         else if (line.length)
31         {
32             put(buf, line);
33             put(buf, suffix);
34         }
35         put(buf, "\n");
36     }
37 
38     put(buf, g_suffix);
39 
40     return buf.data;
41 }
42 
43 unittest
44 {
45     enum src = `
46     int foo(int a, int b)
47 
48     // comment
49 
50     %version (Windows) {}
51     %else {
52         int bar(some / random % string)
53     %}
54     `;
55 
56     enum r1 = appendToAllLines(src, ";", "{", "}");
57     enum e1 = `{
58 
59 int foo(int a, int b);
60 
61 // comment
62 
63 version (Windows) {}
64 else {
65 int bar(some / random % string);
66 }
67 
68 }`;
69 
70     static assert(r1 == e1);
71 
72     enum r2 = appendToAllLines(src, "{ mixin(rtLib); }", "", "");
73     enum e2 = `
74 int foo(int a, int b){ mixin(rtLib); }
75 
76 // comment
77 
78 version (Windows) {}
79 else {
80 int bar(some / random % string){ mixin(rtLib); }
81 }
82 
83 `;
84 
85     static assert(r2 == e2);
86 }
87 
88 string pastFunctions(string input, string libname="lib")
89 {
90     version (libssh_rtload)
91         return appendToAllLines(input, "{ mixin(SSLL_CALL); }",
92                     `mixin SSLL_INIT; @api("`~libname~`") {`, `}`);
93     else
94         return appendToAllLines(input, ";", "extern (C) {", "}");
95 }