TAG

首都機能移轉 (2) 歌詞 (2) 靠北文 (40) 戲言 (30) 糟糕 (7) ACG (23) Assembly (2) Boost (2) C (31) C++ (69) CMake (4) CSIE (67) Debian (34) Design_Pattern (2) Django (1) Eclipse (1) en_US (13) FFmpeg (3) FoolproofProject (26) FreeBSD (2) Git (4) GNU_Linux (65) IDE (5) Java (11) JavaScript (19) KDE (15) Khopper (16) KomiX (3) Kubuntu (18) Life (1) Lighttpd (2) Mac_OS_X (2) Opera (1) PHP (2) PicKing (2) Programing (21) Prolog (1) Python (7) QSnapshot (2) Qt (30) Qt_Jambi (1) Regular_Expression (1) Shell_Script (7) Talk (98) VirtualBox (7) Visual_Studio (13) Windows (18) zh_TW (36)

2009年9月29日 星期二

爆了

部落格觀察的貼紙爆了。
我不知道是怎麼回事,也不是很在意。基本上那個 widget 是載入最慢的 widget,我只不過是想把它改成 onload 之後再載入到 DOM,失敗之後 rollback,就變這樣了。
我還是認為 HTML 要有個 post 的機制,讓整個文件 layout 出來之後再載入外部文件。這是為什麼 img 標籤希望你指定圖片的寬高,因為不指定的話就要等圖片載入才能知道大小,然後文件就要重新 render,然後你在看的文件內容就會一直改變位置。
不過這樣就沒計數器了,其實我對排名不是很在意。自己寫一個好像也還好,不過有點麻煩。

2009年9月18日 星期五

如何讓你的程式更難理解(5)

int uglystrieq( const char * l, const char * r ) {
    while(*l&&*r&&(*l++|32)==(*r++|32));return *l--||*r--||(*l|32)!=(*r|32);
}
Compare the equivalence of two strings. Case insensitive.
[Edit]
This implementation while crash when passing a 0-lengthed string. Another version:
int _(const char*l,const char*O) {
    return ((*l|32)-(*O|32))?1:*l?_(l+1,O+1):0;
}

2009年9月13日 星期日

Install Windows XP on VirtualBox with SATA support

Briefly in Windows XP:
  1. Download the drivers from Intel
  2. Extract the archive:
    • Windows: Just extract it. You will get an floppy image named F32.IMA
    • Linux: Because of it is a self-extract archive, you can use unzip or p7zip to extract f6flpy32.exe and can still get F32.IMA
  3. Mount the floppy image. No bother to use a real floppy.
  4. In the initialization stage, press F6 to get the external SATA drivers.
  5. Press S to select driver. Please select Intel(R) 82801HEM/HBM SATA AHCI Controller (Mobile ICH8M-E/M)
  6. Then go ahead

2009年9月11日 星期五

Packages in Opera's FTP repository

There is a deb repository that provides apt service. But packages in that one are still depends on Qt3. Packages which are built with Qt4 are only avaliable in FTP repository. Weird Opera.

2009年9月1日 星期二

Pitfalls in shell scripts

When you iterate paths and do something with them, you might be tempted write this:
find . -name blah | xargs rm -f
yeah, I know there is a switch -exec in find, I just don't like it.
This command looks fine, but has two problems:
  1. The length of arguments maybe exceeds the limit of the shell.
  2. The file path may contains some special characters, such like quotes, spaces.
To solve the first issue, a loop maybe useful:
for path in `find . -name blah` ; do
    rm -f "path"
done
This solves the first issue, but the second one remains. For loop treats spaces and newlines as delimiters. But if paths contain spaces, they will cause error.
You can change the delimiter temporary as a workaround, but this will impacts all actions in the loop, I personally don't recommend this.
Or we can use a while loop:
find . -name blah | while read path ; do
    rm -f "$path"
done
should be just fine.
Another common error , comes from:
if [ $str = blah ] ; then
The problem is, $str maybe unset or a null string, or worse, injected with a string such like -f.
Good practice is:
if [ x"$str" = xblah ] ; then

2009年8月27日 星期四

Enable frame buffer in grub2

With legacy grub, if you want to enable frame buffer built in kernel, the option "vga=xxx" is needed in boot command.
However, grub2 provides a newer way to enable the feature. You should set gfxpayload=1280x1024x32, and insmod vbe manually if needed. So where to add? I write it to /etc/grub.d/40_custom, as it is an user custom hook script.
cat <<EOF
insmod vbe
set gfxpayload=1280x1024x32
EOF
You can use vbeinfo in grub2 shell to look up which modes are available.
By the way, DO NOT FORGET to run:
# update-grub
to make newer grub.cfg generated.

2009年8月20日 星期四

Overview of Observer Pattern

如果想要讓某物件在「發生某事」時通知另一個物件「做某事」,那麼我們會使用 Observer Pattern 來實現。簡單的做法是:
class Sender {
    +__new__() {
        this.listener = []
    }
    +somethingHappend() {
        this.listener.each( lambda( l ) {
            l.refresh( arguments )
        } )
    }
    +addListener( that ) {
        this.listener.append( that )
    }
    -trigger() {
        this.somethingHappend()
    }
}
class Receiver {
    +__new__() {
        sender = Sender()
        sender.addListener( this )
    }
    +refresh() {
        // blah blah
    }
}
當 Sender 的 somethingHappend 執行時,它會通知所有已被 addListener 加入的物件執行 refresh 動作。
這個做法很單純,但是不夠泛化,Sender 可能不只有一個事件,該事件也不一定只會呼叫 refresh。
class Observer {
    +connect( slot ) {
        this.listeners.append( slot )
    }
    +__call__() {
        this.listeners.each( lambda( args, l ) {
            l( args )
        }.bind( arguments ) )
    }
    -listeners = []
}
為此我們需要一個統一的介面來操作,class Observer 就此應運而生。
就 connect 而言,我們關心的是事件發出者是誰,它發生什麼事件,事件接收者是誰,它做了什麼事。
稍後我們會處理好事件發出者以及發生什麼事件的辨別方式,因此在這個 Observer 裡只儲存事件接收者和對應的處理函式。slot 即代表被註冊進來的處理函式,儲存起來以備以後使用。
__call__ 這個函式會在事件發生時被呼叫,它做的事很單純,就是呼叫每一個註冊起來的處理函式,並把自己接收到的參數傳給那些處理函式。
當然在這裡最麻煩的就是參數型態及個數,這裡端看各種語言的特性會有不同的實作。基本上動態語言都不會有什麼大問題,但那些靜態語言就需要一些特殊的手法。
使用時就像這樣:
class Sender() {
    +somethingHappend = Observer()
    -trigger() {
        this.somethingHappend( arguments )
    }
}
class Receiver() {
    +__new__() {
        sender = Sender()
        sender.somethingHappend.connect( this.refresh )
    }
    +refresh() {
        // blah blah
    }
}
可以看到 Sender 本身可以持有數個不同的 Observer,而且不同的 Sender 實體可以各自綁定不同的事件。當 Sender 的 trigger 發出事件通知,Receiver 相對應的處理函式就會被喚起。
這裡並沒有討論細節,比方說 mutex lock,解除監聽,還有 receiver 反查 sender 的機制。