}
str = ""
h.each {|k, v|
-# p [k, v]
+ # p [k, v]
if length == v #全部に顔を出していたら
str += k
end
}
-# p str
+ # p str
str
end
def compose()
return "" #attributeを持つものが一つも無かったら、""にする
end
def aggregate()
-#selfである文字列をIDSだと仮定し、それを完全にcomposeしきらないで、
-#その部分集合だけをとりだして、compose可能であればできるだけcomposeする。
+ #selfである文字列をIDSだと仮定し、それを完全にcomposeしきらないで、
+ #その部分集合だけをとりだして、compose可能であればできるだけcomposeする。
tree = IDS_Tree.new(self)
return self if tree.depth <= 1 #sub_nodesが無い場合はここでさよなら
tree.sub_nodes.each {|node|
c = node.compose
next if c.nil? || c == ""
-# print "#{self} #{node} #{c}\n"
-# p [self, node, c]
+ # print "#{self} #{node} #{c}\n"
+ # p [self, node, c]
n = self.gsub(node, c)
return n.aggregate
}
return "" unless er =~ Regexp.new(REGEXP_ALL) #なんか、間違ってる?
er = $1 #ついでに中身の部分を取り出す
return $1.hex if er =~ /^MCS-([0-9A-Fa-f]+)/ #MCS
-# if er =~ /^U[-+]?([0-9A-Fa-f]+)/ #Unicode直打ち
+ # if er =~ /^U[-+]?([0-9A-Fa-f]+)/ #Unicode直打ち
if er =~ /^U[-+]?([0-9A-Fa-f]+)/ || er =~ /^#x([0-9A-Fa-f]+)/ #Unicode直打ち
return $1.hex
end
ar = %w{ucs-jis ucs =>ucs-jis}
#並び順は恣意的で、ucs-jisを先に出している。本来はこれも指定できるようにするべき。
ar.each {|a| #p [a]
- u = get_char_attribute(a)
- return u if u != nil
- }
- return nil
- end
-
- #----------------------------------------------------------------------CCS関係
- def to_utf8() Uconv.u4tou8(Character.u4itou4(ucs())) end #UTF8文字列を返す
- #alias to_s to_utf8
- alias to_s mcs_utf8
- def map_utf8()
- u = ucs()
- if u.nil? || 0xffff < u
- return to_er()
- else
- return to_utf8()
- end
- end
- alias map_ucs map_utf8
- def map_ucs_er()
- u = ucs()
- if u.nil? || 0xffff < u
- return to_er()
- else
- return Character.get(u).to_er()
- end
- end
- def to_euc()
- u = ucs()
- return "" if u.nil? || 0xffff < u
- Uconv.u16toeuc(Uconv.u4tou16(Character.u4itou4(ucs())))
- end
- def map_euc()
- e = to_euc()
- return e if e != ""
- return to_er()
- end
- def to_sjis()
- u = ucs()
- return "" if u.nil? || 0xffff < u
- Uconv.u16tosjis(Uconv.u4tou16(Character.u4itou4(ucs())))
- end
- def map_sjis()
- e = to_sjis()
- return e if e != ""
- return to_er()
- end
-
- #----------------------------------------------------------------------
- def to_er(codesys=nil) #実体参照を返す、希望するcodesysが引数(未実装)
- return "" if @char_id == nil
- return sprintf("&#x%04x;", @char_id) if @char_id <= 0xffff
- return sprintf("&#x%05x;", @char_id) if @char_id <= 0xfffff
- EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
- code = self[codesys]
- next if code == nil
- return sprintf("&#{er_prefix}%0#{keta}#{numtype};", code)
- }
- return sprintf("&MCS-%08X;", @char_id) #本当はこれは無しにしたい
- end
- def to_er_list()
- ar = []
- EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
- er = to_er(codesys)
- ar << er if er != nil
- }
- ar
- end
-
- def inspect_x()
- return "<>" if @char_id == nil
- ar = [to_utf8(), to_er().sub(/^&/,'').chop]
- "<"+ar.join(',')+">"
- end
- alias inspect inspect_x
- def inspect_all_codesys() #未完成
- #to_erを全てのcodesysにおいて実行する。その結果をコンパクトにまとめる
- end
- def inspect_all()
- ar = [inspect.chop]
- alist.to_a.sort.each {|a, v| ar << "#{a}:#{v}" }
- return ar.join(',')+">"
- end
- def get_attributes()
- str = ""
- alist.to_a.sort.each {|a, v|
- str += "#{a}: #{v}\n"
- }
- str
- end
-
- def inspect_ids(hex_flag=false)
- ids = decompose
- ar = []
- ar << (hex_flag ? "x"+mcs_hex : to_utf8)
- if to_s != ids #idsが部品そのものだったら部品追加はしない
- ids.each_char {|ch|
- char = ch.char
- next if char.is_ids?
- if hex_flag then
- ar << "x"+char.mcs_hex
- else
- u = char.to_utf8
- if u != ""
- ar << u
- else
- ar << char.to_er
- end
- end
- }
- end
- return "("+ar.join("\t")+")"
- end
-
- #----------------------------------------------------------------------IDS関係
- def decompose
- k = self.to_s
-# idss = self['ids']
-# return idss if idss
-# return k if self.is_basic_kanji? #基本漢字はstop kanjiとするぞと。
- return self['ids-represent'] if self['ids-represent'] #ids_representを持っている場合はその値とする。
- return self['ids-element'] if self['ids-element'] #ids_elementを持っている場合はその値とする。
-
- idss = self['ids-meaning']
- return idss if idss != nil && 0 < idss.length && k != idss
- idss = self['ids-aggregated']
- return idss if idss != nil && 0 < idss.length && k != idss
- idss = self['ids']
- return idss if idss != nil && 0 < idss.length && k != idss
- return k
-# return k if idss.nil? || idss.length == 0 || k == idss
-# if idss.char_length == 2
-# p ['What???', k, idss, k.inspect_all]
-# #return idssx[1] #二個目だけ返すとか?
-# return k #IDSに展開する方法が無いと。
-# end
-# return k if k == idss
-# if idss.include?(k) #<C5-4C4D><C6-4A37>この二文字のBUG対策
-# #return idss.sub(k, '')
-# return k #IDSに展開する方法が無いと。
-# end
-# return idss
- end
- def decompose_all
- pde = ""
- de = self.decompose #出発点
- level = 0
- while true
- pde = de
- de = pde.decompose #もう一度分解をしてみる。
- break if pde == de #ループを抜けだす
- exit if 10 < level #p ['too many recursive', self]
- level += 1
- end
- return de
- end
- def decompose_all_nu(level=nil)
- level = 0 if level.nil?
- if 10 < level
- p ['too many recursive', self]
- exit
- end
- de = self.decompose
- return de.decompose_all(level+1) if de != self #なにか変化があったから再帰
- return de #もうこれ以上変化は無さそうだぞと。
- end
- def is_ids?() 0x2ff0 <= @char_id && @char_id <= 0x2fff end
- def ids_operator_argc()
- return 0 unless is_ids?
- return 3 if @char_id == 0x2ff2 || @char_id == 0x2ff3
- return 2
- end
- end
-
- class DBS #======================================================================複数のDBを集めたclass、未完成
- end
-
- class ADB < BDB::Hash #======================================================================一つのDB
- def initialize(*args)
- super
- @modified = false
- at_exit {
- if @modified
- self.close #これがないと、うまくデータベースがセーブされないのです。
- end
- }
- end
- def self.open_create(filename)
- ADB.open(filename, nil, BDB::CREATE | BDB::EXCL) #上書きはしない
- end
- def mykey(key)
- if key.is_a?(String)
- if key.char_length == 1
- return '?'+key #Stringだったら引く前に?を足す
- end
- end
- #key = key.to_s if key.is_a?(Numeric) #NumberだったらStringにする。
- #ここで && key ! =~ /^\?/ をいれると、?自身を検索できなくなってしまう。
- return key
- end
- def myvalue(v)
- return v if v == nil
- return v.to_i if v =~ /^\d+$/ #数字だったらここで変換しておく
- return v.sub(/^\?/, '') if v =~ /^\?/ #冒頭の?は取り除く
- return $1 if v =~ /^"(.+)"$/ #最初と最後に"がついていたら、取り除く
- #p ['get', v, t, key, db]
- #return parse_sexp(v) if v =~ /^\(.+\)$/ #最初と最後が()の時は、S式にparseする
- return v #それ以外って何?
- end
- def myget(key) #keyキーを引いて返す
- key = mykey(key)
- v = get(key) #存在しなかったらnilを返すことになる
- return myvalue(v)
- end
- def myput(key, v) #keyにvをいれる
- key = mykey(key)
- put(key, v) #putする
- @modified = true
- end
- end
-
- class DB #======================================================= データベース群のabstract class
- def self.unix_to_win(unix) #Windowsファイル名制限のため、変換する
- win = unix.gsub(/</, '(')
- win.gsub!(/>/, ')')
- win.gsub!(/\*/, '+')
- win.gsub!(/\?/, '!')
- return win
- end
- def self.win_to_unix(win)
- unix = win.gsub(%r|\)|, '>')
- unix.gsub!(%r|\(|, '<')
- unix.gsub!(%r|!|, '?')
- unix.gsub!(%r|\+|, '*')
- return unix
- end
- def get_filename(t)
- return @pre + DB.unix_to_win(t) + @post if windows?
- return @pre + t + @post
- end
- def get_dirname(t) File.dirname(get_filename(t)) end
- def open_dbs()
- @dbs = Hash.new
- keys = find_keys()
- keys.each {|key| open_db(key) }
- end
- def find_keys()
- files = []
- Dir.glob(@glob){|f|
- next if ! File.file?(f)
- next if f =~ /.txt$/
- files << f
- }
- keys = []
- files.each {|f|
- t = DB.win_to_unix(f)
- t.sub!(%r|^#{@pre}|, '')
- t.sub!(%r|#{@post}$|, '') if @post != ""
- keys << t
- }
- return keys
- end
- def close_db(t)
- db = get(t)
- return nil if db.nil?
- db.close
- @dbs.delete(t)
- end
- def open_db(t)
- return nil if get(t) #すでにopenしていたら再openはしない。
- begin
- bdb = ADB.open(get_filename(t), nil, 0)
- @dbs[t] = bdb if bdb != nil
- rescue
- p ["open error", get_filename(t)]; return nil
- end
- return true
- end
- def make_db(t, h=nil) #tという名前でhという中身のデータベースを作る
- return nil if get(t) #すでにある場合はreturn
- Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
- db = nil
- begin
- db = ADB.open_create(get_filename(t)) #上書きはしない
- if h != nil
- h.each {|k, v|
- k = '?'+k if k.is_a?(String)
- db[k] = v
- }
- end
- db.close
- rescue
- p ["make error", get_filename(t)]; return nil
- end
- return true
- end
- def make_db_no_question_mark(t, h=nil) #tという名前でhという中身のデータベースを作る
- return nil if get(t) #すでにある場合はreturn
- Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
- db = nil
- begin
- db = ADB.open_create(get_filename(t)) #上書きはしない
- if h != nil
- h.each {|k, v|
-# k = '?'+k if k.is_a?(String)
- db[k] = v
- }
- end
- db.close
- rescue
- p ["make error", get_filename(t)]; return nil
- end
- return true
- end
- def remove_db(t) #tという名前のデータベースを消去する
- db = get(t)
- if db
- db.close
- @dbs.delete(t)
- end
- begin
- File.unlink(get_filename(t)) if FileTest.file?(get_filename(t))
- rescue
- p ["unlink error", get_filename(t)]; return nil
- end
- dn = get_dirname(t)
- Dir.rmdir(dn) if FileTest.directory?(dn) && Dir.entries(dn).length <= 2 #空directoryだったら消す
- return true
- end
- def to_num(s)
- return s.to_i if s =~ /^\d+$/
- return s
- end
- def dump_db(t)
- db = get(t)
- return nil unless db
- file = get_filename(t)
- open("#{file}.txt", "w"){|out|
-# out.binmode.sync = true
- ar = db.to_a
- ar.map! {|k, v| [to_num(k), to_num(v)] }
- ar.sort.each {|k, v|
- out.printf("%s\t%s\n", k, v)
- }
- }
- return true
- end
- def each_db() @dbs.to_a.sort.each {|t, db| yield(t, db) } end
- def dump_all() each_db {|t, db| dump_db(t) } end
- def close_all() each_db {|t, db| db.close } end
- def keys() @dbs.keys end
- def each(t)
- return unless block_given?
- db = @dbs[t]
- return nil unless db
- db.each {|k, v|
- k = to_num(k)
- v = to_num(v)
- k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
- vv = get(t, k) #p ['each', t, k, v, vv]
- yield(k, vv)
- }
- end
- def each_sort(t)
- return unless block_given?
- db = @dbs[t]
- return nil unless db
- ar = db.to_a
- ar.map! {|k, v| [to_num(k), to_num(v)] }
- ar.sort.each {|k, v|
- k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
- vv = get(t, k) #p ['each', t, k, v, vv]
- yield(k, vv)
- }
- end
- #----------------------------------------------------------------------
- def get(t, key=nil) #tというデータベースのkeyキーを引いて返す
- db = @dbs[t]
- return db if key.nil?
- return nil unless db
- return db.myget(key)
- end
- def put(t, key, v) #tというデータベースのkeyにvをいれる
- db = @dbs[t]
- if db == nil
- db = make_db(t)
- db = open_db(t)
- db = @dbs[t]
- end
- db.myput(key, v) #putする
- end
- end
-
- class CharDB < DB #------------------------------------ MCS-UTF8をキーとした属性へのデータベース
- include Singleton
- def initialize()
- super
- @glob, @pre, @post = "#{DB_DIR}/system-char-id/*", "#{DB_DIR}/system-char-id/", ""
- open_dbs()
- end
- def get_all(u8) #全データベースのu8キーを引いてHashにまとめて返す
- atrs = Hash.new
- @dbs.each {|t, db|
- v = get(t, u8)
- atrs[t] = v if v != nil
- }
- return atrs
- end
- end
-
- class CodesysDB < DB #----------------------------------------------------------------------
- include Singleton
- def initialize()
- super
- @glob, @pre, @post = "#{DB_DIR}/*/system-char-id", "#{DB_DIR}/", "/system-char-id"
- open_dbs()
- end
- #def keys() @dbs.keys.sort end #どんなCodesysの情報を持っているかの一覧
- def keys() @dbs.keys end #どんなCodesysの情報を持っているかの一覧
- def get_codesys(t)
- db = get(t)
- return nil unless db
- return Codesys.new(t)
- end
- end
-
- class Codesys < DB #======================================================================
- def initialize(name)
-# super
- @name = name
- @dbs = CodesysDB.instance
- end
- def keys() #どんなコードポイントの情報を持っているかの一覧
- ks = @dbs.get(@name).keys
- if @name =~ /jisx0208/ #特別処理
- n = @dbs.get('=jis-x0208').keys
- # p ['keys', @name, ks, n]
- ks += n
- end
- ks.map! {|k| to_num(k) }
- ks
- end
- def get(key)
- v = @dbs.get(@name, key)
- return v if v
- if @name =~ /jisx0208/ #jisx0208が含まれている場合だけ特別処理する
- return @dbs.get('=jis-x0208', key)
- end
- return nil
- end
- def each()
- return unless block_given?
- db = @dbs.get(@name)
- return nil unless db
- db.each {|k, v|
- k = to_num(k)
- v = to_num(v)
- k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
- vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
- yield(k, vv)
- }
- end
- def each_sort()
- return unless block_given?
- db = @dbs.get(@name)
- return nil unless db
- ar = db.to_a
- ar.map! {|k, v| [to_num(k), to_num(v)] }
- ar.sort.each {|k, v|
- k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
- vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
- yield(k, vv)
- }
- end
- end
+ u = get_char_attribute(a)
+ return u if u != nil
+ }
+ return nil
+ end
+
+ #----------------------------------------------------------------------CCS関係
+ def to_utf8() Uconv.u4tou8(Character.u4itou4(ucs())) end #UTF8文字列を返す
+ #alias to_s to_utf8
+ alias to_s mcs_utf8
+ def map_utf8()
+ u = ucs()
+ if u.nil? || 0xffff < u
+ return to_er()
+ else
+ return to_utf8()
+ end
+ end
+ alias map_ucs map_utf8
+ def map_ucs_er()
+ u = ucs()
+ if u.nil? || 0xffff < u
+ return to_er()
+ else
+ return Character.get(u).to_er()
+ end
+ end
+ def to_euc()
+ u = ucs()
+ return "" if u.nil? || 0xffff < u
+ Uconv.u16toeuc(Uconv.u4tou16(Character.u4itou4(ucs())))
+ end
+ def map_euc()
+ e = to_euc()
+ return e if e != ""
+ return to_er()
+ end
+ def to_sjis()
+ u = ucs()
+ return "" if u.nil? || 0xffff < u
+ Uconv.u16tosjis(Uconv.u4tou16(Character.u4itou4(ucs())))
+ end
+ def map_sjis()
+ e = to_sjis()
+ return e if e != ""
+ return to_er()
+ end
+
+ #----------------------------------------------------------------------
+ def to_er(codesys=nil) #実体参照を返す、希望するcodesysが引数(未実装)
+ return "" if @char_id == nil
+ return sprintf("&#x%04x;", @char_id) if @char_id <= 0xffff
+ return sprintf("&#x%05x;", @char_id) if @char_id <= 0xfffff
+ EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
+ code = self[codesys]
+ next if code == nil
+ return sprintf("&#{er_prefix}%0#{keta}#{numtype};", code)
+ }
+ return sprintf("&MCS-%08X;", @char_id) #本当はこれは無しにしたい
+ end
+ def to_er_list()
+ ar = []
+ EntityReference.each_codesys {|codesys, er_prefix, keta, numtype|
+ er = to_er(codesys)
+ ar << er if er != nil
+ }
+ ar
+ end
+
+ def inspect_x()
+ return "<>" if @char_id == nil
+ ar = [to_utf8(), to_er().sub(/^&/,'').chop]
+ "<"+ar.join(',')+">"
+ end
+ alias inspect inspect_x
+ def inspect_all_codesys() #未完成
+ #to_erを全てのcodesysにおいて実行する。その結果をコンパクトにまとめる
+ end
+ def inspect_all()
+ ar = [inspect.chop]
+ alist.to_a.sort.each {|a, v| ar << "#{a}:#{v}" }
+ return ar.join(',')+">"
+ end
+ def get_attributes()
+ str = ""
+ alist.to_a.sort.each {|a, v|
+ str += "#{a}: #{v}\n"
+ }
+ str
+ end
+
+ def inspect_ids(hex_flag=false)
+ ids = decompose
+ ar = []
+ ar << (hex_flag ? "x"+mcs_hex : to_utf8)
+ if to_s != ids #idsが部品そのものだったら部品追加はしない
+ ids.each_char {|ch|
+ char = ch.char
+ next if char.is_ids?
+ if hex_flag then
+ ar << "x"+char.mcs_hex
+ else
+ u = char.to_utf8
+ if u != ""
+ ar << u
+ else
+ ar << char.to_er
+ end
+ end
+ }
+ end
+ return "("+ar.join("\t")+")"
+ end
+
+ #----------------------------------------------------------------------IDS関係
+ def decompose
+ k = self.to_s
+ # idss = self['ids']
+ # return idss if idss
+ # return k if self.is_basic_kanji? #基本漢字はstop kanjiとするぞと。
+ return self['ids-represent'] if self['ids-represent'] #ids_representを持っている場合はその値とする。
+ return self['ids-element'] if self['ids-element'] #ids_elementを持っている場合はその値とする。
+
+ idss = self['ids-meaning']
+ return idss if idss != nil && 0 < idss.length && k != idss
+ idss = self['ids-aggregated']
+ return idss if idss != nil && 0 < idss.length && k != idss
+ idss = self['ids']
+ return idss if idss != nil && 0 < idss.length && k != idss
+ return k
+ # return k if idss.nil? || idss.length == 0 || k == idss
+ # if idss.char_length == 2
+ # p ['What???', k, idss, k.inspect_all]
+ # #return idssx[1] #二個目だけ返すとか?
+ # return k #IDSに展開する方法が無いと。
+ # end
+ # return k if k == idss
+ # if idss.include?(k) #<C5-4C4D><C6-4A37>この二文字のBUG対策
+ # #return idss.sub(k, '')
+ # return k #IDSに展開する方法が無いと。
+ # end
+ # return idss
+ end
+ def decompose_all
+ pde = ""
+ de = self.decompose #出発点
+ level = 0
+ while true
+ pde = de
+ de = pde.decompose #もう一度分解をしてみる。
+ break if pde == de #ループを抜けだす
+ exit if 10 < level #p ['too many recursive', self]
+ level += 1
+ end
+ return de
+ end
+ def decompose_all_nu(level=nil)
+ level = 0 if level.nil?
+ if 10 < level
+ p ['too many recursive', self]
+ exit
+ end
+ de = self.decompose
+ return de.decompose_all(level+1) if de != self #なにか変化があったから再帰
+ return de #もうこれ以上変化は無さそうだぞと。
+ end
+ def is_ids?() 0x2ff0 <= @char_id && @char_id <= 0x2fff end
+ def ids_operator_argc()
+ return 0 unless is_ids?
+ return 3 if @char_id == 0x2ff2 || @char_id == 0x2ff3
+ return 2
+ end
+ end
+
+ class DBS #======================================================================複数のDBを集めたclass、未完成
+ end
+
+ class ADB < BDB::Hash #======================================================================一つのDB
+ def initialize(*args)
+ super
+ @modified = false
+ at_exit {
+ if @modified
+ self.close #これがないと、うまくデータベースがセーブされないのです。
+ end
+ }
+ end
+ def self.open_create(filename)
+ ADB.open(filename, nil, BDB::CREATE | BDB::EXCL) #上書きはしない
+ end
+ def mykey(key)
+ if key.is_a?(String)
+ if key.char_length == 1
+ return '?'+key #Stringだったら引く前に?を足す
+ end
+ end
+ #key = key.to_s if key.is_a?(Numeric) #NumberだったらStringにする。
+ #ここで && key ! =~ /^\?/ をいれると、?自身を検索できなくなってしまう。
+ return key
+ end
+ def myvalue(v)
+ return v if v == nil
+ return v.to_i if v =~ /^\d+$/ #数字だったらここで変換しておく
+ return v.sub(/^\?/, '') if v =~ /^\?/ #冒頭の?は取り除く
+ return $1 if v =~ /^"(.+)"$/ #最初と最後に"がついていたら、取り除く
+ #p ['get', v, t, key, db]
+ #return parse_sexp(v) if v =~ /^\(.+\)$/ #最初と最後が()の時は、S式にparseする
+ return v #それ以外って何?
+ end
+ def myget(key) #keyキーを引いて返す
+ key = mykey(key)
+ v = get(key) #存在しなかったらnilを返すことになる
+ return myvalue(v)
+ end
+ def myput(key, v) #keyにvをいれる
+ key = mykey(key)
+ put(key, v) #putする
+ @modified = true
+ end
+ end
+
+ class DB #======================================================= データベース群のabstract class
+ def self.unix_to_win(unix) #Windowsファイル名制限のため、変換する
+ win = unix.gsub(/</, '(')
+ win.gsub!(/>/, ')')
+ win.gsub!(/\*/, '+')
+ win.gsub!(/\?/, '!')
+ return win
+ end
+ def self.win_to_unix(win)
+ unix = win.gsub(%r|\)|, '>')
+ unix.gsub!(%r|\(|, '<')
+ unix.gsub!(%r|!|, '?')
+ unix.gsub!(%r|\+|, '*')
+ return unix
+ end
+ def get_filename(t)
+ return @pre + DB.unix_to_win(t) + @post if windows?
+ return @pre + t + @post
+ end
+ def get_dirname(t) File.dirname(get_filename(t)) end
+ def open_dbs()
+ @dbs = Hash.new
+ keys = find_keys()
+ keys.each {|key| open_db(key) }
+ end
+ def find_keys()
+ files = []
+ Dir.glob(@glob){|f|
+ next if ! File.file?(f)
+ next if f =~ /.txt$/
+ files << f
+ }
+ keys = []
+ files.each {|f|
+ t = DB.win_to_unix(f)
+ t.sub!(%r|^#{@pre}|, '')
+ t.sub!(%r|#{@post}$|, '') if @post != ""
+ keys << t
+ }
+ return keys
+ end
+ def close_db(t)
+ db = get(t)
+ return nil if db.nil?
+ db.close
+ @dbs.delete(t)
+ end
+ def open_db(t)
+ return nil if get(t) #すでにopenしていたら再openはしない。
+ begin
+ bdb = ADB.open(get_filename(t), nil, 0)
+ @dbs[t] = bdb if bdb != nil
+ rescue
+ p ["open error", get_filename(t)]; return nil
+ end
+ return true
+ end
+ def make_db(t, h=nil) #tという名前でhという中身のデータベースを作る
+ return nil if get(t) #すでにある場合はreturn
+ Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
+ db = nil
+ begin
+ db = ADB.open_create(get_filename(t)) #上書きはしない
+ if h != nil
+ h.each {|k, v|
+ k = '?'+k if k.is_a?(String)
+ db[k] = v
+ }
+ end
+ db.close
+ rescue
+ p ["make error", get_filename(t)]; return nil
+ end
+ return true
+ end
+ def make_db_no_question_mark(t, h=nil) #tという名前でhという中身のデータベースを作る
+ return nil if get(t) #すでにある場合はreturn
+ Dir.mkdir(get_dirname(t)) unless FileTest.exist?(get_dirname(t))
+ db = nil
+ begin
+ db = ADB.open_create(get_filename(t)) #上書きはしない
+ if h != nil
+ h.each {|k, v|
+ # k = '?'+k if k.is_a?(String)
+ db[k] = v
+ }
+ end
+ db.close
+ rescue
+ p ["make error", get_filename(t)]; return nil
+ end
+ return true
+ end
+ def remove_db(t) #tという名前のデータベースを消去する
+ db = get(t)
+ if db
+ db.close
+ @dbs.delete(t)
+ end
+ begin
+ File.unlink(get_filename(t)) if FileTest.file?(get_filename(t))
+ rescue
+ p ["unlink error", get_filename(t)]; return nil
+ end
+ dn = get_dirname(t)
+ Dir.rmdir(dn) if FileTest.directory?(dn) && Dir.entries(dn).length <= 2 #空directoryだったら消す
+ return true
+ end
+ def to_num(s)
+ return s.to_i if s =~ /^\d+$/
+ return s
+ end
+ def dump_db(t)
+ db = get(t)
+ return nil unless db
+ file = get_filename(t)
+ open("#{file}.txt", "w"){|out|
+ # out.binmode.sync = true
+ ar = db.to_a
+ ar.map! {|k, v| [to_num(k), to_num(v)] }
+ ar.sort.each {|k, v|
+ out.printf("%s\t%s\n", k, v)
+ }
+ }
+ return true
+ end
+ def each_db() @dbs.to_a.sort.each {|t, db| yield(t, db) } end
+ def dump_all() each_db {|t, db| dump_db(t) } end
+ def close_all() each_db {|t, db| db.close } end
+ def keys() @dbs.keys end
+ def each(t)
+ return unless block_given?
+ db = @dbs[t]
+ return nil unless db
+ db.each {|k, v|
+ k = to_num(k)
+ v = to_num(v)
+ k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+ vv = get(t, k) #p ['each', t, k, v, vv]
+ yield(k, vv)
+ }
+ end
+ def each_sort(t)
+ return unless block_given?
+ db = @dbs[t]
+ return nil unless db
+ ar = db.to_a
+ ar.map! {|k, v| [to_num(k), to_num(v)] }
+ ar.sort.each {|k, v|
+ k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+ vv = get(t, k) #p ['each', t, k, v, vv]
+ yield(k, vv)
+ }
+ end
+ #----------------------------------------------------------------------
+ def get(t, key=nil) #tというデータベースのkeyキーを引いて返す
+ db = @dbs[t]
+ return db if key.nil?
+ return nil unless db
+ return db.myget(key)
+ end
+ def put(t, key, v) #tというデータベースのkeyにvをいれる
+ db = @dbs[t]
+ if db == nil
+ db = make_db(t)
+ db = open_db(t)
+ db = @dbs[t]
+ end
+ db.myput(key, v) #putする
+ end
+ end
+
+ class CharDB < DB #------------------------------------ MCS-UTF8をキーとした属性へのデータベース
+ include Singleton
+ def initialize()
+ super
+ @glob, @pre, @post = "#{DB_DIR}/system-char-id/*", "#{DB_DIR}/system-char-id/", ""
+ open_dbs()
+ end
+ def get_all(u8) #全データベースのu8キーを引いてHashにまとめて返す
+ atrs = Hash.new
+ @dbs.each {|t, db|
+ v = get(t, u8)
+ atrs[t] = v if v != nil
+ }
+ return atrs
+ end
+ end
+
+ class CodesysDB < DB #----------------------------------------------------------------------
+ include Singleton
+ def initialize()
+ super
+ @glob, @pre, @post = "#{DB_DIR}/*/system-char-id", "#{DB_DIR}/", "/system-char-id"
+ open_dbs()
+ end
+ #def keys() @dbs.keys.sort end #どんなCodesysの情報を持っているかの一覧
+ def keys() @dbs.keys end #どんなCodesysの情報を持っているかの一覧
+ def get_codesys(t)
+ db = get(t)
+ return nil unless db
+ return Codesys.new(t)
+ end
+ end
+
+ class Codesys < DB #======================================================================
+ def initialize(name)
+ # super
+ @name = name
+ @dbs = CodesysDB.instance
+ end
+ def keys() #どんなコードポイントの情報を持っているかの一覧
+ ks = @dbs.get(@name).keys
+ if @name =~ /jisx0208/ #特別処理
+ n = @dbs.get('=jis-x0208').keys
+ # p ['keys', @name, ks, n]
+ ks += n
+ end
+ ks.map! {|k| to_num(k) }
+ ks
+ end
+ def get(key)
+ v = @dbs.get(@name, key)
+ return v if v
+ if @name =~ /jisx0208/ #jisx0208が含まれている場合だけ特別処理する
+ return @dbs.get('=jis-x0208', key)
+ end
+ return nil
+ end
+ def each()
+ return unless block_given?
+ db = @dbs.get(@name)
+ return nil unless db
+ db.each {|k, v|
+ k = to_num(k)
+ v = to_num(v)
+ k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+ vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
+ yield(k, vv)
+ }
+ end
+ def each_sort()
+ return unless block_given?
+ db = @dbs.get(@name)
+ return nil unless db
+ ar = db.to_a
+ ar.map! {|k, v| [to_num(k), to_num(v)] }
+ ar.sort.each {|k, v|
+ k.sub!(/^\?/, '') if k =~ /^\?/ #冒頭の?は取り除く
+ vv = @dbs.get(@name, k) #p ['each', t, k, v, vv]
+ yield(k, vv)
+ }
+ end
+ end
+
+ class JISX0208
+ def initialize
+ db = CodesysDB.instance
+ @common = db.get_codesys('=jis-x0208')
+ @newest = db.get_codesys('japanese-jisx0208-1990')
+ end
+ def get_char(code)
+ char = @common.get(code)
+ return char unless char.nil?
+ char = @newest.get(code)
+ return char unless char.nil?
+ return nil
+ end
+ end
class IDS_TEXT_DB < DB #======================================================================
include Singleton
dir = File.dirname(file) + '/../ids-error'
Dir.mkdir(dir) unless FileTest.exist?(dir)
errfile = dir + '/' + File.basename(file)
-# p [file, errfile]
+ # p [file, errfile]
open(errfile, "w"){|out|
out.binmode.sync = true
each_line(file){|code, ch, ids|
@same_ids_counter += 1
else #しかしいままでのIDSと新しいIDSが食い違った場合は?
@conflict_ids_counter += 1
-# print "conflict #{char.inspect} #{code} #{ids} #{char['ids']}\n"
+ # print "conflict #{char.inspect} #{code} #{ids} #{char['ids']}\n"
end
end
}
ar.each {|ch|
char = ch.char
v = char[codesys]
-# p [codesys, v] if v
+ # p [codesys, v] if v
if v #EntityReferenceの順番に準拠する。
ar2 << ch
ar.delete(ch)
}
end
if 0 < ar.length
-# p ['yokuwakaran character', ar, ar[0].inspect_all, arorg]
+ # p ['yokuwakaran character', ar, ar[0].inspect_all, arorg]
EntityReference.each_codesys{|codesys, er_prefix, keta, numtype|
ar.dup.each {|ch|
char = ch.char
v = char[codesys]
-# p [codesys, v] if v
+ # p [codesys, v] if v
}
}
end
}
ar.sort!
ar.uniq!
-#やっぱりIDS文字も加えることにする. by eto 2003-02-05
-# ar.delete_if {|ch|
-# ch.char.is_ids? #IDS文字はまぎれこませない。
-# }
+ #やっぱりIDS文字も加えることにする. by eto 2003-02-05
+ # ar.delete_if {|ch|
+ # ch.char.is_ids? #IDS文字はまぎれこませない。
+ # }
str = ar.join('')
char['ids-parts'] = str
}
char = k.char
parts = char.ids_parts
parts.each_char {|ch|
-# part = ch.char
+ # part = ch.char
h[ch] = [] if h[ch].nil?
h[ch] << k
-# h[ch] += k
-# part['ids-contained'] = "" if part['ids-contained'].nil?
-# part['ids-contained'] += k
+ # h[ch] += k
+ # part['ids-contained'] = "" if part['ids-contained'].nil?
+ # part['ids-contained'] += k
}
}
h.each {|k, v|
end
attr_reader :nodenum
alias original_add <<
- private :original_add
+ private :original_add
def <<(obj)
original_add(obj)
@nodenum -= 1 if @nodenum
end
def move_to_obsolete(file)
cmd = "mv #{file} #{@odir}"
-# p cmd
+ # p cmd
system cmd
end
end
#JP_JOYO_FILE = DB_DIR+"/../jp-joyo.txt" #EUC-jisx0213
JP_JOYO_FILE = DB_DIR+"/../joyo-ucs.txt" #UCS
COMPOSIT_KANJI = "鳴名加品古知問間聞取兄見切分粉貧林森校東明住位好岩砂里男畑習休短空坂島倉美孝赤看光初努協解新歌語話張強忘悲答晴現正字安守灰秋秒困国医包同合舌居右左受友反道返迷花菜集机主太氷州点店庫仕帳幼防引配早直班筆重番北化比死夏後進酒福私家世内谷半原前寺思電雲気布旅衆泣"
-# COMPOSIT_KANJI = "鳴名加品古"
+ # COMPOSIT_KANJI = "鳴名加品古"
def initialize
@nchars = []
read_file