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       @ccsstr_db = {}
27     end
28     attr_reader :ds, :location
29
30     def setup_ds
31       return if @ds
32       @ds = DataSource.new(CHISE::DataSource::Berkeley_DB, @location.to_s, 0, 0755)
33     end
34
35     def close
36       # @ds.close if @ds # do not close for now
37       # @ds = nil
38     end
39
40     def each_feature_name()
41       @ds.each_feature_name {|f|
42         next if f.to_s == "." || f.to_s == ".."
43         next if f.to_s =~ /\.txt\Z/
44         yield(f.path.unescape_win_filename.unescape.to_s)
45       }
46     end
47
48     def each_ccs
49       each_entry("character/by_feature") {|f| yield(f) }
50     end
51
52     def get_feature(name)
53       @feature_db[name] = FeatureDB.new(self, name) if @feature_db[name].nil?
54       @feature_db[name]
55     end
56
57     def load_feature(cid, name)
58       feature = get_feature(name)
59       feature.get_value(cid)
60     end
61
62     def get_ccs(name)
63       @ccs_db[name] = CCS_DB.new(self, name) if @ccs_db[name].nil?
64       @ccs_db[name]
65     end
66
67     def decode_char(ccs, code_point)
68       ccsdb = get_ccs(ccs)
69       ccsdb.decode(code_point)
70     end
71
72     def nuget_by_ids_db(n)
73       @byids_db[n] = ByIDS_DB.new(self, n) if @byids_db[n].nil?
74       @byids_db[n]
75     end
76
77     def get_ccs_str(n)
78       @ccsstr_db[n] = CCS_STR.new(self, n) if @ccsstr_db[n].nil?
79 #      @ccsstr_db[n] = CCS_STR_DB.new(self, n) if @ccsstr_db[n].nil?
80       @ccsstr_db[n]
81     end
82
83     private
84     include EachEntryModule
85   end
86
87   module TableManagementModule
88     def to_hash
89       sync # add.
90       h = {}
91       each_char {|k, v| h[k] = v }
92       h
93     end
94
95     def dump
96       txt = @name.path.escape.escape_win_filename.to_s+".txt"
97       t = @cd.location+@category+@keyvalue+txt
98       t.open("wb"){|out|
99         to_hash.sort.each {|k, v|
100           out.printf("%s\t%s\n", k, v)
101         }
102       }
103     end
104   end
105
106   class FeatureDB
107     include ParseValueModule
108     include TableManagementModule
109
110     def initialize(cd, name)
111       @cd, @name = cd, name
112       @ds = @cd.ds
113       @feature = @ds.get_feature(@name.path.escape.escape_win_filename.to_s)
114       @category, @keyvalue = "character", "feature"
115       at_exit {
116         close
117       }
118     end
119     def setup_db(w) @feature.setup_db(w); end
120     def sync
121       #qp "sync"
122       @feature.sync
123     end
124     alias close sync
125
126     def set_value(cid, value)
127       @feature.set_value(cid, value.to_s)
128     end
129
130     def get_value(cid)
131       parse_value(@feature.get_value(cid))
132     end
133
134     def each_char
135       @feature.each_char {|cid, value|
136         #qp cid, value
137         yield(cid, parse_value(value))
138       }
139     end
140   end
141
142   class CCS_DB
143     include TableManagementModule
144
145     def initialize(cd, name)
146       @cd, @name = cd, name
147       @ds = @cd.ds
148       @ccs = @ds.get_ccs(@name)
149       @dsr = @ccsr = nil
150       @category, @keyvalue = "character", "by_feature"
151       at_exit {
152         close
153       }
154     end
155     def setup_db(w) @ccs.setup_db(w); end
156     def sync() @ccs.sync(); end
157     alias close sync
158     def set(code_point, cid) @ccs.set(code_point, cid); end
159     def decode(code_point) @ccs.decode(code_point); end
160
161     def setup_ccs_r
162       db_dir = CHISE::DataSource::DB_DIR
163       @dsr = DataSource_R.new(CHISE::DataSource::Berkeley_DB, db_dir, 0, 0755) if @dsr.nil?
164       #qp @name
165       @ccsr = CCS_R.new(@dsr, @name) if @ccsr.nil?
166     end
167
168     def each_char # call CCS_R here.
169       setup_ccs_r
170       @ccsr.each_char {|code_point, cid|
171         yield(code_point, cid)
172       }
173     end
174   end
175
176   class CCS_STR_DB
177     include ParseValueModule
178     include ChiseValue
179     include TableAccessModule
180     include TableManagementModule
181
182     def initialize(cd, name)
183       @cd, @name = cd, name
184       @ds = @cd.ds
185       @category, @keyvalue = "character", "by_ids"
186       reset
187       at_exit {
188         close
189       }
190     end
191
192     def get_by_str(str)
193       setup_db
194       return nil if @db.nil?
195       parse_c_string(@db.get(str))
196     end
197
198     def set_by_str(str, cid)
199       setup_db(true)
200       raise "@db is nil." if @db.nil?
201       @db.put(str, format_char_id(cid))
202     end
203
204     def each_char
205       setup_db
206       raise "@db is nil." if @db.nil?
207       @db.each {|k, v|
208         yield(parse_value(k), parse_c_string(v))
209       }
210     end
211   end
212
213 end