YAML/オブジェクトシリアライズ処理を読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#g43b2130]
YAMLの説明は[[ここら辺>http://jp.rubyist.net/magazine/?00...
まず適当に定義したクラスをYAMLライブラリでシリアライズし...
require 'yaml'
class Bar
def initialize
@array = [1, 2, 3]
@hash = {'a' => 123, 'b' => 'abc'}
end
end
class Foo
def initialize
@int = 1
@string = 'str'
@bar = Bar.new
end
end
foo = Foo.new
puts YAML.dump(foo)
上記のスクリプトを実行すると以下の出力が得られます。
--- !ruby/object:Foo
bar: !ruby/object:Bar
array:
- 1
- 2
- 3
hash:
a: 123
b: abc
int: 1
string: str
今回読んだバージョンはruby-1.8.5-p12添付のYAMLライブラリ...
*YAML.dump(yaml.rb) [#m483bd78]
では、YAML.dumpメソッドから見ていくことにしましょう。
def YAML.dump( obj, io = nil )
obj.to_yaml( io || io2 = StringIO.new )
io || ( io2.rewind; io2.read )
end
第2引数は指定していないので、StringIOオブジェクトに出力さ...
*Object#to_yaml(yaml/rubytypes.rb) [#k4f96f76]
Object#to_yamlメソッドは以下のように定義されています。
def to_yaml( opts = {} )
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
to_yaml_properties.each do |m|
map.add( m[1..-1], instance_variable_get( m ) )
end
end
end
end
YAML.quick_emitメソッドです。optsはStringIOオブジェクトが...
def YAML.quick_emit( oid, opts = {}, &e )
out =
if opts.is_a? YAML::Emitter
opts
else
emitter.reset( opts )
end
out.emit( oid, &e )
end
*YAML::Syck::Emitter(ext/syck/rubyext.c) [#f6f8854a]
**内部表現の構築 [#dd54f22d]
YAML::Syck::Emitterクラスはどこで定義されているかというと...
Emitter#resetメソッドを実装しているのはsyck_emitter_reset...
-引数が1個でwriteメソッドが定義されているので出力先として...
ということをしています。
次に、Emitter#emitメソッドを実装しているsyck_emitter_emit...
ブロック中のout.mapメソッドが呼ばれるとまたCに戻ります。o...
def taguri
if respond_to? :to_yaml_type
YAML::tagurize( to_yaml_type[1..-1] )
else
return @taguri if defined?(@taguri) and @taguri
tag = #{ tag.dump }
if self.class.yaml_tag_subclasses? and self.class !=...
tag = "\#{ tag }:\#{ self.class.yaml_tag_class_nam...
end
tag
end
end
冒頭のFooメソッドの場合、"tag:ruby.yaml.org,2002:object:F...
to_yaml_styleはnilが返るはずなので、syck_out_mapメソッド...
Objectのto_yaml_propertiesメソッドはインスタンス変数の一...
if ( rb_respond_to( emitter, s_node_export ) ) {
key = rb_funcall( emitter, s_node_export, 1, key );
val = rb_funcall( emitter, s_node_export, 1, val );
}
emitterはYAML::Syck::Emitterオブジェクトです。node_export...
**出力の構築 [#e11f4f18]
さて、syck_emitter_emit関数に戻って、次は出力です。emitte...
syck_emit関数はアンカー処理などをやっていますが無視して、...
Objectの場合、以下の部分が実行されるはずです。
case syck_map_kind:
{
int i;
syck_emit_map( e, n->type_id, n->data.pairs->sty...
for ( i = 0; i < n->data.pairs->idx; i++ )
{
syck_emit_item( e, syck_map_read( n, map_key...
syck_emit_item( e, syck_map_read( n, map_val...
}
syck_emit_end( e );
}
break;
syck_emit_map関数(emitter.c)内で呼ばれているsyck_emit_t...
次にsyck_emit_item関数ではHashやArrayのためのマーキング文...
最後にsyck_emit_flush関数を見てみましょう。ハンドラが呼ば...
*おわりに [#x5dd1a8d]
今回はYAMLライブラリのオブジェクトシリアライズ処理を読み...
-汎用的に書かれたライブラリのRubyインターフェースの書き方
といったところでしょうか。
それではみなさんもよいコードリーディングを。
終了行:
#contents
*はじめに [#g43b2130]
YAMLの説明は[[ここら辺>http://jp.rubyist.net/magazine/?00...
まず適当に定義したクラスをYAMLライブラリでシリアライズし...
require 'yaml'
class Bar
def initialize
@array = [1, 2, 3]
@hash = {'a' => 123, 'b' => 'abc'}
end
end
class Foo
def initialize
@int = 1
@string = 'str'
@bar = Bar.new
end
end
foo = Foo.new
puts YAML.dump(foo)
上記のスクリプトを実行すると以下の出力が得られます。
--- !ruby/object:Foo
bar: !ruby/object:Bar
array:
- 1
- 2
- 3
hash:
a: 123
b: abc
int: 1
string: str
今回読んだバージョンはruby-1.8.5-p12添付のYAMLライブラリ...
*YAML.dump(yaml.rb) [#m483bd78]
では、YAML.dumpメソッドから見ていくことにしましょう。
def YAML.dump( obj, io = nil )
obj.to_yaml( io || io2 = StringIO.new )
io || ( io2.rewind; io2.read )
end
第2引数は指定していないので、StringIOオブジェクトに出力さ...
*Object#to_yaml(yaml/rubytypes.rb) [#k4f96f76]
Object#to_yamlメソッドは以下のように定義されています。
def to_yaml( opts = {} )
YAML::quick_emit( object_id, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
to_yaml_properties.each do |m|
map.add( m[1..-1], instance_variable_get( m ) )
end
end
end
end
YAML.quick_emitメソッドです。optsはStringIOオブジェクトが...
def YAML.quick_emit( oid, opts = {}, &e )
out =
if opts.is_a? YAML::Emitter
opts
else
emitter.reset( opts )
end
out.emit( oid, &e )
end
*YAML::Syck::Emitter(ext/syck/rubyext.c) [#f6f8854a]
**内部表現の構築 [#dd54f22d]
YAML::Syck::Emitterクラスはどこで定義されているかというと...
Emitter#resetメソッドを実装しているのはsyck_emitter_reset...
-引数が1個でwriteメソッドが定義されているので出力先として...
ということをしています。
次に、Emitter#emitメソッドを実装しているsyck_emitter_emit...
ブロック中のout.mapメソッドが呼ばれるとまたCに戻ります。o...
def taguri
if respond_to? :to_yaml_type
YAML::tagurize( to_yaml_type[1..-1] )
else
return @taguri if defined?(@taguri) and @taguri
tag = #{ tag.dump }
if self.class.yaml_tag_subclasses? and self.class !=...
tag = "\#{ tag }:\#{ self.class.yaml_tag_class_nam...
end
tag
end
end
冒頭のFooメソッドの場合、"tag:ruby.yaml.org,2002:object:F...
to_yaml_styleはnilが返るはずなので、syck_out_mapメソッド...
Objectのto_yaml_propertiesメソッドはインスタンス変数の一...
if ( rb_respond_to( emitter, s_node_export ) ) {
key = rb_funcall( emitter, s_node_export, 1, key );
val = rb_funcall( emitter, s_node_export, 1, val );
}
emitterはYAML::Syck::Emitterオブジェクトです。node_export...
**出力の構築 [#e11f4f18]
さて、syck_emitter_emit関数に戻って、次は出力です。emitte...
syck_emit関数はアンカー処理などをやっていますが無視して、...
Objectの場合、以下の部分が実行されるはずです。
case syck_map_kind:
{
int i;
syck_emit_map( e, n->type_id, n->data.pairs->sty...
for ( i = 0; i < n->data.pairs->idx; i++ )
{
syck_emit_item( e, syck_map_read( n, map_key...
syck_emit_item( e, syck_map_read( n, map_val...
}
syck_emit_end( e );
}
break;
syck_emit_map関数(emitter.c)内で呼ばれているsyck_emit_t...
次にsyck_emit_item関数ではHashやArrayのためのマーキング文...
最後にsyck_emit_flush関数を見てみましょう。ハンドラが呼ば...
*おわりに [#x5dd1a8d]
今回はYAMLライブラリのオブジェクトシリアライズ処理を読み...
-汎用的に書かれたライブラリのRubyインターフェースの書き方
といったところでしょうか。
それではみなさんもよいコードリーディングを。
ページ名: