cerealのJSONフォーマットで最後の波括弧が抜ける問題

Unityのゲームデータ保存で紹介されたシリアライズの方法がなかなかいい感じがしたので、C++の場合でも同じ方法を採用してみたいと思い、C++のシリアライズライブラリcerealを使ってみました。

デモプログラムは無事動作したことを確認し、いざ本番実装となると、構造体をJSONフォーマット(OUT)に変えられましたが、その逆(IN)ができませんでした。
調べたところ、出力(OUT)した結果の一番最後の括弧が抜けることが分かりました。
こんな感じです:

{
    "value0": {
        "value0": 1,
        "value1": 2,
        "value2": 1.5
    }
// 本来ならここにもう一つの波括弧がなくてはいけません

これなら当然JSONとして読み込まず、下記のようなエラーが出ます。

Error: rapidjson internal assertion failure: IsObject()

参考2は同じ問題で、なんと解決策は括弧ブロックにありました。
エラーの例:

int main()
{
  std::stringstream ss;

  cereal::JSONOutputArchive archive( ss );
  SomeData myData;
  archive( myData );

  std::cout << ss.str() << std::endl;

  return 0;
}

正しい例:

int main()
{
  std::stringstream ss;
  { // このブロックがないとダメです。
    cereal::JSONOutputArchive archive( ss );
    SomeData myData;
    archive( myData );
  }
  std::cout << ss.str() << std::endl;

  return 0;
}

デモプログラムのstringstream直後の波括弧ブロックはただソースの見た目をよくするためだと思いましたが、動きまで異なるとは勉強になりました。

参考
  1. cereal – A C++11 library for serialization
  2. The output of json archive using std::stringstream as Output will miss the last “}”

Findコマンドの便利な使い方

基本的な使い方

find . -name "ファイル名"

ディレクトリー直下すべての.txtファイル検索

find . -name *.txt -type f

ファイルサイズ指定

512k以上のファイルを検索:
find . -type f -size +512k

512k以上のファイルをリストアップ:
find . -type f -size +512k -exec ls -lh {} \;
詳細が見れるようになります。

1Mb以下のファイルを削除:
find . -type f -size -1M -exec rm {} \;

詳しくは参考1が参考になります。

時間指定

5分以内修正されたファイルを検索:
find . -type f -mmin -5
直近でいじったファイルの名前が忘れた時に役に立つでしょう。

30日以上経つすべてのファイルを削除:
find . -type f -mtime +30 | xargs rm -f
バックアップスクリプト書く時に役に立ちます。

詳しくは参考2が参考になります。

  1. Linux Tips: Find All Files of a Particular Size
  2. findコマンドのmtimeオプションまとめ

Sublime Text 3をインストールしたらまずやること

テキストエディターとして、Sublime Textはすごく使いやすいと思いますが、OS再インストールなどでインストールし直すとなれば、また最初から設定をカスタマイズしなければいけないのが面倒ですね。
いろいろなプラグインがあり、自由度が高いのはメリットですが、設定に手間がかかるデメリットにもなります。
ここではウェブ開発用に最初の設定をまとめてみました。

環境:
macOS Mojave v10.14.1
Sublime Text v3.1.1
Emmet v2018.06.28.07.42.25

Sublime Textインストールしたら、まずやりたいことは3つです。

  1. タブキーの日本語対応
  2. オートインデント有効化
  3. Emmet

タブキーの日本語対応

このステップはウェブ開発とは限らず、日本語入力行うなら必須になるでしょう。

デフォルトのキーバインディングにあるタブキーを削除(コメントアウト)するにあたって、まず参考1で指摘されたようにすればできます。
しかしながら、Sublime TextメニューからPreferences => Key Bindingsを選んだら、デフォルトのキーバインディングを開くことができたが、編集できない状況になっていました。

