bit_mask 0.0.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +44 -0
- data/Gemfile +3 -14
- data/LICENSE.txt +4 -1
- data/{README.rdoc → README.md} +14 -19
- data/Rakefile +1 -49
- data/VERSION +1 -1
- data/bit_mask.gemspec +17 -66
- data/lib/bit_mask/field.rb +77 -0
- data/lib/bit_mask/radix.rb +44 -0
- data/lib/bit_mask/version.rb +3 -0
- data/lib/bit_mask.rb +74 -147
- data/spec/bit_mask_spec.rb +4 -4
- data/spec/models/dealership_search.rb +2 -2
- metadata +57 -94
data/.gitignore
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
.rvmrc
|
2
|
+
Gemfile.lock
|
3
|
+
# rcov generated
|
4
|
+
coverage
|
5
|
+
|
6
|
+
# rdoc generated
|
7
|
+
rdoc
|
8
|
+
|
9
|
+
# yard generated
|
10
|
+
doc
|
11
|
+
.yardoc
|
12
|
+
|
13
|
+
# bundler
|
14
|
+
.bundle
|
15
|
+
|
16
|
+
# jeweler generated
|
17
|
+
pkg
|
18
|
+
|
19
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
20
|
+
#
|
21
|
+
# * Create a file at ~/.gitignore
|
22
|
+
# * Include files you want ignored
|
23
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
24
|
+
#
|
25
|
+
# After doing this, these files will be ignored in all your git projects,
|
26
|
+
# saving you from having to 'pollute' every project you touch with them
|
27
|
+
#
|
28
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
29
|
+
#
|
30
|
+
# For MacOS:
|
31
|
+
#
|
32
|
+
.DS_Store
|
33
|
+
#
|
34
|
+
# For TextMate
|
35
|
+
#*.tmproj
|
36
|
+
#tmtags
|
37
|
+
#
|
38
|
+
# For emacs:
|
39
|
+
#*~
|
40
|
+
#\#*
|
41
|
+
#.\#*
|
42
|
+
#
|
43
|
+
# For vim:
|
44
|
+
*.swp
|
data/Gemfile
CHANGED
@@ -1,15 +1,4 @@
|
|
1
|
-
source
|
2
|
-
# Add dependencies required to use your gem here.
|
3
|
-
# Example:
|
4
|
-
# gem "activesupport", ">= 2.3.5"
|
5
|
-
# Add dependencies to develop your gem here.
|
6
|
-
# Include everything needed to run rake, tests, features, etc.
|
7
|
-
gem 'activesupport'
|
1
|
+
source 'https://rubygems.org'
|
8
2
|
|
9
|
-
|
10
|
-
|
11
|
-
gem "bundler", "~> 1.0.0"
|
12
|
-
gem "jeweler", "~> 1.5.2"
|
13
|
-
gem "rcov", ">= 0"
|
14
|
-
gem "rspec"
|
15
|
-
end
|
3
|
+
# Specify your gem's dependencies in bit_mask.gemspec
|
4
|
+
gemspec
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2012 Ryan Ong
|
2
|
+
|
3
|
+
MIT License
|
2
4
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
6
|
a copy of this software and associated documentation files (the
|
@@ -18,3 +20,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
22
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# BitMask
|
2
2
|
|
3
3
|
A simple class that allows you to store data in a bit mask. It automagically manages bit sizes and base conversion of binary bitmask.
|
4
4
|
|
5
|
-
|
5
|
+
## Usage
|
6
6
|
|
7
7
|
When writing these config maps. Try to put the mose used options first so the string can be shorter.
|
8
8
|
|
@@ -14,12 +14,12 @@ When writing these config maps. Try to put the mose used options first so the st
|
|
14
14
|
# Integer up to 62
|
15
15
|
set_base 62
|
16
16
|
|
17
|
-
field :air, :values => 2
|
17
|
+
field :air, :values => 2 # number of options must be 2 or greater
|
18
18
|
field :color, :values => ['blue','green','red'] # bit_mask can map arrays of data, the default setting will be the first value in the array
|
19
19
|
field :body_style, :values => [:sedan,:mini_van,:suv] # Array values can be anything that can be found using the Array#index function
|
20
|
-
field :transmission,:values => 6
|
20
|
+
field :transmission,:values => 6
|
21
21
|
field :min_price, :values => (50..100).to_a # ( just a way to store ranges of numbers)
|
22
|
-
field :max_price, :values => (1..5).to_a.map {|n| 10000+(n*20)}
|
22
|
+
field :max_price, :values => (1..5).to_a.map {|n| 10000+(n*20)}
|
23
23
|
|
24
24
|
# overwrite default accessors
|
25
25
|
|
@@ -57,32 +57,27 @@ When writing these config maps. Try to put the mose used options first so the st
|
|
57
57
|
SearchParams.load(@search.to_s(36),36) # load from different base
|
58
58
|
SearchParams.load(@search.to_s('asldkfjv'),'asldkfjv')
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
== TODO
|
60
|
+
## TODO
|
63
61
|
|
64
62
|
* Impliment more tests
|
65
63
|
* Storage of strings?
|
66
|
-
* Allow for embeded bit_masks
|
67
64
|
* create javascript version for easy communication between ruby and javascript
|
68
65
|
|
69
|
-
|
66
|
+
## Contributing
|
70
67
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
77
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
68
|
+
1. Fork it
|
69
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
70
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
71
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
72
|
+
5. Create new Pull Request
|
78
73
|
|
79
|
-
|
74
|
+
## Credits
|
80
75
|
|
81
76
|
Ryan Ong - ryanong@gmail.com
|
82
77
|
|
83
78
|
Developed for and with CarZen[link:http://carzen.com]
|
84
79
|
|
85
|
-
|
80
|
+
## Copyright
|
86
81
|
|
87
82
|
Copyright (c) 2011 Ryan Ong. See LICENSE.txt for
|
88
83
|
further details.
|
data/Rakefile
CHANGED
@@ -1,49 +1 @@
|
|
1
|
-
require
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
-
gem.name = "bit_mask"
|
16
|
-
gem.homepage = "http://github.com/ryanong/bit_hash"
|
17
|
-
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{bit_mask allows you to serialize/bitmask simple data sets into short compact ascii strings.}
|
19
|
-
gem.description = %Q{bit_mask creates a simple api to create bit mask models. By bit masking dataing you can compress the amount of data that needs to be sent between servers and clients}
|
20
|
-
gem.email = "ryanong@gmail.com"
|
21
|
-
gem.authors = ["Ryan Ong"]
|
22
|
-
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
-
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
-
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
25
|
-
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
27
|
-
|
28
|
-
require 'rspec/core'
|
29
|
-
require 'rspec/core/rake_task'
|
30
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
-
end
|
33
|
-
|
34
|
-
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
-
spec.rcov = true
|
37
|
-
end
|
38
|
-
|
39
|
-
task :default => :spec
|
40
|
-
|
41
|
-
require 'rake/rdoctask'
|
42
|
-
Rake::RDocTask.new do |rdoc|
|
43
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
-
|
45
|
-
rdoc.rdoc_dir = 'rdoc'
|
46
|
-
rdoc.title = "bit_mask #{version}"
|
47
|
-
rdoc.rdoc_files.include('README*')
|
48
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bit_mask.gemspec
CHANGED
@@ -1,73 +1,24 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bit_mask/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "bit_mask"
|
8
|
+
gem.version = BitMask::VERSION
|
9
|
+
gem.authors = ["Ryan Ong"]
|
10
|
+
gem.email = ["ryanong@gmail.com"]
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
s.description = %q{bit_mask creates a simple api to create bit mask models. By bit masking dataing you can compress the amount of data that needs to be sent between servers and clients}
|
14
|
-
s.email = %q{ryanong@gmail.com}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE.txt",
|
17
|
-
"README.rdoc"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".document",
|
21
|
-
".rspec",
|
22
|
-
"Gemfile",
|
23
|
-
"LICENSE.txt",
|
24
|
-
"README.rdoc",
|
25
|
-
"Rakefile",
|
26
|
-
"VERSION",
|
27
|
-
"bit_mask.gemspec",
|
28
|
-
"lib/bit_mask.rb",
|
29
|
-
"spec/bit_mask_spec.rb",
|
30
|
-
"spec/models/car_search.rb",
|
31
|
-
"spec/models/dealership_search.rb",
|
32
|
-
"spec/spec_helper.rb"
|
33
|
-
]
|
34
|
-
s.homepage = %q{http://github.com/ryanong/bit_hash}
|
35
|
-
s.licenses = [%q{MIT}]
|
36
|
-
s.require_paths = [%q{lib}]
|
37
|
-
s.rubygems_version = %q{1.8.5}
|
38
|
-
s.summary = %q{bit_mask allows you to serialize/bitmask simple data sets into short compact ascii strings.}
|
39
|
-
s.test_files = [
|
40
|
-
"spec/bit_mask_spec.rb",
|
41
|
-
"spec/models/car_search.rb",
|
42
|
-
"spec/models/dealership_search.rb",
|
43
|
-
"spec/spec_helper.rb"
|
44
|
-
]
|
12
|
+
gem.description = %q{bit_mask creates a simple api to create bit mask models. By bit masking dataing you can compress the amount of data that needs to be sent between servers and clients}
|
13
|
+
gem.summary = %q{bit_mask allows you to serialize/bitmask simple data sets into short compact ascii strings.}
|
14
|
+
gem.homepage = %q{http://github.com/ryanong/bit_hash}
|
45
15
|
|
46
|
-
|
47
|
-
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
48
20
|
|
49
|
-
|
50
|
-
|
51
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
52
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
54
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
55
|
-
s.add_development_dependency(%q<rspec>, [">= 0"])
|
56
|
-
else
|
57
|
-
s.add_dependency(%q<activesupport>, [">= 0"])
|
58
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
59
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
60
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
61
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
62
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
63
|
-
end
|
64
|
-
else
|
65
|
-
s.add_dependency(%q<activesupport>, [">= 0"])
|
66
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
69
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
70
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
71
|
-
end
|
21
|
+
gem.add_development_dependency "activesupport", ">= 0"
|
22
|
+
gem.add_development_dependency "rspec", ">= 0"
|
72
23
|
end
|
73
24
|
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class BitMask::Field
|
2
|
+
attr_reader :name
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize(name, opts)
|
6
|
+
@name = name
|
7
|
+
@options = opts
|
8
|
+
if !values.is_a?(Integer) && !values.is_a?(Array)
|
9
|
+
raise "#{values.class} is an invalid class for values."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def bits
|
14
|
+
@bits ||=
|
15
|
+
if options[:bits]
|
16
|
+
options[:bits]
|
17
|
+
elsif values.kind_of?(Integer) && values < 0
|
18
|
+
-1
|
19
|
+
else
|
20
|
+
if options[:limit]
|
21
|
+
max_number = options[:limit]
|
22
|
+
elsif values.is_a?(Integer)
|
23
|
+
max_number = values
|
24
|
+
elsif values.is_a?(Array)
|
25
|
+
max_number = values.size
|
26
|
+
end
|
27
|
+
|
28
|
+
max_number += 1 if null
|
29
|
+
|
30
|
+
Math.log2(max_number).ceil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def values
|
35
|
+
options[:values]
|
36
|
+
end
|
37
|
+
|
38
|
+
def null
|
39
|
+
options[:null]
|
40
|
+
end
|
41
|
+
|
42
|
+
def default
|
43
|
+
@default ||=
|
44
|
+
if null
|
45
|
+
nil
|
46
|
+
elsif values.kind_of? Integer
|
47
|
+
0
|
48
|
+
elsif values.respond_to? :first
|
49
|
+
values.first
|
50
|
+
elsif values.respond_to? :defaults
|
51
|
+
values.defaults
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_bin(value)
|
56
|
+
if self.null && value.nil?
|
57
|
+
value = 0
|
58
|
+
elsif self.values.respond_to? :index
|
59
|
+
value = self.values.index(value)
|
60
|
+
value += 1 if self.null
|
61
|
+
end
|
62
|
+
value = value.to_s(2)
|
63
|
+
value = value.rjust(self.bits,'0') if self.bits > 0
|
64
|
+
value
|
65
|
+
end
|
66
|
+
|
67
|
+
def from_i(value)
|
68
|
+
value -= 1 if self.null
|
69
|
+
|
70
|
+
if self.null && value == -1
|
71
|
+
value = nil
|
72
|
+
elsif self.values.respond_to?(:at)
|
73
|
+
value = self.values.at(value)
|
74
|
+
end
|
75
|
+
value
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class BitMask
|
2
|
+
module Radix
|
3
|
+
class << self
|
4
|
+
def integer_to_string(integer, characters)
|
5
|
+
characters = process_characters(characters)
|
6
|
+
radix = characters.length
|
7
|
+
|
8
|
+
result = ''
|
9
|
+
while integer != 0
|
10
|
+
result += characters[integer%radix].chr
|
11
|
+
integer /= radix
|
12
|
+
end
|
13
|
+
result.reverse
|
14
|
+
end
|
15
|
+
|
16
|
+
def string_to_integer(string, characters)
|
17
|
+
characters = process_characters(characters)
|
18
|
+
radix = characters.length
|
19
|
+
|
20
|
+
int_val = 0
|
21
|
+
string.reverse.split('').each_with_index do |char,index|
|
22
|
+
if char_index = characters.index(char)
|
23
|
+
int_val += (char_index)*(radix**(index))
|
24
|
+
else
|
25
|
+
raise ArgumentError, "Character #{char} at index #{index} is not a valid character for Base #{characters} String."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
int_val
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def process_characters(characters)
|
34
|
+
if characters.is_a? String
|
35
|
+
characters = characters.split('')
|
36
|
+
end
|
37
|
+
if characters != characters.uniq
|
38
|
+
raise ArgumentError, "There are duplicate characters in #{characters}"
|
39
|
+
end
|
40
|
+
characters
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/bit_mask.rb
CHANGED
@@ -1,44 +1,50 @@
|
|
1
1
|
require 'active_support/core_ext/class/attribute'
|
2
|
+
require 'active_support/ordered_hash'
|
3
|
+
|
4
|
+
require "bit_mask/version"
|
5
|
+
require "bit_mask/field"
|
6
|
+
require "bit_mask/radix"
|
2
7
|
|
3
8
|
class BitMask
|
4
9
|
CHARACTER_SET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
5
|
-
class_attribute :fields, :
|
10
|
+
class_attribute :fields, :base
|
11
|
+
|
6
12
|
def self.inherited(sub)
|
7
|
-
sub.fields =
|
8
|
-
sub.defaults = {}
|
13
|
+
sub.fields = ActiveSupport::OrderedHash.new
|
9
14
|
sub.base = 62
|
10
15
|
end
|
11
16
|
|
12
|
-
def initialize(
|
13
|
-
|
17
|
+
def initialize(new_attributes = {})
|
18
|
+
@attributes = {}
|
19
|
+
self.assign_attributes(
|
20
|
+
self.class.defaults.merge(new_attributes)
|
21
|
+
)
|
14
22
|
end
|
15
23
|
|
16
|
-
def
|
17
|
-
|
18
|
-
self
|
24
|
+
def assign_attributes(new_attributes)
|
25
|
+
new_attributes.each do |field, value|
|
26
|
+
self.send("#{field}=",value)
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
22
|
-
alias_method :attributes=, :
|
30
|
+
alias_method :attributes=, :assign_attributes
|
23
31
|
|
24
32
|
def [](field)
|
25
|
-
|
26
|
-
self.send(field)
|
33
|
+
self.read_attribute(field)
|
27
34
|
end
|
28
35
|
|
29
36
|
def []=(field,value)
|
30
|
-
|
31
|
-
self.send("#{field}=",value)
|
37
|
+
self.write_attribute(field,value)
|
32
38
|
end
|
33
39
|
|
34
40
|
def read_attribute(key)
|
35
|
-
|
41
|
+
@attributes[key]
|
36
42
|
end
|
37
43
|
|
38
44
|
def write_attribute(key,value)
|
39
|
-
if field = self.fields
|
40
|
-
if self.class.
|
41
|
-
|
45
|
+
if field = self.fields[key]
|
46
|
+
if self.class.check_and_cast_value(field,value)
|
47
|
+
@attributes[field.name] = value
|
42
48
|
else
|
43
49
|
raise "Invalid input for #{key}: #{value} field: #{field}"
|
44
50
|
end
|
@@ -48,17 +54,9 @@ class BitMask
|
|
48
54
|
end
|
49
55
|
|
50
56
|
def to_bin
|
51
|
-
self.fields.reverse.map do |field
|
52
|
-
val = self.read_attribute(field)
|
53
|
-
|
54
|
-
val = 0
|
55
|
-
elsif conf[:values].respond_to? :index
|
56
|
-
val = conf[:values].index(val)
|
57
|
-
val += 1 if conf[:nil]
|
58
|
-
end
|
59
|
-
val = val.to_i.to_s(2)
|
60
|
-
val = val.rjust(conf[:bits],'0') if conf[:bits] > 0
|
61
|
-
val
|
57
|
+
self.fields.values.reverse.map do |field|
|
58
|
+
val = self.read_attribute(field.name)
|
59
|
+
field.to_bin(val)
|
62
60
|
end.join('').sub(/\A0+/,'')
|
63
61
|
end
|
64
62
|
|
@@ -68,23 +66,8 @@ class BitMask
|
|
68
66
|
end
|
69
67
|
|
70
68
|
def to_s(radix=nil)
|
71
|
-
|
72
|
-
characters
|
73
|
-
|
74
|
-
if radix.kind_of? String
|
75
|
-
characters = radix.dup
|
76
|
-
radix = radix.size
|
77
|
-
elsif !radix.kind_of?(Integer) || radix < 0 || radix > 64
|
78
|
-
raise '#{radix} is and invalid base to convert to. It must be a string or between 0 and 64'
|
79
|
-
end
|
80
|
-
|
81
|
-
dec = self.to_i
|
82
|
-
result = ''
|
83
|
-
while dec != 0
|
84
|
-
result += characters[dec%radix].chr
|
85
|
-
dec /= radix
|
86
|
-
end
|
87
|
-
result.reverse
|
69
|
+
characters = self.class.get_characters(radix)
|
70
|
+
Radix.integer_to_string(self.to_i, characters)
|
88
71
|
end
|
89
72
|
|
90
73
|
def keys
|
@@ -108,29 +91,17 @@ class BitMask
|
|
108
91
|
self.attributes.inspect
|
109
92
|
end
|
110
93
|
|
94
|
+
private
|
95
|
+
|
111
96
|
class << self
|
112
97
|
|
113
98
|
def keys
|
114
|
-
self.fields.
|
99
|
+
self.fields.keys
|
115
100
|
end
|
116
101
|
|
117
102
|
def from_s(string,radix = nil)
|
118
|
-
|
119
|
-
|
120
|
-
char_ref = radix
|
121
|
-
radix = radix.size
|
122
|
-
elsif !radix.kind_of?(Integer) || radix < 0 || radix > 64
|
123
|
-
raise '#{radix} is and invalid base to convert to. It must be a string or between 0 and 64'
|
124
|
-
else
|
125
|
-
char_ref = CHARACTER_SET[0..radix]
|
126
|
-
end
|
127
|
-
|
128
|
-
int_val = 0
|
129
|
-
string.reverse.split('').each_with_index do |char,index|
|
130
|
-
raise ArgumentError, "Character #{char} at index #{index} is not a valid character for to_insane Base #{radix} String." unless char_index = char_ref.index(char)
|
131
|
-
int_val += (char_index)*(radix**(index))
|
132
|
-
end
|
133
|
-
self.from_i(int_val)
|
103
|
+
characters = self.get_characters(radix)
|
104
|
+
self.from_i(Radix.string_to_integer(string, characters))
|
134
105
|
end
|
135
106
|
|
136
107
|
alias_method :load, :from_s
|
@@ -141,109 +112,65 @@ class BitMask
|
|
141
112
|
|
142
113
|
def from_bin(binary_string)
|
143
114
|
binary_array = binary_string.split('')
|
144
|
-
|
145
|
-
self.fields.each do |field
|
146
|
-
value = (
|
115
|
+
bit_mask = self.new
|
116
|
+
self.fields.values.each do |field|
|
117
|
+
value = (field.bits == -1) ? binary_array : binary_array.pop(field.bits)
|
147
118
|
break if value.nil?
|
148
|
-
value = value.join
|
149
|
-
value
|
150
|
-
|
151
|
-
if conf[:nil] && value == -1
|
152
|
-
value = nil
|
153
|
-
elsif conf[:values].respond_to?(:at)
|
154
|
-
value = conf[:values].at(value)
|
155
|
-
elsif conf[:values].respond_to?(:from_i)
|
156
|
-
value = conf[:values].from_i(value)
|
157
|
-
end
|
158
|
-
bit_hash.write_attribute(field,value)
|
159
|
-
end
|
160
|
-
bit_hash
|
161
|
-
end
|
162
|
-
|
163
|
-
def set_base(base)
|
164
|
-
if base.kind_of? Integer && base <= 36
|
165
|
-
self.base = base
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def bit_length
|
170
|
-
bits = 0
|
171
|
-
self.fields.each do |field,opts|
|
172
|
-
bits += opts[:bits]
|
119
|
+
value = value.join.to_i(2)
|
120
|
+
value = field.from_i(value)
|
121
|
+
bit_mask.write_attribute(field.name,value)
|
173
122
|
end
|
174
|
-
|
123
|
+
bit_mask
|
175
124
|
end
|
176
125
|
|
177
126
|
def field(name,opts)
|
178
127
|
name = name.to_sym
|
179
|
-
|
180
|
-
unless opts[:limit]
|
181
|
-
if opts[:characters]
|
182
|
-
opts[:limit] = opts[:characters].to_i*self.base
|
183
|
-
elsif opts[:values].respond_to? :bit_length
|
184
|
-
opts[:bits] = opts[:values].bit_length
|
185
|
-
elsif opts[:values].kind_of? Integer
|
186
|
-
if opts[:values] == -1
|
187
|
-
opts[:bits] = -1
|
188
|
-
else
|
189
|
-
opts[:limit] = opts[:values]
|
190
|
-
opts[:limit] += 1 if opts[:nil]
|
191
|
-
end
|
192
|
-
else
|
193
|
-
opts[:limit] = opts[:values].size
|
194
|
-
opts[:limit] += 1 if opts[:nil]
|
195
|
-
end
|
196
|
-
end
|
197
|
-
opts[:bits] ||= (opts[:limit].to_i-1).to_s(2).length
|
198
|
-
end
|
199
|
-
raise "value cannot be negative" if opts[:values].class == Integer && opts[:values] < 0
|
200
|
-
options = {:values => opts[:values], :bits => opts[:bits].to_i, :nil => opts[:nil]}
|
201
|
-
if index = self.fields.index{|f| f[0] == name}
|
202
|
-
self.fields[index][1] = options
|
203
|
-
else
|
204
|
-
self.fields << [name, options]
|
205
|
-
end
|
206
|
-
self.defaults[name]=get_default(options)
|
207
|
-
|
208
|
-
define_method name do
|
209
|
-
self.read_attribute(name)
|
210
|
-
end
|
128
|
+
self.fields[name] = Field.new(name,opts)
|
211
129
|
|
212
|
-
|
213
|
-
|
214
|
-
|
130
|
+
include(Module.new do
|
131
|
+
define_method(name) do
|
132
|
+
read_attribute(name)
|
133
|
+
end
|
215
134
|
|
135
|
+
define_method("#{name}=") do |*args|
|
136
|
+
write_attribute(name,*args)
|
137
|
+
end
|
138
|
+
end)
|
216
139
|
end
|
217
140
|
|
218
|
-
def
|
219
|
-
|
220
|
-
|
221
|
-
if values.kind_of? Integer
|
222
|
-
0
|
223
|
-
elsif values.respond_to? :first
|
224
|
-
values.first
|
225
|
-
elsif values.respond_to? :defaults
|
226
|
-
values.defaults
|
141
|
+
def defaults
|
142
|
+
fields_array = fields.values.map do |field|
|
143
|
+
[field.name, field.default]
|
227
144
|
end
|
145
|
+
Hash[fields_array]
|
228
146
|
end
|
229
147
|
|
230
|
-
def
|
231
|
-
field = (key.
|
232
|
-
|
233
|
-
|
234
|
-
return true if opts[:nil] && value.nil?
|
235
|
-
if values = opts[:values]
|
148
|
+
def check_and_cast_value(key,value)
|
149
|
+
if field = (key.is_a? Field) ? key : self.fields[key]
|
150
|
+
return true if field.null && value.nil?
|
151
|
+
if values = field.values
|
236
152
|
if values.kind_of? Integer
|
237
|
-
|
238
|
-
return
|
239
|
-
|
240
|
-
return value.kind_of? BitMask && value.fields.hash == value.fields.hash
|
153
|
+
value = value.to_i
|
154
|
+
return nil if value < 0
|
155
|
+
return value if (values == -1 || value <= values)
|
241
156
|
else
|
242
|
-
return values.include?(value)
|
157
|
+
return value if values.include?(value)
|
243
158
|
end
|
244
159
|
end
|
245
160
|
end
|
246
|
-
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
|
164
|
+
def get_characters(radix = nil)
|
165
|
+
radix ||= self.base
|
166
|
+
|
167
|
+
if radix.kind_of?(String)
|
168
|
+
radix
|
169
|
+
elsif radix.kind_of?(Integer) && radix > 1 && radix <= CHARACTER_SET.length
|
170
|
+
CHARACTER_SET[0..radix-1]
|
171
|
+
else
|
172
|
+
raise "#{radix} is and invali base to convert to. It must be a string or between 2 and #{CHARACTER_SET.length}"
|
173
|
+
end
|
247
174
|
end
|
248
175
|
end
|
249
176
|
end
|
data/spec/bit_mask_spec.rb
CHANGED
@@ -3,15 +3,15 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
3
3
|
describe BitMask do
|
4
4
|
|
5
5
|
it "should have values set at 2" do
|
6
|
-
CarSearch.fields
|
6
|
+
CarSearch.fields[:segment_1].values.should == 2
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should have bits set to 1" do
|
10
|
-
CarSearch.fields
|
10
|
+
CarSearch.fields[(:segment_1)].bits.should == 1
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should have bits set to 4" do
|
14
|
-
CarSearch.fields
|
14
|
+
CarSearch.fields[(:min_price_cents)].bits.should == 4
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should raise an error if config lacks name" do
|
@@ -45,7 +45,7 @@ describe BitMask do
|
|
45
45
|
|
46
46
|
it "should replace setting" do
|
47
47
|
config = CarSearch.new
|
48
|
-
config.
|
48
|
+
config.assign_attributes({:air=>1})
|
49
49
|
config[:air].should eql(1)
|
50
50
|
end
|
51
51
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class DealershipSearch < BitMask
|
2
|
-
field :makes, :values => ['honda','toyota','ford'], :
|
3
|
-
field :zip, :values => 99999, :
|
2
|
+
field :makes, :values => ['honda','toyota','ford'], :null => true
|
3
|
+
field :zip, :values => 99999, :null => true
|
4
4
|
field :distance, :values => -1
|
5
5
|
end
|
metadata
CHANGED
@@ -1,137 +1,100 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: bit_mask
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.0.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Ryan Ong
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-12-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: activesupport
|
17
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
|
-
requirements:
|
20
|
-
- -
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version:
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: shoulda
|
28
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
29
|
-
none: false
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: "0"
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: bundler
|
39
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
40
|
-
none: false
|
41
|
-
requirements:
|
42
|
-
- - ~>
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version: 1.0.0
|
45
|
-
type: :development
|
46
|
-
prerelease: false
|
47
|
-
version_requirements: *id003
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: jeweler
|
50
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
|
-
requirements:
|
53
|
-
- - ~>
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: 1.5.2
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
56
22
|
type: :development
|
57
23
|
prerelease: false
|
58
|
-
version_requirements:
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: rcov
|
61
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
62
25
|
none: false
|
63
|
-
requirements:
|
64
|
-
- -
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version:
|
67
|
-
|
68
|
-
prerelease: false
|
69
|
-
version_requirements: *id005
|
70
|
-
- !ruby/object:Gem::Dependency
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
71
31
|
name: rspec
|
72
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
73
33
|
none: false
|
74
|
-
requirements:
|
75
|
-
- -
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version:
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
78
38
|
type: :development
|
79
39
|
prerelease: false
|
80
|
-
version_requirements:
|
81
|
-
|
82
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: bit_mask creates a simple api to create bit mask models. By bit masking
|
47
|
+
dataing you can compress the amount of data that needs to be sent between servers
|
48
|
+
and clients
|
49
|
+
email:
|
50
|
+
- ryanong@gmail.com
|
83
51
|
executables: []
|
84
|
-
|
85
52
|
extensions: []
|
86
|
-
|
87
|
-
|
88
|
-
- LICENSE.txt
|
89
|
-
- README.rdoc
|
90
|
-
files:
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
91
55
|
- .document
|
56
|
+
- .gitignore
|
92
57
|
- .rspec
|
93
58
|
- Gemfile
|
94
59
|
- LICENSE.txt
|
95
|
-
- README.
|
60
|
+
- README.md
|
96
61
|
- Rakefile
|
97
62
|
- VERSION
|
98
63
|
- bit_mask.gemspec
|
99
64
|
- lib/bit_mask.rb
|
65
|
+
- lib/bit_mask/field.rb
|
66
|
+
- lib/bit_mask/radix.rb
|
67
|
+
- lib/bit_mask/version.rb
|
100
68
|
- spec/bit_mask_spec.rb
|
101
69
|
- spec/models/car_search.rb
|
102
70
|
- spec/models/dealership_search.rb
|
103
71
|
- spec/spec_helper.rb
|
104
72
|
homepage: http://github.com/ryanong/bit_hash
|
105
|
-
licenses:
|
106
|
-
- MIT
|
73
|
+
licenses: []
|
107
74
|
post_install_message:
|
108
75
|
rdoc_options: []
|
109
|
-
|
110
|
-
require_paths:
|
76
|
+
require_paths:
|
111
77
|
- lib
|
112
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
79
|
none: false
|
114
|
-
requirements:
|
115
|
-
- -
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
|
118
|
-
|
119
|
-
- 0
|
120
|
-
version: "0"
|
121
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
85
|
none: false
|
123
|
-
requirements:
|
124
|
-
- -
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
version:
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
127
90
|
requirements: []
|
128
|
-
|
129
91
|
rubyforge_project:
|
130
|
-
rubygems_version: 1.8.
|
92
|
+
rubygems_version: 1.8.23
|
131
93
|
signing_key:
|
132
94
|
specification_version: 3
|
133
|
-
summary: bit_mask allows you to serialize/bitmask simple data sets into short compact
|
134
|
-
|
95
|
+
summary: bit_mask allows you to serialize/bitmask simple data sets into short compact
|
96
|
+
ascii strings.
|
97
|
+
test_files:
|
135
98
|
- spec/bit_mask_spec.rb
|
136
99
|
- spec/models/car_search.rb
|
137
100
|
- spec/models/dealership_search.rb
|