2009/07/07


kazuhoさんがやってくれました。
ずいぶん前からjsonをC++でパース(SAXじゃなくてDOM)するのに小さいライブラリないかなーと思ってました。個人的にはjson-cというのを使ってたのですが、幾らか気に入らない所があったりビルドが少し手間だったりしていました。STLしか使わなくてvectorとかmapで表現されるツリー構造な物が欲しいなぁって思ってたんです。
とあるIRCで昨日、kazuhoさんと「ほしいですよねー」という話から始まって、githubにあるjsonxxとかも物色しながら「いいのないねー」とか言ってたらkazuhoさんが「もすこし綺麗に書けそう」って言い出して朝から本格的に書き始めてついさっき出来上がりました。速いw
名前はpicojson
とても小さく、実装コードだと300数十ステップ程です。しかもヘッダファイルだけなので管理が楽です。

試しにwassrのpublicタイムラインをパースしてみました。
コードはこんな感じ。
curlのコードではなく、jsonのパース部分を見てください。
#include <curl/curl.h>
#include "../picojson.h"

typedef struct {
  char* data;   // response data from server
  size_t size;  // response size of data
} MEMFILE;

MEMFILE*
memfopen() {
  MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE));
  mf->data = NULL;
  mf->size = 0;
  return mf;
}

void
memfclose(MEMFILE* mf) {
  if (mf->data) free(mf->data);
  free(mf);
}

size_t
memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) {
  MEMFILE* mf = (MEMFILE*) stream;
  int block = size * nmemb;
  if (!mf->data)
    mf->data = (char*) malloc(block);
  else
    mf->data = (char*) realloc(mf->data, mf->size + block);
  if (mf->data) {
    memcpy(mf->data + mf->size, ptr, block);
    mf->size += block;
  }
  return block;
}

char*
memfstrdup(MEMFILE* mf) {
  char* buf = (char*)malloc(mf->size + 1);
  memcpy(buf, mf->data, mf->size);
  buf[mf->size] = 0;
  return buf;
}

using namespace std;
using namespace picojson;

int
main(int argc, char* argv[]) {
  char error[256];

  MEMFILE* mf = memfopen();
  CURL* curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, "http://api.wassr.jp/statuses/public_timeline.json");
  curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
  if (curl_easy_perform(curl) != CURLE_OK) {
    cerr << error << endl;
  } else {
    value v;
    string err;
    parse(v, mf->data, mf->data + mf->size, &err);
    if (err.empty()) {
      array arr = v.get<array>();
      array::iterator it;
      for (it = arr.begin(); it != arr.end(); it++) {
        object obj = it->get<object>();
        cout << obj["user_login_id"].to_str() << ": " << obj["text"].to_str() << endl;
      }
    } else {
      cerr << err << endl;
    }
  }
  curl_easy_cleanup(curl);
  memfclose(mf);

  return 0;
}
こんなに短いコードでアプリが作れる!
STLに慣れた人ならイメージ沸くかと思います。すばらしい!
こういうのが欲しかったんです。
ただまだ出来上がったばっかりですしバグはあるかもしれません。また高機能にするつもりもないでしょうから使用目的を選ぶのが先決かと思います。
ライセンスはBSDとの事なので、バイナリ配布も可能です。

share - Revision 34226: /lang/cplusplus/picojson/trunk

picojson

http://svn.coderepos.org/share/lang/cplusplus/picojson/trunk/
ありがたや、ありがたや。

追記
kazuhoさんも記事を書いてますんでそちらも...
Kazuho@Cybozu Labs: 今更 C++ で JSON パーサ「picojson」を書いたわけ
http://developer.cybozu.co.jp/kazuho/2009/07/c-json-picojson.html
Posted at by



2009/07/05


