You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

314 lines
7.7 KiB
C

6 years ago
/*
* QueueArray.h
*
* Library implementing a generic, dynamic queue (array version).
*
* ---
*
* Copyright (C) 2010 Efstathios Chatzikyriakidis (contact@efxa.org)
*
* This program 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.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ---
*
* Version 1.0
*
* 2014-02-03 Brian Fletcher <brian.jf.fletcher@gmail.com>
*
* - added enqueue(), dequeue() and front().
*
* 2010-09-29 Efstathios Chatzikyriakidis <contact@efxa.org>
*
* - added resize(): for growing, shrinking the array size.
*
* 2010-09-25 Efstathios Chatzikyriakidis <contact@efxa.org>
*
* - added exit(), blink(): error reporting and handling methods.
*
* 2010-09-24 Alexander Brevig <alexanderbrevig@gmail.com>
*
* - added setPrinter(): indirectly reference a Serial object.
*
* 2010-09-20 Efstathios Chatzikyriakidis <contact@efxa.org>
*
* - initial release of the library.
*
* ---
*
* For the latest version see: http://www.arduino.cc/
*/
// header defining the interface of the source.
#ifndef _QUEUEARRAY_H
#define _QUEUEARRAY_H
#include <Arduino.h>
// the definition of the queue class.
template<typename T>
class QueueArray {
public:
// init the queue (constructor).
QueueArray ();
// clear the queue (destructor).
~QueueArray ();
// add an item to the queue.
void enqueue (const T i);
// remove an item from the queue.
T dequeue ();
// push an item to the queue.
void push (const T i);
// pop an item from the queue.
T pop ();
// get the front of the queue.
T front () const;
// get an item from the queue.
T peek () const;
// check if the queue is empty.
bool isEmpty () const;
// get the number of items in the queue.
int count () const;
// check if the queue is full.
bool isFull () const;
// set the printer of the queue.
void setPrinter (Print & p);
private:
// resize the size of the queue.
void resize (const int s);
// exit report method in case of error.
void exit (const char * m) const;
// led blinking method in case of error.
void blink () const;
// the initial size of the queue.
static const int initialSize = 2;
// the pin number of the on-board led.
static const int ledPin = 13;
Print * printer; // the printer of the queue.
T * contents; // the array of the queue.
int size; // the size of the queue.
int items; // the number of items of the queue.
int head; // the head of the queue.
int tail; // the tail of the queue.
};
// init the queue (constructor).
template<typename T>
QueueArray<T>::QueueArray () {
size = 0; // set the size of queue to zero.
items = 0; // set the number of items of queue to zero.
head = 0; // set the head of the queue to zero.
tail = 0; // set the tail of the queue to zero.
printer = NULL; // set the printer of queue to point nowhere.
// allocate enough memory for the array.
contents = (T *) malloc (sizeof (T) * initialSize);
// if there is a memory allocation error.
if (contents == NULL)
exit ("QUEUE: insufficient memory to initialize queue.");
// set the initial size of the queue.
size = initialSize;
}
// clear the queue (destructor).
template<typename T>
QueueArray<T>::~QueueArray () {
free (contents); // deallocate the array of the queue.
contents = NULL; // set queue's array pointer to nowhere.
printer = NULL; // set the printer of queue to point nowhere.
size = 0; // set the size of queue to zero.
items = 0; // set the number of items of queue to zero.
head = 0; // set the head of the queue to zero.
tail = 0; // set the tail of the queue to zero.
}
// resize the size of the queue.
template<typename T>
void QueueArray<T>::resize (const int s) {
// defensive issue.
if (s <= 0)
exit ("QUEUE: error due to undesirable size for queue size.");
// allocate enough memory for the temporary array.
T * temp = (T *) malloc (sizeof (T) * s);
// if there is a memory allocation error.
if (temp == NULL)
exit ("QUEUE: insufficient memory to initialize temporary queue.");
// copy the items from the old queue to the new one.
for (int i = 0; i < items; i++)
temp[i] = contents[(head + i) % size];
// deallocate the old array of the queue.
free (contents);
// copy the pointer of the new queue.
contents = temp;
// set the head and tail of the new queue.
head = 0; tail = items;
// set the new size of the queue.
size = s;
}
// add an item to the queue.
template<typename T>
void QueueArray<T>::enqueue (const T i) {
// check if the queue is full.
if (isFull ())
// double size of array.
resize (size * 2);
// store the item to the array.
contents[tail++] = i;
// wrap-around index.
if (tail == size) tail = 0;
// increase the items.
items++;
}
// push an item to the queue.
template<typename T>
void QueueArray<T>::push (const T i) {
enqueue(i);
}
// remove an item from the queue.
template<typename T>
T QueueArray<T>::dequeue () {
// check if the queue is empty.
if (isEmpty ())
exit ("QUEUE: can't pop item from queue: queue is empty.");
// fetch the item from the array.
T item = contents[head++];
// decrease the items.
items--;
// wrap-around index.
if (head == size) head = 0;
// shrink size of array if necessary.
if (!isEmpty () && (items <= size / 4))
resize (size / 2);
// return the item from the array.
return item;
}
// pop an item from the queue.
template<typename T>
T QueueArray<T>::pop () {
return dequeue();
}
// get the front of the queue.
template<typename T>
T QueueArray<T>::front () const {
// check if the queue is empty.
if (isEmpty ())
exit ("QUEUE: can't get the front item of queue: queue is empty.");
// get the item from the array.
return contents[head];
}
// get an item from the queue.
template<typename T>
T QueueArray<T>::peek () const {
return front();
}
// check if the queue is empty.
template<typename T>
bool QueueArray<T>::isEmpty () const {
return items == 0;
}
// check if the queue is full.
template<typename T>
bool QueueArray<T>::isFull () const {
return items == size;
}
// get the number of items in the queue.
template<typename T>
int QueueArray<T>::count () const {
return items;
}
// set the printer of the queue.
template<typename T>
void QueueArray<T>::setPrinter (Print & p) {
printer = &p;
}
// exit report method in case of error.
template<typename T>
void QueueArray<T>::exit (const char * m) const {
// print the message if there is a printer.
if (printer)
printer->println (m);
// loop blinking until hardware reset.
blink ();
}
// led blinking method in case of error.
template<typename T>
void QueueArray<T>::blink () const {
// set led pin as output.
pinMode (ledPin, OUTPUT);
// continue looping until hardware reset.
while (true) {
digitalWrite (ledPin, HIGH); // sets the LED on.
delay (250); // pauses 1/4 of second.
digitalWrite (ledPin, LOW); // sets the LED off.
delay (250); // pauses 1/4 of second.
}
// solution selected due to lack of exit() and assert().
}
#endif // _QUEUEARRAY_H