Skip to content

Commit

Permalink
- Book::read_book()で最終行の空行をnoneと解釈してしまう不具合を修正。
Browse files Browse the repository at this point in the history
	- cf. #113
- TextFileReaderのReadLine()でtrimを引数の取るのやめる。
	- SetTrim()で設定するようにする。
  • Loading branch information
yaneurao committed Apr 30, 2020
1 parent 9c2a45d commit 1048b6a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 30 deletions.
8 changes: 6 additions & 2 deletions source/extra/book/book.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,10 @@ namespace Book
sync_cout << "info string read book file : " << filename << sync_endl;

TextFileReader reader;
// ReadLine()の時に行の末尾のスペース、タブを自動トリム。空行は自動スキップ。
reader.SetTrim(true);
reader.SkipEmptyLine(true);

auto result = reader.Open(filename);
if (result.is_not_ok())
{
Expand Down Expand Up @@ -822,9 +826,9 @@ namespace Book
// (これがtrueならばsfenから手数を除去しておく)
bool ignoreBookPly = Options["IgnoreBookPly"];

while(!reader.Eof())
std::string line;
while(reader.ReadLine(line).is_ok())
{
auto line = reader.ReadLine(/* trim = */true);

// バージョン識別文字列(とりあえず読み飛ばす)
if (line.length() >= 1 && line[0] == '#')
Expand Down
58 changes: 35 additions & 23 deletions source/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,19 +631,19 @@ Tools::Result FileOperator::ReadAllLines(const std::string& filename, std::vecto
// ifstreamを使わない形で書き直す。これで4倍ぐらい速くなる。

TextFileReader reader;

// ReadLine()時のトリムの設定を反映させる。
reader.SetTrim(trim);
// 空行をスキップするモードにする。
reader.SkipEmptyLine(true);

auto result = reader.Open(filename);
if (!result.is_ok())
return result;

while (!reader.Eof())
{
std::string line;
line = reader.ReadLine(trim);

// 空行ではないなら書き出す
if (line.length())
lines.push_back(line);
}
string line;
while (reader.ReadLine(line).is_ok())
lines.emplace_back(line);

return Tools::Result::Ok();
}
Expand Down Expand Up @@ -726,6 +726,11 @@ TextFileReader::TextFileReader()
buffer.resize(1024 * 1024);
line_buffer.reserve(2048);
clear();

// この2つのフラグはOpen()したときに設定がクリアされるべきではないので、
// コンストラクタで一度だけ初期化する。
trim = false;
skipEmptyLine = false;
}

TextFileReader::~TextFileReader()
Expand Down Expand Up @@ -762,16 +767,12 @@ void TextFileReader::Close()
clear();
}

// ファイルの終了判定。
// ファイルを最後まで読み込んだのなら、trueを返す。
bool TextFileReader::Eof() const
{
return is_eof;
}

// 1行読み込む(改行まで)
std::string TextFileReader::ReadLine(bool trim)
Tools::Result TextFileReader::ReadLine(std::string& line)
{
while (true)
{

// buffer[cursor]から読み込んでいく。
// 改行コードに遭遇するとそこまでの文字列を返す。
line_buffer.clear();
Expand All @@ -787,12 +788,17 @@ std::string TextFileReader::ReadLine(bool trim)
よって"\r"(CR)がきたときに次の"\n"(LF)は無視するという処理になる。
*/

while (!Eof())
while (!is_eof)
{
// カーソル(解析位置)が読み込みバッファを超えていたら
if (cursor >= read_size)
{
read_next();
read_next_block();

// バッファ読み込み中に(改行コードに遭遇せずに)eofに達した
if (is_eof && line_buffer.size() == 0)
return Tools::ResultCode::Eof;

continue;
}

Expand Down Expand Up @@ -836,11 +842,17 @@ std::string TextFileReader::ReadLine(bool trim)
line_buffer.resize(line_buffer.size() - 1);
}

return std::string((const char*)line_buffer.data(),line_buffer.size());
// 空行をスキップするモートであるなら、line_bufferが結果的に空になった場合は繰り返すようにする。
if (skipEmptyLine && line_buffer.size() == 0)
continue;

line = std::string((const char*)line_buffer.data(), line_buffer.size());
return Tools::ResultCode::Ok;
}
}

// 次のblockのbufferへの読み込み。
void TextFileReader::read_next()
void TextFileReader::read_next_block()
{
if (::feof(fp))
read_size = 0;
Expand Down Expand Up @@ -1209,7 +1221,7 @@ namespace Directory

// カレントフォルダ相対で指定する。
// フォルダを作成する。日本語は使っていないものとする。
// どうもmsys2環境下のgccだと_wmkdir()だとフォルダの作成に失敗する。原因不明。
// どうもMSYS2環境下のgccだと_wmkdir()だとフォルダの作成に失敗する。原因不明。
// 仕方ないので_mkdir()を用いる。
// ※ C++17のfilesystemがどの環境でも問題なく動くようになれば、
// std::filesystem::create_directories()を用いて書き直すべき。
Expand Down Expand Up @@ -1258,7 +1270,7 @@ namespace Directory {
#else

// Linux環境かどうかを判定するためにはmakefileを分けないといけなくなってくるな..
// linuxでフォルダ掘る機能は、とりあえずナシでいいや..。評価関数ファイルの保存にしか使ってないし…。
// Linuxでフォルダ掘る機能は、とりあえずナシでいいや..。評価関数ファイルの保存にしか使ってないし…。

namespace Directory {
Tools::Result CreateFolder(const std::string& dir_name)
Expand Down
27 changes: 22 additions & 5 deletions source/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ namespace Tools
// 正常終了
Ok,

// ファイルの終端に達した
Eof,

// 原因の詳細不明。何らかのエラー。
SomeError,

Expand Down Expand Up @@ -404,20 +407,28 @@ struct TextFileReader

// ファイルの終了判定。
// ファイルを最後まで読み込んだのなら、trueを返す。
bool Eof() const;

// 1行読み込む(改行まで)
// 1行読み込む(改行まで) 引数のlineに代入される。
// 改行コードは返さない。
// 引数のtrimがtrueの時は、末尾のスペース、タブはトリムする
std::string ReadLine(bool trim = false);
// SkipEmptyLine(),SetTrim()の設定を反映する。
// Eofに達した場合は、返し値としてTools::ResultCode::Eofを返す。
Tools::Result ReadLine(std::string& line);

// ReadLine()で空行を読み飛ばすかどうかの設定。
// (ここで行った設定はOpen()/Close()ではクリアされない。)
void SkipEmptyLine(bool skip = true) { skipEmptyLine = skip; }

// ReadLine()でtrimするかの設定。
// 引数のtrimがtrueの時は、ReadLine()のときに末尾のスペース、タブはトリムする
// (ここで行った設定はOpen()/Close()ではクリアされない。)
void SetTrim(bool trim = true) { this->trim = trim; }

private:
// 各種状態変数の初期化
void clear();

// 次のblockのbufferへの読み込み。
void read_next();
void read_next_block();

// オープンしているファイル。
// オープンしていなければnullptrが入っている。
Expand All @@ -443,6 +454,12 @@ struct TextFileReader

// 直前が\r(CR)だったのか?のフラグ
bool is_prev_cr;

// ReadLine()で行の末尾をtrimするかのフラグ。
bool trim;

// ReadLine()で空行をskipするかのフラグ
bool skipEmptyLine;
};

// --------------------
Expand Down

0 comments on commit 1048b6a

Please sign in to comment.