# gfs_pio_readdelim

## Name

gfs_pio_readdelim -- 一レコード読み込み

## Synopsis

    #include <gfarm/gfarm.h>

```char *gfs_pio_readdelim``(GFS_File `f`, char **`bufp`, size_t *`sizep`, size_t *`lenp`, char *`delimiter`, size_t `delimlen`);`

## DESCRIPTION

この関数は、gfs_pio_readline(3) と同様に働きますが、ただし、 入力のセパレータを改行文字に限らず、一般的に指定できるように したものです。 この関数は、ファイル `gf` から、 引数 `delimiter` で指定されたバイト列をレコード間区切りとして、1レコード読みとり ます。 引数 `delimiter` には文字 '\0' を含むこともできます。このため、区切りの長さを 引数 `delimlen` で指定します。 なお、 引数 `delimiter` が NULL の場合、ファイル全体を1レコードとしてメモリ上に読み込みます。 そうではなく、かつ 引数 `delimlen` が 0 の場合、一個以上の連続する空行 (正規表現では /\n\n+/) を レコード区切りと見なします。この仕様は perl 言語の INPUT_RECORD_SEPARATOR を参考にしています。

引数 `bufp` は、最初は NULL で初期化されたポインタ変数のアドレスを指定します。 関数 `gfs_pio_readdelim()` は、入出力に用いる バッファを動的に割り当て、そのアドレスをこのポインタ変数に記録します。 引数 `sizep` は、0 で初期化した size_t 型の変数 のアドレスを指定します。この変数は、バッファのサイズを記録するために 使われます。 あるいは、malloc(3) で割り当てたバッファを指すポインタのアドレスを 引数 `bufp` に指定することもできます。この場合、 引数 `sizep` は、割り当てたバッファのサイズで初期化しておきます。 行の長さがバッファのサイズを越える場合には、バッファは自動的に realloc(3) され、 引数 `bufp` および 引数 `sizep` で指定された変数もそれに従って更新されます。 ファイルを読み終わったら、このポインタを free(3) で解放する必要が あります。

引数 `lenp` の指す変数には、読み込んだレコードの長さを返します。 この長さには、レコード区切りの分も含みます。

この関数はレコード末の区切りを削除しません。 また、 引数 `lenp` の指す変数に返った値を利用すれば良いので冗長ですが、 レコード末に '\0' 文字を付加します。

EOF は、入力の長さが 0 バイトであることで判断します。

引数として gfs_pio_readdelim(f, bufp, sizep, lenp, "\n", 1) と指定すると、関数 `gfs_pio_readline()` と 等価になります。

## RETURN VALUES

`NULL`

  正常終了を示します。

`GFARM_ERR_NO_MEMORY`

  メモリ不足のため処理を中止しました。

  この場合も、`bufp` の指すポインタ変数の 指す領域を free(3) する必要がありますから注意してください。

その他

  上記以外のエラーが生じたことを示します。

## EXAMPLES

Example 1. `gfs_pio_readdelim` 関数の使用例

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <gfarm/gfarm.h>

    int
    main(int argc, char **argv)
    {
    	char *e;
    	GFS_File gf;
    	size_t bufsize = 0, delimlen = 1, len;
    	char *buffer = NULL, *delim = "\n";

    	e = gfarm_initialize(&argc, &argv);
    	if (e != NULL) {
    		fprintf(stderr, "gfarm_initialize: %s\n", e);
    		return (EXIT_FAILURE);
    	}
    	while ((c = getopt(argc, argv, "d:D")) != -1) {
    		switch (c) {
    		case 'd':
    			delim = optarg;
    			delimlen = strlen(optarg);
    			break;
    		case 'D':
    			delim = NULL;
    			delimlen = 0;
    			break;
    		case '?':
    		default:
    			fprintf(stderr, "invalid option: %c\n", c);
    			return (EXIT_FAILURE);
    		}
    	}
    	if (optind >= argc) {
    		fprintf(stderr, "missing gfarm filename\n");
    		return (EXIT_FAILURE);
    	}
    	e = gfs_pio_open(argv[optind], GFARM_FILE_RDONLY, &gf);
    	if (e != NULL) {
    		fprintf(stderr, "%s: %s\n", argv[optind], e);
    		return (EXIT_FAILURE);
    	}
    	e = gfs_pio_set_view_global(gf, 0);
    	if (e != NULL) {
    		fprintf(stderr, "%s: gfs_pio_set_view_global: %s\n",
    		    argv[optind], e);
    		return (EXIT_FAILURE);
    	}

    	while ((e = gfs_pio_readdelim(gf, &buffer, &bufsize, &len,
    	    delim, delimlen)) == NULL && len > 0) {
    		printf("<%6d/%6d >%s", len, bufsize, buffer);
    	}
    	if (buffer != NULL)
    		free(buffer);
    	if (e != NULL) {
    		fprintf(stderr, "ERROR: %s\n", e);
    		return (EXIT_FAILURE);
    	}
    	e = gfs_pio_close(gf);
    	if (e != NULL) {
    		fprintf(stderr, "gfs_pio_close: %s\n", e);
    		return (EXIT_FAILURE);
    	}
    	e = gfarm_terminate();
    	if (e != NULL) {
    		fprintf(stderr, "gfarm_initialize: %s\n", e);
    		return (EXIT_FAILURE);
    	}
    	return (EXIT_SUCCESS);
    }

## SEE ALSO

gfs_pio_open(3), gfs_pio_getline(3), gfs_pio_gets(3), gfs_pio_readline(3)