2009-07-15
本を検索して yonda4.com に呟きやすくするブックマークレット作りました
はじめに
Twitter 経由で、読んだ本を紹介しあえるサイト yonda4.com がリリースされましたね!
このサイトは @yonda4 に本の名前をつぶやくだけで、本の紹介ページが生成されるという「本格書籍紹介サイト」です!
すごいですね!きゃっふきゃふですね!
というわけで
このサイトに本を紹介しやすくするために、 twitter のページから本を検索するブックマークレットを作ってみました。
javascript:(function(s){s.src="http://amachang.sakura.ne.jp/misc/amazon/search.js";document.body.appendChild(s)})(document.createElement('script'))
twitter のホームに行って、このコードをブラウザのロケーションバーに貼付ければ、実行できます!
使い方も簡単!
1. 本の名前を入力
2. 右上に候補が出るので、本を選ぶ
3. メッセージが作成されるので、あとは呟くだけ!
あ、あと、書籍名の後に、半角スペース空けて感想なんかも書き込むと、ナウでクールでヤングにバカうけな感じと思います1
ぜひぜひ
ご利用ください。
追記
バグ修正しました><
2009-07-13
Amino というライブラリを使ってみた
これ
CBBs - Concurrent Building Blocks
内容
スレッド 1 で入力を Shift_JIS -> UTF-16 変換して、 UTF-16 のデータをキューに入れる。
スレッド 2 でキューから UTF-16 のデータを取り出して、 UTF-16 -> EUC-JP 変換して出力
結果
$ g++ -O2 -lpthread -licuuc -licudata main.cpp && time ./a.out > out 0.37user 0.03system 0:00.40elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+8408minor)pagefaults 0swaps $ g++ -O2 -lpthread -licuuc -licudata main.cpp -DMULTI_THREAD && time ./a.out > out 0.34user 0.07system 0:00.30elapsed 139%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+6784minor)pagefaults 0swaps
うーん
なんか 0.1 秒早くなったけど、たぶん使いどころ違うんだろうなー。
ソース
#include <iostream> #include <unicode/uclean.h> #include <unicode/ucnv.h> #include <amino/thread.h> #include <amino/queue.h> #include <boost/tuple/tuple.hpp> const size_t CHUNKSIZE = 4096; class DecodeOp { std::istream &in_; UErrorCode uerr_; UConverter &ucnv_; int8_t charSize_; amino::LockFreeQueue<boost::tuple<UChar*, size_t> >& queue_; public: DecodeOp(std::istream &in, const std::string &charset, amino::LockFreeQueue<boost::tuple<UChar*, size_t> >& queue) : in_(in), uerr_(U_ZERO_ERROR), ucnv_(*ucnv_open(charset.c_str(), &uerr_)), charSize_(ucnv_getMinCharSize(&ucnv_)), queue_(queue) { } ~DecodeOp() { ucnv_close(&ucnv_); } void operator()() { char inBuf[CHUNKSIZE]; std::streamsize readSize = 0, consumedSize = 0, lastReadSize = 0; while (readSize = in_.rdbuf()->sgetn(inBuf, CHUNKSIZE - lastReadSize + consumedSize)) { const char* inBufBegin = inBuf; const char* inBufEnd = inBufBegin + readSize; size_t bufSize = charSize_ * readSize; UChar* buf = new UChar[bufSize]; UChar* bufBegin = buf; const UChar* bufEnd = bufBegin + bufSize; ucnv_toUnicode(&ucnv_, &bufBegin, bufEnd, &inBufBegin, inBufEnd, NULL, false, &uerr_); consumedSize = inBufBegin - inBuf; queue_.enqueue(boost::tuple<UChar*, size_t>(buf, bufBegin - buf)); lastReadSize = readSize; } size_t bufSize = charSize_ * (lastReadSize - consumedSize); UChar* buf = new UChar[bufSize]; UChar* bufBegin = buf; const UChar* bufEnd = bufBegin + bufSize; ucnv_toUnicode(&ucnv_, &bufBegin, bufEnd, NULL, NULL, NULL, true, &uerr_); queue_.enqueue(boost::tuple<UChar*, size_t>(buf, bufEnd - bufBegin)); queue_.enqueue(boost::tuple<UChar*, size_t>(NULL, 0)); } }; class EncodeOp { std::ostream &out_; UErrorCode uerr_; UConverter &ucnv_; int8_t charSize_; amino::LockFreeQueue<boost::tuple<UChar*, size_t> >& queue_; public: EncodeOp(std::ostream &out, const std::string &charset, amino::LockFreeQueue<boost::tuple<UChar*, size_t> >& queue) : out_(out), uerr_(U_ZERO_ERROR), ucnv_(*ucnv_open(charset.c_str(), &uerr_)), charSize_(ucnv_getMaxCharSize(&ucnv_)), queue_(queue) { } ~EncodeOp() { ucnv_close(&ucnv_); } void operator()() { boost::tuple<UChar*, size_t> bufData; while (true) { while (!queue_.dequeue(bufData)) { } UChar* buf = boost::get<0>(bufData); size_t bufSize = boost::get<1>(bufData); if (buf == NULL) { break; } const UChar* bufBegin = buf; const UChar* bufEnd = buf + bufSize; size_t writeSize = bufSize * charSize_; char* outBuf = new char[writeSize]; char* outBufBegin = outBuf; const char* outBufEnd = outBufBegin + writeSize; ucnv_fromUnicode(&ucnv_, &outBufBegin, outBufEnd, &bufBegin, bufEnd, NULL, false, &uerr_); out_.write(outBuf, (outBufBegin - outBuf)); assert(bufEnd == bufBegin); delete[] outBuf; delete[] buf; } } }; #include <sstream> int main() { struct Guard { UErrorCode err; Guard() : err(U_ZERO_ERROR) { u_init(&err); } ~Guard() { u_cleanup(); } } guard; amino::LockFreeQueue<boost::tuple<UChar*, size_t> > queue; std::stringstream s; int i = 1000000; while (i--) { s << "\x82\xA0"; s << "\x82\xA1"; s << "\x82\xA2"; s << "\x82\xA3"; } DecodeOp fromSjisOp(s, "Shift_JIS", queue); EncodeOp toEucOp(std::cout, "EUC-JP", queue); #ifdef MULTI_THREAD amino::Thread encoderThread(fromSjisOp), decoderThread(toEucOp); encoderThread.join(); decoderThread.join(); #else fromSjisOp(); toEucOp(); #endif }
今日の出来事
天野「ツインタワーの・・・」
誰か「え、プリンタワーですか?」
天「あ、ツ、です。ツインタワー」
誰「はい」
天「サイボウズ・ラボです」
誰「え、サイボウズ・ブラボーですか?」
天「・・・」
プリンタワーのサイボウズ!ブラボー!
Visual Studio で exe を ldd する(依存する dll を調べる)方法
今日、教えていただいた方法。
Visual Studio には dumpbin.exe というコマンドラインツールがついているので、それを使う。
C:\bin> dumpbin /DEPENDENTS hoge.exe Microsoft (R) COFF/PE Dumper Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file hoge.exe File Type: EXECUTABLE IMAGE Image has the following dependencies: KERNEL32.dll msvcrt.dll msvcrt.dll Summary 4000 .bss 6000 .data 1000 .idata 35000 .rdata 7000 .stab 27000 .stabstr CE000 .text
これは便利
2009-07-10
tmux 入れてみた
以下を見て
時代はGNU screenからtmuxへ - それ、Gentooだとどうなる?
Ubuntu に tmux を入れてみた
インストール方法
まず ncurses を入れる
$ sudo apt-get install libncurses5-dev
次に、最新版をダウンロード
$ wget http://downloads.sourceforge.net/sourceforge/tmux/tmux-0.9.tar.gz?use_mirror=jaist
次に、ビルド
$ tar xvfz tmux-0.9.tar.gz $ cd tmux-0.9 $ ./configure $ make && sudo make install
設定ファイル
時代はGNU screenからtmuxへ - それ、Gentooだとどうなる? に書かれている例をそのまま ~/.tmux.conf にコピペ。
起動
$ tmux
とりあえず
C-b c と C-b n だけでも、便利に使えることが分かったのでジョジョに覚えていこう。ジョジョに。
- C-b c
- ウィンドウを作る
- C-b n
- ウィンドウの移動
vim の :tabe と gt に似ている。
もうちょっといろいろやってみた
- C-b ?
- ヘルプ
- C-b =
- スクロールしたいときに
- C-b "
- ペイン追加
- C-b o
- ペインの選択
- C-b :select-layout main-vertical
- main-vertical レイアウトが一番使い易い
- C-b [
- C-b ]
- はり付け
純粋な感動
2009-07-07
boost::is_convertible はどうやってるか
概ね以下のような感じ
template <typename From, typename To> struct is_convertible_basic_impl { // 2 つの同名関数を作って static no_type _m_check(...); static yes_type _m_check(To); // 関数の戻り値の型を見る(どっちの関数が使われるかを見る) static bool value = sizeof( _m_check(From) ) == sizeof(yes_type); };
これで From 型のオブジェクトが To 型に代入できるかが、コンパイル時に分かるのな
sizeof の以外な使い道。
2009-07-06
みんなの願い事が分かる API
みなさん!七夕ですね!
七夕といえば、願い事!
みなさんは、どんな願い事をしますか?
そして、気になるあの子はどんな願い事をしているのでしょうか?
気になりません?
それならこれ!
Twitter ユーザーみんなの願い事が以下の API に集まって来るようです。
http://search.twitter.com/search.json?q=%23tanzaku
なんだかワクワクしますね!
さっそく
僕もこんなものを作ってみました(IE は 8 以上でしか確認していません><)
というわけで
みなさんも一年に一度だけの、 API 試してはいかがでしょうか☆キラッ
C++ で Buzztter を Growl する
はじめに
Buzztter の RSS を持ってきて、新しいキーワードを Growl に表示するものを作ってみた。
C++ でも boost::asio とか、 libxml2 とかを使うとけっこうサクっと書ける。ってこともないか。。
必要なもの
ソース
#include <libxml/xmlreader.h> #include <boost/asio.hpp> #include <boost/shared_ptr.hpp> #include <boost/unordered_map.hpp> #include <Growl/Growl.h> static CFTypeRef notifications[] = { CFSTR("Buzz word arrived.") }; static int notifyReading(void *in, char* buf, int len) { return static_cast<std::istream*>(in)->rdbuf()->sgetn(buf, len); } int main(int argc, char *argv[]) { Growl_Delegate delegate; InitGrowlDelegate(&delegate); delegate.applicationName = CFSTR("cppclient"); CFTypeRef keys[] = { GROWL_NOTIFICATIONS_ALL, GROWL_APP_ID }; boost::shared_ptr<const __CFArray> allNotifications( CFArrayCreate( NULL, notifications, sizeof(notifications) / sizeof(notifications[0]), &kCFTypeArrayCallBacks ), &CFRelease ); CFTypeRef values[] = { allNotifications.get(), CFSTR("com.buzzter") }; CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values, sizeof(keys) / sizeof(CFTypeRef), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); delegate.registrationDictionary = dict; Growl_SetDelegate(&delegate); bool first = true; boost::unordered_map<std::string, bool> seen; while (true) { boost::asio::ip::tcp::iostream s("buzztter.com", "http"); s << "GET /ja/rss HTTP/1.0\r\n" << "Host: buzztter.com\r\n" << "\r\n" << std::flush; std::string line; while (std::getline(s, line)) { if (line == "\r") break; } boost::shared_ptr<xmlTextReader> reader(xmlReaderForIO(notifyReading, NULL, &s, NULL, NULL, 0), xmlFreeTextReader); while (xmlTextReaderRead(reader.get()) == 1) { if (xmlTextReaderDepth(reader.get()) == 3 && std::string("title") == reinterpret_cast<const char*>(xmlTextReaderConstName(reader.get()))) { std::ostringstream title; while (xmlTextReaderRead(reader.get()) == 1 && xmlTextReaderDepth(reader.get()) == 4) { title << std::string(reinterpret_cast<const char*>(xmlTextReaderConstValue(reader.get()))); } if (!first && !title.str().empty() && !seen[title.str()]) { boost::shared_ptr<const __CFString> word( CFStringCreateWithCString( NULL, reinterpret_cast<const char*>(title.str().c_str()), kCFStringEncodingUTF8 ), CFRelease ); Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext( CFSTR("Buzzter"), word.get(), CFSTR("Buzz word arrived."), NULL, 0, false, NULL ); } seen[title.str()] = true; } } first = false; sleep(60); } }
こんな感じでコンパイル
$ g++ -framework Growl -framework Carbon -lboost_system-mt -lxml2 main.cpp