2015/04/09


おなじみC/C++から使えるJSONライブラリを紹介するコーナー。まずは過去のまとめ。

僕は C++ では STL が好きなので JSON をパースした後の構造も、std::mapstd::vector で文字列も std::string なのが好きです。なので picojson をひたすら使ってきましたが、picojson と同じ様に STL フレンドリな JSON ライブラリが ujson(μjson) です。

awangk / ujson — Bitbucket
https://bitbucket.org/awangk/ujson

特徴は以下の通り。

  • 単純な API で小さなライブラリ
  • 小綺麗なフォーマットでの JSON 出力
  • UTF-8 を扱える速いパーサ
  • 自由なライセンス
  • C++11 フレンドリ

μjson は MIT ライセンスで提供されています。ただし double の変換(IEEE double)に v8 でも使われている double-conversion というライブラリを使用しており、その部分については double-conversion のライセンスに委ねられます。

double の変換を行うという事で、つまり Bignum が扱えます。picojson はヘッダオンリーですが、ujson はビルド済みライブラリをリンクしてビルドします。

#include <iostream>
#include <string>
#include <algorithm>
#include <ujson.hpp>

struct book_t {
  std::string title;
  std::vector<std::string> authors;
  int year;
};

book_t
make_book(ujson::value v) {
  if (!v.is_object())
    throw std::invalid_argument("object expected for make_book");

  book_t book;
  std::vector<std::pair<std::string, ujson::value>> object =
    object_cast(std::move(v));

  auto it = find(object, "title");
  if (it == object.end() || !it->second.is_string())
    throw std::invalid_argument("'title' with type string not found");
  book.title = string_cast(std::move(it->second));

  it = find(object, "authors");
  if (it == object.end() || !it->second.is_array())
    throw std::invalid_argument("'authors' with type array not found");
  std::vector<ujson::value> array = array_cast(std::move(it->second));
  book.authors.reserve(array.size());
  for (auto it = array.begin(); it != array.end(); ++it) {
    if (!it->is_string())
      throw std::invalid_argument("'authors' must be array of strings");
    book.authors.push_back(string_cast(std::move(*it)));
  }

  it = find(object, "year");
  if (it == object.end() || !it->second.is_number())
    throw std::invalid_argument("'year' with type number not found");
  book.year = int32_cast(it->second);

  return book;
}

int
main(int argc, char* argv[]) {
  auto v = ujson::parse(R"(
    {
      "title":"foo",
      "authors":["bar", "baz"],
      "year": 123
    }
  )");
  auto t = make_book(v);
  std::cout << "title:" << t.title << std::endl;
  std::for_each(t.authors.begin(), t.authors.end(), [&](std::string& x) {
    std::cout << "author:" << x << std::endl;
  });
  std::cout << "year:" << t.year << std::endl;
  return 0;
}

オブジェクトにキーが存在した場合に find でイテレータを戻してくれるのでかなりスッキリ書けます。

Posted at by



2015/03/26


Goでchannelがcloseしてるかどうか知りたい というアンチパターン - beatsync.net

そもそもGoのchannelがcloseしてるかどうかを知りたいっていう理由は、だいたい「Goのchannelはナイーブだから」というところに起因するのはないかと思います。

https://beatsync.net/main/log20150325.html

golang には元々 closed() という、channel が閉じられているかどうかを返す組み込み関数がありました。しかし廃止されました。

closed は API としては目的を達成出来ているのですが、builtin が1つ増える、channel から取り出す前に一度確認する必要があるという理由で削除されたと私は記憶しています。

Goでchannelがcloseしてるかどうか知りたい というアンチパターン - beatsync.net

selectをつかってブロックする可能性のある文をcaseにかけば一番最初にブロックが外れたやつに分岐します。で、これは@fujiwaraさんに教えてもらった技ですが、なんもしないdefaultを書けばブロックせずにすぐdefaultにおちるとのこと。

https://beatsync.net/main/log20150325.html

実際には closed() が無くなった訳ではなく、型アサーションと同じインタフェースに置き換えられました。

Issue 4243072: code review 4243072: go code: replace closed(c) with x, ok := <-c - Code Review

LGTM http://codereview.appspot.com/4243072/diff/5001/src/pkg/os/inotify/inotify_li... File src/pkg/o...

https://codereview.appspot.com/4243072/
x, ok := <-c

戻り値の2つ目に channel から取り出せたかどうかが bool で返ります。

例: Go Playground

select はどちらかと言うと、複数の channel を同時に待てる仕組みであり、閉じている channel の case には飛ばないという理由で動いています。ですのでどうしても select は嫌だという方は以下の様に書くと良いです。(注意: ブロックはするので select とは動作が違う事に注意)

if x, ok := <-c; ok {
    // x を使った処理
}
Posted at by



2015/03/20


Google Code が終了する様です。
Google Open Source Blog: Bidding farewell to Google Code
http://google-opensource.blogspot.com/2015/03/farewell-to-google-code.html

GitHub が無かった頃、私はコード置き場として Google Code を使っていました。とても安定していたし落ちるのを見た事がありませんでした。

残念ながらその Google Code がサービスを終えようとしています。

しかし我々 Gopher のコードには、この Google Code にホスティングされている golang のパッケージが幾らかあります。

Google Code が終了するまでに、私達は移行を完了させなければなりません。

mattn/check-code-google-com - GitHub
https://github.com/mattn/check-code-google-com

パッケージが code.google.com のパッケージに依存しているかどうかを調べてくれます。

例えば mahonia に依存している jvgrep であれば

この様に表示され、code.google.com に依存していない twty であれば

この様に表示されます。中には依存しているパッケージのその依存しているパッケージが code.google.com に依存している事がありますが、それも検索します。-v オプションを付ける事で、どのパッケージが code.google.com に依存しているのかが分かる様になっています。

よろしければどうぞ。

Posted at by