update.
[chise/ruby.git] / chise / chisedb.rb
1 # Copyright (C) 2002-2004 Kouichirou Eto, All rights reserved.
2
3 require "singleton"
4 require "chise/libchise"
5
6 module CHISE
7   module ParseValueModule
8     def parse_value(v)
9       return nil if v.nil?
10       return v.to_i if /\A\d+\Z/ =~ v # number?
11       return $1 if /\A"(.+)"\Z/ =~ v # remove surrounding "
12       v # sexp? or the other?
13     end
14   end
15
16   class ChiseDB
17     include Singleton
18
19     def initialize
20       @location = CHISE::DataSource::DB_DIR.path
21       @ds = nil
22       setup_ds
23       @feature_db = {}
24       @ccs_db = {}
25       @byids_db = {}
26     end
27     attr_reader :ds, :location
28
29     def setup_ds
30       return if @ds
31       @ds = DataSource.new(CHISE::DataSource::Berkeley_DB, @location.to_s, 0, 0755)
32     end
33
34     def close
35       # @ds.close if @ds # do not close for now
36       # @ds = nil
37     end
38
39     def each_feature_name()
40       @ds.each_feature_name {|f|
41         next if f.to_s == "." || f.to_s == ".."
42         next if f.to_s =~ /\.txt\Z/
43         yield(f.path.unescape_win_filename.unescape.to_s)
44       }
45     end
46
47     def each_ccs
48       each_entry("character/by_feature") {|f| yield(f) }
49     end
50
51     def get_feature(name)
52       @feature_db[name] = FeatureDB.new(self, name) if @feature_db[name].nil?
53       @feature_db[name]
54     end
55
56     def load_feature(cid, name)
57       feature = get_feature(name)
58       feature.get_value(cid)
59     end
60
61     def get_ccs(name)
62       @ccs_db[name] = CCS_DB.new(self, name) if @ccs_db[name].nil?
63       @ccs_db[name]
64     end
65
66     def decode_char(ccs, code_point)
67       ccsdb = get_ccs(ccs)
68       ccsdb.decode(code_point)
69     end
70
71     def get_by_ids_db(n)
72       @byids_db[n] = ByIDS_DB.new(self, n) if @byids_db[n].nil?
73       @byids_db[n]
74     end
75
76     private
77     include EachEntryModule
78   end
79
80   module TableManagementModule
81     def to_hash
82       sync # add.
83       h = {}
84       each_char {|k, v| h[k] = v }
85       h
86     end
87
88     def dump
89       txt = @name.path.escape.escape_win_filename.to_s+".txt"
90       t = @cd.location+@category+@keyvalue+txt
91       t.open("wb"){|out|
92         to_hash.sort.each {|k, v|
93           out.printf("%s\t%s\n", k, v)
94         }
95       }
96     end
97   end
98
99   class FeatureDB
100     include ParseValueModule
101     include TableManagementModule
102
103     def initialize(cd, name)
104       @cd, @name = cd, name
105       @ds = @cd.ds
106       @feature = @ds.get_feature(@name.path.escape.escape_win_filename.to_s)
107       @category, @keyvalue = "character", "feature"
108       at_exit {
109         close
110       }
111     end
112     def setup_db(w) @feature.setup_db(w); end
113     def sync
114       #qp "sync"
115       @feature.sync
116     end
117     alias close sync
118
119     def set_value(cid, value)
120       @feature.set_value(cid, value)
121     end
122
123     def get_value(cid)
124       parse_value(@feature.get_value(cid))
125     end
126
127     def each_char
128       @feature.each_char {|cid, value|
129         #qp cid, value
130         yield(cid, parse_value(value))
131       }
132     end
133   end
134
135   class CCS_DB
136     include TableManagementModule
137
138     def initialize(cd, name)
139       @cd, @name = cd, name
140       @ds = @cd.ds
141       @ccs = @ds.get_ccs(@name)
142       @dsr = @ccsr = nil
143       @category, @keyvalue = "character", "by_feature"
144       at_exit {
145         close
146       }
147     end
148     def setup_db(w) @ccs.setup_db(w); end
149     def sync() @ccs.sync(); end
150     alias close sync
151     def set(code_point, cid) @ccs.set(code_point, cid); end
152     def decode(code_point) @ccs.decode(code_point); end
153
154     def setup_ccs_r
155       db_dir = CHISE::DataSource::DB_DIR
156       @dsr = DataSource_R.new(CHISE::DataSource::Berkeley_DB, db_dir, 0, 0755) if @dsr.nil?
157       #qp @name
158       @ccsr = CCS_R.new(@dsr, @name) if @ccsr.nil?
159     end
160
161     def each_char # call CCS_R here.
162       setup_ccs_r
163       @ccsr.each_char {|code_point, cid|
164         yield(code_point, cid)
165       }
166     end
167   end
168
169   class ByIDS_DB
170     include ParseValueModule
171     include ChiseValue
172     include TableAccessModule
173     include TableManagementModule
174
175     def initialize(cd, name)
176       @cd, @name = cd, name
177       @ds = @cd.ds
178       @category, @keyvalue = "character", "by_ids"
179       reset
180       at_exit {
181         close
182       }
183     end
184
185     def decode(ids)
186       setup_db
187       return nil if @db.nil?
188       parse_c_string(@db.get(ids))
189     end
190
191     def set_decoded_char(ids, cid)
192       setup_db(true)
193       raise "@db is nil." if @db.nil?
194       @db.put(ids, format_char_id(cid))
195     end
196
197     def each_char
198       setup_db
199       raise "@db is nil." if @db.nil?
200       @db.each {|k, v|
201         yield(parse_value(k), parse_c_string(v))
202       }
203     end
204   end
205 end