cbuffer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2011, Duncan Robertson, British Broadcasting Corporation
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ * CBuffer
2
+
3
+ ** Overview
4
+
5
+ A circular buffer, cyclic buffer or ring buffer is a data structure that uses
6
+ a single, fixed-size buffer as if it were connected end-to-end. This structure
7
+ lends itself easily to buffering data streams. This library impliments such a
8
+ buffer.
9
+
10
+ ** Installation
11
+
12
+ : gem install cbuffer
13
+
14
+ ** Usage
15
+
16
+ : require 'cbuffer'
17
+ :
18
+ : a = CBuffer.new 5 => <CBuffer @size=5>
19
+ : a.put 1 => false
20
+ : a.put 2 => false
21
+ : a.put "Duncan" => false
22
+ : a.put 999 => false
23
+ : a.get => 1
24
+ : a.get => 2
25
+ : a.get => "Duncan"
26
+ : a.put "xxx" => false
27
+ : a.get => 999
28
+
29
+ ** Todo
30
+
31
+ - threading support
32
+ - fetch items by index
33
+ - view onto items
34
+
35
+ ** Contributing
36
+ - Fork the project
37
+ - Send a pull request
38
+ - Don't touch the .gemspec, I'll do that when I release a new version
39
+
40
+ ** Author
41
+
42
+ [[http://whomwah.com][Duncan Robertson]] - BBC R&D
@@ -0,0 +1,19 @@
1
+ require 'rake/testtask'
2
+ require 'bundler'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ desc "Run tests"
7
+ Rake::TestTask.new do |t|
8
+ t.libs << "lib"
9
+ t.libs << "test"
10
+ t.test_files = FileList['test/test_*.rb']
11
+ t.verbose = true
12
+ end
13
+
14
+ desc "Run benchmark"
15
+ task :benchmark do
16
+ ruby "test/benchmark.rb"
17
+ end
18
+
19
+ task :default => [:test]
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cbuffer/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cbuffer"
7
+ s.version = CBuffer::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Duncan Robertson"]
10
+ s.email = ["duncan.robertson@bbc.co.uk"]
11
+ s.homepage = "https://github.com/bbcrd/CBuffer"
12
+ s.summary = %q{A simple implementation of a circular buffer}
13
+ s.description = %q{A circular buffer, cyclic buffer or ring buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end. This structure lends itself easily to buffering data streams. This library impliments such a buffer.}
14
+
15
+ s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
16
+
17
+ s.add_development_dependency "rake"
18
+ s.add_development_dependency("bundler", ">= 1.0.0")
19
+
20
+ s.has_rdoc = false
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,47 @@
1
+ class CBuffer
2
+ class BufferFull < StandardError; end
3
+
4
+ def initialize(capacity)
5
+ @capacity = capacity
6
+ @f = @b = @fc = 0
7
+ @buffer = Array.new(capacity)
8
+ end
9
+
10
+ def get
11
+ return if empty?
12
+ element = @buffer[@b]
13
+ @buffer[@b] = nil
14
+ @b = (@b + 1) % @capacity
15
+ @fc = @fc - 1
16
+ element
17
+ end
18
+
19
+ def put(element)
20
+ raise BufferFull if full?
21
+ @buffer[@f] = element
22
+ @f = (@f + 1) % @capacity
23
+ @fc = @fc + 1
24
+ full?
25
+ end
26
+
27
+ def full?
28
+ @f == @b && @fc != 0
29
+ end
30
+
31
+ def empty?
32
+ @f == @b && @fc == 0
33
+ end
34
+
35
+ def size
36
+ @capacity
37
+ end
38
+
39
+ def clear
40
+ @buffer = Array.new(@capacity)
41
+ @f = @b = @fc = 0
42
+ end
43
+
44
+ def to_s
45
+ "<#{self.class} @size=#{@capacity}>"
46
+ end
47
+ end
@@ -0,0 +1,3 @@
1
+ module CBuffer
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,63 @@
1
+ require_relative '../lib/cbuffer.rb'
2
+ require "benchmark"
3
+
4
+ # Comparing a circular buffer implimentation for creating
5
+ # a fixed size FIFO message queue to doing the same with
6
+ # an Array. As you can see, the circualr buffer approach
7
+ # is much faster when it comes to writing to the queue.
8
+
9
+ # user system total real
10
+ #Put: Array 0.480000 0.010000 0.490000 ( 0.488787)
11
+ #Put: CBuffer 0.010000 0.000000 0.010000 ( 0.009931)
12
+ # user system total real
13
+ #Get: Array 0.010000 0.000000 0.010000 ( 0.004768)
14
+ #Get: CBuffer 0.010000 0.000000 0.010000 ( 0.007814)
15
+
16
+ SAMPLE_SIZE=10000
17
+
18
+ class ABuffer < Array
19
+ def initialize(size)
20
+ @ring_size = size
21
+ super( size )
22
+ end
23
+
24
+ def put(element)
25
+ if length == @ring_size
26
+ shift
27
+ end
28
+ push element
29
+ end
30
+
31
+ def get(offset=0)
32
+ self[ -1 + offset ]
33
+ end
34
+ end
35
+
36
+ def pushing
37
+ ary = ABuffer.new(SAMPLE_SIZE)
38
+ buf = CBuffer.new(SAMPLE_SIZE)
39
+
40
+ Benchmark.bm(15) do |x|
41
+ x.report("Put: Array") { (1..SAMPLE_SIZE).each { |i| ary.put(i) } }
42
+ x.report("Put: CBuffer") { (1..SAMPLE_SIZE).each { |i| buf.put(i) } }
43
+ end
44
+ end
45
+
46
+ def pulling
47
+ ary = ABuffer.new(SAMPLE_SIZE)
48
+ (1..SAMPLE_SIZE).each { |i| ary.put(i) }
49
+ buf = CBuffer.new(SAMPLE_SIZE)
50
+ (1..SAMPLE_SIZE).each { |i| buf.put(i) }
51
+
52
+ Benchmark.bm(15) do |x|
53
+ x.report("Get: Array") { (1..SAMPLE_SIZE).each { |i| ary.get } }
54
+ x.report("Get: CBuffer") { (1..SAMPLE_SIZE).each { |i| buf.get } }
55
+ end
56
+ end
57
+
58
+ def init
59
+ pushing
60
+ pulling
61
+ end
62
+
63
+ init
@@ -0,0 +1,3 @@
1
+ require 'test/unit'
2
+
3
+ require_relative '../lib/cbuffer.rb'
@@ -0,0 +1,117 @@
1
+ require 'helper'
2
+
3
+ class TestCBuffer < Test::Unit::TestCase
4
+ def test_simple
5
+ b = CBuffer.new(7)
6
+ assert b.empty?
7
+ b.put "one"
8
+ b.put "two"
9
+ b.put "three"
10
+ assert_equal "one", b.get
11
+ b.put "four"
12
+ assert_equal "two", b.get
13
+ b.put "five"
14
+ b.put "six"
15
+ b.put "seven"
16
+ assert_equal "three", b.get
17
+ b.put "eight"
18
+ b.put "nine"
19
+ b.put nil
20
+ assert_equal "four", b.get
21
+ assert_equal "five", b.get
22
+ assert_equal "six", b.get
23
+ assert_equal "seven", b.get
24
+ assert_equal "eight", b.get
25
+ assert_equal "nine", b.get
26
+ assert_equal nil, b.get
27
+ end
28
+
29
+ def test_circularness
30
+ b = CBuffer.new(5)
31
+ b.put 1 # [1,nil,nil,nil,nil]
32
+ b.put 2 # [1,2,nil,nil,nil]
33
+ b.put 3 # [1,2,3,nil,nil]
34
+ b.get # [nil,2,3,nil,nil]
35
+ b.put 4 # [nil,2,3,4,nil]
36
+ b.put 5 # [nil,2,3,4,5]
37
+ b.put 6 # [6,2,3,4,5]
38
+ assert_raise(CBuffer::BufferFull) {
39
+ b.put(3)
40
+ }
41
+ b.get # [6, nil, 3, 4, 5]
42
+ b.put 7 # [6,7,3,4,5]
43
+ assert_raise(CBuffer::BufferFull) {
44
+ b.put(8)
45
+ }
46
+ end
47
+
48
+ def test_buffer_overload
49
+ b = CBuffer.new(3)
50
+ assert_raise(CBuffer::BufferFull) {
51
+ b.put(1)
52
+ b.put(2)
53
+ b.put(3)
54
+ b.put(4)
55
+ }
56
+ end
57
+
58
+ def test_buffer_overload_with_nil
59
+ b = CBuffer.new(3)
60
+ assert_raise(CBuffer::BufferFull) {
61
+ b.put 1
62
+ b.put 2
63
+ b.put 3
64
+ b.put nil
65
+ }
66
+ end
67
+
68
+ def test_clear_buffer
69
+ b = CBuffer.new(3)
70
+ b.put(1)
71
+ b.put(2)
72
+ b.put(8)
73
+ assert_raise(CBuffer::BufferFull) {
74
+ b.put(nil)
75
+ }
76
+ b.clear
77
+ assert b.empty?
78
+ end
79
+
80
+ def test_example_used_in_readme
81
+ b = CBuffer.new(4)
82
+ b.put({ :item => "one" })
83
+ b.put({ :item => "two" })
84
+ b.put({ :item => "three" })
85
+ assert_equal({:item => "one"}, b.get)
86
+ assert_equal({:item => "two"}, b.get)
87
+ b.put(nil)
88
+ b.put({ :item => "four" })
89
+ assert_equal({:item => "three"}, b.get)
90
+ assert_equal(nil, b.get)
91
+ assert_equal({ :item => "four" }, b.get)
92
+ end
93
+
94
+ def test_again
95
+ b = CBuffer.new(5)
96
+ assert !b.put(1)
97
+ assert !b.put(2)
98
+ assert !b.put(3)
99
+ assert !b.put(4)
100
+ assert b.put(5)
101
+ assert_equal 1, b.get
102
+ assert_equal 2, b.get
103
+ assert_equal 3, b.get
104
+ assert_equal 4, b.get
105
+ assert_equal 5, b.get
106
+ assert_equal nil, b.get
107
+ assert_equal nil, b.get
108
+ assert !b.put(1)
109
+ assert !b.put(2)
110
+ assert !b.put(3)
111
+ assert !b.put(4)
112
+ assert_equal 1, b.get
113
+ assert_equal 2, b.get
114
+ assert_equal 3, b.get
115
+ assert_equal 4, b.get
116
+ end
117
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cbuffer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Duncan Robertson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-09 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &70139950427700 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70139950427700
25
+ - !ruby/object:Gem::Dependency
26
+ name: bundler
27
+ requirement: &70139950427160 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70139950427160
36
+ description: A circular buffer, cyclic buffer or ring buffer is a data structure that
37
+ uses a single, fixed-size buffer as if it were connected end-to-end. This structure
38
+ lends itself easily to buffering data streams. This library impliments such a buffer.
39
+ email:
40
+ - duncan.robertson@bbc.co.uk
41
+ executables: []
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - LICENSE
48
+ - README.org
49
+ - Rakefile
50
+ - cbuffer.gemspec
51
+ - lib/cbuffer.rb
52
+ - lib/cbuffer/version.rb
53
+ - test/benchmark.rb
54
+ - test/helper.rb
55
+ - test/test_cbuffer.rb
56
+ homepage: https://github.com/bbcrd/CBuffer
57
+ licenses: []
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: 1.3.6
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 1.8.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A simple implementation of a circular buffer
80
+ test_files:
81
+ - test/benchmark.rb
82
+ - test/helper.rb
83
+ - test/test_cbuffer.rb