#                                                         -*- Perl -*-
# Copyright (c) 1999, 2000  Motoyuki Kasahara
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#

#
# 参照情報ファイルを生成するためのクラス。
#
package FreePWING::Reference;

require 5.005;
require Exporter;
use FileHandle;
use English;
use strict;
use integer;

use vars qw(@ISA
	    @EXPORT
	    @EXPORT_OK);

@ISA = qw(Exporter);

#
# 書式:
#	new()
# メソッドの区分:
# 	public クラスメソッド。
# 説明:
# 	新しいオブジェクトを作る。
# 戻り値:
# 	作成したオブジェクトへのリファレンスを返す。
#
sub new {
    my $type = shift;
    my $new = {
	# 参照情報ファイルのハンドラ
	'handle' => FileHandle->new(),

	# 参照情報ファイル名
	'file_name' => '',

	# これまでに書き込んだエントリ数
	'entry_count' => 0,

	# エラーメッセージ
	'error_message' => '',
    };
    return bless($new, $type);
}

#
# 書式:
#	open(file_name)
#           file_name
#		開く参照情報ファイルの名前。
# メソッドの区分:
# 	public インスタンスメソッド
# 説明:
# 	書き込み用に参照情報ファイルを開く。
# 戻り値:
#	成功すれば 1 を返す。失敗すれば 0 を返す。
#
sub open {
    my $self = shift;
    my ($file_name) = @ARG;

    #
    # 参照情報ファイルを開く。
    #
    $self->{'file_name'} = $file_name;
    if (!$self->{'handle'}->open($self->{'file_name'}, 'w')) {
	$self->{'error_message'} = 
	    "failed to open the file, $ERRNO: " . $self->{'file_name'};
	return 0;
    }

    return 1;
}

#
# 書式:
#	close()
# メソッドの区分:
# 	public インスタンスメソッド。
# 説明:
# 	参照情報ファイルを閉じる。開いていなければ、何もしない。
# 戻り値:
#	常に 1 を返す。
#
sub close {
    my $self = shift;

    $self->close_internal();
    return 1;
}

#
# 書式:
#	close_internal()
# メソッドの区分:
# 	private インスタンスメソッド。
# 説明:
#	close() の内部処理用メソッド。
#
sub close_internal {
    my $self = shift;

    if ($self->{'handle'}->fileno()) {
	$self->{'handle'}->close();
    }
}

#
# 書式:
#	add_block_entry(source_position, target_position, target_file_name)
#           source_position
# 		参照元の位置
#           target_position
# 		参照先の位置
#           target_file_name
# 		参照先のファイル名
# メソッドの区分:
# 	public インスタンスメソッド。
# 説明:
# 	参照情報ファイルにブロック参照エントリを一つ追加する。
# 戻り値:
#	成功すれば 1 を返す。失敗すれば 0 を返す。
#
sub add_block_entry {
    my $self = shift;
    my ($source_position, $target_position, $target_file_name)
	= @ARG;

    if (!$self->{'handle'}->printf("block\t%08x\t%08x\t%s\n",
				   $source_position, $target_position,
				   $target_file_name)) {
	$self->{'error_message'} = 
	    "failed to write the file, $ERRNO: " . $self->{'file_name'};
	return 0;
    }
    $self->{'entry_count'}++;
    return 1;
}

#
# 書式:
#	add_position_entry(source_position, target_position,
#		target_file_name)
#           source_position
# 		参照元の位置
#           target_position
# 		参照先の位置 (0 以上の整数値)
#           target_file_name
# 		参照先のファイル名
# メソッドの区分:
# 	public インスタンスメソッド。
# 説明:
# 	参照情報ファイルに位置参照エントリを一つ追加する。
# 戻り値:
#	成功すれば 1 を返す。失敗すれば 0 を返す。
#
sub add_position_entry {
    my $self = shift;
    my ($source_position, $target_position, $target_file_name)
	= @ARG;

    if (!$self->{'handle'}->printf("position\t%08x\t%08x\t%s\n",
				   $source_position, $target_position,
				   $target_file_name)) {
	$self->{'error_message'} = 
	    "failed to write the file, $ERRNO: " . $self->{'file_name'};
	return 0;
    }
    $self->{'entry_count'}++;
    return 1;
}

#
# 書式:
#	add_tag_entry(source_position, target_tag)
#           source_position
# 		参照元の位置
#           target_tag
# 		参照先の位置 (タグ名)
# メソッドの区分:
# 	public インスタンスメソッド。
# 説明:
# 	参照情報ファイルにタグ参照エントリを一つ追加する。
# 戻り値:
#	成功すれば 1 を返す。失敗すれば 0 を返す。
#
sub add_tag_entry {
    my $self = shift;
    my ($source_position, $target_tag) = @ARG;

    if (!$self->{'handle'}->printf("tag\t%08x\t%s\n", $source_position,
				   $target_tag)) {
	$self->{'error_message'} = 
	    "failed to write the file, $ERRNO: " . $self->{'file_name'};
	return 0;
    }
    $self->{'entry_count'}++;
    return 1;
}

######################################################################
# <インスタンス変数の値を返すメソッド群>
#
# 書式:
#	インスタンス変数名()
# メソッドの区分:
# 	public インスタンスメソッド。
# 戻り値:
#	インスタンス変数の値を返す。
#
sub file_name {
    my $self = shift;
    return $self->{'file_name'};
}

sub reference_file_name {
    my $self = shift;
    return $self->{'reference_file_name'};
}

sub entry_count {
    my $self = shift;
    return $self->{'entry_count'};
}

sub error_message {
    my $self = shift;
    return $self->{'error_message'};
}

1;
