#-- # =========================================================================== # Copyright (c) 2005-2012 Christopher Kleckner # All rights reserved # # This file is part of the Rio library for ruby. # # Rio is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Rio is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Rio; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # =========================================================================== #++ # require 'singleton' require 'rio/handle' require 'rio/rrl/builder' # module RIO # autoload :Path, 'rio/rrl/path' # module Path # autoload :Str,'rio/path' # autoload :Reset , 'rio/path/reset' # autoload :Empty , 'rio/path' # autoload :NonExisting , 'rio/path' # module Stream # autoload :Open , 'rio/scheme/path' # end # end # autoload :StdIO, 'rio/scheme/stdio' # autoload :StdErr, 'rio/scheme/stderr' # autoload :Null, 'rio/scheme/null' # module Null # module Stream # autoload :Open , 'rio/scheme/null' # end # end # autoload :Temp, 'rio/scheme/temp' # module Temp # autoload :Reset , 'rio/scheme/temp' # module Stream # autoload :Open , 'rio/scheme/temp' # end # end # autoload :StrIO, 'rio/scheme/strio' # module StrIO # module Stream # autoload :Open , 'rio/scheme/strio' # end # end # autoload :CmdPipe, 'rio/scheme/cmdpipe' # module CmdPipe # module Stream # autoload :Reset , 'rio/scheme/cmdpipe' # end # end # autoload :AryIO, 'rio/scheme/aryio' # autoload :HTTP, 'rio/scheme/http' # module HTTP # module Stream # autoload :Input , 'rio/scheme/http' # autoload :Open , 'rio/scheme/http' # end # end # autoload :FTP, 'rio/scheme/ftp' # autoload :TCP, 'rio/scheme/tcp' # autoload :SysIO, 'rio/scheme/sysio' # autoload :FD, 'rio/scheme/fd' # autoload :CmdIO, 'rio/scheme/cmdio' # end # module RIO # module Dir # autoload :Existing, 'rio/dir' # autoload :NonExisting, 'rio/dir' # autoload :Open , 'rio/dir' # autoload :Close , 'rio/dir' # autoload :Stream , 'rio/dir' # end # module File # autoload :NonExisting, 'rio/file' # autoload :Existing, 'rio/file' # end # end # module RIO # module Stream # autoload :Close , 'rio/stream/open' # autoload :Reset , 'rio/stream' # autoload :Open , 'rio/stream/open' # autoload :Input , 'rio/stream' # autoload :Output , 'rio/stream' # autoload :InOut , 'rio/stream' # module Duplex # autoload :Open , 'rio/stream/duplex' # autoload :Input , 'rio/stream/duplex' # autoload :Ouput , 'rio/stream/duplex' # autoload :InOut , 'rio/stream/duplex' # autoload :Close , 'rio/stream/duplex' # autoload :Reset , 'rio/stream/duplex' # end # end # end # 'Ext::YAML::Doc::Existing' , 'rio/ext/yaml/doc', # 'Ext::YAML::Doc::Open' , 'rio/ext/yaml/doc', # 'Ext::YAML::Doc::Stream' , 'rio/ext/yaml/doc', # 'Ext::YAML::Doc::Close' , 'rio/ext/yaml/doc', module RIO class Factory #:nodoc: all include Singleton def initialize() @ss_module = {} @reset_class = {} @state_class = {} @ss_class = {} end def subscheme_module(sch) #p "subscheme_module(#{sch})" @ss_module[sch] ||= case sch when 'file','path' require 'rio/rrl/path' Path when 'zipfile' require 'rio/ext/zipfile/rl' ZipFile::RootDir when 'stdio','stdin','stdout' require 'rio/scheme/stdio' StdIO when 'stderr' require 'rio/scheme/stderr' StdErr when 'null' require 'rio/scheme/null' Null when 'tempfile' require 'rio/scheme/temp' Temp::File when 'temp' require 'rio/scheme/temp' Temp when 'tempdir' require 'rio/scheme/temp' Temp::Dir when 'strio','stringio','string' require 'rio/scheme/strio' StrIO when 'cmdpipe' require 'rio/scheme/cmdpipe' CmdPipe when 'aryio' require 'rio/scheme/aryio' AryIO when 'http','https' require 'rio/scheme/http' HTTP when 'ftp' require 'rio/scheme/ftp' FTP when 'tcp' require 'rio/scheme/tcp' TCP when 'sysio' require 'rio/scheme/sysio' SysIO when 'fd' require 'rio/scheme/fd' FD when 'cmdio' require 'rio/scheme/cmdio' CmdIO else require 'rio/rrl/path' Path end end STATE2FILE = { 'Path::Reset' => 'rio/path/reset', 'Path::Empty' => 'rio/path', 'Path::Str' => 'rio/path', 'Path::NonExisting' => 'rio/path', 'File::Existing' => 'rio/file', 'File::NonExisting' => 'rio/file', 'Dir::Existing' => 'rio/dir', 'Dir::Open' => 'rio/dir', 'Dir::Close' => 'rio/dir', 'Dir::Stream' => 'rio/dir', 'Dir::NonExisting' => 'rio/dir', 'Stream::Close' => 'rio/stream/open', 'Stream::Reset' => 'rio/stream', 'Stream::Open' => 'rio/stream/open', 'Stream::Input' => 'rio/stream', 'Stream::Output' => 'rio/stream', 'Stream::InOut' => 'rio/stream', 'Stream::Duplex::Open' => 'rio/stream/duplex', 'Stream::Duplex::Input' => 'rio/stream/duplex', 'Stream::Duplex::Output' => 'rio/stream/duplex', 'Stream::Duplex::InOut' => 'rio/stream/duplex', 'Stream::Duplex::Close' => 'rio/stream/duplex', 'Stream::Duplex::Reset' => 'rio/stream/duplex', 'Path::Stream::Open' => 'rio/scheme/path', 'StrIO::Stream::Open' => 'rio/scheme/strio', 'Null::Stream::Open' => 'rio/scheme/null', 'CmdPipe::Stream::Reset' => 'rio/scheme/cmdpipe', 'HTTP::Stream::Input' => 'rio/scheme/http', 'HTTP::Stream::Open' => 'rio/scheme/http', 'Temp::Reset' => 'rio/scheme/temp', 'Temp::Stream::Open' => 'rio/scheme/temp', 'Ext::YAML::Doc::Existing' => 'rio/ext/yaml/doc', 'Ext::YAML::Doc::Open' => 'rio/ext/yaml/doc', 'Ext::YAML::Doc::Stream' => 'rio/ext/yaml/doc', 'Ext::YAML::Doc::Close' => 'rio/ext/yaml/doc', } def riorl_class(sch) ssm = subscheme_module(sch) cls = ssm.const_get(:RRL) cls end def reset_state(rl) mod = subscheme_module(rl.scheme) mod.const_get(:RESET_STATE) unless mod.nil? end def state2class(state_name) return @state_class[state_name] if @state_class.has_key?(state_name) if STATE2FILE.has_key?(state_name) require STATE2FILE[state_name] return @state_class[state_name] = RIO.module_eval(state_name) else raise ArgumentError,"Unknown State Name (#{state_name})" end end def try_state_proc1(current_state,rio_handle) proc { |new_state_name| _change_state(state2class(new_state_name,rio_handle),current_state,rio_handle) } end def try_state_proc(current_state,rio_handle) proc { |new_state_name| _change_state(state2class(new_state_name),current_state,rio_handle) } end def _change_state(new_state_class,current_state,rio_handle) # wipe out the reference to this proc so GC can get rid of rsc current_state.try_state = proc { p "try_state for "+current_state.to_s+" used already??" nil } new_state = new_state_class.new_other(current_state) new_state.try_state = try_state_proc(new_state,rio_handle) rio_handle.target = new_state return rio_handle.target end private :_change_state # factory creates a state from args def create_state(*args) riorl = RIO::RRL::Builder.build(*args) create_handle(state2class(reset_state(riorl)).new(rl: riorl)) end def clone_state(state) create_handle(state.target.clone) end def create_handle(new_state) hndl = Handle.new(new_state) new_state.try_state = try_state_proc(new_state,hndl) hndl end end end if $0 == __FILE__ eval DATA.read, nil, $0, __LINE__+4 end __END__