Class: Sequence::IO

Inherits:
Sequence show all
Includes:
StringLike
Defined in:
lib/sequence/io.rb

Overview

external iterator over data in an general IO object (a pipe, console, socket, serial port, or the like). For Files, please use Sequence::File instead, as it is more capable. This Sequence class can only go forward, and can only read, it cannot write to the data stream. Thus many of Sequence’s usual methods will not work with this class. At the moment, this even includes #scan and friends, tho I will try to make those work somewhat. Also note that this is one of the few Sequence classes that might return less that the amount asked for in a read, even if not at the end of file. Due to use of nonblocking io, this might not work on windows. The value of #size in this sequence continually increases over its lifetime, and it isn’t possible to know the final value beforehand. Likewise, #eof? may return false even tho it’s destined to return true at the same position. This is because the ‘other end’ may not have closed the IO, even if there’s no more data to send.

if you need to be able to scan forward and back, consider wrapping the IO in a Buffered or Shifting Sequence.

Constant Summary

Constants inherited from Sequence

SubSequence, VERSION

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io) ⇒ IO

Returns a new instance of IO.



25
26
27
28
29
30
31
32
33
# File 'lib/sequence/io.rb', line 25

def initialize(io)
  @io=io
  @pos=0
  
  @io.fcntl(::Fcntl::F_SETFL, ::Fcntl::O_NONBLOCK)
  #I gather this won't work on windows....
  
  @fragment=''
end

Instance Attribute Details

#posObject (readonly)

Returns the value of attribute pos.



35
36
37
# File 'lib/sequence/io.rb', line 35

def pos
  @pos
end

Instance Method Details

#_pos=(newpos) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/sequence/io.rb', line 87

def _pos=newpos
  newpos<pos and raise ArgumentError
  if newpos<=@pos+@fragment.size
    len=newpos-@pos
    @fragment.slice!(0,len)
    @pos=newpos
  else
    len=newpos-(@pos+@fragment.size)
    len > 10*4096 and raise ArgumentError
    @fragment=''
    tossit=@io.sysread(len)
    @pos=newpos-(len-tossit.size)
  end
end

#eof?Boolean

Returns:

  • (Boolean)


57
58
59
60
# File 'lib/sequence/io.rb', line 57

def eof?; 
  @fragment.empty? and #need to be at buffer end
    @io.eof?  
end

#match(pat) ⇒ Object



81
82
83
84
85
# File 'lib/sequence/io.rb', line 81

def match pat
  @fragment.size>=scanbuflen or @fragment<<@io.sysread(4096)
  result=@fragment.match(pat)
  result if result.begin(0).zero?
end

#more_data?Boolean

Returns:

  • (Boolean)


50
51
52
53
54
55
# File 'lib/sequence/io.rb', line 50

def more_data?
  #refill fragment if needed
  @fragment=@io.sysread(4096) if @fragment.empty?
  
  return !eof 
end

#read(len) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/sequence/io.rb', line 62

def read len
  if len<= @fragment.size
    @pos+=len
    @fragment.slice! 0,len
  else
    result=@fragment
    len-=@fragment.size
    
    readlen=len
    rem=len%4096
    rem.nonzero? and readlen+=4096-rem
    
    @fragment=@io.sysread(readlen) 
    result+=@fragment.slice!(0,len)
    @pos+=result.size
    result
  end
end

#sizeObject



43
44
45
46
47
48
# File 'lib/sequence/io.rb', line 43

def size
  #refill fragment if needed
  @fragment=@io.sysread(4096) if @fragment.empty?

  return @pos+@fragment.size 
end