IT戦記 このページをアンテナに追加 RSSフィード

2009-07-15

本を検索して yonda4.com に呟きやすくするブックマークレット作りました

はじめに

Twitter 経由で、読んだ本を紹介しあえるサイト yonda4.com がリリースされましたね!

twitterで読書記録。読んだ4!

このサイトは @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. 本の名前を入力

f:id:amachang:20090715140448p:image

2. 右上に候補が出るので、本を選ぶ

f:id:amachang:20090715140447p:image

3. メッセージが作成されるので、あとは呟くだけ!

f:id:amachang:20090715140446p:image

あ、あと、書籍名の後に、半角スペース空けて感想なんかも書き込むと、ナウでクールでヤングにバカうけな感じと思います1

ぜひぜひ

ご利用ください。

追記

バグ修正しました><

2009-07-13

Amino というライブラリを使ってみた

これ

CBBs - Concurrent Building Blocks

via:オレンジニュース(2009-07-10)

内容

スレッド 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 ]
    • はり付け

純粋な感動

コピペすごすぎるだろ JK!(いまさら

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 する

はじめに

BuzztterRSS を持ってきて、新しいキーワード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