FSA: File of Stream Array(C/C++ Library)

このソフトウェアはGNU Lesser General Public Licenseに従って再配布できます。
ソースコード等はGitHubから全てをダウンロードできます。
Copylight (c) 2023 Shigeo Kobayashi. All rights reserved.
[==>English]
概要関数一覧サンプルプログラム(tans.c)

FSA(File of Stream Array) は独立した複数ストリーム構造を持ったファイルを構築(アクセス)するための C/C++ 関数ライブラリーです。

概要

FSAを使用すれば、一つの(FSA)ファイルの中に完全に独立した複数のストリーム(バイトデータ列)を構築することが出来ます。 個々のストリームはストリーム番号(インデックス)を指定してアクセスされ、それぞれ独立したサイズ(byte単位)を持ちます。ストリームのインデックスは配列のインデックスと同様に 0 から始まる整数で指定します。つまり、FSAファイルは内部に複数のストリームを持ち、I/O処理は個々のストリームに対して独立に実行されます。

標準 C 関数での読み書き手順FSA 関数での読み書き手順説明
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int fd;
fd=open(pathname,openmode);
read(fd,buf,count);
write(fd,buf,count);
close(fd);
/* fsa.h must be included before using FSA API */
#include "fsa.h"

FSA_HANDLE h;
FsaOpen(&h,pathname, openmode);
FsaReadStream(h,i,buf,from,count);
FsaWriteStream(h,i,buf,from,count);
FsaClose(&h);
標準 C ライブラリィも FSA も最初に対象ファイルをオープンして処理後にクローズするのは同じです。
標準 C の write() に FSA では FsaWriteStream()、 標準 C の read() に FSA では FsaReadStream() が対応します。
FSA では seek() が無いので、引数に処理開始バイト位置の from を指定する必要があります。

最大の違いは FsaReadStream() と FsaWriteStream() ではストリームのインデックス i を指定していることです。
FSA では 同じファイルに読み書きを実行しても、 i が異なれば全く独立した互いに異なる処理と見なされます。従って、各 i 毎にサイズ(ストリームサイズ)が存在します。

標準 C の I/OFSA の I/O


関数一覧

全ての関数の戻り値は整数です。
戻り値: ※データや情報は全て関数の引数でやり取りします。
※すべてのストリームの初期サイズはゼロです。
※FSAで提供されるライブラリー関数は全て Fsa という接頭語で開始します。
※関数を呼び出す前に #include "fsa.h" をプログラムの先頭で記述する必要があります。

主要関数

関数名説明(引数)
FsaOpen(FSA_HANDLE *h,const char* file, const char mode) 処理対象の FSA ファイルをオープンします。
  • FSA_HANDLE *h
    オープンが成功した場合、以後の全ての処理(第一引数)に必要なハンドル値を受け取ります。
  • const char* file
    オープンする FSA ファイルのパス。
  • const char mode
    オープンモードで以下の一文字を指定します(大文字でも可です)。
    • 't'
      新規ファイルを読み書き用に作成します。対象ファイルが存在すれば一旦削除されてから新規に作成されます。
    • 'n'
      新規ファイルを読み書き用に作成します。対象ファイルが存在すればエラーになります。
    • 'w'
      既存ファイルを読み書き用にオープンします。対象ファイルが存在しなければすればエラーになります。
    • 'r'
      既存ファイルを読み込み専用でオープンします。対象ファイルが存在しなければすればエラーになります。
FsaWriteStream(FSA_HANDLE h, U_INT i, void* buff,U_LONG from, U_INT bytes)ストリームにデータを書き込みます。
  • FSA_HANDLE h
    オープンされているFSAファイルハンドル。
  • U_INT i
    書き込み対象のストリーム番号(0-n:注1)。
    (0 <= from <= stream i の現サイズ)
  • void* buff
    書き込みデータ領域のアドレス。
  • U_LONG from
    ストリーム(i)上の書き込み開始バイト位置。
  • U_INT bytes
    ストリーム(i)上に書き込むバイト数。
FsaReadStream (FSA_HANDLE h, U_INT i, void* buff,U_LONG from, U_INT bytes) ストリームからデータを読み込みます。
  • FSA_HANDLE h
    オープンされているFSAファイルハンドル。
  • U_INT i
    読み込み対象のストリーム番号(0-n:注1)。
  • void* buff
    読み込み用データ領域のアドレス。
  • U_LONG from
    ストリーム(i)上の読み込み開始バイト位置。
    (from + bytes <= stream i の現サイズ)
  • U_INT bytes
    ストリーム(i)上の読み込みバイト数。
