Skip to content

Instantly share code, notes, and snippets.

@miau
Created February 8, 2011 22:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miau/817427 to your computer and use it in GitHub Desktop.
Save miau/817427 to your computer and use it in GitHub Desktop.
// D で作る Win32 DLL - プログラミング言語 D 2.0
// http://www.kmonos.net/alang/d/2.0/dll.html
// から拝借。
//
// -w オプションつきでコンパイルすると以下のエラーになったので default: を追加しています
// warning - dll.d(8): Error: switch statement has no default
// warning - dll.d(8): Error: statement is not reachable
import core.runtime;
import std.c.windows.windows;
HINSTANCE g_hInst;
extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
Runtime.initialize();
break;
case DLL_PROCESS_DETACH:
Runtime.terminate();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
// Multiple threads not supported yet
return false;
default:
}
g_hInst=hInstance;
return true;
}
// コンパイル方法:
// dmd -ofhttp.dll http.d wstring.d dll.d http.def OLEAUT32.LIB
//
// テスト方法:
// rdmd -unittest http.d wstring.d dll.d http.def OLEAUT32.LIB
//
// wtypes、oleauto 利用のため、
// svn export http://svn.dsource.org/projects/bindings/trunk/win32
// で取得した Bindings for the Windows API を
// %programfiles%\dmd2\src\phobos\win32
// として配置しています。
module http;
import std.stdio;
import std.conv; // for to!wstring
import std.c.wcharh;
import win32.oleauto; // for SysAllocString
import win32.wtypes; // for BSTR
import wstring;
import std.algorithm; // for splitter
import std.string; // for string
version (none)
{
import std.regex;
}
extern (Windows) {
int GetPluginType() {
return 1;
}
BSTR GetName() {
return SysAllocString("http");
}
BSTR GetVersion() {
return SysAllocString("0.0.2");
}
BSTR GetAuthor() {
return SysAllocString("@miau_jp");
}
BSTR GetSyntax() {
return SysAllocString("[http://~:title=タイトル]");
}
BSTR GetDescription() {
return SysAllocString("http記法");
}
BSTR GetExample() {
return SysAllocString("[http://www.google.co.jp/:title=Google]");
}
BSTR PluginInline(
in char* escapedString,
in char* plainString,
in char* documentName,
in char* fileName,
in char* documentFolder,
in char* templateFolder,
in char* settingsName) {
string s = ntsToString(plainString);
wstring ws = SjisToUtf16(s);
return SysAllocString(_PluginInline(ws).ptr);
}
}
wstring _PluginInline(wstring s) {
version (none)
{
// 以下のエラーになるので正規表現を利用しない形に変更
// core.exception.AssertError@D:\dmd2\windows\bin\..\..\src\phobos\std\regex.d(1689): 5
wstring re_url = to!wstring(std.regex.url);
auto captures = match("http:" ~ s, "(" ~ re_url ~ "):title=(.*)").captures;
if (!captures.empty) {
return `<a href="` ~ captures[1] ~ `">` ~ captures[captures.length] ~ `</a>` ~ "\0";
}
}
auto split = split(s, ":title=");
if (split.length == 2) {
return `<a href="http:` ~ split[0] ~ `">` ~ split[1] ~ `</a>` ~ "\0";
}
return "can't analyse!"; // assert 失敗時に文字化けしないよう、エラーメッセージは ASCII で書く
}
unittest {
wstring expected = `<a href="http://www.google.co.jp/">Google 日本</a>` ~ "\0";
wstring result = _PluginInline("//www.google.co.jp/:title=Google 日本");
assert(result == expected, to!string(result ~ expected));
}
// -unittest で起動した際、main() が無いとエラーになるのでダミーの main() を作成する
version(unittest) {
void main() {
writeln("*** unittest passed ***");
}
}
LIBRARY "http.dll"
EXETYPE NT
CODE PRELOAD DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
GetPluginType
GetName
GetVersion
GetAuthor
GetSyntax
GetDescription
GetExample
PluginInline
module wstring;
import std.c.locale; // for setlocale, LC_CTYPE
import std.c.stdlib; // for wcstombs
import std.c.string; // for strlen
import std.string;
// null-terminated string の char* を string に変換する
string ntsToString(const char* s)
{
if (s is null) {
return cast(string) null;
}
return s[0 .. strlen(s)].idup;
}
// Shift_JIS の string を UTF-16 の wstring で返す
// 参考:
// http://pokohimesama.blog98.fc2.com/?mode=m&no=337
wstring SjisToUtf16(string s)
{
if (s is null) {
return cast(wstring) null;
}
wchar[] ws;
ws.length = s.length + 1;
auto locale_org = setlocale(LC_CTYPE, "");
scope(exit) { setlocale(LC_CTYPE, locale_org); }
auto n = mbstowcs(ws.ptr, s.toStringz(), ws.length);
return ws[0 .. n].idup;
}
unittest
{
wstring expected, result;
expected = "あいう";
result = SjisToUtf16(x"82a0 82a2 82a4"); // 「あいう」の Shift_JIS 表現
assert(expected == result);
expected = "\uff5e"; // 「~」(FULLWIDTH TILDE)。念のためコードポイントで比較する。
result = SjisToUtf16(x"8160"); // 「~」の Shift_JIS 表現
assert(expected == result);
}
// wchar* 同士の wstrcmp()。実装を変更したため未使用。
int wstrcmp(in wchar* a, in wchar* b) {
const(wchar)* p = a;
const(wchar)* q = b;
while (1) {
if (*p == '\0' && *q == '\0') {
return 0;
} else if (*p > *q) {
return 1;
} else if (*p < *q) {
return -1;
} else {
p++;
q++;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment