Skip to content

Commit f4b1c71

Browse files
authored
Merge pull request #7 from vinitjames/feature/buildinggtest
Feature/buildinggtest
2 parents db27aaf + 08f4c15 commit f4b1c71

File tree

9 files changed

+308
-39
lines changed

9 files changed

+308
-39
lines changed

CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
1111
add_library(${PROJECT_NAME} INTERFACE)
1212

1313
target_include_directories(${PROJECT_NAME} INTERFACE ${${PROJECT_NAME}_SOURCE_DIR})
14-
14+
enable_testing()
15+
add_subdirectory(samples)
1516
add_subdirectory(tests)
1617

17-
add_subdirectory(samples)
18+
19+
install(TARGETS circularbuffer DESTINATION lib)

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2020 Vinit James
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

circular_buffer.h

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <memory>
77
#include <iterator>
88
#include <type_traits>
9+
#include <algorithm>
910

1011
template<typename T>
1112
class CircularBuffer {
@@ -28,6 +29,24 @@ class CircularBuffer {
2829
explicit CircularBuffer(size_t size)
2930
:_buff{std::unique_ptr<T[]>(new T[size])}, _max_size{size}{}
3031

32+
CircularBuffer(const CircularBuffer& other)
33+
:_buff{std::unique_ptr<T[]>(new T[other.capacity()])},
34+
_max_size{other.capacity()},
35+
_size{other._size},
36+
_head{other._head},
37+
_tail{other._tail},
38+
_full{other._full}{
39+
40+
std::copy(other.data(), other.data() + _max_size, _buff.get());
41+
}
42+
43+
CircularBuffer& operator=(const CircularBuffer& other){
44+
_buff = std::unique_ptr<T[]>(new T[other.capacity()]);
45+
_max_size = other.capacity();
46+
std::copy(other.data(), other.data() + _max_size, _buff.get());
47+
return *this;
48+
}
49+
3150
void push_back(const value_type& data);
3251
void pop_front();
3352
reference front();
@@ -40,8 +59,12 @@ class CircularBuffer {
4059
size_type capacity() const ;
4160
size_type size() const;
4261
size_type buffer_size() const {return sizeof(T)*_max_size;};
62+
const_pointer data() const { return _buff.get(); }
63+
4364
const_reference operator[](size_type index) const;
4465
reference operator[](size_type index);
66+
const_reference at(size_type index) const;
67+
reference at(size_type index);
4568

4669
iterator begin();
4770
const_iterator begin() const;
@@ -53,6 +76,7 @@ class CircularBuffer {
5376
void _decrement_bufferstate();
5477
mutable std::mutex _mtx;
5578
std::unique_ptr<T[]> _buff;
79+
5680
size_type _head = 0;
5781
size_type _tail = 0;
5882
size_type _size = 0;
@@ -234,7 +258,8 @@ typename CircularBuffer<T>::reference CircularBuffer<T>::back() {
234258
std::lock_guard<std::mutex> _lck(_mtx);
235259
if(empty())
236260
throw std::length_error("back function called on empty buffer");
237-
return _buff[_head-1];
261+
//return _buff[_head - 1];
262+
return _head == 0 ? _buff[_max_size - 1] : _buff[_head - 1];
238263
}
239264

240265
template<typename T>
@@ -252,14 +277,15 @@ typename CircularBuffer<T>::const_reference CircularBuffer<T>::back() const{
252277
std::lock_guard<std::mutex> _lck(_mtx);
253278
if(empty())
254279
throw std::length_error("back function called on empty buffer");
255-
return _buff[_head - 1];
280+
//return _buff[_head - 1];
281+
return _head == 0 ? _buff[_max_size - 1] : _buff[_head - 1];
256282
}
257283

258284
template<typename T>
259285
void CircularBuffer<T>::push_back(const T& data){
260286
std::lock_guard<std::mutex> _lck(_mtx);
261-
if(full())
262-
_buff[_head].~T();
287+
//if(full())
288+
// _buff[_tail].~T();
263289
_buff[_head] = data;
264290
_increment_bufferstate();
265291
}
@@ -271,32 +297,31 @@ void CircularBuffer<T>::_increment_bufferstate(){
271297
_tail = (_tail + 1)%_max_size;
272298
else
273299
++_size;
274-
_head = (_head + 1)%_max_size;
275-
_full = (_head == _tail);
300+
_head = (_head + 1)%_max_size;
276301
}
277302

278303
template<typename T>
279304
inline
280305
void CircularBuffer<T>::pop_front(){
281306
std::lock_guard<std::mutex> _lck(_mtx);
282307
if(empty())
283-
throw std::length_error("pop_back called on empty buffer");
308+
throw std::length_error("pop_front called on empty buffer");
284309
_decrement_bufferstate();
285310
}
286311

287312
template<typename T>
288313
inline
289314
void CircularBuffer<T>::_decrement_bufferstate(){
290-
//_full = false;
291315
--_size;
292316
_tail = (_tail + 1)%_max_size;
293317
}
294318

295319
template<typename T>
296320
inline
297321
typename CircularBuffer<T>::reference CircularBuffer<T>::operator[](size_t index) {
298-
if((index<0)||(index>_max_size))
299-
throw std::out_of_range("Index is out of Range of buffer size");
322+
std::lock_guard<std::mutex> _lck(_mtx);
323+
if((index<0)||(index>=_max_size))
324+
throw std::out_of_range("Index is out of Range of buffer capacity");
300325
index += _tail;
301326
index %= _max_size;
302327
return _buff[index];
@@ -305,7 +330,30 @@ typename CircularBuffer<T>::reference CircularBuffer<T>::operator[](size_t index
305330
template<typename T>
306331
inline
307332
typename CircularBuffer<T>::const_reference CircularBuffer<T>::operator[](size_t index) const {
308-
if((index<0)||(index>_max_size))
333+
std::lock_guard<std::mutex> _lck(_mtx);
334+
if((index<0)||(index>=_max_size))
335+
throw std::out_of_range("Index is out of Range of buffer capacity");
336+
index += _tail;
337+
index %= _max_size;
338+
return _buff[index];
339+
}
340+
341+
template<typename T>
342+
inline
343+
typename CircularBuffer<T>::reference CircularBuffer<T>::at(size_t index) {
344+
std::lock_guard<std::mutex> _lck(_mtx);
345+
if((index<0)||(index>=_size))
346+
throw std::out_of_range("Index is out of Range of buffer size");
347+
index += _tail;
348+
index %= _max_size;
349+
return _buff[index];
350+
}
351+
352+
template<typename T>
353+
inline
354+
typename CircularBuffer<T>::const_reference CircularBuffer<T>::at(size_t index) const {
355+
std::lock_guard<std::mutex> _lck(_mtx);
356+
if((index<0)||(index>=_size))
309357
throw std::out_of_range("Index is out of Range of buffer size");
310358
index += _tail;
311359
index %= _max_size;

samples/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ target_link_libraries(sample_circularbuffer
66
PRIVATE
77
circularbuffer
88
)
9+
10+
add_executable(sample_stringbuffer sample_stringbuffer.cpp)
11+
target_link_libraries(sample_stringbuffer
12+
PRIVATE
13+
circularbuffer
14+
)

samples/sample_circularbuffer.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include "circular_buffer.h"
22
#include <iostream>
33
#include <string.h>
4-
#include "gtest/gtest.h"
5-
64
#include "circular_buffer.h"
75
#include <iostream>
86
#include <string.h>
@@ -13,7 +11,8 @@ struct test_struct{
1311
test_struct(){
1412
bytes = (char*)malloc(100);
1513
std::cout<<"constructing test_struct: "<<count++<<"\n";
16-
}
14+
}
15+
1716
test_struct(const test_struct& other){
1817
bytes = (char*)malloc(100);
1918
memcpy(bytes, other.bytes,100);
@@ -28,9 +27,12 @@ struct test_struct{
2827
}
2928

3029
~test_struct(){
31-
std::cout<<"destructing test_struct"<<--count<<"\n";
3230
free(bytes);
3331
}
32+
33+
friend std::ostream& operator<<(std::ostream& os, const test_struct& ts){
34+
return os<<"\ntest";
35+
}
3436

3537

3638
};
@@ -90,14 +92,34 @@ int main(int argc, char *argv[])
9092
std::cout<<"Checking deference ++ operator "<<*(++it)<<"\n";
9193
std::cout<<"Checking deference -- operator "<<*(--it)<<"\n";
9294

95+
96+
std::cout<<"Checking iterator for loop \n";
97+
for(auto it:test_stringbuf)
98+
std::cout<<"Checking for loop function "<<it<<"\n";
99+
100+
std::cout<<"Checking for loop with iterator \n";
101+
for(auto it = test_stringbuf.begin(); it != test_stringbuf.end(); it++)
102+
std::cout<<"Checking for loop function "<<*it<<"\n";
103+
93104
CircularBuffer<test_struct> test_structbuf{5};
105+
std::cout<<"Checking [] operator"<<test_structbuf[0]<<"\n";
106+
94107
auto temp_struct = test_struct();
108+
95109
test_structbuf.push_back(temp_struct);
110+
std::cout<<"Checking [] operator"<<test_structbuf[1]<<"\n";
111+
std::cout<<"Checking at operator"<<test_structbuf.at(0)<<"\n";
112+
96113
test_structbuf.push_back(temp_struct);
114+
std::cout<<"Checking at operator"<<test_structbuf.at(1)<<"\n";
97115
test_structbuf.push_back(temp_struct);
116+
std::cout<<"Checking at operator"<<test_structbuf.at(2)<<"\n";
98117
test_structbuf.push_back(temp_struct);
118+
std::cout<<"Checking at operator"<<test_structbuf.at(3)<<"\n";
99119
test_structbuf.push_back(temp_struct);
120+
std::cout<<"Checking at operator"<<test_structbuf.at(4)<<"\n";
100121
test_structbuf.push_back(temp_struct);
122+
std::cout<<"Checking at operator"<<test_structbuf.at(0)<<"\n";
101123
test_structbuf.push_back(temp_struct);
102124
test_structbuf.push_back(temp_struct);
103125
test_structbuf.push_back(temp_struct);
@@ -106,8 +128,14 @@ int main(int argc, char *argv[])
106128

107129
test_structbuf.pop_front();
108130

109-
131+
CircularBuffer<std::string> test_stringbufcopy{test_stringbuf};
132+
std::cout<<"Checking maxsize of copy buffer"<<test_stringbufcopy.capacity()<<"\n";
133+
std::cout<<"Checking size of copy buffer"<<test_stringbufcopy.size()<<"\n";
134+
std::cout<<"Checking [] in copybuffer"<<test_stringbufcopy[1]<<"\n";
135+
std::cout<<"Checking maxsize buffer"<<test_stringbuf.capacity()<<"\n";
136+
std::cout<<"Checking size buffer"<<test_stringbuf.size()<<"\n";
110137
return 0;
111138
}
112139

113140

141+

samples/sample_stringbuffer.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#include "circular_buffer.h"
2+
#include <iostream>
3+
#include <string.h>
4+
#include "circular_buffer.h"
5+
#include <iostream>
6+
#include <string.h>
7+
8+
int main(int argc, char *argv[])
9+
{
10+
11+
CircularBuffer<int> test{5};
12+
//std::cout<<"size of data "<<sizeof(data[1].bytes)<<"\n";
13+
std::cout<<"length of buffer "<<test.size()<<"\n";
14+
std::cout<<"size of buffer in bytes "<<test.buffer_size()<<"\n";
15+
std::cout<<"Max capacity of buffer "<<test.capacity()<<"\n";
16+
std::cout<<"Checking is buffer empty function "<<test.empty()<<"\n";
17+
std::cout<<"Pushing back data in bufffer \n";
18+
for(int i = 0; i<100;i++){
19+
test.push_back(i);
20+
std::cout<<"Pushing back i"<<std::endl;
21+
}
22+
23+
CircularBuffer<std::string> test_stringbuf{10};
24+
std::cout<<"Checking is buffer empty function "<<test_stringbuf.empty()<<"\n";
25+
std::cout<<"Checking length of string buffer "<<test_stringbuf.size()<<"\n";
26+
std::cout<<"size of buffer in bytes "<<test_stringbuf.buffer_size()<<"\n";
27+
std::cout<<"Max capacity of buffer "<<test_stringbuf.capacity()<<"\n";
28+
29+
for(int i = 0; i<10;i++){
30+
test_stringbuf.push_back("this is a string" + std::to_string(i));
31+
std::cout<<"Pushing back string "<<i<<std::endl;
32+
}
33+
34+
std::cout<<"Checking is buffer empty function "<<test_stringbuf.empty()<<"\n";
35+
std::cout<<"Checking length of buffer after modification "<<test_stringbuf.size()<<"\n";
36+
std::cout<<"Checking front function "<<test_stringbuf.front()<<"\n";
37+
std::cout<<"Checking back function "<<test_stringbuf.back()<<"\n";
38+
39+
for(int i = 0; i<7;i++){
40+
test_stringbuf.pop_front();
41+
std::cout<<"Poping "<<i<<std::endl;
42+
}
43+
44+
std::cout<<"Checking is buffer empty function "<<test_stringbuf.empty()<<"\n";
45+
std::cout<<"Checking length of buffer after modification "<<test_stringbuf.size()<<"\n";
46+
std::cout<<"Checking front function "<<test_stringbuf.front()<<"\n";
47+
std::cout<<"Checking back function "<<test_stringbuf.back()<<"\n";
48+
/*
49+
//test_stringbuf.pop_front();
50+
std::cout<<"Checking length of buffer after modification "<<test_stringbuf.size()<<"\n";
51+
std::cout<<"Checking front function "<<test_stringbuf.front()<<"\n";
52+
std::cout<<"Checking back function "<<test_stringbuf.back()<<"\n";
53+
54+
/*
55+
std::cout<<"Checking iterator function\n";
56+
auto it = test_stringbuf.begin();
57+
58+
std::cout<<"Checking deference * operator "<<*it<<"\n";
59+
std::cout<<"Checking deference ++ operator "<<*(++it)<<"\n";
60+
std::cout<<"Checking deference -- operator "<<*(--it)<<"\n";
61+
62+
63+
std::cout<<"Checking iterator for loop \n";
64+
for(auto it:test_stringbuf)
65+
std::cout<<"Checking for loop function "<<it<<"\n";
66+
67+
std::cout<<"Checking for loop with iterator \n";
68+
for(auto it = test_stringbuf.begin(); it != test_stringbuf.end(); it++)
69+
std::cout<<"Checking for loop function "<<*it<<"\n";
70+
71+
CircularBuffer<test_struct> test_structbuf{5};
72+
std::cout<<"Checking [] operator"<<test_structbuf[0]<<"\n";
73+
74+
auto temp_struct = test_struct();
75+
76+
test_structbuf.push_back(temp_struct);
77+
std::cout<<"Checking [] operator"<<test_structbuf[1]<<"\n";
78+
std::cout<<"Checking at operator"<<test_structbuf.at(0)<<"\n";
79+
80+
test_structbuf.push_back(temp_struct);
81+
std::cout<<"Checking at operator"<<test_structbuf.at(1)<<"\n";
82+
test_structbuf.push_back(temp_struct);
83+
std::cout<<"Checking at operator"<<test_structbuf.at(2)<<"\n";
84+
test_structbuf.push_back(temp_struct);
85+
std::cout<<"Checking at operator"<<test_structbuf.at(3)<<"\n";
86+
test_structbuf.push_back(temp_struct);
87+
std::cout<<"Checking at operator"<<test_structbuf.at(4)<<"\n";
88+
test_structbuf.push_back(temp_struct);
89+
std::cout<<"Checking at operator"<<test_structbuf.at(0)<<"\n";
90+
test_structbuf.push_back(temp_struct);
91+
test_structbuf.push_back(temp_struct);
92+
test_structbuf.push_back(temp_struct);
93+
test_structbuf.push_back(temp_struct);
94+
95+
96+
test_structbuf.pop_front();
97+
98+
CircularBuffer<std::string> test_stringbufcopy{test_stringbuf};
99+
std::cout<<"Checking maxsize of copy buffer"<<test_stringbufcopy.capacity()<<"\n";
100+
std::cout<<"Checking size of copy buffer"<<test_stringbufcopy.size()<<"\n";
101+
std::cout<<"Checking [] in copybuffer"<<test_stringbufcopy[1]<<"\n";
102+
std::cout<<"Checking maxsize buffer"<<test_stringbuf.capacity()<<"\n";
103+
std::cout<<"Checking size buffer"<<test_stringbuf.size()<<"\n";
104+
*/
105+
std::cout<<"end is reached"<<std::endl;
106+
return 0;
107+
}

0 commit comments

Comments
 (0)