2012/02/23

libxml2での文字列の扱いは、要注意。

iOSアプリ上で、htmlを字句解析する必要が生じた。

NSXMLParserはHTMLのような、アバウトな記述のMLを解析させると確実にエラーを吐いて、途中で解析を投げ出してしまう。
エラー無視のパラメータとかはどうやらないらしい。

というわけで、必然的にCライブラリのlibxml2に白羽の矢がたった。
コレをSAXインタフェースで使用する。
その方法は、google先生にお伺いを立てると、いろいろ教えていただけるので、記載はしない。

だが、SAXインタフェース上で、
cdataBlock検出時(たぶんその他のcharacters/commentでも同様)に渡される文字列にヒトクセあったので備忘録として記載する。


static void cdataHandler(void * ctx, const xmlChar * value, int len) 
{
}

コレが、cdataBlock検出時に呼び出される関数。
こいつの第二引数valueにUTF-8の文字列が格納されている。
そして、第三引数lenには、valueの有効文字列長が格納されている。

クセその1
scriptなどの大規模な文字列の場合、文字列が一括で渡されない。
具体的には、1000Byte単位で上記関数が呼び出される。
1000Byteを超える場合は、複数回関数が呼び出される。

当然、受け側としては受け取った文字列を連結して保持する事になる。
そこで、もう一つのクセが待ち構えているのだ。

クセその2
この文字列の終端はnullターミネートされていない(!)
このため、通常の手段としてNSMutableStringに蓄積しようとしても、NSMutableDataに溜め込もうとしても、strcatで連結しようとしてもゴミが残留するのだ。
このゴミが、最終的にNSStringに変換しようとするときに高確立でエラーとなって、NSStringが生成されないという現象が発生する。

ではどうするか?

ここで信用できる情報は何か?
文字列データは、nullターミネートされていないが、それ以外の部分はおおむね正しい。
そして、文字列長情報も問題ない。
信用できないのは、文字列長を超えた部分に存在しているゴミデータである。

ならば。
文字列の連結の度、有効文字列長の末尾に、自力でnullターミネートを書き込んでやればよろしい。
具体的には、

charLen_ = charLen_ + len;
if ( chars_ == nil ) {
 chars_ = xmlStrdup(value);
} else {
 chars_ = xmlStrcat(chars_, value);
}
chars_[charLen_] = 0x00;


xmlStrxxx関数はxmlChar型の操作関数だ。
これでNSStringに変換出来ないという症状は押さえ込めた。

ちなみに、1000byte未満の文字列の場合、正しくnullターミネートされているらしく、
NSString変換に失敗する事は無いようである。


2012/02/17

Wi-Fi HOME SPOT 導入してみた(続)

auで配って(!)いるHOME SPOT cubeさんが我が家にやってきて、3日目になりました。
現在、特に問題も無く正常に稼働中。

で、ちょびちょびと設定をいじったりしているので、その辺のメモ。

cubeさんにぶら下がる子機としては、
5GHz帯にmacBook。
2.4GHz帯にはiPhoneとiPod touchを割り振っている。
(iPhone/iPod touchは5GHz未対応)

で、このcubeさん、SSIDを3つ持っている。
SSID1/2が2.4GHz帯、
SSID3が5GHz帯。(この割り振りは固定っぽい)
iPhoneとiPod touchをそれぞれSSID1/2に分けてもよかったのですが、それほどヘビーに使用するわけでもないので、初期設定ではゲーム機用(取説にはそう記載されていた)として割り当てられているSSID2は使用不能に設定。

さらにさらに、SSIDの名称が、"auhome_******"と、機種情報が簡単に推測できる名前だったため、独自のものに変更。当然パスワードも変更。
もうちょっと落ち着いたら、それぞれのアンテナ出力も調整しつつ、
macアドレスフィルタリングをかけるようにする。

で、このcubeさん、アクリルの透明ボディーでとってもオサレなのだが、
このアクリルがくせ者だった。

夜、部屋の明かりを落とすと、ピカピカ、チカチカ光るのだ。
本体上面のstateランプが、ではない。
本体背面のWANコネクタのアクセスランプだ。
この光がみごとに透明なアクリルに導かれて、オレンジ色の点滅が本体上面から漏れる。

コレがまた寝しなに目に付くと結構目障りだったりする。
本体はとってもオサレでコンパクトなので、どこにでも置けそうな気になるが、
就寝中に直接目に付かない場所に置くのが良さそうだ。


2012/02/14

Wi-Fi HOME SPOT を早速導入してみた。

本日から提供の始まった。auのサービス(?)Wi-Fi HOME SPOTを早速申し込んでみた。

これは、11n対応の APを実質無料で配るというものだ、

そりゃもう、ゲットしないわけにはいかない。
というか、auが本気で通信量のオフロード化を考えているのだとわかる。



で、申し込み。
Onlineで申し込んでもよかったのだが、
開始予定だったAM 10時に受付が開始していなかったりと、
なんだか雲行きが怪しかった。
なによりも実店舗の方が早くAPを入手できそうな気がしたので、
仕事帰りに寄って来た。


