190792f21421d363b668c70f121041f30e5cc8ed
[chise/ruby.git] / chise / character.rb
1 # Copyright (C) 2002-2004 Kouichirou Eto, All rights reserved.
2
3 require "singleton"
4 require "chise/parser"
5 require "chise/chisedb"
6 require "chise/iconv"
7
8 module CHISE
9   class CharacterFactory # generate Character object and cache them
10     include Singleton
11
12     MAX_CACHE_CHARACTER = 10000
13
14     def initialize
15       clear
16       @parser = CharacterParser.new
17     end
18
19     def clear
20       @chars = {}
21     end
22
23     def get(s)
24       check_max
25       mcs = @parser.parse(s)
26       @chars[mcs] = Character.new(mcs) if @chars[mcs].nil?
27       @chars[mcs]
28     end
29
30     def check_max
31       clear if MAX_CACHE_CHARACTER < @chars.length # clear all cache
32     end
33   end
34
35   class Character
36     def initialize(char_id)
37       raise if char_id.nil?
38       raise unless char_id.is_a?(Fixnum) # char_id sure is a Fixnum.
39       raise if char_id < 0 # char_id sure is a positive value.
40       @char_id = char_id
41       @char_id.freeze
42       @utf8_mcs = CHISE.i_tou8(@char_id)
43       @utf8_mcs.freeze
44       @feature = {}
45       @check_all_done = nil
46     end
47     attr_reader :char_id
48     attr_reader :utf8_mcs
49
50     def self.get(s)
51       CharacterFactory.instance.get(s)
52     end
53
54     def inspect
55       sprintf("Char:%x", @char_id)
56     end
57
58     def to_s()  @utf8_mcs;      end
59
60     def [](f)
61       f = normalize_feature_name(f)
62
63       v = @feature[f]
64       return v if v
65       v = @feature["="+f]
66       return v if v
67
68       v = get_feature(f)
69       if v
70         @feature[f] = v
71         return v
72       end
73
74       v = get_feature("="+f)
75       if v
76         @feature["="+f] = v
77         return v
78       end
79
80       nil
81     end
82
83     def []=(k,v)
84       f = normalize_feature_name(k)
85       cd = ChiseDB.instance
86       ft = cd.get_feature(f)
87       ft.set_value(@char_id, v)
88       @feature[f] = v;
89     end
90
91     def method_missing(mid, *args) # ref. ostruct.rb
92       mname = mid.id2name
93
94       return self[mname] if args.empty? # get
95
96       if args.length == 1 && /=\Z/ =~ mname # put
97         self[mname.chop] = args.shift
98         return
99       end
100
101       raise "error"
102     end
103
104     def to_er
105       en = EntityReferenceEncoder.new
106       en.to_er(self)
107     end
108
109     private
110
111     def get_feature(f)
112       cd = ChiseDB.instance
113       cd.load_feature(f, @char_id)
114     end
115
116     def normalize_feature_name(a)
117       a = a.gsub(/_/, "-") #underlineは-に置換
118       a = a.sub(/-at-/,    "@")
119       a = a.sub(/-plus-/,  "+")
120       a = a.sub(/\Amap-/,  "=>")
121       a = a.sub(/\Ato-/,   "->")
122       a = a.sub(/\Afrom-/, "<-")
123       a
124     end
125   end
126 end