programmingの最近のブログ記事

Brainfu*k のコンパイラを作るという「どう書く?org」のお題投稿してみました。さくっと書いたコードをブラッシュアップしている隙に数分の差で言語一番乗りを逃してしまった上に、さらに出題者の dankogai さんに「256 バイトぐらいケチってんじゃねぇ」と添削されました

すごい。256 バイトの配列を用意して char を添え字に使うという、この発想はなかったわ。勉強にさせてもらいました。

一部のHTMLタグを通すフィルタ」というお題に投稿してみました。 C は意外と言語別の一番乗りになりやすいかも。

どう書く?org初投稿してみた。short code 気味にしてみたつもりだが、今になって for の内部を次のようにもっと短くできることに気づいた。落ち着いたら追加でコメントしておこう。

なんか Web アプリっぽいモノを作るのも楽しいけど、こういうのも楽しい。言語別のカバレッジを見てみると LL, 関数型言語が上位を占めているが、 C が PHP と同程度、さらには Perl より多いのが特徴的。腕の見せ所に余地のある言語が上位に来る傾向だろうか。

libcurl の C++ ラッパライブラリ curlpp を使って HTTP 経由でコンテンツをやり取りしようという試みです。

ネット上の何処かにあるフィードのデータを整形して Twitter へ投げるような場合にはフィードのデータを GET する場合と、Twitter へ データを POST する。2つのパターンがありますが、まずは GET 編。

いきなり答えですが、単純に URL へ GET リクエストを送るという最小限のコードはこれだけ。

cleaner はコンストラタとデストラクタで cURLpp の初期化、終了化をやってくれるもの。 あとの 3 行はほぼ見たままなのだけど、setOpt の仕方が少々変わっていて

のようにでファインマクロは使わなくなっています。 libcurl でいうところの CURL_OPT_XXXX のデファインに対応するクラスが cURLpp::Options に準備されているようです。そして、そのクラスのインスタンスを setOpt に渡すことで curl ハンドラの設定行います。

でも、これだと単に標準出力にコンテンツを出力しておしまいなので、画面に出さずにメモリに入れるようにしてみたいのですが、それにはURL を設定した行の下に下の 2 行を追加すれば大丈夫です。

ちょっと分かりにくいけど、データを受け取ったら CurlHandler::writeMemoryCallback にデータを渡すようにする設定です。 libcurl でいうところの CURLOPT_WRITEFUNCTION の設定です。libcurl のドキュメント には size_t function( void *ptr, size_t size, size_t nmemb, void *stream) とか書いてるわりに、curlpp では 4 つ引数のある関数は受け取ってもらえませんでしたので、3 つで我慢しました。この関数は一回のリクエストで何回呼ばれるかは保証されていませんので、呼ばれるごとに受信したデータを後ろに繋いでいく必要があります。こんな感じで:

以上で、ざーっと curlpp で GET してレスポンスのデータをメモリに代入するところまでやってきました。最後に全体を貼り付けておきます。

前回は xpath で簡単に RSS からタイトルを抜き出す方法を書いたのですが、下記のようにデフォルトの名前空間が指定されている RSS1.0 では、xpath "//title/item" では 取得できないことが分かりました。

<rdf:RDF
  xmlns="http://purl.org/rss/1.0/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xml:lang="ja">

つまり、xpath "//item" は名前空間なしの素の item エレメントであって、デフォルト名前空間の下にある item という名前のエレメントにはマッチしないということらしいのです。じゃあどうやってそれを xpath で表すかというと、表す方法はないとか…あわわ。

ということで、以下のような感じでなんとかクリア。 get_children で地道に辿っていく方法もあるのですが、 RSS1.0 と 2.0 では item ノードの階層が違うので、共通で使えるコードとなると xpath の方が単純に書けていいと思います。厳密さを撮るか簡便さを取るか、ですね。

#include <iostream>
#include <libxml++/document.h>
#include <libxml++/parsers/domparser.h>
#include <libxml++/nodes/node.h>
#include <libxml++/nodes/element.h>
#include <libxml++/nodes/textnode.h>

using namespace std;
using namespace xmlpp;

int main ( void ){
   DomParser parser;
   parser.parse_memory( string_rss );
   Element *root = parser.get_document()->get_root_node();
   NodeSet items = root->find("//*[name()='item']");

   for( NodeSet::iterator it = items.begin(); 
          it != items.end(); it++ ){
      const NodeSet value = (*it)->find( "//*[name()='title']" );
      string title = dynamic_cast< Element *>(value[0])
                       ->get_child_text()->get_content();
      cout << "Title: " + title << endl;
   }

   return 0;
}
find ではなく get_children を使って書くと item の NodeList を取るのは以下のようになります。それほど複雑でもないので xpath に慣れていない場合はこっちの方が良いかも。
   /* RSS 2.0 */
   Node::NodeList items = root->get_children("item");
   /* RSS 1.0 */
   if( items.empty() ){
      const Node::NodeList ch = root->get_children("channel");
      if( ! ch.empty() ){
         items = ch.front()->get_children("item");
      }
   }

ちょっとしたプログラムを書くなら、開発の手軽さとライブラリの豊富さから考えても使う言語は Perl か PHP あたりのスクリプト言語になるのですが、一方で C や C++ のようなコンパイル言語を全く使わないかというと、実は全然そうでもなくて、とはいってももっぱら読む方が多いのですが、C++ のライブラリとかってあまり使ったことがないので、libxml の C++ ラッパライブラリの libxml++を使ってみました。

ドキュメントを読んで、RSS から title を抜き出すのを作ってみました。以下のような感じ。エラー処理とかは一切ないですが。

