Fixes issue #129 - Don't leak gcodes in block.
[clinton/Smoothieware.git] / src / libs / RingBuffer.h
1 /*
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
6
7 With chucks taken from http://en.wikipedia.org/wiki/Circular_buffer, see licence there also
8 */
9
10 #ifndef RINGBUFFER_H
11 #define RINGBUFFER_H
12
13
14 template<class kind, int length> class RingBuffer {
15 public:
16 RingBuffer();
17 int size();
18 int capacity();
19 int next_block_index(int index);
20 int prev_block_index(int index);
21 void push_back(kind object);
22 void pop_front(kind &object);
23 kind* get_tail_ref();
24 void get( int index, kind &object);
25 kind* get_ref( int index);
26 void delete_first();
27
28 kind buffer[length];
29 int head;
30 int tail;
31 };
32
33
34 template<class kind, int length> RingBuffer<kind, length>::RingBuffer(){
35 this->head = this->tail = 0;
36 }
37
38 template<class kind, int length> int RingBuffer<kind, length>::capacity(){
39 return length-1;
40 }
41
42 template<class kind, int length> int RingBuffer<kind, length>::size(){
43 return((this->head>this->tail)?length:0)+this->tail-head;
44 }
45
46 template<class kind, int length> int RingBuffer<kind, length>::next_block_index(int index){
47 index++;
48 if (index == length) { index = 0; }
49 return(index);
50 }
51
52 template<class kind, int length> int RingBuffer<kind, length>::prev_block_index(int index){
53 if (index == 0) { index = length; }
54 index--;
55 return(index);
56 }
57
58 template<class kind, int length> void RingBuffer<kind, length>::push_back(kind object){
59 this->buffer[this->tail] = object;
60 this->tail = (tail+1)&(length-1);
61 }
62
63 template<class kind, int length> kind* RingBuffer<kind, length>::get_tail_ref(){
64 return &(buffer[tail]);
65 }
66
67 template<class kind, int length> void RingBuffer<kind, length>::get(int index, kind &object){
68 int j= 0;
69 int k= this->head;
70 while (k != this->tail){
71 if (j == index) break;
72 j++;
73 k= (k + 1) & (length - 1);
74 }
75 // TODO : this checks wether we are asked a value out of range
76 //if (k == this->tail){
77 // return NULL;
78 //}
79 object = this->buffer[k];
80 }
81
82
83 template<class kind, int length> kind* RingBuffer<kind, length>::get_ref(int index){
84 int j= 0;
85 int k= this->head;
86 while (k != this->tail){
87 if (j == index) break;
88 j++;
89 k= (k + 1) & (length - 1);
90 }
91 // TODO : this checks wether we are asked a value out of range
92 if (k == this->tail){
93 return NULL;
94 }
95 return &(this->buffer[k]);
96 }
97
98 template<class kind, int length> void RingBuffer<kind, length>::pop_front(kind &object){
99 object = this->buffer[this->head];
100 this->head = (this->head+1)&(length-1);
101 }
102
103 template<class kind, int length> void RingBuffer<kind, length>::delete_first(){
104 //kind dummy;
105 //this->pop_front(dummy);
106 this->head = (this->head+1)&(length-1);
107 }
108
109
110 #endif