зеркало из https://github.com/github/ruby.git
168 строки
3.1 KiB
Ruby
168 строки
3.1 KiB
Ruby
# jcode.rb - ruby code to handle japanese (EUC/SJIS) string
|
|
|
|
$vsave, $VERBOSE = $VERBOSE, FALSE
|
|
class String
|
|
printf STDERR, "feel free for some warnings:\n" if $VERBOSE
|
|
|
|
def jlength
|
|
self.split(//).length
|
|
end
|
|
|
|
alias original_succ succ
|
|
private :original_succ
|
|
|
|
def mbchar?
|
|
case $KCODE[0]
|
|
when ?s, ?S
|
|
self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n
|
|
when ?e, ?E
|
|
self =~ /[\xa1-\xfe][\xa1-\xfe]/n
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def succ
|
|
if self[-2] and self[-2, 2].mbchar?
|
|
s = self.dup
|
|
s[-1] += 1
|
|
s[-1] += 1 unless s[-2, 2].mbchar?
|
|
return s
|
|
else
|
|
original_succ
|
|
end
|
|
end
|
|
|
|
def upto(to)
|
|
return if self > to
|
|
|
|
curr = self
|
|
tail = self[-2..-1]
|
|
if tail.length == 2 and tail =~ /^.$/ then
|
|
if self[0..-2] == to[0..-2]
|
|
first = self[-2].chr
|
|
for c in self[-1] .. to[-1]
|
|
if (first+c.chr).mbchar?
|
|
yield self[0..-2]+c.chr
|
|
end
|
|
end
|
|
end
|
|
else
|
|
loop do
|
|
yield curr
|
|
return if curr == to
|
|
curr = curr.succ
|
|
return if curr.length > to.length
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
private
|
|
|
|
def _expand_ch str
|
|
a = []
|
|
str.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r|
|
|
if $3
|
|
a.push $3
|
|
elsif $1.length != $2.length
|
|
next
|
|
elsif $1.length == 1
|
|
$1[0].upto($2[0]) { |c| a.push c.chr }
|
|
else
|
|
$1.upto($2) { |c| a.push c }
|
|
end
|
|
end
|
|
a
|
|
end
|
|
|
|
def expand_ch_hash from, to
|
|
h = {}
|
|
afrom = _expand_ch(from)
|
|
ato = _expand_ch(to)
|
|
afrom.each_with_index do |x,i| h[x] = ato[i] || ato[-1] end
|
|
h
|
|
end
|
|
|
|
def bsquote(str)
|
|
str.gsub(/\\/, '\\\\\\\\')
|
|
end
|
|
|
|
HashCache = {}
|
|
TrPatternCache = {}
|
|
DeletePatternCache = {}
|
|
SqueezePatternCache = {}
|
|
|
|
public
|
|
|
|
def tr!(from, to)
|
|
return self.delete!(from) if to.length == 0
|
|
|
|
pattern = TrPatternCache[from] ||= /[#{bsquote(from)}]/
|
|
if from[0] == ?^
|
|
last = /.$/.match(to)[0]
|
|
self.gsub!(pattern, last)
|
|
else
|
|
h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
|
|
self.gsub!(pattern) do |c| h[c] end
|
|
end
|
|
end
|
|
|
|
def tr(from, to)
|
|
(str = self.dup).tr!(from, to) or str
|
|
end
|
|
|
|
def delete!(del)
|
|
self.gsub!(DeletePatternCache[del] ||= /[#{bsquote(del)}]+/, '')
|
|
end
|
|
|
|
def delete(del)
|
|
(str = self.dup).delete!(del) or str
|
|
end
|
|
|
|
def squeeze!(del=nil)
|
|
pattern =
|
|
if del
|
|
SqueezePatternCache[del] ||= /([#{bsquote(del)}])\1+/
|
|
else
|
|
/(.|\n)\1+/
|
|
end
|
|
self.gsub!(pattern, '\1')
|
|
end
|
|
|
|
def squeeze(del=nil)
|
|
(str = self.dup).squeeze!(del) or str
|
|
end
|
|
|
|
def tr_s!(from, to)
|
|
return self.delete!(from) if to.length == 0
|
|
|
|
pattern = SqueezePatternCache[from] ||= /([#{bsquote(from)}])\1+"/
|
|
if from[0] == ?^
|
|
last = /.$/.match(to)[0]
|
|
self.gsub!(pattern, last)
|
|
else
|
|
h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
|
|
self.gsub!(pattern) do h[$1] end
|
|
end
|
|
end
|
|
|
|
def tr_s(from, to)
|
|
(str = self.dup).tr_s!(from,to) or str
|
|
end
|
|
|
|
def chop!
|
|
self.gsub!(/(?:.|\r?\n)\z/, '')
|
|
end
|
|
|
|
def chop
|
|
(str = self.dup).chop! or str
|
|
end
|
|
|
|
def jcount(str)
|
|
self.delete("^#{str}").jlength
|
|
end
|
|
|
|
end
|
|
$VERBOSE = $vsave
|