2009年1月29日木曜日

const member function

関数が引数を変更しないときにはconstを引数に付ける.
void func(const string & str) ;
これはstrで参照されるオブジェクトをfuncが変更しないという意味になる.

メンバ関数の場合には,引数以外にも変更することの可能なオブジェクトがある.暗黙裏に渡されるthisである.このthisを変更しないという宣言をするには const を後ろに付ける.

class A {
  void func(void) const;
}
なぜかというと前に付けると,返り値がconstである場合と区別がつかないから.ああ,面倒くさい.

AtomフィードのURL

ブラウザのアドレスバーの右側にでるRSSフィードマークを出す方法.
<link rel="alternate" type="application/atom+xml" title="Atom" href="atom.URL" />
もしくは
<link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="URL" />
head内に書くのがポイント.同じサーバ上にある必要すらない.リダイレクトしようかと思っていたのだけどその必要も無かった.

2009年1月28日水曜日

boost regex でURIパーズ

boost のregular expression library を使って URIをパーズ.こちらのページを参考に.ただちょっと古いようでreg_expression -> basic_regexと読み替えてやる必要がある.

しかし,テンプレートを使ったC++のライブラリの出すエラーメッセージは解読不能だ.1カ所ちょっと使うクラスを間違えただけで,みっしり数百行もエラーが出るのはどうなんだろう? 気の弱いプログラマなら卒倒しかねないぞ.しかもエラーメッセージを見てもまったくエラーの原因がわからないし.やっぱりtemplateは好きになれないなあ.まあ理解不能なメッセージという意味では,latexも似たようなものだが.

#include 
#include 
/**
 *  assumed URI
 *  scheme://[user@][host][:port]/[path][?query][#fragment]
 */
class URI {
public:
  std::string scheme;
  std::string authority;
  std::string user;
  std::string host;
  int         port;
  std::string path;
  std::string query;
  std::string fragment;

  URI(std::string s) {
    static const char * pattern = "\\A([^:]+)://"   // scheme
      "((?:([^:/@]*)@)?([^:@/]*)(?::(\\d+))?)/"   // authority = [user-info@]host[:port]
      "([^\\?]*)(?:\\?([^#]*))?(?:#(.*))?\\z";    // body = [path?query#fragment]

    static const boost::regex e(pattern);
    boost::smatch match;
    regex_match(s, match, e);
    this->scheme    = match[1].str();
    this->authority = match[2].str();
    this->user      = match[3].str();
    this->host      = match[4].str();
    this->port      = atoi(match[5].str().c_str());
    this->path      = match[6].str();
    this->query     = match[7].str();
    this->fragment  = match[8].str();
  }
};

C言語 の配列リテラル

配列を直接初期化してCのプログラム中に書くことができる.こんな感じ.
int A[] = {1, 2, 3};
昔は,グローバル変数か,main関数の中でしか初期化つきで宣言できない,とかいう実装が透けて見えるような制約があったように記憶しているのだけど,gccの4だとごく普通に関数の中でも宣言できるようだ.

で,この書き方は変数の初期化にのみ使えて,例えば関数呼び出しの引数に直接書くことはできない.

void foo(int x[]){}
...
foo({1, 2, 3}); // syntax error

int A[] = {1, 2, 3};
foo(A);         // OK
以前から面倒な仕様だと思っていたのだが,調べてみたらいつの間にか直接書く方法ができていた.
void foo(int x[]){}

foo((int []){1, 2, 3});
見通しは悪いけど,一度変数を宣言するよりはだいぶまし.

これは手元のgcc 4.xで試して動いたというだけなので,どの範囲のコンパイラでサポートされているのかは不明.C90あたりで入っていたんじゃないかと思うので,ほとんどのコンパイラで使えそうだけど.

2009年1月25日日曜日

Mac OSとlinuxの EOF エラーハンドルの違い.

lessのように追記されるファイルから次々に読み込む場合,一度EOFが帰ってきたものに対してスリープして,再度読み込みを行ったりする.が,このときの挙動がlinuxとMac OSで違っていてはまった.
  while (1) {
    char * p = fgets(buf, 1000, fp);
    if (p == NULL) {
      sleep(1);
    } else {
      printf("%s\n", p);
    }
  }
このずさんなコードはlinuxやSolarisだとちゃんと動いて,ファイルに追記されると追従することができるのだが,Mac OSでは動かない.ファイルに追記しても,ずっとfgetsがNULLを返す.

ストリームの中にはすでにEOFに当ったという情報が保持されているのだけど,これを明示的にクリアしてやらないと,いけない,ということのようだ.もっとお行儀のいいコードはこんな感じ.そもそもNULLで返ってきたときに,EOFなのかエラーなのかをferrorでちゃんと見てやって,EOFのときだけ,clearerr()でクリアしてやる.こうするとMac OS でもちゃんと動く.

  while (true) {
    char * p = fgets(buf, 1000, fp);
    if (p == NULL) {
      if (ferror(fp)){
        printf("error, abort\n");
        break;
      }
      clearerr(fp);
      sleep(1);
    } else {
      printf("%s\n", p);
    }
  }
