118d3e65eSAxel Dörfler/*
2bc4dd456SAxel Dörfler * Copyright 2008-2013, Axel D��rfler, axeld@pinc-software.de.
318d3e65eSAxel Dörfler * Distributed under the terms of the MIT License.
418d3e65eSAxel Dörfler */
518d3e65eSAxel Dörfler#ifndef CIRCULAR_BUFFER_H
618d3e65eSAxel Dörfler#define CIRCULAR_BUFFER_H
718d3e65eSAxel Dörfler
818d3e65eSAxel Dörfler
918d3e65eSAxel Dörfler#include <stdlib.h>
1018d3e65eSAxel Dörfler
1118d3e65eSAxel Dörfler#include <OS.h>
1218d3e65eSAxel Dörfler
1318d3e65eSAxel Dörfler
1418d3e65eSAxel Dörflertemplate<typename Type>
1518d3e65eSAxel Dörflerclass CircularBuffer {
1618d3e65eSAxel Dörflerpublic:
1718d3e65eSAxel Dörfler	CircularBuffer(size_t size)
1818d3e65eSAxel Dörfler		:
19bc4dd456SAxel Dörfler		fSize(0),
20bc4dd456SAxel Dörfler		fBuffer(NULL)
2118d3e65eSAxel Dörfler	{
228e26f387SAxel Dörfler		SetSize(size);
2318d3e65eSAxel Dörfler	}
2418d3e65eSAxel Dörfler
2518d3e65eSAxel Dörfler	~CircularBuffer()
2618d3e65eSAxel Dörfler	{
2718d3e65eSAxel Dörfler		free(fBuffer);
2818d3e65eSAxel Dörfler	}
2918d3e65eSAxel Dörfler
3018d3e65eSAxel Dörfler	status_t InitCheck() const
3118d3e65eSAxel Dörfler	{
3218d3e65eSAxel Dörfler		return fBuffer != NULL ? B_OK : B_NO_MEMORY;
3318d3e65eSAxel Dörfler	}
3418d3e65eSAxel Dörfler
358e26f387SAxel Dörfler	status_t SetSize(size_t size)
368e26f387SAxel Dörfler	{
378e26f387SAxel Dörfler		MakeEmpty();
388e26f387SAxel Dörfler
398e26f387SAxel Dörfler		if (fSize == size)
408e26f387SAxel Dörfler			return B_OK;
418e26f387SAxel Dörfler
428e26f387SAxel Dörfler		fSize = size;
438e26f387SAxel Dörfler		fBuffer = (Type*)malloc(fSize * sizeof(Type));
442c604c0dSAxel Dörfler		if (fBuffer == NULL) {
452c604c0dSAxel Dörfler			fSize = 0;
462c604c0dSAxel Dörfler			return B_NO_MEMORY;
472c604c0dSAxel Dörfler		}
482c604c0dSAxel Dörfler
492c604c0dSAxel Dörfler		return B_OK;
508e26f387SAxel Dörfler	}
518e26f387SAxel Dörfler
5218d3e65eSAxel Dörfler	void MakeEmpty()
5318d3e65eSAxel Dörfler	{
5418d3e65eSAxel Dörfler		fIn = 0;
5518d3e65eSAxel Dörfler		fFirst = 0;
5618d3e65eSAxel Dörfler	}
5718d3e65eSAxel Dörfler
5818d3e65eSAxel Dörfler	bool IsEmpty() const
5918d3e65eSAxel Dörfler	{
6018d3e65eSAxel Dörfler		return fIn == 0;
6118d3e65eSAxel Dörfler	}
6218d3e65eSAxel Dörfler
6318d3e65eSAxel Dörfler	int32 CountItems() const
6418d3e65eSAxel Dörfler	{
6518d3e65eSAxel Dörfler		return fIn;
6618d3e65eSAxel Dörfler	}
6718d3e65eSAxel Dörfler
6818d3e65eSAxel Dörfler	Type* ItemAt(int32 index) const
6918d3e65eSAxel Dörfler	{
702c604c0dSAxel Dörfler		if (index >= (int32)fIn || index < 0 || fBuffer == NULL)
7118d3e65eSAxel Dörfler			return NULL;
7218d3e65eSAxel Dörfler
7318d3e65eSAxel Dörfler		return &fBuffer[(fFirst + index) % fSize];
7418d3e65eSAxel Dörfler	}
7518d3e65eSAxel Dörfler
7618d3e65eSAxel Dörfler	void AddItem(const Type& item)
7718d3e65eSAxel Dörfler	{
7818d3e65eSAxel Dörfler		uint32 index;
7918d3e65eSAxel Dörfler		if (fIn < fSize)
8018d3e65eSAxel Dörfler			index = fFirst + fIn++;
8118d3e65eSAxel Dörfler		else
8218d3e65eSAxel Dörfler			index = fFirst++;
8318d3e65eSAxel Dörfler
842c604c0dSAxel Dörfler		if (fBuffer != NULL)
852c604c0dSAxel Dörfler			fBuffer[index % fSize] = item;
8618d3e65eSAxel Dörfler	}
8718d3e65eSAxel Dörfler
888e26f387SAxel Dörfler	size_t Size() const
898e26f387SAxel Dörfler	{
908e26f387SAxel Dörfler		return fSize;
918e26f387SAxel Dörfler	}
928e26f387SAxel Dörfler
9318d3e65eSAxel Dörflerprivate:
9418d3e65eSAxel Dörfler	uint32		fFirst;
9518d3e65eSAxel Dörfler	uint32		fIn;
9618d3e65eSAxel Dörfler	uint32		fSize;
9718d3e65eSAxel Dörfler	Type*		fBuffer;
9818d3e65eSAxel Dörfler};
9918d3e65eSAxel Dörfler
100bc4dd456SAxel Dörfler
10118d3e65eSAxel Dörfler#endif	// CIRCULAR_BUFFER_H
102