#$stdout.binmode if $debug
$stdout.sync = true if $debug
-class String
+class String #======================================================================
def to_a() self.split(//) end #$KCODEが設定されているので、UTF-8的な一文字づつがchにはいる
def each_char() to_a.each {|ch| yield ch } end
+ def each_character() to_a.each {|ch| yield ch.char } end
def char_length() to_a.length end
def char_at(n) to_a()[n] end
def char() Character.get(to_a[0]) end
- def method_missing(mid, *args) char.method_missing(mid, *args) end
+ #alias to_c char #悩み中
def char_id() char.char_id() end
def get_char_attribute(a) char.get_char_attribute(a) end
- def ucs() char.ucs() end
+ #def ucs() char.ucs() end
def to_utf8()
return to_a.map {|ch|
ch.char.to_utf8
}.join('')
end
+ def method_missing(mid, *args)
+ if char_length == 1 #省略形が有効なのは、一文字の時だけ
+ char.method_missing(mid, *args)
+ else
+ raise NameError, "undefined method `#{mid.id2name}'", caller(1)
+ end
+ end
+
+ def map_utf8() map_char {|ch| ch.char.map_utf8 } end
+ alias map_ucs map_utf8
+ def map_ucs_er() map_char {|ch| ch.char.map_ucs_er } end
+ def to_er() map_char {|ch| ch.char.to_er } end
+
#put関係、[]関係は用意しないことにした。
def de_er!() #EntityReferenceを取り除く
return self unless self =~ Regexp.new(EntityReference::REGEXP_PART) #それらしいのが無ければ何もしない
def inspect_all() map_char {|ch| ch.char.inspect_all } end
def inspect_x() map_char {|ch| ch.char.inspect_x } end
+ def to_euc() map_char {|ch| ch.char.to_euc } end
+ def map_euc() map_char {|ch| ch.char.map_euc } end
+ def to_sjis() map_char {|ch| ch.char.to_sjis } end
+ def map_sjis() map_char {|ch| ch.char.map_sjis } end
+
def decompose() map_char {|ch| ch.char.decompose } end
def decompose!() self.replace(self.decompose); self; end
- def decompose_all(level=nil)
+ def decompose_all_nu(level=nil)
level = 0 if level.nil?
if 10 < level
p ['too many recursive', self]
return de.decompose_all(level+1) if de != self #なにか変化があったから再帰
de #もうこれ以上変化は無さそうだぞと。
end
+ def decompose_all() map_char {|ch| ch.char.decompose_all } end
def decompose_all!() self.replace(self.decompose_all); self; end
def find() #"日雲"→"曇"とかいう感じの操作
end
end
-module CHISE
+module CHISE #======================================================================
def windows?()
(RUBY_PLATFORM =~ /cygwin/ || RUBY_PLATFORM =~ /mswin32/ || RUBY_PLATFORM =~ /mingw32/)
end
%w( korean-ksc5601 K0- 4 X),
]
CODESYS_ORDER = %w(japanese chinese korean ideograph)
- REGEXP_PART = "&([-+0-9A-Za-z]+);"
+ REGEXP_PART = "&([-+0-9A-Za-z#]+);"
REGEXP_ALL = "^#{REGEXP_PART}$"
def self.match?(er) (er =~ Regexp.new(REGEXP_PART)) != nil end
return "" unless er =~ Regexp.new(REGEXP_ALL) #なんか、間違ってる?
er = $1 #ついでに中身の部分を取り出す
return $1.hex if er =~ /^MCS-([0-9A-Fa-f]+)/ #MCS
- return $1.hex 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
er.sub!(/^I-/, '') if er =~ /^I-/ #I-がついてるとどう違うのかはよくわからない
each_codesys {|codesys, er_prefix, keta, numtype| #p [codesys, er_prefix, keta, numtype]
end
class Character #=============================================================== 文字オブジェクト
+ BASIC_KANJI = "人子女母父王口耳手足力目首毛心犬牛鳥貝角羽虫馬魚羊肉皮米竹木麦豆山川雨風水土石金田穴日月火音糸刀舟門戸衣矢弓車皿一二三四五六七八九十百千万寸尺上中下本玉立回食行止交向歩考入示走生出来書言大小白青多少高長"
+ def is_basic_kanji?
+ BASIC_KANJI.include?(self.to_s)
+ end
+
def initialize(char_id=nil)
@char_id = Character.parse_char_id(char_id)
@attributes = Hash.new
@check_all_database = false
end
attr_reader :char_id
+ def to_i() @char_id end
def mcs_utf8() Character.u4itou8(@char_id) end
+ def mcs_hex() sprintf("%x", @char_id) end
#----------------------------------------------------------------------
def self.get(char_id) CharacterFactory.instance.get(char_id) end #flyweightパターン
#----------------------------------------------------------------------
- def get_char_attribute(a) # XEmacs UTF-2000互換API群
+ def normalize_attribute_name(b)
+ a = b.dup
a.gsub!(/_/, '-') #underlineは-に置換
+ a.sub!(/^map-/, '=>')
+ a.sub!(/^to-/, '->')
+ a.sub!(/^from-/, '<-')
+ a
+ end
+ def get_char_attribute(b) # XEmacs UTF-2000互換API群
+ a = normalize_attribute_name(b)
+ #p [a, b]
atr = @attributes[a]
return atr if atr != nil
atr = check_database(a)
@attributes[a] = atr if atr != nil
- return get_char_attribute("=jis-x0208") if a =~ /jisx0208/
+ return get_char_attribute("=jis-x0208") if a =~ /jisx0208/ #ここだけ特殊形
return @attributes[a]
end
- def put_char_attribute(a,v)
- a.gsub!(/_/, '-') #underlineは-に置換
+ def put_char_attribute(b,v)
+ a = normalize_attribute_name(b)
@attributes[a] = v;
CharDB.instance.put(a, mcs_utf8(), v)
end
char_id = 0x80000000 + char_id if char_id < 0 #補数表現
return char_id.to_i
elsif char_id.is_a?(String)
- return char_id.to_i if char_id =~ /^\d+$/ #文字列による数字だったら数値化してreturn
+ return char_id.to_i if char_id =~ /^\d+$/ && 1 < char_id.length #文字列による数字だったら数値化してreturn
return EntityReference.parse(char_id) if char_id =~ Regexp.new(EntityReference::REGEXP_ALL) #実体参照?
char_id.sub!(/^\?/, '') if char_id =~ /^\?/ #もし先頭に?がついていたら削除
#このへん本当はもっとちゃんとチェックするべし
- u4 = Uconv.u8tou4(char_id) #UCS-4文字列に変換
+ begin
+ u4 = Uconv.u8tou4(char_id) #UCS-4文字列に変換
+ rescue
+ p $!
+ p char_id
+ return 0
+ end
return Character.u4tou4i(u4) #UCS-4数値にしてreturn
else
raise ArgumentError, "unknown object for char_id", caller(1)
return (u4[3] << 24 | u4[2] << 16 | u4[1] << 8 | u4[0]) #UCS-4数値にしてreturn
end
def self.u4itou4(num)
- return "" if num == nil
+ return "" unless num.is_a?(Integer)
return sprintf("%c%c%c%c", num&0xff, (num >> 8)&0xff, (num >> 16)&0xff, (num >> 24)&0xff) #UCS-4数値を文字列にしてreturn
end
def self.u4itou8(char_id) #ucsの数値を受けとり、UTF-8の文字一文字を返す
#----------------------------------------------------------------------
def ucs() #p 'ucs'
#ar = %w{ucs ucs-big5 ucs-cdp ucs-cns ucs-jis ucs-ks =>ucs =>ucs* =>ucs-jis}
- ar = %w{ucs ucs-jis ucs-big5 ucs-cdp ucs-cns ucs-ks =>ucs =>ucs* =>ucs-jis}
+ #ar = %w{ucs ucs-jis ucs-big5 ucs-cdp ucs-cns ucs-ks =>ucs =>ucs* =>ucs-jis}
+ ar = %w{ucs-jis ucs =>ucs-jis}
#並び順は恣意的で、ucs-jisを先に出している。本来はこれも指定できるようにするべき。
ar.each {|a| #p [a]
u = get_char_attribute(a)
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("&U+%04X;", @char_id) if @char_id <= 0xffff
- return sprintf("&U-%05X;", @char_id) if @char_id <= 0xfffff
+ 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
"<"+ar.join(',')+">"
end
alias inspect inspect_x
- def inspect_all_codesys()
+ def inspect_all_codesys() #未完成
#to_erを全てのcodesysにおいて実行する。その結果をコンパクトにまとめる
end
def inspect_all()
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']
# 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?
end
end
- class DBS #======================================================================複数のDBを集めたclass
+ class DBS #======================================================================複数のDBを集めたclass、未完成
end
class ADB < BDB::Hash #======================================================================一つのDB
unix.gsub!(%r|\+|, '*')
return unix
end
-# def windows?() DB.windows?() end
def get_filename(t)
return @pre + DB.unix_to_win(t) + @post if windows?
return @pre + t + @post
keys << t
}
return keys
- #return keys.sort
end
def close_db(t)
db = get(t)
if char != charimg #code表記と文字が一致していない?
unless code =~ /^M-/ || code =~ /^MH-/ || code =~ /^CB/ #食い違っていて当然であるので何もしない
print "unknown char #{char.inspect} #{code} #{ch} #{ids}\n"
- next #それ以外の場合はエラメッセージをだして、次へ。
+ next #それ以外の場合はエラーメッセージをだして、次へ。
end
end
+ #next if !char.has_attribute? #isolated characterはまぎれこませない。
ids.de_er! #実体参照を解除する
next if ids == char.to_s #もし文字とまったく一緒なら、意味が無いので情報を持たない
idstree = IDS_Tree.new(ids)
c = idstree.check_integrity
c = "contains self" if ids.include?(char.to_s)
-# c = "no attribute" if !char.has_attribute? #isolated characterはまぎれこませない。
if c #ちょっとでもエラーがある場合は、
char['ids-error'] = c #エラーを記録して、データとしては保持しない
next
print "length #{h.length}\n"
cdb = CodesysDB.instance
cdb.make_db_no_question_mark('ids', h)
- p ['make db no q mark done.']
cdb.open_db('ids') #これが無いと、dump_dbされません。
cdb.dump_db('ids')
- p ['dump_db done.']
end
def char_sort(composed)
return composed if composed.char_length == 1
end
end
+ class DBS_Management #======================================================================ファイル管理
+ OBSOLETE_ATTRIBUTES = "
+cns-radical
+cns-radical?
+kangxi-radical
+daikanwa-radical
+unicode-radical
+
+cns-strokes
+kangxi-strokes
+daikanwa-strokes
+shinjigen-1-radical
+gb-original-radical
+japanese-strokes
+jis-strokes-a
+jis-strokes-b
+jisx0208-strokes
+jis-x0213-strokes
+jisx0213-strokes
+unicode-strokes
+
+totalstrokes
+cns-total-strokes
+jis-total-strokes-b
+
+non-morohashi
+
+=>ucs*
+#=>mojikyo
+#=mojikyo
+->identical
+
+ancient-ideograph-of
+ancient-char-of-shinjigen-1
+original-ideograph-of
+original-char-of-shinjigen-1
+simplified-ideograph-of
+vulgar-ideograph-of
+vulgar-char-of-shinjigen-1
+ideograph=
+ideographic-variants
+variant-of-shinjigen-1
+
+iso-10646-comment
+".split
+ def initialize
+ @odir = DB_DIR+"/system-char-id/obsolete" #直打ちしている。
+ end
+ def move_obsolete_files # 廃止予定のbdbファイルをobsoleteディレクトリーにつっこむ
+ db = CharDB.instance
+ db.close_all
+ Dir.mkdir(@odir) unless FileTest.directory? @odir
+ OBSOLETE_ATTRIBUTES.each {|attr|
+ next if attr =~ /^#/
+ filename = db.get_filename(attr)
+ move_to_obsolete(filename)
+ move_to_obsolete(filename+".txt")
+ }
+ end
+ def move_to_obsolete(file)
+ cmd = "mv #{file} #{@odir}"
+# p cmd
+ system cmd
+ end
+ end
+
+ class JoyoList #======================================================================
+ include Singleton
+ #JP_JOYO_FILE = DB_DIR+"/../jp-joyo.txt" #EUC-jisx0213
+ JP_JOYO_FILE = DB_DIR+"/../joyo-ucs.txt" #UCS
+ COMPOSIT_KANJI = "鳴名加品古知問間聞取兄見切分粉貧林森校東明住位好岩砂里男畑習休短空坂島倉美孝赤看光初努協解新歌語話張強忘悲答晴現正字安守灰秋秒困国医包同合舌居右左受友反道返迷花菜集机主太氷州点店庫仕帳幼防引配早直班筆重番北化比死夏後進酒福私家世内谷半原前寺思電雲気布旅衆泣"
+# COMPOSIT_KANJI = "鳴名加品古"
+ def initialize
+ @nchars = []
+ read_file
+ end
+ attr_reader :nchars
+ def read_file
+ open(JP_JOYO_FILE) {|f|
+ while line = f.gets
+ next if line =~ /^;/ #コメントはとばす
+ line.chomp!
+ #stroke, nchar, ochar = line.split #new char, old char, old charはnilが多い
+ stroke, nchar = line.split
+ @nchars << nchar
+ end
+ }
+ end
+ def dump_ids(ar)
+ ar.each {|ch|
+ char = ch.char
+ print char.inspect_ids(true), "\t;", char.inspect_ids(false), "\n"
+ }
+ end
+ end
+
end
#----------------------------------------------------------------------終了