2014/07/06


断続的にデータを受けながら並行で時間差リアクションを行う - すぎゃーんメモ

断続的にデータを受けながら並行で時間差リアクションを行う Go はじめて、の次のGo - すぎゃーんメモ にて作った go-genki-bot 、UserStreamから Tweet 取得して返信する...

http://d.hatena.ne.jp/sugyan/20140705/1404493007
ちょっと動きは違うんだけど、こういうパターンもあるよねー。という事で。
package main

import (
    "bufio"
    "fmt"
    "os"
    "runtime"
    "time"
)

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())

    queue := make(chan rune5)

    t := time.AfterFunc(-1func() {
        // ある分だけ読み込む
        leave: for {
            select {
            case r := <-queue:
                fmt.Println("recv"string(r))
            case <-time.After(100 * time.Millisecond):
                // 100ms 読めなかったら諦める
                break leave
            }
        }
    })

    // タイマーは止めておく
    t.Stop()

    in := bufio.NewReader(os.Stdin)
    for {
        // 何かキー入力
        r, _, err := in.ReadRune()
        if err != nil {
            break
        }

        // LFはいらない
        if r == 0x0A {
            continue
        }

        // タイマーを活性化(3秒後)
        t.Reset(3 * time.Second)

        // タイマーに読んで貰う為に入力したキーをchanで送信しておく
        queue<-r
    }
}
入力を得たらタイマーを活性化する。タイマーは一つしか使わなくて、データが来るたびに更新するのでデータが最後の入力から3秒間何も更新がなければ発動する。タイマーは発動すると100ms内に見つかった分だけ抜き取って表示。
$ go run jisa.go 

recv あ
あいうえ
recv あ
recv い
recv う
recv え
この手法は gof の画面表示部分で使われていて、連続するキー入力に対して毎回描画を行っていると画面がチラ付くという問題を回避出来る。

詳しくは以下を参照して下さい。
Golang でコマンドライン Fuzzy Finder 「gof」作った。 - Qiita

この記事は Go Advent Calendar 2013 の 10 日目の投稿です。 はじめに 業務のツールや連携させる一部の機能として golang を使い出している方もチラホラ現れ始めました。 ...

http://qiita.com/mattn/items/edea1be5a6d84663ab8b
Go Advent Day 19 - Eject the Web - The Gopher Academy Blog

Other Articles Next article Go Advent Day 20 - Go in Academia: Emulating Wireless Networks Previous ...

http://blog.gopheracademy.com/day-19-eject-the-web

2014/07/03


先日、C言語向けのパッケージマネージャ clib を紹介したのですが、その後 Windows で使えそうなパッケージを3つ程書きました。
Big Sky :: clib の使い勝手にマジ感動した

C言語でアプリケーションを書くのは他の言語と比べて少し気合が必要ですよね。例えば HTTPからデータを取得する 取得したデータを json パースする 結果の一部を色付きで表示する こんな場合、C言語...

http://mattn.kaoriya.net/software/lang/c/20140627222830.htm

locale-string.c

最近のライブラリは文字列が utf-8 前提で書かれている物が多く、Windows だと「それ、ツライわー(汗)」だったりするのですが、かと言ってこれだけの為に変換ライブラリを入れるのはアレですし、iconv 入れちゃったら GPL(LGPL) だし仕事で使えねー、みたいな事が起きてしまいます。
でもロケール文字列と utf-8 との変換なら mbstowcs や wcstombs があれば出来るし、Windows なら MultiByteToWideChar や WideCharToMultiByte があれば出来るので、それだけのライブラリを書きました。
mattn/locale-string.c - GitHub
https://github.com/mattn/locale-string.c
使い方は簡単。
setlocale(LC_CTYPE"");
const char* ptr = "こんにちわ世界";
char* mbs = utf8_to_locale_alloc(ptr);
assert(NULL != mbs);
char* utf8 = utf8_from_locale_alloc(mbs);
assert(NULL != utf8);
assert(0 == strcmp(ptr, utf8));
使い終わったら free が必要。utf8_to_locale_alloc で utf-8 文字列をロケール文字列へ、utf8_from_locale_alloc でロケール文字列から utf-8 へ変換します。
Linux や Mac だと必要ない機能なのでマクロを用意してあります。
#ifdef _WIN32
# define UTF8_ALLOC(p) utf8_from_locale_alloc(p)
# define UTF8_FREE(p) free(p)
# define LOCALE_ALLOC(p) utf8_to_locale_alloc(p)
# define LOCALE_FREE(p) free(p)
#else
# define UTF8_ALLOC(p) (p)
# define UTF8_FREE(p)
# define LOCALE_ALLOC(p) (p)
# define LOCALE_FREE(p)
#endif
Windows 以外ならばメモリ確保も解放も行いませんので、UTF8_ALLOC して使い終わったら UTF8_FREE しておくと UNIX でも Windows でも同じ様に動作する、という仕組みです。

