1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#--
#Copyright 2007 Nominet UK
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#++
module Dnsruby
# CodeMapper superclass looks after String to code mappings (e.g. OpCode, RCode, etc.)
#
# Subclasses simply define a mapping of codes to variable names, and CodeMapper provides utility methods.
#
# All strings will come out as upper case
#
# Example :
# Types::AAAA or Types.AAAA
# rcode.string or rcode.code
class CodeMapper # :nodoc: all
include Comparable
@@arrays = {}
attr_accessor :string, :code
alias to_code code
alias to_i code
alias to_string string
alias to_s string
class Arrays
attr_accessor :strings, :stringsdown, :values, :maxcode
def initialize
@strings = {}
@stringsdown = {}
@values = {}
@maxcode = 0
end
end
def CodeMapper.strings
strings = []
@@arrays[self].strings.keys.each {|s| strings.push(s)}
return strings
end
def CodeMapper.maxcode
return @maxcode
end
# Creates the CodeMapper from the defined constants
def CodeMapper.update
@@arrays[self] = Arrays.new
constants = self.constants - CodeMapper.constants
constants.each do |i|
@@arrays[self].strings.store(i.to_s, const_get(i))
end
@@arrays[self].maxcode = constants.length
@@arrays[self].values = @@arrays[self].strings.invert
@@arrays[self].stringsdown = Hash.new
@@arrays[self].strings.keys.each do |s|
@@arrays[self].stringsdown.store(s.downcase, @@arrays[self].strings[s])
end
end
# Add new a code to the CodeMapper
def CodeMapper.add_pair(string, code)
array = @@arrays[self]
array.strings.store(string, code)
array.values=array.strings.invert
array.stringsdown.store(string.downcase, code)
array.maxcode+=1
end
def unknown_string(arg) #:nodoc: all
raise ArgumentError.new("String #{arg} not a member of #{self.class}")
end
def unknown_code(arg) #:nodoc: all
# Be liberal in what you accept...
# raise ArgumentError.new("Code #{arg} not a member of #{self.class}")
Classes.add_pair(arg.to_s, arg)
set_code(arg)
end
def self.method_missing(methId) #:nodoc: all
str = methId.id2name
return self.new(str)
end
def initialize(arg) #:nodoc: all
array = @@arrays[self.class]
if (arg.kind_of?String)
arg = arg.gsub("_", "-")
code = array.stringsdown[arg.downcase]
if (code != nil)
@code = code
@string = array.values[@code]
else
unknown_string(arg)
end
elsif (arg.kind_of?Fixnum)
if (array.values[arg] != nil)
@code = arg
@string = array.values[@code]
else
unknown_code(arg)
end
elsif (arg.kind_of?self.class)
@code = arg.code
@string = array.values[@code]
else
raise ArgumentError.new("Unknown argument #{arg} for #{self.class}")
end
end
def set_string(arg)
array = @@arrays[self.class]
@code = array.stringsdown[arg.downcase]
@string = array.values[@code]
end
def set_code(arg)
@code = arg
@string = @@arrays[self.class].values[@code]
end
def inspect
return @string
end
def CodeMapper.to_string(arg)
if (arg.kind_of?String)
return arg
else
return @@arrays[self].values[arg]
end
end
def CodeMapper.to_code(arg)
if (arg.kind_of?Fixnum)
return arg
else
return @@arrays[self].stringsdown[arg.downcase]
end
end
def <=>(other)
if (other.class == Fixnum)
self.code <=> other
else
self.code <=> other.code
end
end
def ==(other)
return true if [@code, @string].include?other
if (CodeMapper === other)
return true if ((other.code == @code) || (other.string == @string))
end
return false
end
alias eql? == # :nodoc:
# Return a regular expression which matches any codes or strings from the CodeMapper.
def self.regexp
# Longest ones go first, so the regex engine will match AAAA before A, etc.
return @@arrays[self].strings.keys.sort { |a, b| b.length <=> a.length }.join('|')
end
end
end
|