class GxG::IO::StringIO
Public Class Methods
new(*args)
click to toggle source
Calls superclass method
# File lib/gxg/gxg_io.rb, line 2063 def initialize(*args) # TODO: override methods to operate in cooperative processing event system # TODO: provide a REAL external:internal encoding translation aspect (stock version is poorly designed/wrong, it would act *exactly* like a real IO) # TODO: optimize this class for memory and call efficiency (see Question at super() call) # LATER: GxG::StringIO : create/learn/whatever an optimized any-encoding-to-any-encoding transcoding/normalization matrix : possibly extend Encoding Class? This should include a conversion newline/field_separator/record_separator for each pair of Encodings. # Question: is there some possible benefit to using a ByteArray instead of a stock StringIO ? params = self.process_parameters(*args) unless params[:mode].size > 0 params[:mode] << :read params[:mode] << :write end if params[:external_encoding] == ::Encoding::ASCII_8BIT unless params[:mode].include?(:binary) params[:mode] << :binary end end # mode_string = "" mode_numeric = 0 @fcntl_mode = ::Fcntl::O_NONBLOCK mode_flags = {:binary => ::IO::BINARY, :text => ::IO::TEXT, :read => ::IO::RDONLY, :write => ::IO::WRONLY, :readwrite => ::IO::RDWR, :create => ::IO::CREAT, :overwrite => ::IO::TRUNC, :append => ::IO::APPEND} modes = GxG::IO::IO::valid_mode_set({:type => :io, :read => true, :write => true, :text => true, :binary => true}) the_mode_used = nil options = {} # :mode #Same as mode parameter if params[:mode] if params[:mode].index(:binary) if params[:mode].index(:read) if params[:mode].index(:write) mode_string = "binary_readwrite" mode_numeric = (mode_numeric | mode_flags[:binary] | mode_flags[:readwrite]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_RDWR) else mode_string = "binary_read" mode_numeric = (mode_numeric | mode_flags[:binary] | mode_flags[:read]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_RDONLY) end else if params[:mode].index(:write) mode_string = "binary_write" mode_numeric = (mode_numeric | mode_flags[:binary] | mode_flags[:write]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_WRONLY) end end else if params[:mode].index(:read) if params[:mode].index(:write) mode_string = "text_readwrite" mode_numeric = (mode_numeric | mode_flags[:text] | mode_flags[:readwrite]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_RDWR) else mode_string = "text_read" mode_numeric = (mode_numeric | mode_flags[:text] | mode_flags[:read]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_RDONLY) end else if params[:mode].index(:write) mode_string = "text_write" mode_numeric = (mode_numeric | mode_flags[:text] | mode_flags[:write]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_WRONLY) end end end if (params[:mode].index(:overwrite) || params[:mode].index(:truncate) ) mode_string << "_overwrite" mode_numeric = (mode_numeric | mode_flags[:overwrite]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_TRUNC) else if params[:mode].index(:append) mode_string << "_append" mode_numeric = (mode_numeric | mode_flags[:append]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_APPEND) else if params[:mode].index(:create) mode_string << "_create" mode_numeric = (mode_numeric | mode_flags[:create]) @fcntl_mode = (@fcntl_mode | ::Fcntl::O_CREAT) end end end # [:read, :write, :readwrite, :overwrite, :truncate:, :append, :text, :binary] modes.to_enum.each do |mode_entry| mode_entry[:synonyms].to_enum.each do |the_synonym| if the_synonym.is_a?(Symbol) if the_synonym == mode_string.to_sym the_mode_used = mode_entry break end else if the_synonym.is_a?(Numeric) if (the_synonym & mode_numeric == mode_numeric) the_mode_used = mode_entry break end end end end if the_mode_used break end # end if (the_mode_used) options[:mode] = the_mode_used[:if_exist].to_i else modes_list = [] modes.to_enum.each do |item| modes_list << item[:synonyms] end raise ArgumentError, "#{params[:mode].inspect} is an invalid :mode, use one of the following: #{modes_list.inspect}" end end # mode_numeric = options.delete(:mode) # @conversion_options = {:external => {}, :internal => {}} # init-text clobber work-around : defer :write of init-text until the end. # init_text = params[:object].dup # params[:object].clear # FORNOW: just use default behavior super(params[:object],mode_numeric) # if params[:mode].include?(:binary) self.set_encoding(::Encoding::ASCII_8BIT) else if params[:external_encoding].is_a?(::Encoding) self.set_encoding(params.delete(:external_encoding)) #:2nd internal_encoding parameter and 3rd parameter optional hash ignored # if you want the supplied string's encoding - best to simply pass it on the .new method call params. else self.set_encoding(::Encoding.default_external) end end # # if external_encoding is BINARY/ASCII_8BIT - just nullify internal_encoding, and skip external/internal conversion option mapping. if params[:mode].include?(:binary) @internal_encoding = nil else if params[:internal_encoding].is_a?(::Encoding) @internal_encoding = params.delete(:internal_encoding) else @internal_encoding = ::Encoding.default_internal end # if @internal_encoding if @internal_encoding != self.external_encoding if params[:external_conversion] # External conversion options will have to be dynamically generated upon transcode_to_external as *any* encoding is possible, not just internal_encoding @conversion_options[:external] = ::String::transcode_options(self.external_encoding,@internal_encoding,params[:external_conversion]) else @conversion_options[:external] = ::String::transcode_options(self.external_encoding,@internal_encoding) end # if @internal_encoding == ::Encoding::ASCII_8BIT # if params[:internal_conversion] nl_op = self.newline_option_used(params[:internal_conversion]) conv_options = {} if nl_op conv_options[(nl_op)] = true end @conversion_options[:internal] = conv_options end else if params[:internal_conversion] @conversion_options[:internal] = ::String::transcode_options(@internal_encoding,self.external_encoding,params[:internal_conversion]) else @conversion_options[:internal] = ::String::transcode_options(@internal_encoding,self.external_encoding) end end # end end # end # @external_field_separator = nil if params[:external_field_separator] self.external_field_separator = params[:external_field_separator] end @external_record_separator = nil if params[:external_record_separator] self.external_record_separator = params[:external_record_separator] end @internal_field_separator = nil if params[:internal_field_separator] self.external_field_separator = params[:internal_field_separator] end @internal_record_separator = nil if params[:internal_record_separator] self.external_field_separator = params[:internal_record_separator] end # # init-text clobber workaround : deferred :write #self.write(init_text) self end
open(the_string="",mode=::IO::RDWR,&block)
click to toggle source
# File lib/gxg/gxg_io.rb, line 1962 def self.open(the_string="",mode=::IO::RDWR,&block) result = nil the_io = GxG::IO::StringIO.new(the_string,mode) # if block.respond_to?(:call) result = block.call(the_io) the_io.close else result = the_io end # result end
Public Instance Methods
<<(*args)
click to toggle source
# File lib/gxg/gxg_io.rb, line 2392 def <<(*args) self.write(*args) self end
binmode()
click to toggle source
Calls superclass method
StringIO#binmode
# File lib/gxg/gxg_io.rb, line 2276 def binmode() if self.binmode? self else @internal_encoding = nil @conversion_options[:internal] = {} @conversion_options[:external] = {} self.set_encoding(::Encoding::ASCII_8BIT) super() end end
binmode?()
click to toggle source
# File lib/gxg/gxg_io.rb, line 2268 def binmode?() if self.external_encoding == ::Encoding::ASCII_8BIT true else false end end
close()
click to toggle source
Calls superclass method
# File lib/gxg/gxg_io.rb, line 2493 def close() super() end
close_read()
click to toggle source
Calls superclass method
# File lib/gxg/gxg_io.rb, line 2497 def close_read() super() end
close_write()
click to toggle source
Calls superclass method
# File lib/gxg/gxg_io.rb, line 2501 def close_write() super() end
external_encoding=(*args)
click to toggle source
# File lib/gxg/gxg_io.rb, line 2288 def external_encoding=(*args) # unless self.binmode? if args[0].is_any?(::Encoding, ::NilClass) # if args[0] == ::Encoding::ASCII_8BIT self.binmode() else old_data = self.string().dup # if args[0].is_a?(::Encoding) self.set_encoding(args[0]) if @internal_encoding if @internal_encoding != self.external_encoding # preserve newline settings nl_op = self.newline_option_used(:external) options = {} if nl_op options[(nl_op)] = true end @conversion_options[:external] = ::String::transcoding_options(self.external_encoding,@internal_encoding,options) end end else self.set_encoding(::Encoding.default_external()) end # if self.external_encoding() != old_data.encoding() # preserve newline settings nl_op = self.newline_option_used(:external) options = {} if nl_op options[(nl_op)] = true end old_data.transcode!(self.external_encoding(),options) # self.string.replace(old_data) end # end # else raise ArgumentError, "Expected an Encoding or NilClass, you provided #{args[0].class}" end end # end
flags()
click to toggle source
Public instance methods
# File lib/gxg/gxg_io.rb, line 1977 def flags() result = [] current = self.fcntl(::Fcntl::F_GETFL) flags = {} if self.binmode?() result << :binary if self.external_encoding == ::Encoding::ASCII_8BIT result << :setenc_by_bom end else result << :text result << :wsplit end if self.tty? result << :tty end # #flag[:read] = 0x00000001 #flag[:write] = 0x00000002 #flag[:readwrite] = (flag[:read] | flag[:write]) #flag[:binmode] = 0x00000004 #flag[:readwrite] = (flag[:read] | flag[:write]) flags[:read] = ::Fcntl::O_RDONLY flags[:write] = ::Fcntl::O_WRONLY flags[:readwrite] =::Fcntl::O_RDWR #flags[:binary] = 0x00000004 flags[:sync] = ::File::SYNC # no internal buffering -- The file will be opened for synchronous I/O. No write operation will complete until the data has been physically written to disk. flags[:dsync] = ::File::DSYNC # only normal data be synchronized after each write operation, not metadata. flags[:rsync] = ::File::RSYNC # the synchronization of read requests as well as write requests. It must be used with one of IO::SYNC or IO::DSYNC #flags[:tty] = 0x00000010 flags[:notcontrol_tty] = ::Fcntl::O_NOCTTY flags[:duplex] = 0x00000020 flags[:append] = ::Fcntl::O_APPEND flags[:create] = ::Fcntl::O_CREAT flags[:exclusive] = ::Fcntl::O_EXCL # flags[:wsplit] = 0x00000200 flags[:wsplit_initialized] = 0x00000400 flags[:trunc] = ::Fcntl::O_TRUNC #flags[:text] = 0x00001000 #flags[:setenc_by_bom] = 0x00100000 flags[:seek_set] = ::File::SEEK_SET flags[:seek_current] = ::File::SEEK_CUR flags[:seek_end] = ::File::SEEK_END # ### file region locking: flags[:shared_lock] = ::File::LOCK_SH # for reading flags[:exclusive_lock] = ::File::LOCK_EX # for writing (implies blocking) flags[:nonblock_lock] = ::File::LOCK_NB # combine with exclusive_lock for immediate non-blocking lock for writing. flags[:unlock] = ::File::LOCK_UN # flags[:nonblocking] = ::Fcntl::O_NONBLOCK flags[:ndelay] = ::Fcntl::O_NDELAY # unrelated to in-memory IO-like objects # flags[:nofollow] = ::File::NOFOLLOW # Do not follow symlinks. # flags[:noaccesstime] = ::File::NOATIME # Do not update the access time (atime) of the file. # flags[:match_noescape] = ::File::FNM_NOESCAPE # # flags[:match_pathname] = ::File::FNM_PATHNAME # # flags[:match_dotmatch] = ::File::FNM_DOTMATCH # # flags[:match_casefold] = ::File::FNM_CASEFOLD # # flags[:match_systemcase] = ::File::FNM_SYSCASE # # flags.keys.to_enum.each do |the_flag_key| if (current & flags[(the_flag_key)]) == flags[(the_flag_key)] case the_flag_key when :readwrite if result.index(:write) result << :read else if result.index(:read) result << :write end end when :wsplit_initialized if result.index(:wsplit) result[(result.index(:wsplit))] = :wsplit_initialized else result << :wsplit_initialized end else result << the_flag_key end end end # result end
inspect()
click to toggle source
:reopen, :string, :string, :lineno, :lineno, :close_read, :close_write, :closed?, :closed_read?, :closed_write?, :eof, :eof?, :fcntl, :flush, :fsync, :pos, :pos, :rewind, :seek, :sync, :sync, :tell, :each, :each_line, :lines, :each_codepoint, :codepoints, :getc, :ungetc, :ungetbyte, :readchar, :getbyte, :readbyte, :gets, :readline, :readlines, :read, :sysread, :readpartial, :read_nonblock, :write, :, :print, :printf, :putc, :puts, :syswrite, :write_nonblock, :isatty, :tty?, :pid, :fileno, :size, :length, :truncate, :external_encoding, :internal_encoding, :set_encoding
# File lib/gxg/gxg_io.rb, line 2264 def inspect() ("<#" << "#{self.class}:#{super().split(" ")[0].split(":").last}") end
read(*args)
click to toggle source
Calls superclass method
# File lib/gxg/gxg_io.rb, line 2336 def read(*args) # read length bytes from StringIO and optionally route to a buffer object if self.closed_read? raise IOError, "not open for reading" else if args[0].is_a?(Numeric) # length data = super(args[0].to_i) else # LATER: provide for StringIO buffer size manipulation??? what is default read length?? data = super() end if data.is_a?(::String) data = self.transcode_to_internal(data) # buffer if args[1].is_any?(::String, ::IO, ::StringIO, ::GxG::ByteArray) # check which classes this can use and in what ways. data.to_enum(:chars).each do |the_character| args[1] << the_character end # return buffer object args[1] else # return string data end else # return nil nil end # end end
Also aliased as: read_nonblock, sysread
readpartial(*args)
click to toggle source
# File lib/gxg/gxg_io.rb, line 2397 def readpartial(*args) # args[0] maxlen (Fixnum) # args[1] (optional) buffer_object # Note: use the same approach to pause/retry as IO.read_nonblock. # # Reads at most maxlen bytes from the I/O stream. It blocks only if ios has no data immediately available. It doesn’t block if some data available. # If the optional outbuf argument is present, it must reference a String, which will receive the data. It raises EOFError on end of file. # readpartial is designed for streams such as pipe, socket, tty, etc. It blocks only when no data immediately available. # This means that it blocks only when following all conditions hold: # the byte buffer in the IO object is empty. # the content of the stream is empty. # the stream is not reached to EOF. # When readpartial blocks, it waits data or EOF on the stream. If some data is reached, readpartial returns with the data. If EOF is reached, # readpartial raises EOFError. # When readpartial doesn’t blocks, it returns or raises immediately. If the byte buffer is not empty, it returns the data in the buffer. # Otherwise if the stream has some content, it returns the data in the stream. Otherwise if the stream is reached to EOF, it raises EOFError. # if self.closed_read? raise IOError, "not open for reading" else if self.eof? raise EOFError, "end of stream reached" else result = "" result.force_encoding(self.internal_encoding) data = self.read(*args) if data # non-nil if data.is_a?(::String) # 'blocking' or not? if (self.eof?() || (data && data.to_s.size > 0)) # no pseudo-blocking result << data data = nil else # pseudo-blocking until (self.eof?() || (data && data.to_s.size > 0)) data = self.read(*args) # string, buffer, or nil if data # if data.is_a?(::String) if (data && data.to_s.size > 0) result << data data = nil break else if self.eof?() raise EOFError, "end of stream reached" end end else # buffer result = data data = nil break end else if self.eof?() raise EOFError, "end of stream reached" end end # pause # end end else # buffer result = data end else if self.eof?() raise EOFError, "end of stream reached" end end # if result if result.is_a?(::String) if result.bytesize > 0 result else nil end else # buffer result end else nil end # end end end
write(data="")
click to toggle source
Calls superclass method
# File lib/gxg/gxg_io.rb, line 2372 def write(data="") # writes from (self.pos) forward : this will clobber any init string that was passed. written = 0 if self.closed_write? raise IOError, "not open for writing" else if data.is_a?(::String) data = self.transcode_to_external(data.dup) else data = self.transcode_to_external(data) end if data.size > 0 written = super(data) end end written end
Also aliased as: write_nonblock, syswrite