この違いは,きっとSys V系(Linux, Solaris)とBSD系(Mac OS X)に由来する違いなんだろうなあ...

2009年1月24日土曜日

Mac OS ar の COMMAND_MODE

通常の端末からはビルドできるC++のシステムが,eclipseのCDTからだとビルドできないので調べてみた.いちどarで.aを作っておいて,さらにldでリンクするようになっているのだけど,ldのところでこんなエラーがでてこける.
ld: in XXXXX.a, archive has no table of contents
arのほうはこんなふうにかかれている.
ar aruv xxx.o xxx.o ..
arのバイナリは同じものが起動されていることはwhich等で確認できる.

とりあえずの解決

tableがarchiveに入っていないというエラーなので,強制的にtableを作るオプション's'を与えると,とりあえずビルドできるようになる.
ar asruv xxx.o xxx.o ..
しかし's'がデフォルトで, tableを作らないようにするためには'S'で明示しなければならないはず.環境変数でも見ているのかとおもって,マニュアルを見ても何も書かれていない.

もう少し調べてみる

バイナリをstringsで見てみる.最後に怪しいものが...
$ stings `which ar`
...
COMMAND_MODE
legacy
eclipseの中で確認してみるとたしかにこのCOMMAND_MODE環境変数がlegacyに設定されている.端末ではunix2003になっている.
$ echo $COMMAND_MODE
unix2003
$ COMMAND_MODE=legacy make
とやってlegacyを指定してビルドするとeclipse内と同じように失敗する.これが原因であることはほぼ確定.つまり,legacyが指定されているとarのデフォルトの挙動が変わるのだろう.問題はなんでこんなものが指定されているのか,だ.

ググってみたら一番上にこんなページを見つけた.推測でしかないのだが,eclipseはMac OS 10.4でも動くようにビルドされているので,launchd が起動時に識別して付けているのではないか,という話.うーん...

ちなみに,arのstringsでunix2003が引っかからないことからも予想できるように'legacy'以外なら何が指定されていてもちゃんとテーブルが生成される.

どう対処するのがただしいのか分からないのだけど s オプションは,他の環境でも付いていて害があるものではないので,かならずこれを付けるという方向で.

2009年1月23日金曜日

Doxygen

javadocのようなドキュメント作成ツール. ホームページ.サポート言語は
C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), 
Fortran, VHDL, PHP, C#, and to some extent D
だそうだ.すごいね.手元のubuntuにはなぜだか入っていた.入れた記憶はないのだが. 出力フォーマットもゆたかで,HTML,latex のほかに,RTF (MS-Word), PostScript, hyperlinked PDF, compressed HTML, Unix man pageをサポート.

使い方

doxygen -f conf
とやると巨大なコンフィギュレーションファイルができる.デフォルトではhtmlとlatexができるようになっている.当面latexはいらないので,
GENERATE_LATEX  = yes
をno に変更.PROJECT_NAME にプロジェクトの名前を,INPUTに入力ファイルのあるディレクトリを指定.何も指定しないと,カレントディレクトリのみになる.EXTRACT_ALLをyesにしとくと,コメントの無いクラスもドキュメントを作ってくれるので最初はyesにしたほうがいいかもしれない.

で,

doxygen conf
でOK

ドキュメントの書き方

C++の場合,クラスやメソッドの前にスラッシュ3つで始まるコメントとして書く.ほかにもJavaDocスタイルとか,いろいろな書き方をサポートしているようだ.
/// this is a class
class a {
public:
  /// this ia a method
  void b();
};
これでOK. 便利.

Pythonの場合は,Python 標準のドキュメントの書き方でOKらしい.

2009年1月21日水曜日

sudo とfile descriptor

親子プロセス間で通信するためにpipeを使うのはよくある方法だが,sudo を使うとこれがうまく行かない.おそらくsudoが対象コマンドにexecする前に3番以上のディスクリプタを全部クローズしているんだろう.0, 1,2は閉じていないようなのでこれらを使うしかなさそうだ.

面倒.

CentOS5 python 2.6

with statement が使いたいということで,2.6を入れてみる. 手順はここに書かれている通り. 2.6はともかくそろそろ2.5は標準のレポジトリに入っていてもいいとおもうのだけど.

2009年1月7日水曜日

Codesynthesis XSD

Codesynthesis XSD. いわゆるxsd スキーマからC++のオブジェクトを生成することができるシステム. JavaのJaxbに相当するものだと思われる.面白いのはオブジェクトツリーを作る コードの他に,SAX的な(でももっと簡単に使える)ストリームパーザを生成するコードも 生成するらしいこと.

