class Jstream

Stream class for reading a file.

It’s just a wrapper class of IO to read characters. when finished to read IO, return a symbol :eof. when found line terminator except CR+LF, exit.

Constants

CR
CRLF
LF

Public Class Methods

new(file_io) click to toggle source

初期化と同時に、いったん最初の行をscanして、改行コードがCR+LFかどうか調べる。 CR+LFでない場合はエラーメッセージを出力してexitする(!)

TODO: 将来的にはさすがにexitまではしないよう、仕様を変更する?

# File lib/jstream.rb, line 22
def initialize(file_io)
  @line = 0
  @current_char = nil
  @file = file_io

  begin
    tmp = @file.readline.chomp!("\r\n")
    raise Aozora2Html::Error, Aozora2Html::I18n.t(:use_crlf) unless tmp
  rescue Aozora2Html::Error => e
    puts e.message(1)
    if e.is_a?(Aozora2Html::Error)
      exit(2)
    end
  ensure
    @file.rewind
  end
end

Public Instance Methods

close() click to toggle source
# File lib/jstream.rb, line 123
def close
  @file.close
end
inspect() click to toggle source
# File lib/jstream.rb, line 40
def inspect
  "#<jcode-stream input #{@file.inspect}>"
end
line() click to toggle source

現在の行数を返す

何も読み込む前は0、読み込み始めの最初の文字からrnまでが1、その次の文字から次のrnは2、……といった値になる

# File lib/jstream.rb, line 130
def line
  if @file.pos == 0
    0
  elsif @current_char == CRLF
    @line
  else
    @line + 1
  end
end
peek_char(pos) click to toggle source

pos個分の文字を先読みし、最後の文字を返す

ファイルディスクリプタは移動しない(実行前の位置まで戻す) 行末の場合は(1文字ではなく)CR+LFを返す 行末の先に進んだ場合の挙動は未定義になる

# File lib/jstream.rb, line 75
def peek_char(pos)
  original_pos = @file.pos
  char = nil

  begin
    pos.times { read_char }

    char = @file.getc
    if char == CR
      char2 = @file.getc
      if char2 != LF
        raise Aozora2Html::Error, Aozora2Html::I18n.t(:use_crlf)
      end

      char += char2
    end
  ensure
    @file.seek(original_pos)
  end

  char
end
read_char() click to toggle source

1文字読み込んで返す

行末の場合は(1文字ではなく)CR+LFを返す EOFまで到達すると :eof というシンボルを返す

TODO: EOFの場合はnilを返すように変更する?

# File lib/jstream.rb, line 50
def read_char
  char = @file.getc

  if char == CR
    char2 = @file.getc
    if char2 != LF
      raise Aozora2Html::Error, Aozora2Html::I18n.t(:use_crlf)
    end

    @line += 1
    @current_char = char + char2
  elsif char.nil?
    @current_char = :eof
  else
    @current_char = char
  end

  @current_char
end
read_line() click to toggle source

1行読み込み

@return [String] 読み込んだ文字列を返す

# File lib/jstream.rb, line 119
def read_line
  read_to("\r\n")
end
read_to(endchar) click to toggle source

指定された終端文字(1文字のStringかCRLF)まで読み込む

@param [String] endchar 終端文字
# File lib/jstream.rb, line 101
def read_to(endchar)
  buf = +''
  loop do
    char = read_char
    break if char == endchar

    if char.is_a?(Symbol)
      print endchar
    end
    buf.concat(char)
  end
  buf
end