Java9のStringABuilder.appndの処理

Java9の変更点を調べていたら、ソースコードが見たくなってきたので、openjdkのソースコードを見てみた。
Stringに関しては以下のブログで紹介されています。

d.hatena.ne.jp

今回調べて見たのでは、StringBuilder.appendの処理。
LATIN1からUTF-16を追加するときの処理です。

ソースコード

StringBuilder

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

AbstractStringBuilder

    public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
    }

ensureCapacityInternalで領域を確保して、putStringAtで結合しているようです。
ensureCapacityInternalに関しては、どのようなオーバーフローを気にしているのか?newCapacityにはどのようなサイズを取得しようとしているのかが、正直良くわからなかったです。

    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        int oldCapacity = value.length >> coder;
        if (minimumCapacity - oldCapacity > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity) << coder);
        }
    }
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = value.length >> coder;
        int newCapacity = (oldCapacity << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

そして本題はputStringAtです。
この中でcoderを比較して違っていたら拡張しています。

    private final void putStringAt(int index, String str) {
        if (getCoder() != str.coder()) {
            inflate();
        }
        str.getBytes(value, index, coder);
    }

ここで一文字ずつコピーしているのがわかります。

   public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
        // We need a range check here because 'putChar' has no checks
        checkBoundsOffCount(dstOff, len, dst);
        for (int i = 0; i < len; i++) {
            putChar(dst, dstOff++, src[srcOff++] & 0xff);
        }
    }
    static void putChar(byte[] val, int index, int c) {
        assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
        index <<= 1;
        val[index++] = (byte)(c >> HI_BYTE_SHIFT);
        val[index]   = (byte)(c >> LO_BYTE_SHIFT);
    }

感想

綺麗なソースコードが読めて、学びはたくさんあるが、読むのは結構難しい。

mac book pro 設定その2

vimプラグイン管理ツールのインストール。

今回インストールしたのはdein.vimです。

dein.vimはneobundleらしいです。よく知らないですが。

インストール方法

$ mkdir -p ~/.cache/dein
$ cd ~/.cache/dein
$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
$ sh ./installer.sh ~/.cache/dein

あとは表示されたスクリプトを~/.vimrcに記述してvimを起動するだけ。
ただし、ここで"deol.nvim requires Neovim"と表示される。
ググったところ、deol.nvimのrevを削除すればできるらしいのでrevを削除し、deol.nvimを削除しvimを再起動。
そしたら今度は"deol.nvim requires Neovim or terminal feature enabled Vim."と表示される。
ここでハマってしまったが、結果的には最新のvimをインストールすることで解決。

もともとデフォルトで入っていたバージョン。

$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jul 26 2017 19:10:24)
Included patches: 1-503, 505-642
Compiled by root@apple.com

最新のものをbrewでインストール。

$ brew install vim
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Feb 13 2018 12:01:41)
macOS version
Included patches: 1-1500
Compiled by Homebrew

参考サイト

dein.vimのインストール自体にハマってしまったメモ

https://qiita.com/DialBird/items/0a96910f13586d635dc0

dein.vimとdeopleteをmacにインストールする。

http://noy.hatenablog.jp/entry/2017/11/26/140256