2011/10/31


node.jsのスライドを見てて、プラットフォームの違いを吸収するnode.jsの核でもある非同期通信ライブラリuvを今日知ったので試してみた。
joyent/libuv - GitHub

platform layer for node.js

https://github.com/joyent/libuv
libev/libeventをwindowsでもちゃんと使いたいという所から出てきたライブラリ。
#include <iostream>
#include <uv/uv.h>

int
main() {
  int r;
  uv_tcp_t tcp;
  struct sockaddr_in server_addr;

  server_addr = uv_ip4_addr("127.0.0.1"80);
  r = uv_tcp_init(uv_default_loop(), &tcp);
  uv_connect_t connect_req;

  r = uv_tcp_connect(&connect_req, &tcp, server_addr,
    [](uv_connect_t *req, int status) {
      std::cout << "connected" << std::endl;

      int r;
      uv_buf_t buf[1];
      uv_stream_t* tcp = req->handle;
      char *req_message = "GET / HTTP/1.0\r\n\r\n";

      buf[0].len = strlen(req_message);
      buf[0].base = req_message;

      uv_write_t write_req;
      r = uv_write(&write_req, tcp, buf, 1,
        [](uv_write_t* req, int status) {
          int r;
          uv_stream_t* tcp = req->handle;

          std::cout << "written" << std::endl;
          r = uv_read_start((uv_stream_t*)tcp,
            [](uv_handle_t* handle, size_t size) -> uv_buf_t {
              std::cout << "alloc " << size << std::endl;
              uv_buf_t buf;
              buf.base = (char*)malloc(size);
              buf.len = size;
              return buf;
            },
            [](uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
              std::cout << "read" << std::endl;

              if (nread < 0) {
                if (buf.base) {
                  free(buf.base);
                }
                uv_close((uv_handle_t*) tcp,
                  [](uv_handle_t* handle) {
                    std::cout << "closed" << std::endl;
                  }
                );
                return;
              }
              std::cout << buf.base << std::endl;
               
              free(buf.base);
              return;
            }
          );
        }
      );
    }
  );

  std::cout << "main" << std::endl;
  uv_run(uv_default_loop());
}
コールバック関数用意するのがめんどくさくなったのでlambdaで。 g++ -std=c++0x foo.cxx -lws2_32
みたいにしてビルドします。
ポート80のサーバに接続して応答を貰うだけ。コールバックベースなので、イベントループで処理待機する事になる。よって結果は main
connected
written
alloc 65536
read
HTTP/1.1 200 OK
Date: Mon, 31 Oct 2011 04:19:52 GMT
Server: Apache/2.2.17 (Win32) mod_fcgid/2.3.6
Last-Modified: Sat, 20 Nov 2004 06:16:26 GMT
ETag: "2000000011333-2c-3e94a902f4280"
Accept-Ranges: bytes
Content-Length: 44
Connection: close
Content-Type: text/html

<html><body><h1>It works!</h1></body></html>
alloc 65536
read
closed

こんな感じになります。1リクエストに対して1つのコールバックが必要になる訳で、若干手間な気がしたのはきっと僕がオッサンになったせいだと思う。まぁWindows特有の手続きやハックが要らないのは良いと思う。

あと、これを実際に生かそうと思うと、処理部もストリーミングに対応する必要があり、例えばリクエストの断片を受信したとしても完了部が来るまで蓄え続ける必要がある点はuvを使っても変わらない訳で、libcurlで良くね?と思ってしまったのも、きっと僕がオッサンになったせいだと思う。


追記
サーバ処理書くならlibcurlでは出来ないので、libuvやpicoev使うといいですね。
Posted at by



2011/10/28


追記:template-vimはthincaさんの物と名前がバッティングしたので、「音速でコーディング出来る」と言う意味でsonictemplate-vimに改名しました。

既に似たのはあると思うので車輪の再発明臭いけど、僕の好みの奴は見た事無かったので自分で書いた。

欲しかった要件としては
  • 同じファイルタイプだけど、使いたい雛形が数パターンある
  • 初期カーソル位置とか欲しい
  • Perlで「package Foo;」とか埋めてくれたら幸せ
  • Go言語でライブラリ書くときとmain書くときで雛形違うよね
みたいなところ。
mattn/sonictemplate-vim - GitHub

template chooser for vim

https://github.com/mattn/sonictemplate-vim
これを使って # vim foo.pl
と新しいPerlスクリプトファイルを開き :Template <TAB> すると
completing templates
みたいに何個か選べる様になる。scriptを選ぶと use strict;
use warnings;
use utf8;

