感嘆符多めの暑苦しい謝罪

依頼されている Laravel 案件のタスクがここ一ヶ月遅滞しております。

申し訳ない!Kさん! (一応依頼主Kさんとは連絡を取り合っており、どうにか理解をいただいております。ありがたや)

今夜ようやく時間を確保できたので早速現状を確認、以前に比べて画面がかなり見やすくなっていて驚いたと同時にさすが、と感銘を受けた次第であります。

お疲れ様であります!ますます申し訳ない! あっしはこれから頑張ります!

今日は1日だらけていた。家事も仕事もしていない。 夜になって気晴らしに妻としょぼいドライブに出た。家で淹れたコーヒーをもって。 港町の夜釣りスポットに車を止めて道途中で買ったチーズバーガーを遅めの夕飯とした。

しばらくして一匹の猫がすぐそばまで来ていてこちらを見つめていることに気づいた。 枯れた声で鳴いて食い物を要求していた。 手元のチーズバーガーのパティとバンズをちぎってやった。 しばらくしたら落ち着いた様子になって佇んで、でも相変わらずこちらを見ていた。 写真でも撮ってやろうかと思ったけど気が変わって撫でてみることにした。 思った通り潮風と排気ガスでベトベトしていたが構わず撫でていると、もっと撫でろと言わんばかりに尻尾を立ててすり寄って来た。 換毛機というのか毛が生え変わる時期らしくすごい勢いで毛が抜けていくのでこちらもとことん抜いてやった。

気が晴れたところで車に戻ったら今度はまた別の猫が現れた。こいつは最初のやつ以上にもふもふしていた。 車の下に潜られて少し面倒だった。

今度は行くときは水と食料持ってってやろう。

両親をスシローに連れてった。去年買った安い軽自動車に乗っけて、妻と一緒に。帰り道途中家に寄ってグアテマラを淹れてやった。親父は要らんというから俺が飲んだけど、やっぱり風味豊かで美味かった。

妻よありがとう。

Twitter アカウントを削除しました。 ヘイトや差別的なツイートに対する Twitter の不十分で緩慢な対応に辟易としたからです。

前回の更新が5年半も前であることにおどろいた。光陰矢の如し。

あるぺちぱーの最期

昨日、某PHP拡張の作者に、5.5対応してくれってんでパッチ送ったんですわ。ええ、恥ずかしながら人生初パッチですわ。
それがね、一時間もしないうちに「その変更は既に行われていて、すぐに公式にリリースする」って、ご丁寧にgithubのURLまで添えて返信返ってきたんですわ。
顔真っ赤にしながら、change log

 
憤死した情弱の手記はここで途切れていた。

 
 
 
 

iOS プログラミングメモ; HTTP を扱う

概要

HTTP リクエストを発行しレスポンスを受信するまでのプログラムの流れはだいたい次の通り。

  1. リクエストヘッダ(NSURLRequest)を作る
  2. NSURLConnection のクラスメソッドを用いリクエストを発行する
  3. レスポンスヘッダ(NSURLResponse)とレスポンスボディを取得する

Request オブジェクトを作る

NSMutableURLRequest を用いる。
NSMutableURLRequest は親クラスである NSURLRequest に比べリクエストボディ(POSTデータ)や HTTP ヘッダの設定が容易に行える。

NSData *query = [[NSString stringWithFormat:@"foo=bar&baz=%@", @"foobar"]
                       dataUsingEncoding: NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest
                      requestWithURL:[NSURL URLWithString:@"http://localhost/test/"]
                      cachePolicy:NSURLRequestUseProtocolCachePolicy
                      timeoutInterval:60.0];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" 
                      forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [query length]] 
                      forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:query];

同期方式

NSURLConnection.sendSynchronousRequest:returningResponse:error: を用いる。
同期方式は sendSynchronousRequest を呼び出したスレッドにおいて、リクエスト・レスポンス送受信が逐次処理される。 仮に UI スレッドでこのメソッドを呼び出すと、呼び出し元に制御を返すまでブロックされ、画面はフリーズする。

NSHTTPURLResponse *httpResponse;

/* HTTP リクエスト送信 */
NSData *contents = [NSURLConnection sendSynchronousRequest:request 
                      returningResponse:&httpResponse error:nil];
NSString *contentsString = [[NSString alloc] initWithData:contents encoding:NSUTF8StringEncoding];
NSLog(@"contents:\n%@", contentsString);

/* HTTP レスポンスヘッダ取得 */
NSDictionary *headers = httpResponse.allHeaderFields;
for (id key in headers) {
    NSLog(@"%@: %@", key, [headers objectForKey:key]);
}

非同期方式

NSURLConnectionDelegate プロトコルを実装する。 NSURLConnection.initWithRequest で接続されるが、同期方式と違い別スレッドでリクエスト・レスポンス送受信が処理されるためブロックされない。

@interface HTTPDownloadDelegate : NSObject<NSURLConnectionDelegate> {
    NSMutableData *contents;
}

@end

@implementation HTTPDownloadDelegate

