From 0a74051300097be0bbb69f0a6712a07160f200ee Mon Sep 17 00:00:00 2001 From: Dmitri Pal Date: Wed, 1 Jul 2009 18:22:19 -0400 Subject: Queue and stack APIs using collection. Patch adds two interfaces for stack and queue using collection as underlaying implementation. It also fixes a bug in the insterion code - the unsigned properties were created as long. --- collection/Makefile.am | 10 +- collection/collection_cnv.c | 2 +- collection/collection_queue.c | 350 +++++++++++++++++++++++++++++++++++++++ collection/collection_queue.h | 81 +++++++++ collection/collection_queue_ut.c | 101 +++++++++++ collection/collection_stack.c | 350 +++++++++++++++++++++++++++++++++++++++ collection/collection_stack.h | 81 +++++++++ collection/collection_stack_ut.c | 108 ++++++++++++ 8 files changed, 1081 insertions(+), 2 deletions(-) create mode 100644 collection/collection_queue.c create mode 100644 collection/collection_queue.h create mode 100644 collection/collection_queue_ut.c create mode 100644 collection/collection_stack.c create mode 100644 collection/collection_stack.h create mode 100644 collection/collection_stack_ut.c (limited to 'collection') diff --git a/collection/Makefile.am b/collection/Makefile.am index 8df9fc6..fe07490 100644 --- a/collection/Makefile.am +++ b/collection/Makefile.am @@ -15,12 +15,20 @@ libcollection_la_SOURCES = \ collection.c \ collection_tools.c \ collection_cnv.c \ + collection_queue.c \ + collection_stack.c \ collection.h \ collection_tools.h \ collection_priv.h \ + collection_queue.h \ + collection_stack.h \ ../trace/trace.h # Build unit test -noinst_PROGRAMS = collection_ut +noinst_PROGRAMS = collection_ut collection_stack_ut collection_queue_ut collection_ut_SOURCES = collection_ut.c collection_ut_LDADD = libcollection.la +collection_stack_ut_SOURCES = collection_stack_ut.c +collection_stack_ut_LDADD = libcollection.la +collection_queue_ut_SOURCES = collection_queue_ut.c +collection_queue_ut_LDADD = libcollection.la diff --git a/collection/collection_cnv.c b/collection/collection_cnv.c index ca9c483..1ead75f 100644 --- a/collection/collection_cnv.c +++ b/collection/collection_cnv.c @@ -151,7 +151,7 @@ int insert_unsigned_property(struct collection_item *ci, index, flags, property, - COL_TYPE_LONG, + COL_TYPE_UNSIGNED, (void *)&number, sizeof(unsigned), NULL); diff --git a/collection/collection_queue.c b/collection/collection_queue.c new file mode 100644 index 0000000..0d5c0ac --- /dev/null +++ b/collection/collection_queue.c @@ -0,0 +1,350 @@ +/* + QUEUE + + Implementation of the queue on top of collection library interface. + + Copyright (C) Dmitri Pal 2009 + + Collection Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Collection Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Collection Library. If not, see . +*/ + +#include "stdlib.h" +#include "errno.h" +#include "collection_queue.h" +#include "trace.h" + +/* Function that creates a queue object */ +int create_queue(struct collection_item **queue) +{ + int error = EOK; + + TRACE_FLOW_STRING("create_queue", "Entry point."); + + error = create_collection(queue, COL_NAME_QUEUE, COL_CLASS_QUEUE); + + TRACE_FLOW_STRING("create_queue", "Exit."); + return error; +} + +/* Function that destroys a queue object */ +void destroy_queue(struct collection_item *queue) +{ + TRACE_FLOW_STRING("destroy_queue", "Entry point."); + + destroy_collection(queue); + + TRACE_FLOW_STRING("destroy_queue", "Exit"); +} + + +/* Put a string property into a queue. */ +int enqueue_str_property(struct collection_item *queue, + const char *property, char *string, int length) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_str_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_str_property(queue, NULL, property, string, length); + + TRACE_FLOW_STRING("enqueue_str_property", "Exit."); + return error; +} + +/* Put a binary property into a queue. */ +int enqueue_binary_property(struct collection_item *queue, + const char *property, void *binary_data, int length) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_binary_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_binary_property(queue, NULL, property, binary_data, length); + + TRACE_FLOW_STRING("enqueue_binary_property", "Exit."); + return error; +} + + +/* Put an int property into a queue. */ +int enqueue_int_property(struct collection_item *queue, + const char *property, int number) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_int_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_int_property(queue, NULL, property, number); + + TRACE_FLOW_STRING("enqueue_int_property", "Exit."); + return error; +} + +/* Put an unsigned int property into a queue. */ +int enqueue_unsigned_property(struct collection_item *queue, + const char *property, unsigned int number) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_unsigned_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_unsigned_property(queue, NULL, property, number); + + TRACE_FLOW_STRING("enqueue_unsigned_property", "Exit."); + return error; +} + + +/* Put a long property. */ +int enqueue_long_property(struct collection_item *queue, + const char *property, long number) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_long_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_long_property(queue, NULL, property, number); + + TRACE_FLOW_STRING("enqueue_long_property", "Exit."); + return error; +} + +/* Put an unsigned long property. */ +int enqueue_ulong_property(struct collection_item *queue, + const char *property, unsigned long number) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_ulong_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_ulong_property(queue, NULL, property, number); + + TRACE_FLOW_STRING("enqueue_ulong_property", "Exit."); + return error; +} + +/* Put a double property. */ +int enqueue_double_property(struct collection_item *queue, + const char *property, double number) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_double_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_double_property(queue, NULL, property, number); + + TRACE_FLOW_STRING("enqueue_double_property", "Exit."); + return error; +} + +/* Put a bool property. */ +int enqueue_bool_property(struct collection_item *queue, + const char *property, unsigned char logical) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_bool_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_bool_property(queue, NULL, property, logical); + + TRACE_FLOW_STRING("enqueue_bool_property", "Exit."); + return error; +} + +/* Put any property */ +int enqueue_any_property(struct collection_item *queue, + const char *property, + int type, + void *data, + int length) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_any_property", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_any_property(queue, NULL, property, type, data, length); + + TRACE_FLOW_STRING("enqueue_any_property", "Exit."); + return error; +} + +/* Enqueue item */ +int enqueue_item(struct collection_item *queue, + struct collection_item *item) +{ + int error = EOK; + + TRACE_FLOW_STRING("enqueue_item", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = insert_item_into_current(queue, + item, + COL_DSP_END, + NULL, + 0, + COL_INSERT_NOCHECK); + + TRACE_FLOW_STRING("enqueue_item", "Exit."); + return error; +} + +/* Dequeue item */ +int dequeue_item(struct collection_item *queue, + struct collection_item **item) +{ + int error = EOK; + + TRACE_FLOW_STRING("dequeue_item", "Entry point."); + + /* Check that queue is not empty */ + if (queue == NULL) { + TRACE_ERROR_STRING("queue can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a queue */ + if (!is_of_class(queue, COL_CLASS_QUEUE)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = extract_item_from_current(queue, + COL_DSP_FRONT, + NULL, + 0, + 0, + item); + + TRACE_FLOW_STRING("dequeue_item", "Exit."); + return error; +} diff --git a/collection/collection_queue.h b/collection/collection_queue.h new file mode 100644 index 0000000..113fcbf --- /dev/null +++ b/collection/collection_queue.h @@ -0,0 +1,81 @@ +/* + QUEUE + + Header file for queue implemented using collection interface. + + Copyright (C) Dmitri Pal 2009 + + Collection Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Collection Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Collection Library. If not, see . +*/ + +#ifndef COLLECTION_QUEUE_H +#define COLLECTION_QUEUE_H + +#include "collection.h" + + +#define COL_CLASS_QUEUE 40000 +#define COL_NAME_QUEUE "queue" + +/* Function that creates a queue object */ +int create_queue(struct collection_item **queue); + +/* Function that destroys a queue object */ +void destroy_queue(struct collection_item *queue); + +/* Family of functions that add property to a queue */ +/* Put a string property to queue. */ +int enqueue_str_property(struct collection_item *queue, + const char *property, char *string, int length); +/* Put a binary property to queue. */ +int enqueue_binary_property(struct collection_item *queue, + const char *property, void *binary_data, int length); +/* Put an int property to queue. */ +int enqueue_int_property(struct collection_item *queue, + const char *property, int number); +/* Put an unsigned int property to queue. */ +int enqueue_unsigned_property(struct collection_item *queue, + const char *property, unsigned int number); +/* Put a long property. */ +int enqueue_long_property(struct collection_item *queue, + const char *property, long number); +/* Put an unsigned long property. */ +int enqueue_ulong_property(struct collection_item *queue, + const char *property, unsigned long number); +/* Put a double property. */ +int enqueue_double_property(struct collection_item *queue, + const char *property, double number); +/* Put a bool property. */ +int enqueue_bool_property(struct collection_item *queue, + const char *property, unsigned char logical); + +/* Put any property */ +int enqueue_any_property(struct collection_item *queue, /* Queue */ + const char *property, /* Name */ + int type, /* Data type */ + void *data, /* Pointer to the data */ + int length); /* Length of the data. For + strings it includes the + trailing 0 */ +/* Push item */ +int enqueue_item(struct collection_item *queue, + struct collection_item *item); + + +/* Get item from queue */ +int dequeue_item(struct collection_item *queue, + struct collection_item **item); + + +#endif diff --git a/collection/collection_queue_ut.c b/collection/collection_queue_ut.c new file mode 100644 index 0000000..b4bd5c2 --- /dev/null +++ b/collection/collection_queue_ut.c @@ -0,0 +1,101 @@ +/* + QUEUE INTERFACE + + Queue unit test. + + Copyright (C) Dmitri Pal 2009 + + Collection Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Collection Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Collection Library. If not, see . +*/ + + +#include +#include +#include +#define TRACE_HOME +#include "trace.h" +#include "collection_queue.h" +#include "collection_tools.h" + + +int queue_test() +{ + struct collection_item *queue = NULL; + char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + struct collection_item *item = NULL; + int i; + unsigned count; + int error = EOK; + + TRACE_FLOW_STRING("queue_test","Entry."); + + printf("\n\nQUEUE TEST!!!.\n\n\n"); + + if((error = create_queue(&queue)) || + (error = enqueue_str_property(queue, "item1","value 1" ,0)) || + (error = enqueue_int_property(queue, "item2", -1)) || + (error = enqueue_unsigned_property(queue, "item3", 1)) || + (error = enqueue_long_property(queue, "item4", 100)) || + (error = enqueue_ulong_property(queue, "item5", 1000)) || + (error = enqueue_double_property(queue, "item6", 1.1)) || + (error = enqueue_bool_property(queue, "item7", 1)) || + (error = enqueue_binary_property(queue, "item8", binary_dump, sizeof(binary_dump)))) { + printf("Failed to enqueue property. Error %d\n", error); + destroy_collection(queue); + return error; + } + + debug_collection(queue,COL_TRAVERSE_DEFAULT); + + error = get_collection_count(queue, &count); + if (error) { + printf("Failed to get count. Error %d\n", error); + destroy_collection(queue); + return error; + } + + count--; + + printf("Rotate the queue.\n"); + + for (i = 0; i < count; i++) { + if ((error = dequeue_item(queue, &item)) || + (error = enqueue_item(queue, item))) { + printf("Failed to dequeue or enqueue items. Error %d\n", error); + destroy_collection(queue); + return error; + } + debug_collection(queue,COL_TRAVERSE_DEFAULT); + } + + destroy_collection(queue); + TRACE_FLOW_NUMBER("queue_test. Returning", error); + + printf("\n\nEND OF QUEUE TEST!!!.\n\n\n"); + + return error; +} + +/* Main function of the unit test */ + +int main() +{ + int error = EOK; + + printf("Start\n"); + if ((error = queue_test())) printf("Failed!\n"); + else printf("Success!\n"); + + return error; +} diff --git a/collection/collection_stack.c b/collection/collection_stack.c new file mode 100644 index 0000000..347d9b6 --- /dev/null +++ b/collection/collection_stack.c @@ -0,0 +1,350 @@ +/* + STACK + + Implementation of the stack on top of collection library interface. + + Copyright (C) Dmitri Pal 2009 + + Collection Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Collection Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Collection Library. If not, see . +*/ + +#include "stdlib.h" +#include "errno.h" +#include "collection_stack.h" +#include "trace.h" + +/* Function that creates a stack object */ +int create_stack(struct collection_item **stack) +{ + int error = EOK; + + TRACE_FLOW_STRING("create_stack", "Entry point."); + + error = create_collection(stack, COL_NAME_STACK, COL_CLASS_STACK); + + TRACE_FLOW_STRING("create_stack", "Exit."); + return error; +} + +/* Function that destroys a stack object */ +void destroy_stack(struct collection_item *stack) +{ + TRACE_FLOW_STRING("destroy_stack", "Entry point."); + + destroy_collection(stack); + + TRACE_FLOW_STRING("destroy_stack", "Exit"); +} + + + +int push_str_property(struct collection_item *stack, + const char *property, char *string, int length) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_str_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_str_property(stack, NULL, property, string, length); + + TRACE_FLOW_STRING("push_str_property", "Exit."); + return error; +} + +/* Push a binary property to stack. */ +int push_binary_property(struct collection_item *stack, + const char *property, void *binary_data, int length) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_binary_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_binary_property(stack, NULL, property, binary_data, length) + + TRACE_FLOW_STRING("push_binary_property", "Exit."); + return error; +} + + +/* Push an int property to stack. */ +int push_int_property(struct collection_item *stack, + const char *property, int number) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_int_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_int_property(stack, NULL, property, number); + + TRACE_FLOW_STRING("push_int_property", "Exit."); + return error; +} + +/* Push an unsigned int property to stack. */ +int push_unsigned_property(struct collection_item *stack, + const char *property, unsigned int number) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_unsigned_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_unsigned_property(stack, NULL, property, number); + + TRACE_FLOW_STRING("push_unsigned_property", "Exit."); + return error; +} + + +/* Push a long property. */ +int push_long_property(struct collection_item *stack, + const char *property, long number) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_long_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_long_property(stack, NULL, property, number); + + TRACE_FLOW_STRING("push_long_property", "Exit."); + return error; +} + +/* Push an unsigned long property. */ +int push_ulong_property(struct collection_item *stack, + const char *property, unsigned long number) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_ulong_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_ulong_property(stack, NULL, property, number); + + TRACE_FLOW_STRING("push_ulong_property", "Exit."); + return error; +} + +/* Push a double property. */ +int push_double_property(struct collection_item *stack, + const char *property, double number) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_double_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_double_property(stack, NULL, property, number); + + TRACE_FLOW_STRING("push_double_property", "Exit."); + return error; +} + +/* Push a bool property. */ +int push_bool_property(struct collection_item *stack, + const char *property, unsigned char logical) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_bool_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_bool_property(stack, NULL, property, logical); + + TRACE_FLOW_STRING("push_double_property", "Exit."); + return error; +} + +/* Push any property */ +int push_any_property(struct collection_item *stack, + const char *property, + int type, + void *data, + int length) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_bool_property", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = add_any_property(stack, NULL, property, type, data, length); + + TRACE_FLOW_STRING("push_bool_property", "Exit."); + return error; +} + +/* Push item */ +int push_item(struct collection_item *stack, + struct collection_item *item) +{ + int error = EOK; + + TRACE_FLOW_STRING("push_item", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = insert_item_into_current(stack, + item, + COL_DSP_END, + NULL, + 0, + COL_INSERT_NOCHECK); + + TRACE_FLOW_STRING("push_item", "Exit."); + return error; +} + +/* Pop_item */ +int pop_item(struct collection_item *stack, + struct collection_item **item) +{ + int error = EOK; + + TRACE_FLOW_STRING("pop_item", "Entry point."); + + /* Check that stack is not empty */ + if (stack == NULL) { + TRACE_ERROR_STRING("Stack can't be NULL", ""); + return EINVAL; + } + + /* Make sure it is a stack */ + if (!is_of_class(stack, COL_CLASS_STACK)) { + TRACE_ERROR_STRING("Wrong class", ""); + return EINVAL; + } + + error = extract_item_from_current(stack, + COL_DSP_END, + NULL, + 0, + 0, + item); + + TRACE_FLOW_STRING("pop_item", "Exit."); + return error; +} diff --git a/collection/collection_stack.h b/collection/collection_stack.h new file mode 100644 index 0000000..447b3df --- /dev/null +++ b/collection/collection_stack.h @@ -0,0 +1,81 @@ +/* + STACK + + Header file for stack implemented using collection interface. + + Copyright (C) Dmitri Pal 2009 + + Collection Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Collection Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Collection Library. If not, see . +*/ + +#ifndef COLLECTION_STACK_H +#define COLLECTION_STACK_H + +#include + + +#define COL_CLASS_STACK 30000 +#define COL_NAME_STACK "stack" + +/* Function that creates a stack object */ +int create_stack(struct collection_item **stack); + +/* Function that destroys a stack object */ +void destroy_stack(struct collection_item *stack); + +/* Family of functions that push property to stack */ +/* Push a string property to stack. */ +int push_str_property(struct collection_item *stack, + const char *property, char *string, int length); +/* Push a binary property to stack. */ +int push_binary_property(struct collection_item *stack, + const char *property, void *binary_data, int length); +/* Push an int property to stack. */ +int push_int_property(struct collection_item *stack, + const char *property, int number); +/* Push an unsigned int property to stack. */ +int push_unsigned_property(struct collection_item *stack, + const char *property, unsigned int number); +/* Push a long property. */ +int push_long_property(struct collection_item *stack, + const char *property, long number); +/* Push an unsigned long property. */ +int push_ulong_property(struct collection_item *stack, + const char *property, unsigned long number); +/* Push a double property. */ +int push_double_property(struct collection_item *stack, + const char *property, double number); +/* Push a bool property. */ +int push_bool_property(struct collection_item *stack, + const char *property, unsigned char logical); + +/* Push any property */ +int push_any_property(struct collection_item *stack, /* Stack */ + const char *property, /* Name */ + int type, /* Data type */ + void *data, /* Pointer to the data */ + int length); /* Length of the data. For + strings it includes the + trailing 0 */ +/* Push item */ +int push_item(struct collection_item *stack, + struct collection_item *item); + + +/* Pop item */ +int pop_item(struct collection_item *stack, + struct collection_item **item); + + +#endif diff --git a/collection/collection_stack_ut.c b/collection/collection_stack_ut.c new file mode 100644 index 0000000..667af10 --- /dev/null +++ b/collection/collection_stack_ut.c @@ -0,0 +1,108 @@ +/* + STACK INTERFACE + + Stack unit test. + + Copyright (C) Dmitri Pal 2009 + + Collection Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Collection Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Collection Library. If not, see . +*/ + + +#include +#include +#include +#define TRACE_HOME +#include "trace.h" +#include "collection_stack.h" +#include "collection_tools.h" + + +int stack_test() +{ + struct collection_item *stack = NULL; + char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + struct collection_item *item1 = NULL; + struct collection_item *item2 = NULL; + + int error = EOK; + + TRACE_FLOW_STRING("stack_test", "Entry."); + + printf("\n\nSTACK TEST!!!.\n\n\n"); + + if ((error = create_stack(&stack)) || + (error = push_str_property(stack, "item1", "value 1", 0)) || + (error = push_int_property(stack, "item2", -1)) || + (error = push_unsigned_property(stack, "item3", 1)) || + (error = push_long_property(stack, "item4", 100)) || + (error = push_ulong_property(stack, "item5", 1000)) || + (error = push_double_property(stack, "item6", 1.1)) || + (error = push_bool_property(stack, "item7", 1)) || + (error = push_binary_property(stack, "item8", binary_dump, sizeof(binary_dump)))) { + printf("Failed to push property. Error %d\n", error); + destroy_collection(stack); + return error; + } + + debug_collection(stack, COL_TRAVERSE_DEFAULT); + + printf("Swapping last two items by popping and pushing them back.\n"); + + if ((error = pop_item(stack, &item1)) || + (error = pop_item(stack, &item2))) { + printf("Failed to pop items. Error %d\n", error); + destroy_collection(stack); + return error; + } + + printf("\nPopped two last items.\n"); + debug_collection(stack, COL_TRAVERSE_DEFAULT); + + printf("\nLast item.\n"); + debug_item(item1); + + printf("\nPrevious item.\n"); + debug_item(item2); + + if ((error = push_item(stack, item1)) || + (error = push_item(stack, item2))) { + printf("Failed to pop or push items. Error %d\n", error); + destroy_collection(stack); + return error; + } + + printf("\n\nPushed two items again in reverse order.\n\n"); + + debug_collection(stack, COL_TRAVERSE_DEFAULT); + destroy_collection(stack); + TRACE_FLOW_NUMBER("stack_test. Returning", error); + + printf("\n\nEND OF STACK TEST!!!.\n\n"); + + return error; +} + +/* Main function of the unit test */ + +int main() +{ + int error = EOK; + + printf("Start\n"); + if ((error = stack_test())) printf("Failed!\n"); + else printf("Success!\n"); + + return error; +} -- cgit