-->

2010-03-30

UTF-8 と UCS-4 の変換を php で行う場合の例

この記事は文字コードの変換に関する例ではありません。

phpでは文字コードの変換は用意されています。
http://jp2.php.net/manual/ja/function.mb-convert-encoding.php
http://jp2.php.net/manual/ja/mbstring.encodings.php

(例1) unicode番号にして戻す。
$ php -r 'var_export(unpack("N", mb_convert_encoding("〓", "UCS-4", "UTF-8"))); print "\n";';
array (
  1 => 12307,
)
$ php -r 'var_export(mb_convert_encoding(pack("N", 12307), "UTF-8", "UCS-4")); print "\n";';
'〓'

(例2) htmlの数値文字参照に使う。
utf8ucs4.php.2010-03-30.gz

文字参照 - Wikipedia: 数値文字参照(文字参照)
HTML Document Representation: 5.3.1 Numeric character references

UTF-8の正規表現

array.patterns.Blocks.UTF-8.php part2 が新しい記事です。

この記事は array.patterns.Blocks.UTF-8.php の紹介です。
wagahaiwa_nekodearu.2010-03-30.tar.gz をダウンロードします。
青空文庫 から 789_ruby_5639.zip をダウンロードして wagahaiwa_nekodearu.txt を同じディレクトリにコピーします。
$ tar xvzf wagahaiwa_nekodearu.2010-03-30.tar.gz
$ cd wagahaiwa_nekodearu
$ cp -i /tmp/wagahaiwa_nekodearu.txt .
$ php wagahaiwa_nekodearu.txt.php > wagahaiwa_nekodearu.txt.php.txt
$ head -n20 wagahaiwa_nekodearu.txt.php.txt
112: CJK Unif: 吾輩
100: Hiragana: は
112: CJK Unif: 猫
100: Hiragana: である
  1: Basic La: \r\n
112: CJK Unif: 夏目漱石
  1: Basic La: \r\n\r\n-------------------------------------------------------\r\n
 99: CJK Symb: 【
101: Katakana: テキスト
112: CJK Unif: 中
100: Hiragana: に
112: CJK Unif: 現
100: Hiragana: れる
112: CJK Unif: 記号
100: Hiragana: について
 99: CJK Symb: 】
  1: Basic La: \r\n\r\n
 99: CJK Symb: 《》
149: Halfwidt: :
101: Katakana: ルビ
これは使い方のサンプルなので、文字を分割したい場合は chasen, kakasi, mecab がお勧めです。
array.patterns.Blocks.UTF-8.php の元となるデータはhttp://unicode.org/Public/UNIDATA/Blocks.txtです。

2010-03-29

phpの配列関数の多次元配列対応

array_ksort.2010-04-01.tar.gz
このファイルは ksort() の例です。
グローバル関数に登録すると、ややこしいので extra::array_ksort() などにすると邪魔にならないかもしれません。

2010-03-27

jsparsenodetree.c part2

このファイルの差分は、例えば javascript に対する php で言うところの token_get_all() のような機能が欲しい場合の例です。

http://ido.nu/kuma/2009/10/22/spidermonkey-parsenode-to-json/ の jsparsenodetree.c に関数の引数のための修正をした際の差分が下記になります。
jsparsenodetree.c.2010-03-27.diff.gz
インストールに成功した場合、下記のようになります。
$ cat good.js
function test(arg1, arg2)
{
}
$ jsparsenodetree good.js
{
  "node":  "LIST",
  "token": "LC",
  "list": [
    {
      "node":  "FUNC",
      "token": "FUNCTION",
      "name": "test",
      "argv": 2,
      "args": [ "arg1", "arg2" ],
      "body": [
      {
        "node":  "LIST",
        "token": "LC",
        "list": [
        ]
      }      ]
    }
  ]
}

jsparsenodetree.c
jsparsenodetree.c part3

javascriptの画像読み込み part2

