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