wcwidth.c

皆さんしってる wcwidth です。
wcwidth, wcswidth, wcwidth_cjk, wcswidth_cjk がそろっていますが、オマケで utf-8 文字列の幅を求める string_width と string_width_cjk も付いてきます。
mattn/wcwidth.c - GitHub
https://github.com/mattn/wcwidth.c
assert(14 == string_width("こんにちわ世界"));
assert(20 == string_width("こ★ん■に●ち▲わ☆世◆界"));
assert(26 == string_width_cjk("こ★ん■に●ち▲わ☆世◆界"));
こんな感じに使います。

ansicolor-w32

最近の Linux のアプリケーションでコンソールに色付きで出力される物も最近では珍しくなくなってきました。
ただ Windows だと API が超メンドクサイので Constellation さんの console-colors.c を使うのが良いのですが、UNIX 系ツールを移植していてなるべくオリジナルコードを触りたくない場合にはツライんです。
mattn/ansicolor-w32.c - GitHub
https://github.com/mattn/ansicolor-w32.c
そこで ansicolor-w32.c というのを書きました。ansicolor-w32.h を include すると、エスケープシーケンスを解析して Windows でも色付けで表示してくれます。
ansicon というツールも存在しますが、このライブラリはそれ無しでも色付け可能です。

fprintf, fputs, printf, puts だけ対応しています。

#include <stdio.h>
#ifdef _WIN32
# include "ansicolor-w32.h"
#endif

int
main(int argc, char* argv[]) {
  printf("\x1b[2J\x1b[10,10H\x1b[24m\x1b[30m");
  printf("\x1b[42m博\x1b[43m多\x1b[46mの\x1b[45m塩\x1b[0m"); 
  return 0;
}
例えばこんなコードを書いて実行すると
博多の塩
この様に表示されます。

よろしければお使い下さい。MIT ライセンスです。

2014/06/30


夏だし、怖い話しようぜ!
#include <cstdio>
#include <math.h>
 
class C {
public:
  C() {}
  C(double) { printf("hello world\n"); }
};
 
int main(int argc, char** argv)
{
  C(NAN);
  return 0;
}
僕は今日... こんなコードをコンパイルしたんだ...。gcc でコンパイルして実行したんだ...。

hello world
期待通りだった。
僕は安心し、これを今度は MSVC でビルドしたんだ...。

実行すると...

何も出ない...

僕は怖くなった。

何なんだ!何なんだ!NaN なんだーーー!

僕の C++ 人生はなんだったのか...。僕は病に侵されているに違いない...。

怖いながらもデバッガで追ったんだ...

C++ の怖い話
そしてステップインした...
C++ の怖い話
C++ の怖い話
えっ...

尋常ではない程の汗が僕の頬を伝った。

まっ...まさか!

そう、MSVC には NAN が宣言されていない。
これのおかげで2時間程無駄にした。
Fix test. MSVC doesn't have definition of NAN by mattn - Pull Request #43 - kazuho/picojson - GitHub

Note: https://gist.github.com/mattn/bf1e56aa832c031e5df6 illustrates the problem. MSVC somehow succe...

https://github.com/kazuho/picojson/pull/43
NAN が宣言されていない為に、NAN という変数が宣言されてしまっていた。
NAN なんだ、まったく。
酷い一日だった。
なんて日だ!