メモリストリーム

プログラミング言語 C における文字列というのはメモリの塊そのものです。 見えているままのデータがメモリ上のどこかに配置されています。 余計なことをしない単純さは機械の性能を引き出しやすい一方で、ちょっとしたことでもプログラマが手間をかけなければいけません。 もちろん、文字列を扱うライブラリを導入したり作ったりすればいくらでも複雑なことは出来るのですが、凝ったデータ構造は標準ライブラリとの組合せがやり難くなります。 そのあたりを考慮して使い勝手がよく汎用性が高い仕組みが作れないものかと私は考えていました。 そして、思い出したのは以前に作ったメモリをストリームとして読みだす仕組みのことです。

これと同様にメモリへの書き込みをストリームを通して出来る仕組みがあれば便利でしょう。 Scheme の文字列ポートによって、ファイル操作と同じ要領で文字列を構築できる便利さを私は知っています。

結果として出来たライブラリに memstream と名付けて Github に置きました。

例えば数をストリームに出力する関数があったとして、関数 open_output_memstream がオープンしたストリームを出力先にすればそのまま文字列を構築することが出来ます。 以下のように使えます。

#include <stdio.h>
#include <stdlib.h>
#include "memstream.h"

int count_three(FILE* fp) {
  int total=0;
  for(int i=3; i>0; i--)
    total += fprintf(fp, "%d\n", i);
  return total;
}

char* count_three_string(void) {
  FILE* fp=open_output_memstream();
  count_three(fp);
  fputc('\0', fp);
  size_t len;
  char* str = mclose(fp, &len);
  return str;
}

int main(void) {
  count_three(stdout);
  char* str=count_three_string();
  printf("%s\n", str);
  free(str);
  return 0;
}

ライブラリ memstream は Windows のパイプの機能を利用しています。 パイプの読書きのハンドルに対しては、シークを除いてはファイルに対しての読書きとほぼ同じ操作が可能なので、パイプのもう一旦で受取った情報を文字列として構築するという考え方です。

POSIX に有る open_memstream という機能とよく似ています。 インターフェイスも合わせることも考えたのですが、別スレッドで動いている都合上、タイミングを待つ必要があって現在の形に落ち着きました。

Document ID: 7f7c141b7a1c51ba27bf73ac15996653