#include <iostream>
#include <libxml++/document.h>
#include <libxml++/parsers/domparser.h>
#include <libxml++/nodes/node.h>
#include <libxml++/nodes/element.h>
#include <libxml++/nodes/textnode.h>

using namespace std;
using namespace xmlpp;

int main ( void ){
   DomParser parser;
   parser.parse_memory( string_rss );
   Element *root = parser.get_document()->get_root_node();
   NodeSet items = root->find("//item");

   for( NodeSet::iterator it = items.begin(); 
          it != items.end(); it++ ){
      const NodeSet value = (*it)->find( "title" );
      string title = dynamic_cast< Element *>(value[0])
                       ->get_child_text()->get_content();
      cout << "Title: " + title << endl;
   }

   return 0;
}

get_root_node で ルートノードを取ってきた後は、ルートノードに対して find で欲しいノードを検索して、見つかったノードの集合をイテレータを使って各ノードにアクセスするという形です。 find は XPath を引数にして欲しいノードを取ってこれるので、 思っていたより簡単にできました。タイトルだけを抜き出すなら本当は find("//item/title") でも良いのですが、title の他にも link や pubDate を取ってきたいときは上記のような形になります。

とまあ、これだけでは何ですので、pipes で集約した RSS をポーリングして twitter に更新するプログラムを C++ で作って見ようかななんて思ったり思わなかったりしています。なので次回は curlpp の説明になるかもしれません。

昨日Twiitter ですが、javascript の IE でのバグを修正して、さらに grid.css を適用させてみました。 これで IE, firefox, Wii で同じような見た目になりました。

javascript の IE でのバグだけれども、これは YAHOO.tw.class.Icon みたいにプロパティ名に 'class' という識別子を使ったら動かなかったというもの。これは IE のバグというよりは、予約語を使ってしまった僕が悪いです。

twiitter

Wii のインターネットチャンネルで遊べる Twitter クライアントを作ってみました。 その名も ”Twiitter”。

名前を先に思いついて、twiitter で検索しても今のところパッと見で typo しかでてこないから、誰かに先を越されるのも嫌なんで作ってみた次第です。Wii 向けと言いつつ、リモコンのセンサ情報は使ってないので、ただ文字を大きくしただけと言われればそれまでなのですが…。

左側のリプライや URL にリンクを貼られてなかったり、機能不足の感は否めませんが、だらだらと wii リモコンで twitter をブラウジングするのもそんなに悪くないかなという感じ。右側に並ぶアイコンをドラッグ&ドロップで上のマスに入れるか、public timeline で左側に表示されるアイコンをクリックすることで、ユーザを渡り歩いていくことが出来ます。 認証周りが面倒なので update 機能はありませんし、protected な friend も表示されません。

実装の話をすると、ブラウザ上の動作は javascript で YUI を使っています。裏側つまり、 twitter api と XHR のプロクシは curl でバイパスさせるだけの php。

一番苦労したところはロゴ。よろしければお試しください。

Wii meets YUI

| | トラックバック(0) http://tsuyuguchi.com/masaaki/mt/archives/2007/09/08-2351.php のはてなブックマーク件数

今更かもしれないが、Wii 向けのページでも YUI が使えると言うことが分かった。正確に言うと、Wii リモコンのセンサ情報を扱う処理以外は YUI が使えると言うこと。

もう少し詳しく説明すると、Wii に搭載されているブラウザは Opera 9 for Deviceで、YUI は 多くの OS で Opera 9.x がサポートされている ということなので、試しに Ajax と Drag and Drop を使ったページを作って Wii で試してみたが、問題なく動いた。Clendar や RichText Editor など重そうなのは試していない。

僕が作ったページに限った部分で言えば、Wii と Firefox で javascript の動作が変わるところはひとつ、「JSON の尻カンマ」だけ。これは Firefox では syntax error にならないが、どうやら Opera ではエラーになるようだ。言語仕様的にはおそらく Opera の方の動作が正しいと思われるが、私のように尻カンマの癖がある人は Wii 向けページを作るときは要注意だと思う。

後は特に気になることはない PC 上で開発とデバッグ&テストを繰り返し、最終的な動作と見栄えの確認を Wii でやるという開発サイクルで OK。

先日、更新処理だけを書きましたが、スクリプト全体を晒してみます。ドキュメントも書いてみました

標準モジュールしか使っていないので、導入も簡単だと思う。導入には .forward とか /etc/aliase を編集できる環境が必要なので、誰でもって訳じゃないけど、twittermail を使うのもちょっと気が引けてしまうと言う場合はおすすめです。

メールから更新というわりにはエンコード変換ルーチン from_to の引数が Guess だったりと、無駄に汎用的に作ってしまったため、短い文章だと文字コードの判定に失敗して文字化けする可能性があるかも。

1 2 3 4 5 6

最近の画像

Zero History - ギブスンの新作が 9 月に発売 -
虐殺器官
ドミニオンのランダマイザアプリ、dominion minion が日本語対応!
ハイペリオンの没落 ~ 完結...でもまだ続く~
ハイペリオンの没落 ~ 完結...でもまだ続く~
ハイペリオン - 長大な叙事詩 SF のスタート -
ハイペリオン - 長大な叙事詩 SF のスタート -
「都市と星」 - 10億年と言われてもよく分からない -
「星を継ぐもの」 - 良い Sci-Fi -
トールサイズのニューロマンサーを買った
虎よ、虎よ! - 主人公フォイルの執念の物語 -

私の本棚

 

自転車走行距離

自転車走行距離

Flickr Photos

FlickrPhotos

なかのひと

Y!ログール

このサイトについて

2015年2月

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28

アーカイブ

My Update

  • Loading...

その他

あわせて読みたいブログパーツ