#include <stdlib.h>
#include <string.h>
-void UDPC_Deque_init(UDPC_Deque *deque, uint32_t alloc_size)
+int UDPC_Deque_init(UDPC_Deque *deque, uint32_t alloc_size)
{
- deque->head = 0;
- deque->tail = 0;
- deque->size = 0;
+ UDPC_Deque_clear(deque);
deque->alloc_size = alloc_size;
deque->buf = malloc(alloc_size);
+ if(deque->buf)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void UDPC_Deque_destroy(UDPC_Deque *deque)
+{
+ free(deque->buf);
+ deque->buf = NULL;
+}
+
+int UDPC_Deque_realloc(UDPC_Deque *deque, uint32_t new_size)
+{
+ if(new_size < deque->size)
+ {
+ return 0;
+ }
+ else if(deque->size != 0 && deque->tail <= deque->head)
+ {
+ char *buf = malloc(new_size);
+ memcpy(buf, &deque->buf[deque->head], deque->alloc_size - deque->head);
+ if(deque->tail != 0)
+ {
+ memcpy(&buf[deque->alloc_size - deque->head], deque->buf, deque->tail);
+ }
+ free(deque->buf);
+ deque->buf = buf;
+ deque->alloc_size = new_size;
+ return 1;
+ }
+ else
+ {
+ void *buf = realloc(deque->buf, new_size);
+ if(buf)
+ {
+ deque->buf = buf;
+ deque->alloc_size = new_size;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
}
int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size)
return deque->alloc_size - deque->size;
}
+uint32_t UDPC_Deque_get_used(UDPC_Deque *deque)
+{
+ return deque->size;
+}
+
int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
{
*size = 0;
+ *data = NULL;
return 0;
}
else if(*size > deque->size)
if(deque->size == 0)
{
*size = 0;
+ *data = NULL;
return 0;
}
else if(*size > deque->size)
}
else if(deque->size <= size)
{
- deque->head = 0;
- deque->tail = 0;
- deque->size = 0;
+ UDPC_Deque_clear(deque);
return;
}
}
else if(deque->size <= size)
{
- deque->head = 0;
- deque->tail = 0;
- deque->size = 0;
+ UDPC_Deque_clear(deque);
return;
}
}
}
}
+
+int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out)
+{
+ uint32_t pos = unitSize * index;
+ uint32_t abspos;
+ if(pos >= deque->alloc_size)
+ {
+ *out = NULL;
+ return 0;
+ }
+
+ *out = malloc(unitSize);
+
+ if(pos + deque->head >= deque->alloc_size)
+ {
+ abspos = pos + deque->head - deque->alloc_size;
+ }
+ else
+ {
+ abspos = pos + deque->head;
+ }
+
+ if(abspos + unitSize >= deque->alloc_size)
+ {
+ memcpy(*out, &deque->buf[abspos], deque->alloc_size - abspos);
+ memcpy(*out, deque->buf, unitSize - (deque->alloc_size - abspos));
+ }
+ else
+ {
+ memcpy(*out, &deque->buf[abspos], unitSize);
+ }
+
+ return 1;
+}
+
+int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out)
+{
+ uint32_t pos = unitSize * (index + 1);
+ uint32_t abspos;
+ if(pos >= deque->alloc_size)
+ {
+ *out = NULL;
+ return 0;
+ }
+
+ *out = malloc(unitSize);
+
+ if(pos > deque->tail)
+ {
+ abspos = deque->alloc_size - (pos - deque->tail);
+ }
+ else
+ {
+ abspos = deque->tail - pos;
+ }
+
+ if(abspos + unitSize >= deque->alloc_size)
+ {
+ memcpy(*out, &deque->buf[abspos], deque->alloc_size - abspos);
+ memcpy(*out, deque->buf, unitSize - (deque->alloc_size - abspos));
+ }
+ else
+ {
+ memcpy(*out, &deque->buf[abspos], unitSize);
+ }
+
+ return 1;
+}
+
+void UDPC_Deque_clear(UDPC_Deque *deque)
+{
+ deque->head = 0;
+ deque->tail = 0;
+ deque->size = 0;
+}
char *buf;
} UDPC_Deque;
-void UDPC_Deque_init(UDPC_Deque *deque, uint32_t alloc_size);
+/*!
+ * \return non-zero on success
+ */
+int UDPC_Deque_init(UDPC_Deque *deque, uint32_t alloc_size);
+
+/*!
+ * Frees resources used by a UDPC_Deque
+ */
+void UDPC_Deque_destroy(UDPC_Deque *deque);
+
+/*!
+ * Fails if new_size is smaller than current size of Deque.
+ * On failure, deque remains unchanged.
+ * \return non-zero on success
+ */
+int UDPC_Deque_realloc(UDPC_Deque *deque, uint32_t new_size);
/*!
* If there was not enough space in the Deque, then no data is inserted at all.
*/
int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size);
+/*!
+ * \return size in bytes of available data
+ */
uint32_t UDPC_Deque_get_available(UDPC_Deque *deque);
+/*!
+ * \return size in bytes of used data
+ */
+uint32_t UDPC_Deque_get_used(UDPC_Deque *deque);
+
/*!
* \brief Get data from back of deque
* Data must be free'd after use as it was allocated with malloc.
*/
void UDPC_Deque_pop_front(UDPC_Deque *deque, uint32_t size);
+/*!
+ * \brief Get a unitSize sized chunk of data at position unitSize * index
+ * The data will be indexed relative to the head of the Deque.
+ * The out pointer will be malloc'd with size unitSize and will have a copy of
+ * the data at the specified unitSize * index.
+ * Note that the out data must be free'd, but nothing will be malloc'd on fail
+ * and *out will be set to NULL.
+ * \return non-zero if unitSize * index < allocated_size_of_Deque
+ */
+int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out);
+
+/*!
+ * \brief Get a unitSize sized chunk of data at position relative to tail
+ * The out pointer will be malloc'd with size unitSize and will have a copy of
+ * the data at the specified unitSize * (index + 1) relative to tail in reverse
+ * direction.
+ * Note that the out data must be free'd, but nothing will be malloc'd on fail
+ * and *out will be set to NULL.
+ * \return non-zero if unitSize * (index + 1) < allocated_size_of_Deque
+ */
+int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, char **out);
+
+void UDPC_Deque_clear(UDPC_Deque *deque);
+
#endif