追記: http://www.appelsiini.net/projects/lazyload がお勧めです。



このjavascriptは、例えば、ブラウザのスクロールが必要な、大量の画像が張ってあるページで、一番下までユーザーが閲覧することが無い場合に、画像のダウンロード量を減らす、といったことに使えます。
仮に、10画面分の長さがあるとして、すべての画像のサイズの合計が10MBの場合で、スクロールしないで閉じた場合には1MBで、半分スクロールした場合に5MB、といったトラフィックの量になります。
ユーザーの回線が遅い場合や、古いブラウザの場合や、javascriptがOFFの場合で、そういったユーザーがメインの場合には使えません。

dummyThumbnail.2010-03-28.tar.gz をダウンロードします。
$ tar xvzf dummyThumbnail.2010-03-28.tar.gz
$ cd dummyThumbnail
$ cp -i ../../jquery-1.4.2.min.js .
$ php sample.php > sample.html
$ cat sample.html | sed 's/dummyThumbnail.js/dummyThumbnail.min.js/' | sed 's/sample.html/sample2.html/' > sample2.html
http://jquery.com/ で jquery-1.4.2.min.js をダウンロードして同じディレクトリに入れます。
出来上がった sample.html にブラウザでアクセスします。
ブラウザのスクロールなどに反応して画像が読み込まれます。

2010-03-23

jsparsenodetree.c

こちらに新しい記事があります。
jsparsenodetree.c part2

