Skip to content
This repository was archived by the owner on Aug 1, 2021. It is now read-only.

add circular buffer exercism #17

Merged
merged 1 commit into from
May 16, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions EXERCISES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ gigasecond
triangle
scrabble-score
roman-numerals
circular-buffer
binary
prime-factors
raindrops
Expand Down
103 changes: 103 additions & 0 deletions circular-buffer/circular-buffer_test.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
var circularBuffer = require('./circular-buffer').circularBuffer;
var bufferEmptyException = require('./circular-buffer').bufferEmptyException;
var bufferFullException = require('./circular-buffer').bufferFullException;

describe("CircularBuffer", function() {

it("reading an empty buffer throws a BufferEmptyException", function() {
var buffer = circularBuffer(1);
expect(buffer.read).toThrow(bufferEmptyException());
});

xit("write and read back one item", function() {
var buffer = circularBuffer(1);
buffer.write('1');
expect(buffer.read()).toBe('1');
expect(buffer.read).toThrow(bufferEmptyException());
});

xit("write and read back multiple items", function() {
var buffer = circularBuffer(2);
buffer.write('1');
buffer.write('2');
expect(buffer.read()).toBe('1');
expect(buffer.read()).toBe('2');
expect(buffer.read).toThrow(bufferEmptyException());
});

xit("clearing a buffer", function() {
var buffer = circularBuffer(2);
buffer.write('1');
buffer.write('2');
buffer.clear();
expect(buffer.read).toThrowError
buffer.write('3');
buffer.write('4');
expect(buffer.read()).toBe('3');
expect(buffer.read()).toBe('4');
});

xit("alternate write and read", function() {
var buffer = circularBuffer(2);
buffer.write('1');
expect(buffer.read()).toBe('1');
buffer.write('2');
expect(buffer.read()).toBe('2');
});

xit("reads back oldest item", function() {
var buffer = circularBuffer(3);
buffer.write('1');
buffer.write('2');
buffer.read();
buffer.write('3');
expect(buffer.read()).toBe('2');
expect(buffer.read()).toBe('3');
});

xit("writes of undefined or null don't occupy buffer", function() {
var buffer = circularBuffer(3);
buffer.write(null);
buffer.write(undefined);
[1,2,3].map(function(i) { buffer.write(i.toString()) })
expect(buffer.read()).toBe('1');
});

xit("writing to a full buffer throws a BufferFullException", function() {
var buffer = circularBuffer(2);
buffer.write('1');
buffer.write('2');
expect(function() {
buffer.write('A');
}).toThrow(bufferFullException());
});

xit("forced writes over write oldest item in a full buffer", function() {
var buffer = circularBuffer(2);
buffer.write('1');
buffer.write('2');
buffer.forceWrite('A');
expect(buffer.read()).toBe('2');
expect(buffer.read()).toBe('A');
expect(buffer.read).toThrow(bufferEmptyException());
});

xit("alternate force write and read into full buffer", function() {
var buffer = circularBuffer(5);
[1,2,3].map(function(i) { buffer.write(i.toString()) })
buffer.read();
buffer.read();
buffer.write('4');
buffer.read();
[5,6,7,8].map(function(i) { buffer.write(i.toString()) })
buffer.forceWrite('A');
buffer.forceWrite('B');
expect(buffer.read()).toBe('6');
expect(buffer.read()).toBe('7');
expect(buffer.read()).toBe('8');
expect(buffer.read()).toBe('A');
expect(buffer.read()).toBe('B');
expect(buffer.read).toThrow(bufferEmptyException());
});

});
99 changes: 99 additions & 0 deletions circular-buffer/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
function CircularBuffer(capacity) {

var readPoint = 0;
var writePoint = 0;
var buffer = new Array(capacity);

return {
read: function() {
if (isBufferEmpty()) { throw new BufferEmptyException(); }
var data = buffer[readPoint];
buffer[readPoint] = null;
updateReadPoint();
return data;
},

write: function(data) {
updateBuffer(data, function() {
if (isBufferFull()) { throw new BufferFullException(); }
buffer[writePoint] = data;
})
},

forceWrite: function(data) {
updateBuffer(data, function(){
buffer[writePoint] = data;
if (isBufferFull()) { updateReadPoint() }
})
},

clear: function() {
readPoint = 0;
writePoint = 0;
buffer = new Array(capacity);
},

isFull: function() {
return isBufferFull();
},

isEmpty: function() {
return isBufferEmpty();
}
};

function isBufferEmpty() {
return buffer.every(isEmpty);
};

function isBufferFull() {
return buffer.filter(isFull).length === capacity;
};

function updateBuffer(data, callback) {
if (isEmpty(data)) { return; }
callback();
updateWritePoint();
};

function updateWritePoint() {
writePoint = (writePoint + 1) % capacity;
};

function updateReadPoint() {
readPoint = (readPoint + 1) % capacity;
};

function isFull(data) {
return !isEmpty(data);
};

function isEmpty(data) {
return data === null || data === undefined;
};

};

function BufferEmptyException() {
this.name = "BufferEmptyException";
this.message = "Buffer is empty.";
};

function BufferFullException() {
this.name = "BufferFullException";
this.message = "Buffer is full.";
};

module.exports = {
circularBuffer: function(capacity) {
return new CircularBuffer(capacity);
},

bufferEmptyException: function() {
return new BufferEmptyException();
},

bufferFullException: function() {
return new BufferFullException();
}
};