Subscribed unsubscribe Subscribe Subscribe

東京R不動産2

東京R不動産2 (realtokyoestate)

東京R不動産2 (realtokyoestate)

久しぶりに R 不動産関係の本を読んだ。2010 年発行なので、学生の頃に読んでると思ったけど読んでなかった。

そろそろ引っ越したい。

clipboard にあるテキスト等を hotkey でいい感じに preview する PreviewBoard というのを作った

https://soh335.github.io/PreviewBoard/latest.zip

https://dl.dropboxusercontent.com/s/fw75bulty1jfwai/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202015-05-20%2015.55.23.png?dl=0

起動したら hotkey を登録し呼び出すと clipboard の中身を上のように表示してくれる。

画像、テキストに対応していて、テキストが url ぽかったらアクセスし png, jpeg だったら表示してくれるというオプションがある。

dropbox の share の url は user-agent が "curl/" だと png とかに redirect してくれるけど、それ以外は preview 画面みたいなのが表示されるという知見も得た。

go で binary.Write してるところで速度が欲しい場合は binary.ByteOrder interface を直に使う

go で binary package の Write は毎回 allocate しているのでもし速度が必要な場合は binary.ByteOrder interface ( binary.BigEndian, binary. LittleEndian ) を直に使うと改善出来る。 もちろん binary.Write の方が使いやすいので速度とかを気にする場合に binary.ByteOrder を使うのが良さそう。

それぞれ下のように利用する。

binary.Write

binary.Write(&buf, binary.BigEndian, uint16(...))

binary.BigEndian

binary.BigEndian.PutUint16(b, uint16(...))

実際のコード

apns のコードを前に書いた時に binary package を使ったのを思い出し比べてみた。apns の仕様自体はこのドキュメントにある

MsgBinaryWrite は愚直に bytes.Buffer を2つに分けて使ったり、余計に grow したりしてるので参考まで。

result

go test -v -bench . -benchmem
=== RUN TestMsg
--- PASS: TestMsg (0.00s)
PASS
BenchmarkMsgBinaryWrite   200000              9573 ns/op            1633 B/op         58 allocs/op
BenchmarkMsgBinaryBigendianNoReuse      20000000                91.9 ns/op             0 B/op          0 allocs/op
BenchmarkMsgBinaryBigendianReuse        30000000                51.2 ns/op             0 B/op          0 allocs/op

main.go

package main

import (
    "bytes"
    "encoding/binary"
)

const (
    DeviceTokenItemId            = 1
    DeviceTokenLength            = 32
    PayloadItemId                = 2
    NotificationIdentifierItemId = 3
    NotificationIdentifierLength = 4
    ExpirationDateItemId         = 4
    ExpirationDateLength         = 4
    PriorityItemId               = 5
    PriorityLength               = 1
)

func MsgBinaryWrite(token []byte, payload []byte, identifier uint32, expire uint32, priority uint8) []byte {

    var b bytes.Buffer

    // device token
    binary.Write(&b, binary.BigEndian, uint8(DeviceTokenItemId))
    binary.Write(&b, binary.BigEndian, uint16(DeviceTokenLength))
    binary.Write(&b, binary.BigEndian, token)

    // payload
    binary.Write(&b, binary.BigEndian, uint8(PayloadItemId))
    binary.Write(&b, binary.BigEndian, uint16(len(payload)))
    binary.Write(&b, binary.BigEndian, payload)

    // nofication identifier
    binary.Write(&b, binary.BigEndian, uint8(NotificationIdentifierItemId))
    binary.Write(&b, binary.BigEndian, uint16(NotificationIdentifierLength))
    binary.Write(&b, binary.BigEndian, identifier)

    // expiration date
    binary.Write(&b, binary.BigEndian, uint8(ExpirationDateItemId))
    binary.Write(&b, binary.BigEndian, uint16(ExpirationDateLength))
    binary.Write(&b, binary.BigEndian, expire)

    // priority
    binary.Write(&b, binary.BigEndian, uint8(PriorityItemId))
    binary.Write(&b, binary.BigEndian, uint16(PriorityLength))
    binary.Write(&b, binary.BigEndian, priority)

    var f bytes.Buffer

    // frame
    binary.Write(&f, binary.BigEndian, uint8(2))        // command
    binary.Write(&f, binary.BigEndian, uint32(b.Len())) // frame length
    binary.Write(&f, binary.BigEndian, b.Bytes())       // frame

    return f.Bytes()
}

