* io.c (rb_open_file): encoding in mode string was ignored if perm is
[ruby-svn.git] / lib / yaml / tag.rb
blob0fb6bef9a0961ea950c9b0b66362a30bfd21a137
1 # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
2 # $Id$
4 # = yaml/tag.rb: methods for associating a taguri to a class.
6 # Author:: why the lucky stiff
7
8 module YAML
9     # A dictionary of taguris which map to
10     # Ruby classes.
11     @@tagged_classes = {}
12     
13     # 
14     # Associates a taguri _tag_ with a Ruby class _cls_.  The taguri is used to give types
15     # to classes when loading YAML.  Taguris are of the form:
16     #
17     #   tag:authorityName,date:specific
18     #
19     # The +authorityName+ is a domain name or email address.  The +date+ is the date the type
20     # was issued in YYYY or YYYY-MM or YYYY-MM-DD format.  The +specific+ is a name for
21     # the type being added.
22     # 
23     # For example, built-in YAML types have 'yaml.org' as the +authorityName+ and '2002' as the
24     # +date+.  The +specific+ is simply the name of the type:
25     #
26     #  tag:yaml.org,2002:int
27     #  tag:yaml.org,2002:float
28     #  tag:yaml.org,2002:timestamp
29     #
30     # The domain must be owned by you on the +date+ declared.  If you don't own any domains on the
31     # date you declare the type, you can simply use an e-mail address.
32     #
33     #  tag:why@ruby-lang.org,2004:notes/personal
34     #
35     def YAML.tag_class( tag, cls )
36         if @@tagged_classes.has_key? tag
37             warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
38         end
39         @@tagged_classes[tag] = cls
40     end
42     # Returns the complete dictionary of taguris, paired with classes.  The key for
43     # the dictionary is the full taguri.  The value for each key is the class constant
44     # associated to that taguri.
45     #
46     #  YAML.tagged_classes["tag:yaml.org,2002:int"] => Integer
47     #
48     def YAML.tagged_classes
49         @@tagged_classes
50     end
51 end
53 class Module
54     # :stopdoc:
56     # Adds a taguri _tag_ to a class, used when dumping or loading the class
57     # in YAML.  See YAML::tag_class for detailed information on typing and
58     # taguris.
59     def yaml_as( tag, sc = true )
60         verbose, $VERBOSE = $VERBOSE, nil
61         class_eval <<-"end;", __FILE__, __LINE__+1
62             attr_writer :taguri
63             def taguri
64                 if respond_to? :to_yaml_type
65                     YAML::tagurize( to_yaml_type[1..-1] )
66                 else
67                     return @taguri if defined?(@taguri) and @taguri
68                     tag = #{ tag.dump }
69                     if self.class.yaml_tag_subclasses? and self.class != YAML::tagged_classes[tag]
70                         tag = "\#{ tag }:\#{ self.class.yaml_tag_class_name }"
71                     end
72                     tag
73                 end
74             end
75             def self.yaml_tag_subclasses?; #{ sc ? 'true' : 'false' }; end
76         end;
77         YAML::tag_class tag, self
78     ensure
79         $VERBOSE = verbose
80     end
81     # Transforms the subclass name into a name suitable for display
82     # in a subclassed tag.
83     def yaml_tag_class_name
84         self.name
85     end
86     # Transforms the subclass name found in the tag into a Ruby
87     # constant name.
88     def yaml_tag_read_class( name )
89         name
90     end
91 end