Class: Jstream

Inherits:
Object
  • Object
show all
Defined in:
lib/jstream.rb

Overview

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.

Constant Summary collapse

CR =
"\r"
LF =
"\n"
CRLF =
CR + LF

Instance Method Summary collapse

Constructor Details

#initialize(file_io) ⇒ Jstream

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

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



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 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

Instance Method Details

#closeObject



123
124
125
# File 'lib/jstream.rb', line 123

def close
  @file.close
end

#inspectObject



40
41
42
# File 'lib/jstream.rb', line 40

def inspect
  "#<jcode-stream input #{@file.inspect}>"
end

#lineObject

現在の行数を返す

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



130
131
132
133
134
135
136
137
138
# 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) ⇒ Object

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

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



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# 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_charObject

1文字読み込んで返す

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

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



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 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_lineString

1行読み込み

Returns:

  • (String)

    読み込んだ文字列を返す



119
120
121
# File 'lib/jstream.rb', line 119

def read_line
  read_to("\r\n")
end

#read_to(endchar) ⇒ Object

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

@param [String] endchar 終端文字


101
102
103
104
105
106
107
108
109
110
111
112
113
# 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