2011/12/07


この記事は Oppai Advent Calendar 2011 の7日目の記事です。
C++11のユーザ定義リテラルを使うと、ユーザ指定のサフィックスに従って型変換や任意の処理を行う事が出来ます。
今日はこれを使って、おっぱいを判定するコードを書いてみました。
#include <iostream>
#include <string>

#define X(x) #x ")"_oppai
#define _(x) "(" #x ")(" X

char constoperator "" _oppai(char const* str, std::size_t len) {
  std::string x(str, len);
  return
    x == "(・)(・)" ? "ハリのあるおっぱい" :
    x == "(.)(.)"   ? "垂れ気味のおっぱい" :
    x == "(◎)(◎)" ? "立体的なおっぱい" :
    x == "(○)(○)" ? "乳輪が大きいおっぱい" :
    x == "(●)(●)" ? "乳輪が大きく、黒いおっぱい" :
    x == "(。)(。)" ? "色が薄く、左向きのおっぱい" :
    "もはやおっぱいではない";
}

int
main(int argc, char* argv[]) {
  std::cout << _(・)(・) << std::endl; // ハリのあるおっぱい
  std::cout << _(.)(.)   << std::endl; // 垂れ気味のおっぱい
  std::cout << _(◎)(◎) << std::endl; // 立派なおっぱい
  std::cout << _(○)(○) << std::endl; // 乳輪が大きいおっぱい
  std::cout << _(●)(●) << std::endl; // 乳輪が大きく、黒いおっぱい
  std::cout << _(。)(。) << std::endl; // 色が薄く、左向きのおっぱい
  return 0;
}
ユーザ定義リテラル便利ですね!
Posted at by



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/09/30


※ネタです

※UDFです


正誤表を書くのにしばらくこの本をちょっと眺めてみたら、SQLiteのUDFって簡単に作れるんだなー、と思った && そういやV8ってライブラリとして簡単にリンクできるはずだな、と思い出した ので、ついカッとなって作った。

sqlite3udf-jseval - GitHub

http://github.com/mattn/sqlite3udf-jseval

UDFうんぬn

ほとんど↑の本、全然関係ないと思ってたけど、やっぱりSQLiteのUDFについて全然書いてなかった。しょうがないので軽く紹介しておくと

UDFを追加する場合、SQLiteの再コンパイルは必要ない (しかるべき所に.soがおいてあればいい)
UDFはこの辺読んどけばだいたい分かる。

例えば文字列っぽいものを返すmyfuncっていうUDFを作りたい場合
SQLITE_EXTENSION_INIT1 static void js_eval_func(sqlite3_context *context, int argc, sqlite3_value **argv);
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api);
の二つの関数を実装したmyfunc.cっていうコードを用意してあげて gcc -o myfunc.so myfunc.c `sqlite_config --cflags` -shared という風にコンパイルして(これはLinuxの場合)、しかるべき場所(LD_LIBRARY_PATHが通る場所)に置いた後、sqliteのシェルで > select load_extension("myfunc.so"); とやればいきなり使える。

sqlite3_value_textはアロケートした文字列を渡して、最終引数に開放関数を渡すというのがUDFのお作法らしい。strdupで確保したポインタは最終引数の関数でfreeする、みたいな。

動かす手順

で、今回作ったのはV8とリンクして、JSの文字列をevalしてくれるjs_evalというUDF。
多分試す人はいないと思うけど、動かすための手順を書くと

V8のビルド

V8を落としてきてビルドする。ただし、SQLiteのUDFは別に-fPICを付けなくてもおk。

js_eval.cppをコンパイル

V8をビルドしたディレクトリにもっていって
g++ -o js_eval.so js_eval.cpp `sqlite_config --cflags` -shared -Iinclude libv8.a -lpthread
そうすると、js_eval.soができるので、これをLD_LIBRARY_PATHが通ったディレクトリに置く

読み込むる

シェルに入って
> select load_extension("myfunc.so"); (※このUDF、食わせるものによってはSQLiteごと落ちるかもしれないので良い子のみんなは注意だ)

キターーーッ

すごい。
sqlite3udf1

全然
sqlite3udf2
役に立つ気がしない。
sqlite3udf3
というかSQLite力が低すぎてどうしたら面白くなるか思いつかない。これを発展させていってTEXTとかに突っ込んだJSONの中身を効率よく検索とか出来たら面白い&実用的なんだけど、道は遠そうだ。


参考
やったーJavaScriptの動くMySQLできたよー - 愛と勇気と缶ビール

しばらく 積ん読 していたこの本をちょっと眺めてみたら、 MySQL のUDFって簡単に作れるんだなー、と思った && そういや V8 って ライブラリ として簡単にリンクできるはずだな、と思い出した...

http://d.hatena.ne.jp/zentoo/20110925/1316961032
Posted at by