たぶん私が、その店舗では最初のHOME SPOT申込者だったのだろう、

auのおねーちゃんに、
「提携のインターネット回線を契約していないと、提供できません」
と、同日開始のauスマートバリューの契約条件を突きつけられ、
「そんなことはねーべ」と契約条件を確認ししてもらう。
多少手間取ったが、無事申し込みできた。

あとは持って帰るだけだろうと思ったら、
「お使いのiPhoneに設定が必要です」とねーちゃん。
「たぶん大丈夫だよ」といいつつも、ナニをするのか見ていると、
「au WiFi SPOT」(公衆無線LANの方)のプロファイルをインストールしていた。
(既に導入済みだったが、それでも上書きインストールされた。)
さらに、初期設定のアクセスポイントの設定をしてメデタク引き渡しとなった。

で、持ってかえってきたのがこれ、




意外と小さい。


正常に動作させると、 緑のLEDがぽつんと点灯する。

本体の設定は普通に行える。
Wifi設定、WAN設定ともにそれぞれ普通に設定できる。

一点問題は、ウチの環境(ケーブルTV環境)では、
AutoモードではWANのIPアドレスが取得できなかった。
しょうがないので、Routerモードに設定し強制的に動作させている。

現状、Macちゃんと、iPhone 、iPod touchで元気に動作中。
プライバシーセパレータ、隔離設定をOFFにして、
WifiでのiTune同期も確認できた。

これで、macをAP代りにしなくてもすむ。

2012/02/03

Storyboardの使用方法(Segue)補足

Storyboardの使用方法(Segue)」に
UIStoryboardSegueを継承してごにょごにょする方法を投稿したが、
もっと簡単な方法が有ったので、
忘れないうちに追記。

UIViewControllerのメソッドにprepareForSegue:sender:がある、
これは、Segueで画面遷移する直前に実行されるメソッドなので、
こいつをオーバーライドして、
segueのidentiferで遷移を判別しつつ、
senderから契機となったUIViewの情報を引き出して、
画面遷移を制御する。

これで、遷移元がTableViewCellであっても、
Cell毎に処理を切り分ける事が可能になる。

よかったよかった。


2012/02/02

しまなみ海道縦走計画 積載量補完計画

しまなみ海道縦走計画を練っていると、
荷物の積載量がいささか不安になってきた。

愛車が小径車であるIDIOM2(2010)であるため、
積載用のポイントがそもそも少ない。
ボトルゲージはアンダーチューブの一カ所のみ、
シートチューブはボトルゲージを取り付けられるほど長くない。
トップチューブは独特の形状をしていて、ここに何かを括り付けると、
後輪ブレーキワイヤーと干渉しそう。

バックパックは当然背負うが、アップダウンのある長丁場だ、
あまり背中に大荷物というのは面白くない。
(バックパックの中には着替えが詰められる事になるだろうし)
そうなってくると、ハンドルバッグか、大型のサドルバッグに負荷を分散
という答えが順当に出てくる。

で、週末ちょっとこコレ↓の実物を見てきた。


写真で見ると、よさそうに見えたのだが、
実物は思っていた以上に左右が短い。
ブルホーンの間に収まるにはいいのだが、
もう少し大きくてもいいなぁ〜。

じゃあサドルバッグはと、いろいろ見ていると、
あった。良さそうなブツが。

トータルで結構な値段になるが、6.8Lの容量は、
低温対策用の上着、輪行袋、携行食、リペアキット、その他諸々を
収納してもまだ余裕が有りそうだ。

というわけで、どこかのタイミングでポチッとなする事がほぼ確定した。


2012/02/01

Storyboardの使用方法(Segue)

StoryBoardを使って画面遷移時に独自の処理を実行する方法。

Storyboard上のViewController同士をCtrl+ドラッグで接続すると、
簡単に画面遷移(Push/Modal)は実現できるが、
この方法では、遷移元から遷移先へパラメータを渡せない。
(がんばれば渡せない事は無いと思うが、面倒そう?)

しかし下記の方法なら、
パラメータの譲渡から、画面遷移の制御まで何でもゴザレだ。

Storyboard上の矢印(Segue)を選択、
Attributes InspectorのStyleをCustomに変更する。
Segue Classの入力フィールドが出現する。

というわけで、UIStoryboardSegueのサブクラスを作成する。
オーバーライドするメソッドは、
- (void)perform;
のみ

ここに、画面遷移の途中の制御で必要な処理を記述する。
遷移元のBViewControllerは
self.sourceViewController
遷移先のViewControllerは
self.destinationViewController
でアクセスできるので、適宜キャストして使用する。

忘れてはいけないのは、sourceとdestinationのつながりをcustomに変更したので、
そのままでは、画面間の遷移は発生しない。
ので、pushなりmodalなりでつないであげる必要がある。

これで、おk。