cbuffer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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