2012/11/14


C++ で簡単にフォルダ監視出来るライブラリ無いかなーと思ってたら、手頃なのが見つかった。
simplefilewatcher - Simple, cross platform, object-oriented, file watcher and notifier library. - Google Project Hosting

SimpleFileWatcher is a C++ wrapper for OS file monitoring systems. Currently it uses Win32 ReadDirec...

https://code.google.com/p/simplefilewatcher/
しかもマルチプラットフォームでビルド出来て、さらに他のライブラリに依存しないのでとてもポータブル。
Windows でも inotify を意識せずにコーディング出来ます。
今日はこれと C++ で GNTP Growl する gntppp を使って、あるフォルダ配下のファイルが変更されたら Growl するアプリケーションを作ってみました。
コンパイルには、Crypto++ と、boost が必要です。
mattn/gntppp - GitHub

GNTP++: gntp client library writen in C++

https://github.com/mattn/gntppp
Crypto++ Library 5.6.1 - a Free C++ Class Library of Cryptographic Schemes

Crypto++ Library is a free C++ class library of cryptographic schemes. Currently the library contains the following algorithms

http://www.cryptopp.com/
コードはとてもシンプル!
#include <FileWatcher/FileWatcher.h>
#include <gntp.h>
#include <iostream>

using namespace CryptoPP;
using namespace CryptoPP::Weak1;

gntp* client;

class UpdateListener : public FW::FileWatchListener {
public:
  UpdateListener() {}
  void handleFileAction(
    FW::WatchID watchid,
    const FW::String& dir,
    const FW::String& filename,
    FW::Action action) {
      client->notify<DES, MD5>("changed""File Changed", filename.c_str());
    }
};


int
main(int argc, char **argv) {
  if (argc != 2) {
    std::cerr << "usage: " << argv[0] << " [directory]" << std::endl;
    return -1;
  }

  FW::FileWatcher fileWatcher;
  client = new gntp("file change notifier""");
  client->regist<DES, MD5>("changed");

  try {
    FW::WatchID watchID = fileWatcher.addWatch(
      argv[1], new UpdateListener(), true);

    while(1) {
      fileWatcher.update();
    }
  } catch(std::exception& e) {
    std::cerr << "Exception has occurred: " << e.what() << std::endl;
  }
  return 0;
}
簡単ですね!
mingw32 だと以下の様にコンパイルします。
g++ -g -fpermissive -Iinclude -I.
    source/FileWatcher.cpp source/FileWatcherWin32.cpp
    filechangenotifier.cpp
    -lcryptopp -lws2_32
    -lboost_thread-mgw47-mt-1_50 -lboost_system-mgw47-mt-1_50
※実際は1行
実行してファイルを置いてみる...
file change notifier
おぉ...

ちょっとしたツールを作るには便利ですね。MITなので業務でも使えそうです。
Posted at by



2012/11/07


livedoor Techブログ : 自家製 #isucon2 のつくりかた

先日ISUCON2は幸いにも大好評のうちに終了しましたが、このお題および関係する話題をぜひ多くの人にも知っていただきたい! というかこのまま捨てるとかちょっともったいない! ということもあり、作業対象のアプリケーションコード、およびベンチマークツール一式を公開しています。

http://blog.livedoor.jp/techblog/archives/67728751.html
Go言語が途端に書きたくなったので、Go言語で isucon2 書いてみた。
WAF として web.go を使ってますが、go get を実行すれば勝手にインストールされます。
mattn/go-isucon2 - GitHub

isucon2 written in go

https://github.com/mattn/go-isucon2
作ったばっかりなので、ベンチマーク取ったりはしてません。これからします。
興味のある方どうぞ。
Posted at by



2012/11/05


前回は JSMN というのを試したけど、今度も matsuu さんのブクマから。。。
parson

Lightweight json parser and reader written in C.

http://kgabis.github.com/parson/
特徴は
  • 軽い (2ファイルだけ)
  • 単純なAPI
  • ドット記法による json 値のアドレッシング (C言語の構造体やOO言語のオブジェクトに似た感じ。例: "objectA.objectB.value")
  • C89 コンパティブル
  • テストスーツ
前回の JSMN とは違い、メモリを動的に確保するタイプ。DOM の様にルートノードから探索を始め、最終的にルートノードを指定してメモリを開放する。
今回もtwitterのタイムラインをパースしよう。 #include <assert.h>
#include <string.h>
#include <memory.h>
#include <curl/curl.h>
#include "parson.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));
  if (mf) {
    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) return block; // through
  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;
  if (mf->size == 0return NULL;
  buf = (char*) malloc(mf->size + 1);
  memcpy(buf, mf->data, mf->size);
  buf[mf->size] = 0;
  return buf;
}

int
main() {
  CURL* curl;
  MEMFILE* mf = NULL;
  char* js = NULL;
  int i;

  mf = memfopen();

  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, "http://api.twitter.com/1/statuses/user_timeline.json?screen_name=otsune");
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
  curl_easy_perform(curl);
  curl_easy_cleanup(curl);

  js = memfstrdup(mf);
  memfclose(mf);

  JSON_Value *root_value = json_parse_string(js);
  JSON_Array *tweets = json_value_get_array(root_value);
  for (i = 0; i < json_array_get_count(tweets); i++) {
    JSON_Object *tweet = json_array_get_object(tweets, i);
    printf("%s%s\n",
      json_object_dotget_string(tweet, "user.screen_name"),
      json_object_dotget_string(tweet, "text"));
  }

  json_value_free(root_value);
  free(js);
}
なにこれ!めちゃ簡単。しかもソースを見たところユニコードに対応してる。そしてドット演算子、良いすね。JSON XPath の様ですね。ただ残念ながら JSON XPath の様に .. でスキップする機能は無かったですが。

しかしながらこれC言語の JSON パーサの中では、私が知る限り一番扱いやすいと思いますね。(C++は別です)
MIT ライセンスなのでプロジェクトでも使って行きたいと思います。
Posted at by