最後までC言語で書き直そうかと迷いましたが、結局Perlのままになりました。
スクリーンショットは以下
nhk-news
しくみは、起動時にオートディスカバリでフィード一覧をコンボボックスに展開、コンボボックスが選ばれたらフィードを取得してエントリ一覧をリストに展開、リストがダブルクリックされたらHTMLをスクレイピングしてGtk2::Ex::MPlayerEmbedで再生という単純なもの。プレーヤ部分のツールチップにニュース本文が表示されます。
本当は、fltk2でmplayer埋め込みプレーヤを2年ほど前に作ってあったのでそれを使っても良かったのですが、いかんせんfltkがマイナー過ぎるのでやめました。
mattn's nhk-news-pl at master - GitHub

NHK News Movie Player

http://github.com/mattn/nhk-news-pl/tree/master
ライセンスとか難しい物はありません。ソースは上のリンクにあるのでパクるとか、お好み焼きに付けるとか、勝手にして下さい。
問題ありそうならキャプチャは取り下げる予定です。
Posted at by



2009/06/26


Luaでもやろうと思えば、色んな事が出来ます。先日書いた「LuaでTwitterるわ」を良い例に、Luaでも拡張さえ利用すれば何でも出来るんです。
で、今日は何をしようかと考えて...
Luaでmigemoを使用して、本当に「Lua」で「るわ」が検索出来るかどうかやってみようと思います。
#もう結果が見えていますが、やるんです...
まず、Luaで高度な処理を行うには、拡張モジュールを作る必要があります。
MigemoはC/Migemoを基礎ライブラリとして、ラッパI/Fとして作成します。
まずC/Migemoを、香り屋からsvnで取得して、ビルドします。
#今回は、Windowsでコンパイルしています。
C:¥temp> svn co http://cvs.kaoriya.net/svn/CMigemo/trunk cmigemo
C:¥temp> cd cmigemo
C:¥temp¥cmigemo> cp config.mak config.mk.orig
C:¥temp¥cmigemo> vim config.mak
C:¥temp¥cmigemo> diff config.mk.org config.mk
38,39c38,39
< FILTER_CP932  = qkc -q -u -s
< FILTER_EUCJP  = qkc -q -u -e
---
> #FILTER_CP932 = qkc -q -u -s
> #FILTER_EUCJP = qkc -q -u -e
41,42c41,42
< #FILTER_CP932 = nkf -s
< #FILTER_EUCJP = nkf -e
---
> FILTER_CP932  = nkf -s
> FILTER_EUCJP  = nkf -e

C:¥temp¥cmigemo> vcvars32
Setting environment for using Microsoft Visual C++ tools.
C:¥temp¥cmigemo> nmake msvc
C:¥temp¥cmigemo> nmake msvc-dict

次に、今回作成したluamigemoをビルドします。 C:¥Lua¥luamigemo> nmake 後は以下のコードを実行するまで local migemo = require("migemo")
local rex_pcre = require("rex_pcre")

local mcx = migemo.open("C:/temp/cmigemo/dict/migemo-dict")

--migemo.set(
--  mcx,
--  migemo.DICTID_ROMA2HIRA,
--  "C:/temp/cmigemo/dict/roma2hira.dat")

migemo.set(mcx, migemo.OPINDEX_OR, "|");
migemo.set(mcx, migemo.OPINDEX_NEST_IN, "\\(");
migemo.set(mcx, migemo.OPINDEX_NEST_OUT, "\\)");

function test(subject, query)
  local pattern = migemo.query(mcx, query)
  local match = rex_pcre.match(subject, pattern)
  if match then
    print(subject.." is matched with "..query)
  else
    print(subject.." is not matched with "..query)
  end
end

test("まっつん", "mattun")
test("マッツン", "mattun")
test("マッツン", "mattn")
test("幹事", "kanji")
test("私はマッツンです", "watashiHaMattunDesu")
test("るわ", "lua")

今回は、migemoで取得した正規表現パタンを食わせる為にLrexlibという拡張を使用し、検証しています。
実行結果は まっつん is matched with mattun
マッツン is matched with mattun
マッツン is not matched with mattn
幹事 is matched with kanji
私はマッツンです is matched with watashiHaMattunDesu
るわ is not matched with lua
となり、結果「Lua」では「るわ」は検索出来ない事が分かりました。

ダウンロード:
Posted at by