FsaClose(FSA_HANDLE* h)FSAファイルをクローズして処理を終了します。エラーが検出されてもエラーハンドラーは呼ばれません。
注1:
n は FsaGetMaxStreamCount(h,&m) で取得できます(n=m-1)。また、m は FsaExtendMaxStreamCount(h,M) で自由に拡大できます(最低でも M 個ストリーム数を増やします)。

補助関数

関数名説明(引数)
FsaGetStreamSize(FSA_HANDLE h, U_INT i, U_LONG* size)ストリーム i のバイトサイズを size に読み込みます。
FsaTrimStream(FSA_HANDLE h, U_INT i, U_LONG from)ストリーム i のバイトサイズを from にします(from 以降のデータを切り捨てます)。
FsaGetMaxStreamCount(FSA_HANDLE h, U_INT *cs)現在アクセス可能なストリーム数を cs にセットします。
FsaExtendMaxStreamCount(FSA_HANDLE h, U_INT cs)アクセス可能なストリーム数を最低でも cs 個増やします。
FsaSetFsaTag(FSA_HANDLE h, U_LONG tag)FSAファイルのユーザ固有データ(Tag情報)tag を書き込みます。
FsaGetFsaTag(FSA_HANDLE h, U_LONG* tag)FSAファイルのユーザ固有データ(Tag情報)を tag に読み込みます。
FsaSetStreamTag(FSA_HANDLE h, U_INT i, U_LONG tag)ストリーム i のユーザ固有データ(Tag情報)tag を書き込みます。
FsaGetStreamTag(FSA_HANDLE h, U_INT i, U_LONG* tag)ストリーム i のユーザ固有データ(Tag情報)を tag に読み込みます。
FsaSetErrHandler(FSA_HANDLE h, FSA_ERROR_HANDLER f)エラーハンドラー f をセットします。f が NULL(ゼロ)ならエラーハンドラーの登録を削除します。
FsaGetErrHandler(FSA_HANDLE h, FSA_ERROR_HANDLER *f)セットされているエラーハンドラーを f にセットします。f が NULL(ゼロ)ならエラーハンドラーは登録されていないことを意味します。
FsaGetOpenMode(FSA_HANDLE h, char *mode)FsaOpen()時に指定したオープンモード(大文字)を mode にセットします。

エラーハンドラー

全ての関数は正常終了の場合はゼロ、エラーの場合はゼロ以外の値を返します。 毎回、関数の戻り値をチェックするのは面倒なのでエラーハンドラーを登録することをお勧めします。 内部でエラーが検出された場合、エラーハンドラーが登録されていれば、エラーを通知するために FSA が呼び出してくれます。 この場合。エラーハンドラーの戻り値がFSA関数の戻り値となります。

エラーハンドラーの引数と処理は以下の例(サンプルプログラム tans.c より)を参考にしてください。


int ErrorFunc(
	/* All arguments are set by FSA */
	FSA_HANDLE  handle,       /* FSA_HANDLE currently running.   */
	const char* function,     /* FSA function name the error detected */
	int         fsa_code,     /* FSA error code(see fsa.h) that FSA function detected.
                                     (If this is FSA_ERROR_UNDEFINED,then infomations after err_no may be undefined. */
	int         err_no,       /* copy of C system's errno. Use C standard function strerror(err_no) for detail. */
	const char* msg,          /* The error message that FSA function can describe. */
	const char* source_file,  /* The source file the error occured. */
	int         source_line   /* The source line the error occured. */
	)
{
	char ch;
	printf(" FSA Error: f=%s code=%d c_er=%d msg=%s file=%s line=%d\n", function, fsa_code, err_no, msg, source_file, source_line);
	if(err_no!=0) printf("        c error=%d:%s\n",err_no,strerror(err_no));
	printf("Continue or exit (c|e)?");
	do {
		ch = toupper(getchar());
	} while (ch != 'C' && ch != 'E');
	if (ch == 'E') {
		FsaClose(&handle);
		exit(EXIT_FAILURE);
	}
	return fsa_code;
}

サンプルプログラム(tans.c)

具体的なプログラミングについては付属の簡単なサンプルプログラム tans.c を参考にしてください。
tans は任意の複数ファイルを一つの FSA ファイルの指定されたインデックス番号位置に格納、そして、 取り出すことが出来ます。
コマンドラインは tans <open mode> <FSA(TANS) file> という形で実行します。
ここで<open mode>
FsaOpen()で指定可能なオープンモード文字(1文字)。 <FSA(TANS) file>はオープン対象の FSA ファイル名(パス)です。
プログラムが起動したら '?' でヘルプメッセージを表示させれば処理内容が分かります。
小林 茂雄(shigeo@tinyforest.jp) 2023-2-10