Hash
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.]
# File lib/gettext/runtime/mofile.rb, line 190 190: def hash_string(str) 191: hval = 0 192: i = 0 193: str.each_byte do |b| 194: break if b == '\0' 195: hval <<= 4 196: hval += b.to_i 197: g = hval & (0xf << (HASHWORDBITS - 4)) 198: if (g != 0) 199: hval ^= g >> (HASHWORDBITS - 8) 200: hval ^= g 201: end 202: end 203: hval 204: end
# File lib/gettext/runtime/mofile.rb, line 72 72: def load(arg) 73: if arg.kind_of? String 74: begin 75: st = File.stat(arg) 76: @last_modified = [st.ctime, st.mtime] 77: rescue Exception 78: end 79: load_from_file(arg) 80: else 81: load_from_stream(arg) 82: end 83: @filename = arg 84: self 85: end
# File lib/gettext/runtime/mofile.rb, line 273 273: def load_from_file(filename) 274: @filename = filename 275: begin 276: File.open(filename, 'rb'){|f| load_from_stream(f)} 277: rescue => e 278: e.set_backtrace("File: #{@filename}") 279: raise e 280: end 281: end
# File lib/gettext/runtime/mofile.rb, line 87 87: def load_from_stream(io) 88: magic = io.read(4) 89: case magic 90: when MAGIC_BIG_ENDIAN 91: @little_endian = false 92: when MAGIC_LITTLE_ENDIAN 93: @little_endian = true 94: else 95: raise InvalidFormat.new(sprintf("Unknown signature %s", magic.dump)) 96: end 97: 98: endian_type6 = @little_endian ? 'V6' : 'N6' 99: endian_type_astr = @little_endian ? 'V*' : 'N*' 100: 101: header = HeaderRev1.new(magic, *(io.read(4 * 6).unpack(endian_type6))) 102: 103: if header.revision == 1 104: # FIXME: It doesn't support sysdep correctly. 105: header.n_sysdep_segments = io.read(4).unpack(endian_type6) 106: header.sysdep_segments_offset = io.read(4).unpack(endian_type6) 107: header.n_sysdep_strings = io.read(4).unpack(endian_type6) 108: header.orig_sysdep_tab_offset = io.read(4).unpack(endian_type6) 109: header.trans_sysdep_tab_offset = io.read(4).unpack(endian_type6) 110: elsif header.revision > 1 111: raise InvalidFormat.new(sprintf("file format revision %d isn't supported", header.revision)) 112: end 113: io.pos = header.orig_table_offset 114: orig_table_data = io.read((4 * 2) * header.nstrings).unpack(endian_type_astr) 115: 116: io.pos = header.translated_table_offset 117: trans_table_data = io.read((4 * 2) * header.nstrings).unpack(endian_type_astr) 118: 119: original_strings = Array.new(header.nstrings) 120: for i in 0...header.nstrings 121: io.pos = orig_table_data[i * 2 + 1] 122: original_strings[i] = io.read(orig_table_data[i * 2 + 0]) 123: end 124: 125: clear 126: for i in 0...header.nstrings 127: io.pos = trans_table_data[i * 2 + 1] 128: str = io.read(trans_table_data[i * 2 + 0]) 129: 130: if (! original_strings[i]) || original_strings[i] == "" 131: if str 132: @charset = nil 133: @nplurals = nil 134: @plural = nil 135: str.each_line{|line| 136: if /^Content-Type:/ =~ line and /charset=((?:\w|-)+)/ =~ line 137: @charset = $1 138: elsif /^Plural-Forms:\s*nplurals\s*\=\s*(\d*);\s*plural\s*\=\s*([^;]*)\n?/ =~ line 139: @nplurals = $1 140: @plural = $2 141: end 142: break if @charset and @nplurals 143: } 144: @nplurals = "1" unless @nplurals 145: @plural = "0" unless @plural 146: end 147: else 148: if @output_charset 149: begin 150: str = Iconv.conv(@output_charset, @charset, str) if @charset 151: rescue Iconv::Failure 152: if $DEBUG 153: warn "@charset = ", @charset 154: warn"@output_charset = ", @output_charset 155: warn "msgid = ", original_strings[i] 156: warn "msgstr = ", str 157: end 158: end 159: end 160: end 161: self[original_strings[i]] = str.freeze 162: end 163: self 164: end
# File lib/gettext/runtime/mofile.rb, line 172 172: def next_prime(seed) 173: Prime.instance.find{|x| x > seed } 174: end
# File lib/gettext/runtime/mofile.rb, line 176 176: def next_prime(seed) 177: require 'mathn' 178: prime = Prime.new 179: while current = prime.succ 180: return current if current > seed 181: end 182: end
# File lib/gettext/runtime/mofile.rb, line 291 291: def plural_as_proc 292: unless @plural_proc 293: @plural_proc = Proc.new{|n| eval(@plural)} 294: begin 295: @plural_proc.call(1) 296: rescue 297: @plural_proc = Proc.new{|n| 0} 298: end 299: end 300: @plural_proc 301: end
# File lib/gettext/runtime/mofile.rb, line 166 166: def prime?(number) 167: ('1' * number) !~ /^1?$|^(11+?)\11++$/ 168: end
# File lib/gettext/runtime/mofile.rb, line 283 283: def save_to_file(filename) 284: File.open(filename, 'wb'){|f| save_to_stream(f)} 285: end
Save data as little endian format.
# File lib/gettext/runtime/mofile.rb, line 207 207: def save_to_stream(io) 208: header_size = 4 * 7 209: table_size = 4 * 2 * size 210: 211: hash_table_size = next_prime((size * 4) / 3) 212: hash_table_size = 3 if hash_table_size <= 2 213: header = Header.new( 214: MAGIC_LITTLE_ENDIAN, # magic 215: 0, # revision 216: size, # nstrings 217: header_size, # orig_table_offset 218: header_size + table_size, # translated_table_offset 219: hash_table_size, # hash_table_size 220: header_size + table_size * 2 # hash_table_offset 221: ) 222: io.write(header.to_a.pack('a4V*')) 223: 224: ary = to_a 225: ary.sort!{|a, b| a[0] <=> b[0]} # sort by original string 226: 227: pos = header.hash_table_size * 4 + header.hash_table_offset 228: 229: orig_table_data = Array.new() 230: ary.each{|item, _| 231: orig_table_data.push(item.bytesize) 232: orig_table_data.push(pos) 233: pos += item.bytesize + 1 # +1 is <NUL> 234: } 235: io.write(orig_table_data.pack('V*')) 236: 237: trans_table_data = Array.new() 238: ary.each{|_, item| 239: trans_table_data.push(item.bytesize) 240: trans_table_data.push(pos) 241: pos += item.bytesize + 1 # +1 is <NUL> 242: } 243: io.write(trans_table_data.pack('V*')) 244: 245: hash_tab = Array.new(hash_table_size) 246: j = 0 247: ary[0...size].each {|key, _| 248: hash_val = hash_string(key) 249: idx = hash_val % hash_table_size 250: if hash_tab[idx] != nil 251: incr = 1 + (hash_val % (hash_table_size - 2)) 252: begin 253: if (idx >= hash_table_size - incr) 254: idx -= hash_table_size - incr 255: else 256: idx += incr 257: end 258: end until (hash_tab[idx] == nil) 259: end 260: hash_tab[idx] = j + 1 261: j += 1 262: } 263: hash_tab.collect!{|i| i ? i : 0} 264: 265: io.write(hash_tab.pack('V*')) 266: 267: ary.each{|item, _| io.write(item); io.write("\00"") } 268: ary.each{|_, item| io.write(item); io.write("\00"") } 269: 270: self 271: end
# File lib/gettext/runtime/mofile.rb, line 287 287: def set_comment(msgid_or_sym, comment) 288: #Do nothing 289: end
# File lib/gettext/runtime/mofile.rb, line 61 61: def update! 62: if FileTest.exist?(@filename) 63: st = File.stat(@filename) 64: load(@filename) unless (@last_modified == [st.ctime, st.mtime]) 65: else 66: warn "#{@filename} was lost." if $DEBUG 67: clear 68: end 69: self 70: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.