2 # $Id: db.rb,v 1.1 2003-11-10 08:11:46 eto Exp $
3 # Copyright (C) 2002-2003 Kouichirou Eto, All rights reserved.
4 # This is free software with ABSOLUTELY NO WARRANTY.
5 # You can redistribute it and/or modify it under the terms of the GNU GPL2.
12 class DBS #======================================================================複数のDBを集めたclass、未完成
15 class ADB < BDB::Hash #======================================================================一つのDB
21 # p ['at_exit', @filename, @modified]
23 # p ['close', @filename, @modified]
24 self.close #これがないと、うまくデータベースがセーブされないのです。
28 def self.open_create(filename)
29 ADB.open(filename, nil, BDB::CREATE | BDB::EXCL) #上書きはしない
33 if key.char_length == 1
34 return '?'+key #Stringだったら引く前に?を足す
37 #key = key.to_s if key.is_a?(Numeric) #NumberだったらStringにする。
38 #ここで && key ! =~ /^\?/ をいれると、?自身を検索できなくなってしまう。
43 return v.to_i if v =~ /^\d+$/ #数字だったらここで変換しておく
44 return v.sub(/^\?/, '') if v =~ /^\?/ #冒頭の?は取り除く
45 return $1 if v =~ /^"(.+)"$/ #最初と最後に"がついていたら、取り除く
46 #p ['get', v, t, key, db]
47 #return parse_sexp(v) if v =~ /^\(.+\)$/ #最初と最後が()の時は、S式にparseする
50 def myget(key) #keyキーを引いて返す
52 v = get(key) #存在しなかったらnilを返すことになる
55 def myput(key, v) #keyにvをいれる
62 class DB #======================================================= データベース群のabstract class
63 def self.unix_to_win(unix) #Windowsファイル名制限のため、変換する
64 win = unix.gsub(/</, '(')
70 def self.win_to_unix(win)
71 unix = win.gsub(%r|\)|, '>')
72 unix.gsub!(%r|\(|, '<')
73 unix.gsub!(%r|!|, '?')
74 unix.gsub!(%r|\+|, '*')
78 return @pre + DB.unix_to_win(t) + @post if windows?
79 return @pre + t + @post
81 def get_dirname(t) File.dirname(get_filename(t)) end
85 keys.each {|key| open_db(key) }
90 next if ! File.file?(f)
97 t.sub!(%r|^#{@pre}|, '')
98 t.sub!(%r|#{@post}$|, '') if @post != ""
105 return nil if db.nil?
110 return nil if get(t) #すでにopenしていたら再openはしない。
112 bdb = ADB.open(get_filename(t), nil, 0)
113 @dbs[t] = bdb if bdb != nil
115 p ["open error", get_filename(t)]; return nil
119 def make_db(t, h=nil) #tという名前でhという中身のデータベースを作る
120 return nil if get(t) #すでにある場合はreturn
121 Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
124 db = ADB.open_create(get_filename(t)) #上書きはしない
127 k = '?'+k if k.is_a?(String)
133 p ["make error", get_filename(t)]; return nil
137 def make_db_no_question_mark(t, h=nil) #tという名前でhという中身のデータベースを作る
138 return nil if get(t) #すでにある場合はreturn
139 Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
142 db = ADB.open_create(get_filename(t)) #上書きはしない
145 # k = '?'+k if k.is_a?(String)
151 p ["make error", get_filename(t)]; return nil
155 def remove_db(t) #tという名前のデータベースを消去する
162 File.unlink(get_filename(t)) if FileTest.file?(get_filename(t))
164 p ["unlink error", get_filename(t)]; return nil
167 Dir.rmdir(dn) if FileTest.directory?(dn) && Dir.entries(dn).length <= 2 #空directoryだったら消す
171 return s.to_i if s =~ /^\d+$/
177 file = get_filename(t)
178 open("#{file}.txt", "w"){|out|
179 # out.binmode.sync = true
181 ar.map! {|k, v| [to_num(k), to_num(v)] }
183 out.printf("%s\t%s\n", k, v)
188 def each_db() @dbs.to_a.sort.each {|t, db| yield(t, db) } end
189 def dump_all() each_db {|t, db| dump_db(t) } end
190 def close_all() each_db {|t, db| db.close } end
191 def keys() @dbs.keys end
193 return unless block_given?
199 k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
200 vv = get(t, k) #p ['each', t, k, v, vv]
205 return unless block_given?
209 ar.map! {|k, v| [to_num(k), to_num(v)] }
211 k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
212 vv = get(t, k) #p ['each', t, k, v, vv]
216 #----------------------------------------------------------------------
217 def get(t, key=nil) #tというデータベースのkeyキーを引いて返す
219 return db if key.nil?
223 def put(t, key, v) #tというデータベースのkeyにvをいれる
230 db.myput(key, v) #putする
234 class CharDB < DB #------------------------------------ MCS-UTF8をキーとした属性へのデータベース
238 @glob, @pre, @post = "#{DB_DIR}/system-char-id/*", "#{DB_DIR}/system-char-id/", ""
241 def get_all(u8) #全データベースのu8キーを引いてHashにまとめて返す
245 atrs[t] = v if v != nil
251 class CodesysDB < DB #----------------------------------------------------------------------
255 @glob, @pre, @post = "#{DB_DIR}/*/system-char-id", "#{DB_DIR}/", "/system-char-id"
258 #def keys() @dbs.keys.sort end #どんなCodesysの情報を持っているかの一覧
259 def keys() @dbs.keys end #どんなCodesysの情報を持っているかの一覧
263 return Codesys.new(t)
267 class Codesys < DB #======================================================================
271 @dbs = CodesysDB.instance
273 def keys() #どんなコードポイントの情報を持っているかの一覧
274 ks = @dbs.get(@name).keys
275 # if @name =~ /jisx0208/ #特別処理
276 # n = @dbs.get('=jis-x0208').keys
277 # # p ['keys', @name, ks, n]
280 ks.map! {|k| to_num(k) }
284 v = @dbs.get(@name, key)
286 # if @name =~ /jisx0208/ #jisx0208が含まれている場合だけ特別処理する
287 # return @dbs.get('=jis-x0208', key)
292 return unless block_given?
298 k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
299 vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
304 return unless block_given?
308 ar.map! {|k, v| [to_num(k), to_num(v)] }
310 k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
311 vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
317 class JISX0208 #======================================================================
319 db = CodesysDB.instance
320 @common = db.get_codesys('=jis-x0208')
321 @newest = db.get_codesys('japanese-jisx0208-1990')
324 char = @common.get(code)
325 return char unless char.nil?
326 char = @newest.get(code)
327 return char unless char.nil?
332 class DBS_Management #======================================================================ファイル管理
333 OBSOLETE_ATTRIBUTES = "
365 ancient-char-of-shinjigen-1
366 original-ideograph-of
367 original-char-of-shinjigen-1
368 simplified-ideograph-of
370 vulgar-char-of-shinjigen-1
373 variant-of-shinjigen-1
378 @odir = DB_DIR+"/system-char-id/obsolete" #直打ちしている。
380 def move_obsolete_files # 廃止予定のbdbファイルをobsoleteディレクトリーにつっこむ
383 Dir.mkdir(@odir) unless FileTest.directory? @odir
384 OBSOLETE_ATTRIBUTES.each {|attr|
386 filename = db.get_filename(attr)
387 move_to_obsolete(filename)
388 move_to_obsolete(filename+".txt")
391 def move_to_obsolete(file)
392 cmd = "mv \"#{file}\" #{@odir}"
400 #----------------------------------------------------------------------終了