class BinaryStream
{
	/**
	 * コンストラクタ／デストラクタ
	 */
	function BinaryStream(storage, mode) { if (storage != "") open(storage, mode); }
	function finalize() { if (isvalid this) close(), setFilter(); }

	/**
	 * ストレージを開く
	 * @param storage 対象ストレージ
	 * @param mode    モード指定(bsRead, bsWrite, bsAppend, bsUpdate)
	 */
	function open(storage, mode);

	/**
	 * オープン中のストレージを閉じる
	 */
	function close();

	/**
	 * 指定バイト読み込む
	 * @param size 読み込むサイズ（バイト）
	 * @return     読み込んだデータ（octet形式） 終端などで読めなかった場合はvoid（length=0のoctetではないので注意）
	 */
	function read(size);
	/**
	 * データを書き込む
	 * @param data 書き込むデータ（octet形式または文字列）
	 * @return     書き込んだバイト数
	 * @description dataが文字列の場合は wchar で書き込まれます（コード変換はサポートされません）
	 */
	function write(data);

	/**
	 * {1,2,4,8}バイトを数値として読み込む
	 * @return     読み込んだ数値 / 終端などで読めなかった場合はvoid
	 * @description ※数値は8byte以外はunsigned読み込みになります（符号拡張されません）
	 * ※voidを返すのは1byteも読めなかった場合のみとなります
	 *   1byte以上指定byte未満しか読めなかった場合は足りない部分を0で埋めた値が返されるので注意
	 */
	function readI8();			// 1byte 読み込み

	// 2byte 読み込み (Little Endian)
	function readI16LE();
	// 4byte 読み込み (Little Endian)
	function readI32LE();
	// 8byte 読み込み (Little Endian)
	function readI64LE();

	// 2byte 読み込み (Big Endian)
	function readI16BE();
	// 4byte 読み込み (Big Endian)
	function readI32BE();
	// 8byte 読み込み (Big Endian)
	function readI64BE();


	/**
	 * {1,2,4,8}バイトで数値を書き込む
	 * @param num 書き込む数値
	 * @return    書き込んだバイト数
	 */
	function writeI8(num);			//< 1byte 書き込み

	// 2byte 書き込み (Little Endian)
	function writeI16LE(num);
	// 4byte 書き込み (Little Endian)
	function writeI32LE(num);
	// 8byte 書き込み (Little Endian)
	function writeI64LE(num);

	// 2byte 書き込み (Big Endian)
	function writeI16BE(num);
	// 4byte 書き込み (Big Endian)
	function writeI32BE(num);
	// 8byte 書き込み (Big Endian)
	function writeI64BE(num);

	/**
	 * 別のストレージからデータをコピー
	 * @param storage コピー元のストレージ（現在開いているストレージと同じ場合は例外）
	 * @param elm     動作指定用の辞書（in/out）内容は下記：（省略時は単純コピー，[out]なし）
	 *        offset  :[in] コピー元ストレージの読み込み開始オフセット（省略時先頭）
	 *        length  :[in] コピー元ストレージの最大読み込みサイズ（省略時ファイルサイズ）
	 *
	 *        filter  :[in] フィルタ処理を行う関数名（省略時はフィルタ処理なし）
	 *        fparam  :[in] フィルタに渡すパラメータ値(int)
	 *
	 *        nocopy  :[in] trueを指定すると出力を書き込まない（省略時はfalse，hashのみ取得したい場合などに指定）
	 *        md5     :[in] trueを指定すると出力のMD5ダイジェストを返す
	 *
	 *        hash    :[out]読み込んだファイルのハッシュ値（Adler32）
	 *        read    :[out]読み込んだバイト数
	 *        digest  :[out]書き込んだデータのMD5ダイジェスト（octet） ※md5がtrueの場合にのみ有効
	 * @return              書き込んだバイト数
	 * @description 対象ストレージのoffsetからlength分の内容が，現在のストリームのポジションから書き込まれます
	 * フィルタの詳細は setFilter() の説明を参照してください
	 */
	function copy(storage, elm = void);

	/**
	 * 別のストレージからデータを圧縮しつつコピー
	 * @param storage コピー元のストレージ（現在開いているストレージと同じ場合は例外）
	 * @param elm     動作指定用の辞書（in/out）内容は copy() と同じものに加えて下記：
	 *        comp_lv :[in] zlibによる圧縮レベル（1〜9）省略時，またはelmそのものの指定がない場合は 9
	 * @return              書き込んだバイト数
	 * @description 対象ストレージを zlib/deflate で圧縮しつつ，現在のストリームのポジションから書き込みます
	 * フィルタ関数は圧縮前のバイナリに対して適用されます
	 */
	function compress(storage, elm = void);

	/**
	 * 別のストレージからデータを展開しつつコピー
	 * @param storage コピー元のストレージ（現在開いているストレージと同じ場合は例外）
	 * @param elm     動作指定用の辞書（in/out）内容は copy() と同じ
	 * @return        書き込んだバイト数
	 * @description 対象ストレージを zlib/inflate で展開しつつ，現在のストリームのポジションから書き込みます
	 * 展開に失敗すると例外が発生します
	 * フィルタ関数は展開後のバイナリに対して適用されます
	 * hash[out] は展開後／フィルタ後のバイナリに対して計算されます
	 */
	function decompress(storage, elm = void);

	/**
	 * プログレスコールバックを設定する
	 * @param callback コールバック関数 function(storage, read_size) { return true_if_cancel; }
	 *                 voidの場合は解除
	 * @description copy/compress/decompress の処理中からコールバックする関数を設定します。
	 * コールバックは（現在の実装では） 1MiB 読む毎時および最後まで読んだ時に呼び返されます。
	 * コールバックから true を返すと処理がキャンセルできます。
	 * ※コールバックの間隔は変更される場合があります
	 *
	 * TJS的には処理が固まってしまうのは仕様ですが，別途 windowExProgress プラグインなどを
	 * 使用することで，ユーザーからのキャンセルを受け付けられるようになります。
	 */
	function setProgressCallback(callback);

	/**
	 * フィルタDLLを設定する
	 * @param dll 対象のDLLファイル（voidの場合は設定解除）
	 *  @description copy/compress/decompressのデータに対して外部DLLを使用したフィルタを設定します
	 * elm.filter に関数名を指定た場合に，このDLL中の下記の形式でエクスポートされた関数をフィルタとして使用します
	 * void (__stdcall *FilterProc)(uint32 hash, uint64 offset, void *buffer, uint32 length);
	 */
	function setFilter(dll);

	
	/**
	 * ストリームのポジションを変更する
	 * @param pos    位置
	 * @param whence 基準位置(bsSeekSet, bsSeekCur, bsSeekEnd)
	 * @return       移動後の位置
	 */
	function seek(pos, whence);

	/**
	 * ストリームの現在のポジションを取得する
	 * @return 位置
	 */
	function tell();

	/**
	 * 現在開いているストレージ
	 * @description 開いていない場合はvoid
	 */
	property storage { getter; }

	/**
	 * 現在のモード
	 * @description 開いていない場合は-1
	 */
	property mode    { getter; }
	
	// 定数
	// 読み込み
	const bsRead   = 0;
	// 書き込み
	const bsWrite  = 1;
	// 追記
	const bsAppend = 2;
	// 更新
	const bsUpdate = 3;

	// 先頭から
	const bsSeekSet = 0;
	// 現在位置から
	const bsSeekCur = 1;
	// 末尾から
	const bsSeekEnd = 2;
}


