Class: SPCore::CircularBuffer

Inherits:
Object
  • Object
show all
Defined in:
lib/spcore/core/circular_buffer.rb

Overview

Author:

  • James Tunnell

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(size, opts = {}) ⇒ CircularBuffer

A new instance of CircularBuffer.

Parameters:

  • size (Fixnum)

    The buffer size (and maximum fill count).

  • opts (Hash) (defaults to: {})

    Contain optional arguments to modify buffer push/pop behavior. Valid keys are :override_when_full and :fifo.



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/spcore/core/circular_buffer.rb', line 24

def initialize size, opts = {}
  
  opts = { :fifo => true, :override_when_full => true }.merge opts
  
  @buffer = Array.new(size)
  @oldest = 0;
  @newest = 0;
  @fill_count = 0;

  @fifo = opts[:fifo]
  @override_when_full = opts[:override_when_full]
end

Instance Attribute Details

#fifoObject

Returns the value of attribute fifo.



17
18
19
# File 'lib/spcore/core/circular_buffer.rb', line 17

def fifo
  @fifo
end

#fill_countObject (readonly)

Returns the value of attribute fill_count.



18
19
20
# File 'lib/spcore/core/circular_buffer.rb', line 18

def fill_count
  @fill_count
end

#override_when_fullObject

Returns the value of attribute override_when_full.



17
18
19
# File 'lib/spcore/core/circular_buffer.rb', line 17

def override_when_full
  @override_when_full
end

Instance Method Details

#empty?Boolean

Return true if the buffer is empty.

Returns:

  • (Boolean)


43
44
45
# File 'lib/spcore/core/circular_buffer.rb', line 43

def empty?
  return @fill_count == 0
end

#full?Boolean

Return true if the buffer is full (fill count == buffer size).

Returns:

  • (Boolean)


48
49
50
# File 'lib/spcore/core/circular_buffer.rb', line 48

def full?
  return (@fill_count == size)
end

#newest(relative_index = 0) ⇒ Object

access the latest data element.

Raises:

  • (ArgumentError)


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/spcore/core/circular_buffer.rb', line 116

def newest relative_index = 0
  raise ArgumentError, "buffer is empty" if empty?
  raise ArgumentError, "relative_index is greater or equal to @fill_count" if relative_index >= @fill_count

  # newestIdx is actually @newest - 1
  newestIdx = @newest - 1;
  if(newestIdx < 0)
    newestIdx += @buffer.count;
  end

  absIdx = newestIdx - relative_index;
  if(absIdx < 0)
    absIdx += @buffer.count;
  end

  return @buffer[absIdx];
end

#oldest(relative_index = 0) ⇒ Object

access the oldest data element.

Raises:

  • (ArgumentError)


135
136
137
138
139
140
141
142
143
144
145
# File 'lib/spcore/core/circular_buffer.rb', line 135

def oldest relative_index = 0
  raise ArgumentError, "buffer is empty" if empty?
  raise ArgumentError, "relative_index is greater or equal to @fill_count" if relative_index >= @fill_count
  
  absIdx = @oldest + relative_index;
  if(absIdx >= @buffer.count)
      absIdx -= @buffer.count;
  end
  
  return @buffer[absIdx];
end

#popObject

Pop the oldest/newest element, depending on @fifo flag. When true, pop the oldest, otherwise pop the newest. Set to true by default, can override during initialize or later using fifo=.

Raises:

  • (ArgumentError)


150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/spcore/core/circular_buffer.rb', line 150

def pop
  raise ArgumentError, "buffer is empty" if empty?
  
  if @fifo
    # FIFO - pop the oldest element
    element = oldest
    @oldest += 1
    if(@oldest >= @buffer.count)
      @oldest = 0
    end
    @fill_count -= 1
    return element    
  else
    # FILO - pop the newest element
    element = newest
    if(@newest > 0)
      @newest -= 1
    else
      @newest = @buffer.count - 1
    end
    @fill_count -= 1
    return element      
  end
end

#push(element) ⇒ Object

push a single data element.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/spcore/core/circular_buffer.rb', line 86

def push element
  if full?
    raise ArgumentError, "buffer is full, and override_when_full is false" unless @override_when_full
    
    @buffer[@newest] = element;
    @newest += 1
    @oldest += 1
  else
    @buffer[@newest] = element;
    @newest += 1
    @fill_count += 1      
  end

  if @oldest >= @buffer.count
    @oldest = 0
  end

  if @newest >= @buffer.count
    @newest = 0
  end
end

#push_ary(ary) ⇒ Object

push an array of data elements.



109
110
111
112
113
# File 'lib/spcore/core/circular_buffer.rb', line 109

def push_ary ary
  ary.each do |element|
    push element
  end
end

#resize(size) ⇒ Object

Change the buffer size, allocating a new backing array at the same time.



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/spcore/core/circular_buffer.rb', line 53

def resize size
  rv = false
  if(size != @buffer.count)
    rv = true
    @buffer = Array.new(size)
    @oldest = 0
    @newest = 0
    @fill_count = 0
  end
  return rv
end

#sizeObject

Return the buffer size (max fill count).



38
39
40
# File 'lib/spcore/core/circular_buffer.rb', line 38

def size
  return @buffer.count
end

#to_aryObject

Return an array containing the data layed out contiguously (data normally is split somewhere along the backing array).



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/spcore/core/circular_buffer.rb', line 67

def to_ary
  if empty?
    return []
  end

  # newest index is actually @newest - 1
  newest_idx = @newest - 1;
  if(newest_idx < 0)
    newest_idx += @buffer.count;
  end

  if newest_idx >= @oldest
    return @buffer[@oldest..newest_idx]
  else
    return @buffer[@oldest...@buffer.count] + @buffer[0..newest_idx]
  end
end