これは下記のurlの内容の設定例です。
探したところ、javascriptを分割する場合には
http://siliconforks.com/doc/parsing-javascript-with-spidermonkey/
http://ido.nu/kuma/2009/10/22/spidermonkey-parsenode-to-json/
http://www.mozilla-japan.org/js/spidermonkey/
が良いように見受けられます。
各々のサイトから example.c jsparsenodetree.c js-1.8.0-rc1.tar.gz をダウンロードします。
$ tar xvzf js-1.8.0-rc1.tar.gz
$ cd js/src/
$ cp -i /tmp/jsparsenodetree.c .
const char * TOKENS[] を修正します。
$ gcc -o jsparsenodetree -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN -DX86_LINUX  -DDEBUG -DDEBUG_kuma -DEDITLINE -I./Linux_All_DBG.OBJ -DHAVE_VA_COPY -DVA_COPY=va_copy -L./Linux_All_DBG.OBJ -ljs -Wl,-rpath,'$ORIGIN/Linux_All_DBG.OBJ' jsparsenodetree.c
動作しました。
$ cat /tmp/good.js
print('hello world');
$ ./jsparsenodetree /tmp/good.js
{
  "node":  "LIST",
  "token": "LC",
  "list": [
    {
      "node":  "UNARY",
      "token": "SEMI",
      "kid":       {
        "node":  "LIST",
        "token": "LP",
        "list": [
          { "node":"NAME", "token":"NAME", "identifier":"print"},
          { "node":"NULLARY", "token":"STRING", "opcode":"string", "text": "hello world"}
        ]
      }
    }
  ]
}
php の token_get_all($buf); に似た感じになります。
$ ./jsparsenodetree /tmp/good.js | php -r '$buf = file_get_contents("php://stdin"); var_export(json_decode($buf));'
stdClass::__set_state(array(
   'node' => 'LIST',
   'token' => 'LC',
   'list' =>
  array (
    0 =>
    stdClass::__set_state(array(
       'node' => 'UNARY',
       'token' => 'SEMI',
       'kid' =>
      stdClass::__set_state(array(
         'node' => 'LIST',
         'token' => 'LP',
         'list' =>
        array (
          0 =>
          stdClass::__set_state(array(
             'node' => 'NAME',
             'token' => 'NAME',
             'identifier' => 'print',
          )),
          1 =>
          stdClass::__set_state(array(
             'node' => 'NULLARY',
             'token' => 'STRING',
             'opcode' => 'string',
             'text' => 'hello world',
          )),
        ),
      )),
    )),
  ),
))
また
$ pecl list-all|grep -i spidermonkey
pecl/spidermonkey   0.1.4            JavaScript engine for PHP
が、似たような分割ができるのでは?と思いましたが試していないです。
また
const char * TOKENS[] を修正します。
の詳細は jsscan.h の typedef enum JSTokenType {...} を example.c を参考に修正します。
$ diff /tmp/jsparsenodetree.c jsparsenodetree.c
1d0
<
16,18c15,24
< const char * TOKENS[] = {
< #include "tokens.def"
< NULL
---
> const char * TOKENS[87] = {
>   /*"ERROR",*/ "EOF", "EOL", "SEMI", "COMMA", "ASSIGN", "HOOK", "COLON", "OR", "AND",
> "BITOR", "BITXOR", "BITAND", "EQOP", "RELOP", "SHOP", "PLUS", "MINUS", "STAR", "DIVOP",
> "UNARYOP", "INC", "DEC", "DOT", "LB", "RB", "LC", "RC", "LP", "RP",
> "NAME", "NUMBER", "STRING", "REGEXP", "PRIMARY", "FUNCTION", "EXPORT", "IMPORT", "IF", "ELSE",
> "SWITCH", "CASE", "DEFAULT", "WHILE", "DO", "FOR", "BREAK", "CONTINUE", "IN", "VAR",
> "WITH", "RETURN", "NEW", "DELETE", "DEFSHARP", "USESHARP", "TRY", "CATCH", "FINALLY", "THROW",
> "INSTANCEOF", "DEBUGGER", "XMLSTAGO", "XMLETAGO", "XMLPTAGC", "XMLTAGC", "XMLNAME", "XMLATTR", "XMLSPACE", "XMLTEXT",
> "XMLCOMMENT", "XMLCDATA", "XMLPI", "AT", "DBLCOLON", "ANYNAME", "DBLDOT", "FILTER", "XMLELEM", "XMLLIST",
> "YIELD", "ARRAYCOMP", "ARRAYPUSH", "LEXICALSCOPE", "LET", "BODY", "RESERVED", "LIMIT",
また、下記は実行ファイルの移動のサンプルです。
$ gcc -o jsparsenodetree -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN -DX86_LINUX  -DDEBUG -DDEBUG_kuma -DEDITLINE -I./Linux_All_DBG.OBJ -DHAVE_VA_COPY -DVA_COPY=va_copy -L./Linux_All_DBG.OBJ -ljs -Wl,-rpath,'$ORIGIN/../lib64' jsparsenodetree.c

$ mkdir /usr/local/stow/jsparsenodetree-2009-10-22/
$ mkdir /usr/local/stow/jsparsenodetree-2009-10-22/bin
$ mkdir /usr/local/stow/jsparsenodetree-2009-10-22/lib64
$ cp -i jsparsenodetree /usr/local/stow/jsparsenodetree-2009-10-22/bin/
$ cp -i Linux_All_DBG.OBJ/libjs.so /usr/local/stow/jsparsenodetree-2009-10-22/lib64/
$ cd /usr/local/stow/
$ stow jsparsenodetree-2009-10-22/

$ find jsparsenodetree-2009-10-22/ ! -type d
jsparsenodetree-2009-10-22/bin/jsparsenodetree
jsparsenodetree-2009-10-22/lib64/libjs.so

$ find /usr/local/ -type l -exec ls -al {} \; | grep jsparsenodetree-2009-10-22
lrwxrwxrwx 1 root root 54 2010-03-24 07:07 /usr/local/bin/jsparsenodetree -> ../stow/jsparsenodetree-2009-10-22/bin/jsparsenodetree
lrwxrwxrwx 1 root root 49 2010-03-24 07:07 /usr/local/lib64/libjs.so -> ../stow/jsparsenodetree-2009-10-22/lib64/libjs.so

$ find jsparsenodetree-2009-10-22/ -type f -exec strip {} \;

jsparsenodetree.c part2
jsparsenodetree.c part3

php の 正規表現 (Perl 互換) 入れ子 サンプル

$buf = "...";
$pattern = "/"
    . "{";
$bracketsNum = 8;
for ($i = 0; $i < $bracketsNum; $i++)
{
    $pattern .= ""
        . "(?:(?:"
        . "(?:[^\{\}]*)"
        . "|"
        . "(?:(?:"
        . "{";
}
$pattern .= ""
    . "(?:[^\{\}]*)";
for ($i = 0; $i < $bracketsNum; $i++)
{
    $pattern .= ""
        . "}"
        . ")*)"
        . ")*)";
}
$pattern .= ""
    . "}"
    . "/";
if (preg_match_all($pattern, $buf, $matches))
{
    var_export($matches);
}
大外の{...}ごとに分割します。
"...", '...', /.../ などに {} があると失敗します。
その場合、そういったパターンを用意します。
$p1 = "(?:[^\{\}]*)";

$p2_1 = "[^\{\}\"\\\\]";
$p2_2 = "(?:\"(?:(?:[^\"\\\\]|(?:\\\\.))*)\")";

$p2 = "(?:(?:{$p2_1}|{$p2_2})*)";

$p3_1 = "[^\{\}\'\"\\\\]";
$p3_2 = "(?:\'(?:(?:[^\'\\\\]|(?:\\\\.))*)\')";

$p3 = "(?:(?:{$p3_1}|{$p3_2}|{$p2_2})*)";

$p4_1 = "[^\{\}\\/\'\"\\\\]";
$p4_2 = "(?:\\/(?:(?:[^\\/\\\\]|(?:\\\\.))*)\\/)";

$p4 = "(?:(?:{$p4_1}|{$p4_2}|{$p3_2}|{$p2_2})*)";
一部をコメント付きにした場合の例
$p2 = "
# 内部オプションにxを指定した場合に使えます。
# (?x:pattern) は無理です。
# / ... (?:pattern) ... /x とする場合。
(?:           # 括弧始まり
(?:           #     括弧始まり
[^\{\}\"\\\\] #         {}”¥ を含まない文字
|             #         もしくは
(?:           #         括弧始まり
\"            #             ” で始まり
(?:           #             括弧始まり
(?:           #                 括弧始まり
[^\"\\\\]     #                     ”¥ を含まない文字
|             #                     もしくは
(?:           #                     括弧始まり
\\\\.         #                         ¥ で始まる任意の(¥を含めて)2文字
)             #                     括弧終わり
)             #                 括弧終わり
*             #                 を0回以上
)             #             括弧終わり
\"            #             ” で終わる
)             #         括弧終わり
)             #     括弧終わり
*             #     を0回以上
)             # 括弧終わり
";

2010-03-22

jslint

こちらに新しい記事があります。
jslint part2
http://d.hatena.ne.jp/cooldaemon/20090119/1232344701
http://www.jslint.com/lint.html
上記のurlの内容の設定例です。
jsコマンドをインストールします。
$ emerge -av dev-lang/spidermonkey
ファイルを設置します。
/usr/local/bin/jslint
/usr/local/bin/js/jslint.js
/usr/local/bin/js/fulljslint.js
ファイルの修正部分です。
$ diff jslint.js /usr/local/bin/js/jslint.js
2c2
< load('./fulljslint.js');
---
> load('/usr/local/bin/js/fulljslint.js');
$ chmod +x /usr/local/bin/jslint
$ diff jslint.sh /usr/local/bin/jslint
9c9
< js ./jslint.js $1 "`cat $1`"
---
> js /usr/local/bin/js/jslint.js $1 "`cat $1`"
emacs では shell-mode や M-x grep で呼び出せます。
Run grep (like this): jslint ./jquery-1.4.2.min.js
長すぎるとエラーになりますが解決していません。
$ ulimit -s 65535
$ jslint prototype.js
/usr/local/bin/jslint: line 10: /usr/bin/js: 引数リストが長すぎます
$ LC_ALL=C LANG=C jslint prototype.js
/usr/local/bin/jslint: line 10: /usr/bin/js: Argument list too long
$ expr `getconf ARG_MAX` \/ 1024 \/ 1024
15
$ expr `ulimit -s` \/ 4 \/ 1024
15
コマンドの1つのオプションに付き、71KB ~ 131KB の間に限界が有るようです。
http://x68000.q-e-d.net/~68user/unix/pickup?keyword=%B0%FA%BF%F4&target=command
http://blog.paz-para.com/?p=1301
http://www.atmarkit.co.jp/flinux/rensai/watch2007/watch10a.html

2010-03-14

javascriptの画像読み込み

追記: http://www.appelsiini.net/projects/lazyload がお勧めです。



この記事は javascript で画像の読み込みを扱う場合の例です。

こちらに新しい記事があります。
javascriptの画像読み込み part2

imgタグが表示されている画面内に来たら読み込む javascript のサンプルです。
ダウンロードは下記になります。
dummyThumbnail.2010-03-15.tar.gz

使い方は下記になります。
http://jquery.com/で jquery-1.4.2.min.js をダウンロードして同じディレクトリに入れます。
下記のコマンドを実行し sample.html にブラウザでアクセスします。
$ php sample.php > sample.html

ブラウザは windowsXP の firefox3.6, opeara10.10, ieTeserの6,7,8, chrome4.0.249.89, safari4.0.5 でテストしました。
firefox のみ 3.5.8 を linux 上でテストしています。
画像のサイズ指定無しや文字などが読み込み後に追加されたりするなどの、画面構成が変化すると失敗します。
chrome の innerWidth などは setTimeout で指定した関数内で取得すると、古い内容を取得するかもしれません。

修正版です。
dummyThumbnail.2010-03-22.tar.gz
主な修正点は下記になります。
横のスクロールバーに対応しました。
setTimeout する時間の指定を分けました。
$ php sample.php > sample.html
$ cat sample.html | sed 's/dummyThumbnail.js/dummyThumbnail.min.js/' | sed 's/sample.html/sample2.html/' | sed 's/init.js/init.min.js/' > sample2.html

修正版です。
dummyThumbnail.2010-03-25.tar.gz
主な修正点は下記になります。
eval の部分を修正しました。 (settimeout)
グローバル変数が常に2個消費されるようになりました。(dummyThumbnail, dT$)
$ php sample.php > sample.html
$ cat sample.html | sed 's/dummyThumbnail.js/dummyThumbnail.min.js/' | sed 's/sample.html/sample2.html/' > sample2.html
$ cat sample.html | sed 's/dummyThumbnail.js/dummyThumbnail.min.min.js/' | sed 's/sample.html/sample3.html/' | sed 's/init.js/init.min.min.js/' > sample3.html

http://dev.opera.com/articles/view/efficient-javascript-ja/?page=2

2010-03-13

j$("html").scrollTop = 0

これは javascript の prototype.js, jquery.js の参考です。

サンプルを動作させるため、両方同時に使ったところ、不具合がありました。
IE8 で prototype.js を呼んだだけで jquery の結果が変化しました。

下記の部分は変えていません。
jQuery.noConflict();
var j$ = jQuery;

IE8 で prototype.js を利用する。
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
...
IE8
j$("body").scrollTop = 0
j$("html").scrollTop = 0

IE8 で prototype.js を利用しない。
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
...
IE8
j$("body").scrollTop = 0
j$("html").scrollTop = 1662

opera10.10 で prototype.js を利用する。
j$("body").scrollTop = 0 => prototype.js を呼ぶと 1434 になります。
j$("html").scrollTop = 1434

firefox3.6, ieTester4.2 の ie6,ie7, chrome4.0.249.89 は変化しません。