/* レスポンスヘッダを受け取る */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // (NSHTTPURLResponse *)にキャストする
    NSHTTPURLResponse *httpResopnse = (NSHTTPURLResponse *)response;
    // レスポンスヘッダを列挙
    NSDictionary *headers = httpResopnse.allHeaderFields;
    for (id key in headers) {
        NSLog(@"%@: %@", key, [headers objectForKey:key]);
    }
}

/* データを受け取る度に呼び出される */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [contents appendData:data];
}

/* データを全て受け取ると呼び出される */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSString *csvContents = [[NSString alloc] initWithData:contents
                      encoding:NSShiftJISStringEncoding];
    NSLog(@"%@", csvContents);
}

@end

int main(int argc, char *argv[]) {
    /* リクエストを作る */
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost/"]];

    /* 上で定義した NSURLConnectionDelegate のインスタンスを作る */
    HTTPDownloadDelegate *delegate = [[HTTPDownloadDelegate alloc] init];

    /* リクエストを送信する。 
     * この main スレッドから分岐し別のスレッドでリクエスト・レスポンスの送受信が行われる。
     * そのためアプリはここでブロックされない。 */
    NSURLConnection *connection = [[NSURLConnection alloc]
                      initWithRequest:request delegate:delegate];
    if (!connection) NSLog(@"failed to create connection");

    [[NSRunLoop currentRunLoop] run];
}

参考

webcam の descriptor についてのメモ

手元にある webcam を用いて確認したことについてのメモです。
次のボタンを押すと今回ダンプした config descriptor が JavaScript コンソールに表示されます。

descriptor には extra というプロパティに Class Specific なディスクリプタが存在する場合、バイナリで直接格納されます。JavaScript コンソールに表示させるにあたってこれらに base64 エンコードを施しています。

IAD について

9.X.Y Interface Association

The Interface Association Descriptor is used to describe that two or more interfaces are associated to the same function. A device must use an Interface Association descriptor for each device function that requires more than one interface. An Interface Association descriptor is always returned as part of the configuration information returned by a GetDescriptor(Configuration) request.
An interface association descriptor cannot be directly accessed with a GetDescriptor() or SetDescriptor() request.

(IAD は一つの機能(functionality)に複数の interface を関連付けるために使われる。
バイスは、ひとつ以上の interface を要するデバイスのすべての機能に IAD を使う必要がある。
IAD は GetDescriptor(Configuration) リクエストの結果の一部として返される。
IAD は GetDescriptor() または SetDescriptor() で直接にはアクセスできない。)

InterfaceAssociationDescriptor_ecn.pdf (PDF)

8.1. Standard USB AV Descriptors

It is highly recommended that USB Devices that incorporate AV functionality use the value triplet (0xEF, 0x02, 0x01) for their bDeviceClass, bDeviceSubclass, and bDeviceProtocol fields in the standard Device Descriptor

USB AV Specification Rev 1.0/AVFunction v1.0.pdf
Base Class EFh (Miscellaneous)

手元にある webcam の config descriptor でも、 IAD を有する config descriptor の特徴を確認できた。

  • bDeviceClass: 0xEF
  • bDeviceSubClass: 0x02
  • bDeviceProtocol: 0x01

config descriptor の取得には usb_get_active_config_descriptor() を用いた。
この関数の戻り値は stdClassインスタンスであり、 IAD ディスクリプタextra プロパティに単なるバイナリとして格納される。

IAD structure

Offset Field Size Value Description
0 bLength 1 Number Size of this descriptor in bytes.
1 bDescriptorType 1 Constant INTERFACE ASSOCIATION Descriptor.
2 bFirstInterface 1 Number Interface number of the first interface that is associated with this function.
3 bInterfaceCount 1 Number Number of contiguous interfaces that are associated with this function.
4 bFunctionClass 1 Class Class code (assigned by USB-IF). A value of zero is not allowed in this descriptor. If this field is FFH, the function class is vendor-specific. All other values are reserved for assignment by the USB-IF.
5 bFunctionSubClass 1 SubClass Subclass code (assigned by USB-IF). If the bFunctionClass field is not set to FFH all values are reserved for assignment by the USB-IF.
6 bFunctionProtocol 1 Protocol Protocol code (assigned by USB-IF). These codes are qualified by the values of the bFunctionClass and bFunctionSubClass fields.
7 iFunction 1 Index Index of string descriptor describing this function.

Interface Association Descriptors (PDF)

この IAD 以外にも二つ extra を持つ descriptor があった。

  • descriptor.interface[0].altsetting[0].extra // ... (1)
  • descriptor.interface[1].altsetting[0].extra // ... (2)

どちらの extra もどういった構造になっているのか全体を把握できていないが、それぞれの先頭部分には次の descriptor が位置していることが先頭2バイト、 bLength, bDescriptorType から読み取れる。

  • (1) Class-specific VideoControl Interface Descriptor
    USB_Video_Example 1.5.pdf 2.3.4.2 Class-specific VC Interface Descriptor
  • (2) Class-specific VideoStreaming Header Descriptor (Input)
    USB_Video_Example 1.5.pdf 3.3.5.1.2 Class-specific VS Header Descriptor (Input)

bLength が固定長として定義されない descriptor がこれらに続いている様。