ライセンス

以下は,私の解釈.

GPL.生成されたコードもGPL.なのだが,例外条項がもうけられていて, XSDの機能に対して十分な付加機能がある場合に限っては, XSDおよび生成されたコードを含んだコードを 他のオープンソースライセンスで公開することが可能になっている. さらに,それをその後proprietaryな製品に転用することも可能.

スタイルファイルを整備

改行が br に変換される設定だったのを直して,スタイルファイルをいじった.その結果以前書いたものがめちゃめちゃになったので,手でタグを入れるという地味な作業.

随分読みやすくなった.書く気がおきるというもの.

bjam on ubuntu

いろいろはまってしまったが、 apt-get一発で入るようだ。bjamは独立したパッケージになっているが、それだけ入れてもだめなのがポイント。
sudo apt-get boost-build
設定としては、ホームディレクトリにuser-config.jamファイルを作り下のように書く。ポイントはgcc と ; の間を開けておくこと。どうもパーザが貧弱なので、トークン切り出しがうまくできていないようだ。
using gcc ;

プログラムを用意

test.hpp をtest.cppとmain.cppが共有。

test.hpp

void test();
test.cpp:
#include "test.hpp"
void test() {}
main.cpp
#include "test.hpp"
int main(){
    test();
}

Jamroot ファイルを書く

: は引数間の区切り. つまりrule exe は2引数で、第一引数がターゲットバイナリ名、第二引数に、ソースファイルのリストをとっている。
exe main : main.cpp test.cpp ;

実行

$ bjam
...found 13 targets...
...updating 6 targets...
MkDir1 bin
MkDir1 bin/gcc
MkDir1 bin/gcc/debug
gcc.compile.c++ bin/gcc/debug/main.o
gcc.compile.c++ bin/gcc/debug/test.o
gcc.link bin/gcc/debug/main
...updated 6 targets...
できた。test.hppにタッチするとちゃんと依存関係を認識していて再度コンパイルする。
$ touch test.hpp
$ bjam
...found 13 targets...
...updating 3 targets...
gcc.compile.c++ bin/gcc/debug/main.o
gcc.compile.c++ bin/gcc/debug/test.o
gcc.link bin/gcc/debug/main
...updated 3 targets...
すばらしい。。。

2009年1月6日火曜日

wordpress DB_HOST 書式

wordpress でmysql 接続にunix domain socketを使う場合wp-config.phpに
define('DB_HOST', 'localhost:XXXX');
のように書く.XXXXのところにはパスを書くのだが,これを間違って名前だけ(mysql5.sock)など書くと,なにもエラーが出ずにデフォルトのmysqlソケットに接続してしまうようだ.エラーがでないので気がつくのが遅れて被害拡大.くそー.

2009年1月2日金曜日

pythonのregular expressionで置換

import re
pat = re.compile('aaa.*?aaa', re.DOTALL)
subst = 'aaa --- aaa'
replacd = pat.sub(subst, target)
  • re.DOTALL は'.'が改行にもマッチするように.
  • .*? の '?'は最短マッチ.

firefox 3.0 のワナ

下のようなコードで
   var contentsNodes = document.getElementsByClassName("contents");
   contentsNodes.each( function(node) {
         xxxx
   });
each is not a function というエラーがでる.googleで検索してこのページを見つけた. getElementsByClassNameをfirefox3.0以降が独自実装したため,返ってくる型がprototypeのenumerableでなくなってしまったということらしい.余計なことをしてくれるなあ.prototypeのバージョンが上がれば大丈夫になるんだろうか?

2009年1月1日木曜日

Google Reader を使ったfeed のaggregate と mixi 設定

Google Readerを使って複数のfeedを一つにまとめることができる.
  • フォルダを一つ作り,まとめたいものをそこに入れる.
  • 設定 の フォルダとタブ のタブで,そのフォルダを「公開」に設定
  • 右側に ページへのリンクができるのでそこをクリック
  • ページの右にatomフィードへのリンクができているのでそのURLを取り出す
  • mixi の外部日記のrssにこのURLを登録
とりあえず動いているようだ.

mixi 日記のバックアップ

というか外部ブログに切り替えるので取り出し.
http://milk-tea.que.jp/milk-cake/soft/
のbackup_mixiをつかわせていただく.

rubyで書かれたツール.ちゃんとスロットリングしながらひとつづつダウンロードしてくれる.スロットリングしないとアタックだと判断されてアクセスが停止されるかららしい.適当にタイムアウトしてリトライするようにできていたり,いろいろと芸がこまかい.

日記だけでなくメッセージもダウンロードしてくれるしマイミクさんのアイコンまで..よくできている.

blogger のバックアップ

wget -O - http://hidemon-memo.blogspot.com/feeds/posts/default?max-results=1000 > filename
でatom形式でダウンロードできるようだ.文字だけだから時間も全然かからない.