func MsgBinaryBigendian(b []byte, token []byte, payload []byte, identifier uint32, expire uint32, priority uint8) []byte {
    index := 0

    // device token
    b[index] = uint8(DeviceTokenItemId)
    binary.BigEndian.PutUint16(b[index+1:], uint16(DeviceTokenLength))
    copy(b[index+3:], token)

    index += 3 + len(token)

    // payload
    b[index] = uint8(PayloadItemId)
    binary.BigEndian.PutUint16(b[index+1:], uint16(len(payload)))
    copy(b[index+3:], payload)

    index += 3 + len(payload)

    // notification identifier
    b[index] = uint8(NotificationIdentifierItemId)
    binary.BigEndian.PutUint16(b[index+1:], uint16(NotificationIdentifierLength))
    binary.BigEndian.PutUint32(b[index+3:], identifier)

    index += 7

    // expiration date
    b[index] = uint8(ExpirationDateItemId)
    binary.BigEndian.PutUint16(b[index+1:], uint16(ExpirationDateLength))
    binary.BigEndian.PutUint32(b[index+3:], expire)

    index += 7

    // priority
    b[index] = uint8(PriorityItemId)
    binary.BigEndian.PutUint16(b[index+1:], uint16(PriorityLength))
    b[index+3] = priority

    index += 4

    // frame
    copy(b[5:], b[:index])
    b[0] = uint8(2)
    binary.BigEndian.PutUint32(b[1:], uint32(index))

    return b[:index+5]
}

main_test.go

package main

import (
    "bytes"
    "testing"
    "time"
)

var (
    token      = []byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
    payload    = []byte(`{"apns":{"alert":"hi"}}`)
    identifier = uint32(8888)
    expire     = uint32(time.Now().Add(time.Second).Unix())
    priority   = uint8(10)
)

func TestMsg(t *testing.T) {

    b1 := MsgBinaryWrite(token, payload, identifier, expire, priority)
    buffer := make([]byte, 2048)
    b2 := MsgBinaryBigendian(buffer, token, payload, identifier, expire, priority)

    if !bytes.Equal(b1, b2) {
        t.Errorf("b1:%v b2:%v", b1, b2)
    }
}

func BenchmarkMsgBinaryWrite(b *testing.B) {
    for i := 0; i < b.N; i++ {
        MsgBinaryWrite(token, payload, identifier, expire, priority)
    }
}

func BenchmarkMsgBinaryBigendianNoReuse(b *testing.B) {
    for i := 0; i < b.N; i++ {
        buffer := make([]byte, 2048)
        MsgBinaryBigendian(buffer, token, payload, identifier, expire, priority)
    }
}

func BenchmarkMsgBinaryBigendianReuse(b *testing.B) {
    buffer := make([]byte, 2048)
    for i := 0; i < b.N; i++ {
        MsgBinaryBigendian(buffer, token, payload, identifier, expire, priority)
    }
}

NSStatusBar にあるアイコンをクリックした際に NSPopover を表示し、フォーカスが外れたら自動で閉じる

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    
    let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-2)
    let popover = NSPopover()

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        
        if let button = statusItem.button {
            button.image = NSImage(named: "...")
            button.action = Selector("showPopover:")
            button.target = self
        }
        
        let vc = //  create ViewController
        popover.contentViewController = vc
        popover.behavior = .Transient
    }

    func showPopover(sender: AnyObject?) {
        if popover.shown {
            popover.performClose(sender)
        } else {
            if let button = statusItem.button {
                popover.showRelativeToRect(button.bounds, ofView: button, preferredEdge: NSMinYEdge)
                NSApplication.sharedApplication().activateIgnoringOtherApps(true)
            }
            
        }
    }
}

popover.behavior.Transient にすることでフォーカスが外れた場合に閉じられる。 さらに popover を表示する場合に NSApplication.sharedApplication().activateIgnoringOtherApps(true) とすることで、一番まえに持ってこれる。

こうしないと statusbar をクリックして popover は表示されるがフォーカスがそもそもされてないので、一度 viewcontroller の view をクリックしてからでないとフォーカスが外れない。結果 popover が閉じられないということが起きる。

Webエンジニアが知っておきたいインフラの基本

Webエンジニアが知っておきたいインフラの基本

Webエンジニアが知っておきたいインフラの基本

Web制作者のためのCSS設計の教科書

kindle のライブラリに何故かあったから読んだ。

脳内ポイズンベリー

www.nou-poi.com

キサラギの監督で面白い。