Class | MOFile |
In: |
lib/gettext/mo.rb
|
Parent: | Hash |
Header | = | Struct.new(:magic, :revision, :nstrings, :orig_table_offset, :translated_table_offset, :hash_table_size, :hash_table_offset) | ||
MAGIC_BIG_ENDIAN | = | "\x95\x04\x12\xde" | ||
MAGIC_LITTLE_ENDIAN | = | "\xde\x12\x04\x95" | ||
HASHWORDBITS | = | 32 | From gettext-0.12.1/gettext-runtime/intl/hash-string.h Defines the so called `hashpjw’ function by P.J. Weinberger [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, 1986, 1987 Bell Telephone Laboratories, Inc.] |
charset | [R] | |
filename | [R] | |
last_modified | [RW] | |
little_endian | [RW] | |
nplurals | [R] | |
path | [RW] | |
plural | [R] |
# File lib/gettext/mo.rb, line 42 42: def initialize(output_charset = nil) 43: @filename = nil 44: @last_modified = nil 45: @little_endian = true 46: @output_charset = output_charset 47: super() 48: end
# File lib/gettext/mo.rb, line 37 37: def self.open(arg = nil, output_charset = nil) 38: result = self.new(output_charset) 39: result.load(arg) 40: end
# File lib/gettext/mo.rb, line 170 170: def hash_string(str) 171: hval = 0 172: i = 0 173: str.each_byte do |b| 174: break if b == '\0' 175: hval <<= 4 176: hval += b.to_i 177: g = hval & (0xf << (HASHWORDBITS - 4)) 178: if (g != 0) 179: hval ^= g >> (HASHWORDBITS - 8) 180: hval ^= g 181: end 182: end 183: hval 184: end
# File lib/gettext/mo.rb, line 61 61: def load(arg) 62: if arg.kind_of? String 63: begin 64: st = File.stat(arg) 65: @last_modified = [st.ctime, st.mtime] 66: rescue Exception 67: end 68: load_from_file(arg) 69: else 70: load_from_stream(arg) 71: end 72: @filename = arg 73: self 74: end
# File lib/gettext/mo.rb, line 253 253: def load_from_file(filename) 254: @filename = filename 255: File.open(filename, 'rb'){|f| load_from_stream(f)} 256: end
# File lib/gettext/mo.rb, line 76 76: def load_from_stream(io) 77: magic = io.read(4) 78: case magic 79: when MAGIC_BIG_ENDIAN 80: @little_endian = false 81: when MAGIC_LITTLE_ENDIAN 82: @little_endian = true 83: else 84: raise InvalidFormat.new(sprintf("Unknown signature %s", magic.dump)) 85: end 86: 87: header = Header.new(magic, *(io.read(4 * 6).unpack(@little_endian ? 'V6' : 'N6'))) 88: raise InvalidFormat.new(sprintf("file format revision %d isn't supported", header.revision)) if header.revision > 0 89: 90: io.pos = header.orig_table_offset 91: orig_table_data = io.read((4 * 2) * header.nstrings).unpack(@little_endian ? 'V*' : 'N*') 92: 93: io.pos = header.translated_table_offset 94: trans_table_data = io.read((4 * 2) * header.nstrings).unpack(@little_endian ? 'V*' : 'N*') 95: 96: original_strings = Array.new(header.nstrings) 97: for i in 0...header.nstrings 98: io.pos = orig_table_data[i * 2 + 1] 99: original_strings[i] = io.read(orig_table_data[i * 2 + 0]) 100: end 101: 102: clear 103: for i in 0...header.nstrings 104: io.pos = trans_table_data[i * 2 + 1] 105: str = io.read(trans_table_data[i * 2 + 0]) 106: 107: if (! original_strings[i]) || original_strings[i] == "" 108: if str 109: @charset = nil 110: @nplurals = nil 111: @plural = nil 112: str.each_line{|line| 113: if /^Content-Type:/i =~ line and /charset=((?:\w|-)+)/i =~ line 114: @charset = $1 115: elsif /^Plural-Forms:\s*nplurals\s*\=\s*(\d*);\s*plural\s*\=\s*([^;]*)\n?/ =~ line 116: @nplurals = $1 117: @plural = $2 118: end 119: break if @charset and @nplurals 120: } 121: @nplurals = "1" unless @nplurals 122: @plural = "0" unless @plural 123: end 124: else 125: if @output_charset 126: begin 127: str = Iconv.conv(@output_charset, @charset, str) if @charset 128: rescue Iconv::Failure 129: if $DEBUG 130: $stderr.print "@charset = ", @charset, "\n" 131: $stderr.print "@output_charset = ", @output_charset, "\n" 132: $stderr.print "msgid = ", original_strings[i], "\n" 133: $stderr.print "msgstr = ", str, "\n" 134: end 135: end 136: end 137: end 138: self[original_strings[i]] = str 139: end 140: self 141: end
From gettext-0.12.1/gettext-tools/lib/hash.c
# File lib/gettext/mo.rb, line 157 157: def next_prime(seed) 158: seed |= 1 159: while (! prime?(seed)) 160: seed += 2 161: end 162: seed 163: end
From gettext-0.12.1/gettext-tools/lib/hash.c
# File lib/gettext/mo.rb, line 144 144: def prime?(candidate) 145: divn = 3 146: sq = divn * divn 147: 148: while (sq < candidate && candidate % divn != 0) 149: divn += 1 150: sq += 4 * divn 151: divn += 1 152: end 153: candidate % divn != 0 154: end
# File lib/gettext/mo.rb, line 258 258: def save_to_file(filename) 259: File.open(filename, 'wb'){|f| save_to_stream(f)} 260: end
# File lib/gettext/mo.rb, line 186 186: def save_to_stream(io) 187: #Save data as little endian format. 188: header_size = 4 * 7 189: table_size = 4 * 2 * size 190: 191: hash_table_size = next_prime((size * 4) / 3) 192: hash_table_size = 3 if hash_table_size <= 2 193: header = Header.new( 194: MAGIC_LITTLE_ENDIAN, # magic 195: 0, # revision 196: size, # nstrings 197: header_size, # orig_table_offset 198: header_size + table_size, # translated_table_offset 199: hash_table_size, # hash_table_size 200: header_size + table_size * 2 # hash_table_offset 201: ) 202: io.write(header.to_a.pack('a4V*')) 203: 204: ary = to_a 205: ary.sort!{|a, b| a[0] <=> b[0]} # sort by original string 206: 207: pos = header.hash_table_size * 4 + header.hash_table_offset 208: 209: orig_table_data = Array.new() 210: ary.each{|item, _| 211: orig_table_data.push(item.size) 212: orig_table_data.push(pos) 213: pos += item.size + 1 # +1 is <NUL> 214: } 215: io.write(orig_table_data.pack('V*')) 216: 217: trans_table_data = Array.new() 218: ary.each{|_, item| 219: trans_table_data.push(item.size) 220: trans_table_data.push(pos) 221: pos += item.size + 1 # +1 is <NUL> 222: } 223: io.write(trans_table_data.pack('V*')) 224: 225: hash_tab = Array.new(hash_table_size) 226: j = 0 227: ary[0...size].each {|key, _| 228: hash_val = hash_string(key) 229: idx = hash_val % hash_table_size 230: if hash_tab[idx] != nil 231: incr = 1 + (hash_val % (hash_table_size - 2)) 232: begin 233: if (idx >= hash_table_size - incr) 234: idx -= hash_table_size - incr 235: else 236: idx += incr 237: end 238: end until (hash_tab[idx] == nil) 239: end 240: hash_tab[idx] = j + 1 241: j += 1 242: } 243: hash_tab.collect!{|i| i ? i : 0} 244: 245: io.write(hash_tab.pack('V*')) 246: 247: ary.each{|item, _| io.write(item); io.write("\0") } 248: ary.each{|_, item| io.write(item); io.write("\0") } 249: 250: self 251: end