Fix build on sparc64-linux-gnu.
[official-gcc.git] / libphobos / src / std / windows / syserror.d
blob73863607dd10d89761cc897a71d544bee5cc0f72
1 // Written in the D programming language.
3 /**
4 * Convert Win32 error code to string.
6 * Copyright: Copyright Digital Mars 2006 - 2013.
7 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
8 * Authors: $(HTTP digitalmars.com, Walter Bright)
9 * Credits: Based on code written by Regan Heath
11 /* Copyright Digital Mars 2006 - 2013.
12 * Distributed under the Boost Software License, Version 1.0.
13 * (See accompanying file LICENSE_1_0.txt or copy at
14 * http://www.boost.org/LICENSE_1_0.txt)
16 module std.windows.syserror;
17 import std.traits : isSomeString;
19 version (StdDdoc)
21 private
23 alias DWORD = uint;
24 enum LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1;
27 /** Query the text for a Windows error code, as returned by
28 $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
29 $(D GetLastError)), as a D string.
31 string sysErrorString(
32 DWORD errCode,
33 // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
34 int langId = LANG_NEUTRAL,
35 int subLangId = SUBLANG_DEFAULT) @trusted;
37 /*********************
38 Thrown if errors that set
39 $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
40 $(D GetLastError)) occur.
42 class WindowsException : Exception
44 private alias DWORD = int;
45 final @property DWORD code(); /// $(D GetLastError)'s return value.
46 this(DWORD code, string str=null, string file = null, size_t line = 0) @trusted;
49 /++
50 If $(D !!value) is true, $(D value) is returned. Otherwise,
51 $(D new WindowsException(GetLastError(), msg)) is thrown.
52 $(D WindowsException) assumes that the last operation set
53 $(D GetLastError()) appropriately.
55 Example:
56 --------------------
57 wenforce(DeleteFileA("junk.tmp"), "DeleteFile failed");
58 --------------------
60 T wenforce(T, S)(T value, lazy S msg = null,
61 string file = __FILE__, size_t line = __LINE__) @safe
62 if (isSomeString!S);
64 else:
66 version (Windows):
68 import core.sys.windows.windows;
69 import std.array : appender;
70 import std.conv : to;
71 import std.format : formattedWrite;
72 import std.windows.charset;
74 string sysErrorString(
75 DWORD errCode,
76 // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
77 int langId = LANG_NEUTRAL,
78 int subLangId = SUBLANG_DEFAULT) @trusted
80 auto buf = appender!string();
82 if (!putSysError(errCode, buf, MAKELANGID(langId, subLangId)))
84 throw new Exception(
85 "failed getting error string for WinAPI error code: " ~
86 sysErrorString(GetLastError()));
89 return buf.data;
92 bool putSysError(Writer)(DWORD code, Writer w, /*WORD*/int langId = 0)
94 wchar *lpMsgBuf = null;
95 auto res = FormatMessageW(
96 FORMAT_MESSAGE_ALLOCATE_BUFFER |
97 FORMAT_MESSAGE_FROM_SYSTEM |
98 FORMAT_MESSAGE_IGNORE_INSERTS,
99 null,
100 code,
101 langId,
102 cast(LPWSTR)&lpMsgBuf,
104 null);
105 scope(exit) if (lpMsgBuf) LocalFree(lpMsgBuf);
107 if (lpMsgBuf)
109 import std.string : strip;
110 w.put(lpMsgBuf[0 .. res].strip());
111 return true;
113 else
114 return false;
118 class WindowsException : Exception
120 import core.sys.windows.windows : DWORD;
122 final @property DWORD code() { return _code; } /// $(D GetLastError)'s return value.
123 private DWORD _code;
125 this(DWORD code, string str=null, string file = null, size_t line = 0) @trusted
127 _code = code;
129 auto buf = appender!string();
131 if (str != null)
133 buf.put(str);
134 if (code)
135 buf.put(": ");
138 if (code)
140 auto success = putSysError(code, buf);
141 formattedWrite(buf, success ? " (error %d)" : "Error %d", code);
144 super(buf.data, file, line);
149 T wenforce(T, S)(T value, lazy S msg = null,
150 string file = __FILE__, size_t line = __LINE__)
151 if (isSomeString!S)
153 if (!value)
154 throw new WindowsException(GetLastError(), to!string(msg), file, line);
155 return value;
158 T wenforce(T)(T condition, const(char)[] name, const(wchar)* namez, string file = __FILE__, size_t line = __LINE__)
160 if (condition)
161 return condition;
162 string names;
163 if (!name)
165 static string trustedToString(const(wchar)* stringz) @trusted
167 import core.stdc.wchar_ : wcslen;
168 import std.conv : to;
169 auto len = wcslen(stringz);
170 return to!string(stringz[0 .. len]);
173 names = trustedToString(namez);
175 else
176 names = to!string(name);
177 throw new WindowsException(GetLastError(), names, file, line);
180 version (Windows)
181 @system unittest
183 import std.algorithm.searching : startsWith, endsWith;
184 import std.exception;
185 import std.string;
187 auto e = collectException!WindowsException(
188 DeleteFileA("unexisting.txt").wenforce("DeleteFile")
190 assert(e.code == ERROR_FILE_NOT_FOUND);
191 assert(e.msg.startsWith("DeleteFile: "));
192 // can't test the entire message, as it depends on Windows locale
193 assert(e.msg.endsWith(" (error 2)"));
195 // Test code zero
196 e = new WindowsException(0);
197 assert(e.msg == "");
199 e = new WindowsException(0, "Test");
200 assert(e.msg == "Test");