protobuf が更新されてる

いつの間にやら protobuf が 2.0.3 から 2.1.0 に更新されていました.

オブジェクトを初期化するためのメンバ関数 Clear() や,ポインタと文字列長の指定により文字列を更新するメンバ関数なんかが追加されているようです.ByteSize() はシリアライズしたときのサイズを返してくれるのかな…?

「あったら便利かも」と思っていたものが追加されているような気がします.

追記(2009-05-25):上記の説明は C++ の場合です.後,ByteSize() はシリアライズしたときのサイズで合っているようで,Clear() なんかも 2.0.3 のときから普通に使えたとかなんとか….ドキュメントは真面目に読んでおくべきですね….

複数の protocol buffers を出力する場合,ByteSize() でサイズを取得してから,SerializeWithCachedSizes() を呼び出せば問題ないようです.

追記(2009-05-25):複数の protocol buffers を出力ストリームに書き出すクラス protobuf::Writer と一つずつ読み込むクラス protobuf::Reader は,以下のように定義してやれば,とりあえず動作しました.ただし,合計サイズが大きくなると,WARNING や ERROR が出ます.SetTotalBytesLimit() で WARNING を無効にしたり,ERROR になるサイズを変更したりできますが,int で表現可能なサイズを上限としているようです.

#include <iostream>

#include <boost/shared_ptr.hpp>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>

namespace protobuf {

class Reader
{
public:
  explicit Reader(std::istream *stream)
    : zero_copy_stream_(new google::protobuf::io::IstreamInputStream(stream)),
      coded_stream_(new google::protobuf::io::CodedInputStream(zero_copy_stream_.get())) {}

  // Reads a protocol buffer from an input stream.
  template <typename ProtobufType>
  bool Read(ProtobufType *protobuf) {
    google::protobuf::uint32 size;
    if (!coded_stream_->ReadVarint32(&size))
      return false;
    google::protobuf::io::CodedInputStream::Limit limit =
      coded_stream_->PushLimit(static_cast<int>(size));
    if (!protobuf->ParseFromCodedStream(coded_stream_.get()))
      return false;
    coded_stream_->PopLimit(limit);
    return true;
  }

private:
  std::istream *stream_;
  boost::shared_ptr<google::protobuf::io::ZeroCopyInputStream> zero_copy_stream_;
  boost::shared_ptr<google::protobuf::io::CodedInputStream> coded_stream_;
  google::protobuf::uint64 last_byte_count_;

  // Disallows copies.
  Reader(const Reader &);
  Reader &operator=(const Reader &);
};

class Writer
{
public:
  explicit Writer(std::ostream *stream)
    : zero_copy_stream_(new google::protobuf::io::OstreamOutputStream(stream)),
      coded_stream_(new google::protobuf::io::CodedOutputStream(zero_copy_stream_.get())) {}

  // Writes a protocol buffer into an output stream.
  template <typename ProtobufType>
  bool Write(const ProtobufType &protobuf) {
    coded_stream_->WriteVarint32(
      static_cast<google::protobuf::uint32>(protobuf.ByteSize()));
    protobuf.SerializeWithCachedSizes(coded_stream_.get());
    return !coded_stream_->HadError();
  }

private:
  boost::shared_ptr<google::protobuf::io::ZeroCopyOutputStream> zero_copy_stream_;
  boost::shared_ptr<google::protobuf::io::CodedOutputStream> coded_stream_;

  // Disallows copies.
  Writer(const Writer &);
  Writer &operator=(const Writer &);
};

}  // namespace protobuf

他に良い方法があるかも…,というか,こういう使い方が良くないのかも…?