これは以下の手順で編集できるようになるはずです。

  1. $HOME/Library/Application\ Support/Sublime\ Text\ 3/Packages/のところに「Default」という名前のフォルダを作ります。
  2. Sublime Textメニュー => Preferences => Key Bindingsを開き、左側のDefaultに(文字入力)カーソルがある状態で保存(command+s)します。
    そうすると、ステップ1のフォルダの下に「Default (OSX).sublime-keymap」という名前のファイルが出来上がるはずです。

    ※このようなことが言われたら、ステップ1の「Default」という名前のフォルダがないことが原因です。

  3. ここからがおまじないみたいなものですが、ウィンドウが2つに分けられた状態のsublime-keymap — Defaultはまだ編集できないはずですが、それを閉じ、$HOME/Library/Application\ Support/Sublime\ Text\ 3/Packages/Default/Default\ \(OSX\).sublime-keymapをSublime Textで開いても、他のエディタを開いてもいいですが、開いたら何もせずに閉じます。
    そうするだけで再度Preferences=>Key Bindingsで確認するとデフォルトが編集できるようになっているはずです。
  4. タブキー関連の設定をコメントアウトして以下になるはずです。
    	// { "keys": ["tab"], "command": "insert_best_completion", "args": {"default": "\t", "exact": true} },
    	// { "keys": ["tab"], "command": "insert_best_completion", "args": {"default": "\t", "exact": false},
    	// 	"context":
    	// 	[
    	// 		{ "key": "setting.tab_completion", "operator": "equal", "operand": true },
    	// 		{ "key": "preceding_text", "operator": "not_regex_match", "operand": ".*\\b[0-9]+$", "match_all": true },
    	// 	]
    	// },
    

オートインデント有効化

いろいろなプログラミング言語用のインデントプラグインがありますが、毎回インストールのが面倒というよりも、プラグインごとのショートカットが違うので、しばらく使わないと忘れてしまうほうが困ります。
それ故に、デフォルトのオートインデントだけ有効にしたいと思います。
Preferences=>Key Bindingsのsublime-keymap — Userのほうの角括弧に以下のを追加するだけです。

	{"keys": ["alt+shift+f"], "command": "reindent", "args": {"single_line": false}}

Emmetをインストール

プラグインのインストール方法を紹介する記事は多数あるはずですので、ここは簡単に書きますと、

  1. Command+ctrl+p
  2. 「install」を入力する
  3. 「Package Control: Install Package」を選択
  4. 読込みが終わると「Emmet」を入力
  5. 「Emmet」を選択

Ctrl+eを行末移動に変更

キーバインディングの設定になるので、上記タブキーのコメントアウトと似たような感じになります。

  1. $HOME/Library/Application\ Support/Sublime\ Text\ 3/Packages/のところに「Emmet」という名前のフォルダを作ります。
  2. Sublime Textメニュー => Preferences => Package settings => Emmet => Key Bindings – Defaultを選択
  3. Emmetデフォルトの設定を保存します。
  4. 設定ファイルを閉じ、任意エディタで/Library/Application\ Support/Sublime\ Text\ 3/Packages/Emmet/Default\ \(OSX\).sublime-keymapを開いてまた閉じます。
  5. 再度Sublime Textメニュー => Preferences => Package settings => Emmet => Key Bindings – Defaultを選択
  6. 358行あたりの"ctrl+e""super+e"に変更します。

ここはEmmetデフォルトの拡張ショートカットキー”ctrl+e”を”command+e”に変えてます。
そうすればctrl+eはシステムデフォルトの行末移動に戻ります。

すぐ"ctrl+e"下のブロッグでは”tab”キーの設定もありましたが、それは特に変更しなくても拡張が無効になっています。

試しに新規ファイルに!だけ入力し、タブと"ctrl+e"で反応せず、"command+e"でhtmlのフォーマットが展開されることを確認できれば問題ないと思います。

参考2ではEmmetのKey Bindings – Userに設定できると書かれていますが、私の場合、確かにUserのほうに"command+e"を追加することで、command+eで拡張されるようになりますが、ctrl+eは上書きされず、ctrl+eでも同じ拡張されますので、無効にする必要がありました。
それなら直接デフォルトを変えたほうがいいでは?!と思いましてこのようにしました。

参考3の考え方はすごくいいと思いますが、私の場合、"disabled_keymap_actions": "expand_abbreviation"でctrl+eの展開が無効に出来なかったんです。
なので、その続きもないわけですね。

参考
  1. SublimeText3での日本語入力時Tabキーでの変換候補選択を有効にする
  2. 【技術メモ】SublimeTextでEmmetの展開をcommand+eにする
  3. 【Sublime Text3】 Emmet使用時に ctrl + e での展開と行末への移動を両立させる