|
|はカーソルの位置
こんなソースが出て # vim lib/Foo/Bar.pm
の様にPerlのパッケージを開きpackageを選択すると package Foo::Bar;

use strict;
use warnings;
use utf8;

|

1
こんな感じになる。なお、どちらも|の位置がカーソル位置になる。 テンプレートファイルはtemplateフォルダに、名前.ファイルタイプの形式で格納されていて {{_name_}}が拡張子なしのファイル名、{{_cursor_}}がカーソル位置、{{_expr_:XXX}}XXXの位置に好きな式が書ける様になっている。
例えばPerlのパッケージであれば、以下の様にバッファファイル名/path/to/module/lib/Foo/Bar.pmからパッケージ名Foo::Barを作り出している。
package {{_expr_:substitute(substitute(substitute(expand('%'), '.*lib[\\/]', '', 'g'), '[\\/]', '::', 'g'), '\.pm$', '', 'g')}};

use strict;
use warnings;
use utf8;

{{_cursor_}}

1
いまの所

C言語のmainソース

#include <stdio.h>

int
main(int argc, char* argv[]) {
  {{_cursor_}}
  return 0;
}

C++のmainソース

#include <iostream>
#include <string>

int
main(int argc, char* argv[]) {
  {{_cursor_}}
  return 0;
}

Go言語のmainソース

package main

func main() {
    {{_cursor_}}
}

Go言語のパッケージソース

package {{_name_}}

{{_cursor_}}

Perlのパッケージソース

package {{_expr_:substitute(substitute(substitute(expand('%'), '.*lib[\\/]', '', 'g'), '[\\/]', '::', 'g'), '\.pm$', '', 'g')}};

use strict;
use warnings;
use utf8;

{{_cursor_}}

1

Perlのスクリプトソース

use strict;
use warnings;
use utf8;

{{_cursor_}}

Perlのテストスクリプトソース

use strict;
use warnings;
use utf8;
use Test::More;

{{_cursor_}}

おまけでREADME.mkd

{{_expr_:expand("%:p:h:t")}}
{{_expr_:repeat("=", len(expand("%:p:h:t")))}}

Usage:
------
{{_cursor_}}

Requirements:
-------------

Install:
--------

License:
--------

Author:
-------

既にファイルに何かが入力されている時には適用出来ない様になっています。
なお、雛形を募集中なのでこれも入れて欲しい!ってのがあったらgithub上でforkしてpullリクエスト送って下さい。
Posted at by




昨日書いたsonictemplate-vimを使えば...
mattn/sonictemplate-vim - GitHub

sonictemplate chooser for vim

https://github.com/mattn/sonictemplate-vim
注意:DBは既に用意されている物とする
以下をやるにはオプションの設定が必要だったのでデフォルトで動作する様にした
template-vimはthincaさんの物と名前がバッティングしたので、「音速でコーディング出来る」と言う意味でsonictemplate-vimに改名しました。

よーいどん

# vim foo.pl
起動したら :Template script と書いてドーン use strict;
use warnings;
use utf8;

_
_はカーソル位置
ここで use DBI;
を足しておこう。さて :Template dbi-connect-sqlite でドーン use strict;
use warnings;
use utf8;
use DBI;

my $dbh = DBI->connect("dbi:SQLite:dbname=_");
$dbh->disconnect;

SQLiteのDBファイル名を書く部分にカーソルが移動しているので./foo.dbとタイプする。その後一行下に移動して :Template dbi-prepare でドーン use strict;
use warnings;
use utf8;
use DBI;

my $dbh = DBI->connect("dbi:SQLite:dbname=./foo.db");
my $sth = $dbh->prepare("_");
$sth->execute;
while (my @row = $sth->fetchrow_array) {
    # print join(', ', @row), "\n";
}
$dbh->disconnect;

SQLを書く書く部分にカーソルが移動しているのでselect * from priceとタイプ。コメントアウトを外して... use strict;
use warnings;
use utf8;
use DBI;

my $dbh = DBI->connect("dbi:SQLite:dbname=./foo.db");
my $sth = $dbh->prepare("select * from price");
$sth->execute;
while (my @row = $sth->fetchrow_array) {
    print join(''@row), "\n";
}
$dbh->disconnect;

おもむろにvim-quickrunでドーーーン!
みかん, 250
りんご, 100
ってなればいいなーって話です。
Posted at by