1 module dnv.error;
2 
3 import std.conv : to;
4 import std.string : format, split;
5 import std.algorithm : findSplitAfter;
6 import std.range : retro;
7 
8 
9 auto findLast(R1, R2)(R1 haystack, R2 needle) {
10   return haystack.retro
11     .findSplitAfter(needle.retro)[0]
12     .to!R1.retro;
13 }
14 
15 auto findBetween(R1, R2)(R1 haystack, R2 start, R2 end) {
16   // NOTE: this extract first found `end` to backward nearest `start`
17   //       including both corner ranges.
18   return haystack.findSplitAfter(end)[0]
19     .findLast(start);
20 }
21 
22 unittest {
23   assert(findLast("abcdefg abc", "ab").to!string == "abc");
24   assert(findBetween("a abcdefg bc", "a", "bc").to!string == "abc");
25 }
26 
27 
28 enum CImportEnum(string name, string headerPath) = function(){
29   enum start = "typedef enum";
30   enum header = import(headerPath);
31   enum end = "} " ~ name ~ ";";
32   enum cdef = findBetween(header, start, end).to!string;
33   enum content = cdef.findSplitAfter("{")[1].findSplitAfter("}")[0];
34   return "extern (C++) enum %s : int {%s".format(name, content);
35 }();
36 
37 mixin(CImportEnum!("CUresult", "cuda.h"));
38 mixin(CImportEnum!("nvrtcResult", "nvrtc.h"));
39 
40 
41 unittest {
42   static assert(CUresult.CUDA_ERROR_UNKNOWN == 999);
43   static assert(nvrtcResult.NVRTC_SUCCESS == 0);
44 }
45 
46 
47 class CudaError(Result) : Exception {
48   const Result result;
49 
50   this(Result r, string file = __FILE__, int line = __LINE__) {
51     result = r;
52     super(toString, file, line);
53   }
54 
55   override string toString() {
56     return Result.stringof ~ "." ~ result.to!string;
57   }
58 }
59 
60 void check(Result, string file = __FILE__, int line = __LINE__)(Result result) {
61   if (result) {
62     throw new CudaError!Result(result, file, line);
63   }
64 }
65 
66 void cuCheck(string file = __FILE__, int line = __LINE__)(int result) {
67   if (result) {
68       check!(CUresult, file, line)(cast(CUresult) result);
69   }
70 }
71 
72 void nvrtcCheck(string file = __FILE__, int line = __LINE__)(int result) {
73   if (result) {
74       check!(nvrtcResult, file, line)(cast(nvrtcResult) result);
75   }
76 }
77 
78 
79 unittest {
80   import std.exception;
81   import dnv.storage;
82   import dnv.driver;
83 
84   try {
85     check(CUresult.CUDA_ERROR_UNKNOWN);
86   } catch(CudaError!CUresult e) {
87     auto s = e.toString();
88     assert(s == "CUresult.CUDA_ERROR_UNKNOWN");
89   }
90   assertThrown(new Array!float(3, 100));
91 }