Tofu Double Queue

ToFu DQueue (fossil_dqueue_t) is a double-ended queue (deque) container for fossil_tofu_t elements. It allows insertion and removal from both the front and rear in O(1) time and supports indexed access and updates with O(n) complexity. The container provides C and C++ interfaces with copy/move semantics, and convenient getter/setter methods for front, rear, and arbitrary elements. This makes it ideal for queue-like data structures where dynamic size and double-ended operations are required.

HEADER REFERENCE #

#ifndef FOSSIL_TOFU_DQUEUE_H
#define FOSSIL_TOFU_DQUEUE_H

#include "tofu.h"

#ifdef __cplusplus
extern "C" {
#endif

// *****************************************************************************
// Type definitions
// *****************************************************************************

// Node structure for the double-ended queue
typedef struct fossil_tofu_dqueue_node_t {
    fossil_tofu_t data;
    struct fossil_tofu_dqueue_node_t* prev;
    struct fossil_tofu_dqueue_node_t* next;
} fossil_tofu_dqueue_node_t;

// Double-ended queue structure
typedef struct fossil_tofu_dqueue_t {
    fossil_tofu_dqueue_node_t* front;
    fossil_tofu_dqueue_node_t* rear;
    char *type;
} fossil_tofu_dqueue_t;

// *****************************************************************************
// Function prototypes
// *****************************************************************************

/**
 * Create a new dynamic queue with the specified data type.
 *
 * @param list_type The type of data the dynamic queue will store.
 * @return          The created dynamic queue.
 * @note            Time complexity: O(1)
 */
fossil_tofu_dqueue_t* fossil_tofu_dqueue_create_container(char* type);

/**
 * Create a new double-ended queue with default values.
 *
 * @return The created double-ended queue.
 * @note   Time complexity: O(1)
 */
fossil_tofu_dqueue_t* fossil_tofu_dqueue_create_default(void);

/**
 * Create a new double-ended queue by copying an existing queue.
 *
 * @param other The queue to copy.
 * @return      The created double-ended queue.
 * @note        Time complexity: O(n)
 */
fossil_tofu_dqueue_t* fossil_tofu_dqueue_create_copy(const fossil_tofu_dqueue_t* other);

/**
 * Create a new double-ended queue by moving an existing queue.
 *
 * @param other The queue to move.
 * @return      The created double-ended queue.
 * @note        Time complexity: O(1)
 */
fossil_tofu_dqueue_t* fossil_tofu_dqueue_create_move(fossil_tofu_dqueue_t* other);

/**
 * Erase the contents of the dynamic queue and free allocated memory.
 *
 * @param dqueue The dynamic queue to erase.
 * @note         Time complexity: O(n)
 */
void fossil_tofu_dqueue_destroy(fossil_tofu_dqueue_t* dqueue);

// *****************************************************************************
// Utility functions
// *****************************************************************************

/**
 * Insert data into the dynamic queue.
 *
 * @param dqueue The dynamic queue to insert data into.
 * @param data   The data to insert.
 * @return       The error code indicating the success or failure of the operation.
 * @note         Time complexity: O(1)
 */
int32_t fossil_tofu_dqueue_insert(fossil_tofu_dqueue_t* dqueue, char *data);

/**
 * Remove data from the dynamic queue.
 *
 * @param dqueue The dynamic queue to remove data from.
 * @return       The error code indicating the success or failure of the operation.
 * @note         Time complexity: O(1)
 */
int32_t fossil_tofu_dqueue_remove(fossil_tofu_dqueue_t* dqueue);

/**
 * Get the size of the dynamic queue.
 *
 * @param dqueue The dynamic queue for which to get the size.
 * @return       The size of the dynamic queue.
 * @note         Time complexity: O(1)
 */
size_t fossil_tofu_dqueue_size(const fossil_tofu_dqueue_t* dqueue);

/**
 * Check if the dynamic queue is not empty.
 *
 * @param dqueue The dynamic queue to check.
 * @return       True if the dynamic queue is not empty, false otherwise.
 * @note         Time complexity: O(1)
 */
bool fossil_tofu_dqueue_not_empty(const fossil_tofu_dqueue_t* dqueue);

/**
 * Check if the dynamic queue is not a null pointer.
 *
 * @param dqueue The dynamic queue to check.
 * @return       True if the dynamic queue is not a null pointer, false otherwise.
 * @note         Time complexity: O(1)
 */
bool fossil_tofu_dqueue_not_cnullptr(const fossil_tofu_dqueue_t* dqueue);

/**
 * Check if the dynamic queue is empty.
 *
 * @param dqueue The dynamic queue to check.
 * @return       True if the dynamic queue is empty, false otherwise.
 * @note         Time complexity: O(1)
 */
bool fossil_tofu_dqueue_is_empty(const fossil_tofu_dqueue_t* dqueue);

/**
 * Check if the dynamic queue is a null pointer.
 *
 * @param dqueue The dynamic queue to check.
 * @return       True if the dynamic queue is a null pointer, false otherwise.
 * @note         Time complexity: O(1)
 */
bool fossil_tofu_dqueue_is_cnullptr(const fossil_tofu_dqueue_t* dqueue);

// *****************************************************************************
// Getter and setter functions
// *****************************************************************************

/**
 * Get the element at the specified index in the double-ended queue.
 *
 * @param dqueue The double-ended queue from which to get the element.
 * @param index  The index of the element to get.
 * @return       The element at the specified index.
 * @note         Time complexity: O(n)
 */
char *fossil_tofu_dqueue_get(const fossil_tofu_dqueue_t* dqueue, size_t index);

/**
 * Get the first element in the double-ended queue.
 *
 * @param dqueue The double-ended queue from which to get the first element.
 * @return       The first element in the double-ended queue.
 * @note         Time complexity: O(1)
 */
char *fossil_tofu_dqueue_get_front(const fossil_tofu_dqueue_t* dqueue);

/**
 * Get the last element in the double-ended queue.
 *
 * @param dqueue The double-ended queue from which to get the last element.
 * @return       The last element in the double-ended queue.
 * @note         Time complexity: O(1)
 */
char *fossil_tofu_dqueue_get_back(const fossil_tofu_dqueue_t* dqueue);

/**
 * Set the element at the specified index in the double-ended queue.
 *
 * @param dqueue  The double-ended queue in which to set the element.
 * @param index   The index at which to set the element.
 * @param element The element to set.
 * @note         Time complexity: O(n)
 */
void fossil_tofu_dqueue_set(fossil_tofu_dqueue_t* dqueue, size_t index, char *element);

/**
 * Set the first element in the double-ended queue.
 *
 * @param dqueue  The double-ended queue in which to set the first element.
 * @param element The element to set.
 * @note         Time complexity: O(1)
 */
void fossil_tofu_dqueue_set_front(fossil_tofu_dqueue_t* dqueue, char *element);

/**
 * Set the last element in the double-ended queue.
 *
 * @param dqueue  The double-ended queue in which to set the last element.
 * @param element The element to set.
 * @note         Time complexity: O(1)
 */
void fossil_tofu_dqueue_set_back(fossil_tofu_dqueue_t* dqueue, char *element);

#ifdef __cplusplus
}
#include <stdexcept>
#include <string>

namespace fossil {

    namespace tofu {

        /**
         * A C++ wrapper class for the C-style double-ended queue (fossil_tofu_dqueue_t).
         * Provides a more user-friendly interface for managing the queue.
         */
        class DQueue {
        public:
            /**
             * Constructor with a specified data type.
             * Creates a new double-ended queue with the specified data type.
             * 
             * @param type The type of data the double-ended queue will store.
             * @throws std::runtime_error if the queue creation fails.
             */
            DQueue(const std::string& type) : dqueue(fossil_tofu_dqueue_create_container(const_cast<char*>(type.c_str()))) {
                if (dqueue == nullptr) {
                    throw std::runtime_error("Failed to create a new double-ended queue with type: " + type);
                }
            }

            /**
             * Default constructor.
             * Creates a new double-ended queue with default values.
             * 
             * @throws std::runtime_error if the queue creation fails.
             */
            DQueue() : dqueue(fossil_tofu_dqueue_create_default()) {
                if (dqueue == nullptr) {
                    throw std::runtime_error("Failed to create a new double-ended queue.");
                }
            }

            /**
             * Copy constructor.
             * Creates a new double-ended queue by copying an existing queue.
             * 
             * @param other The queue to copy.
             * @throws std::runtime_error if the queue copy operation fails.
             */
            DQueue(const DQueue& other) : dqueue(fossil_tofu_dqueue_create_copy(other.dqueue)) {
                if (dqueue == nullptr) {
                    throw std::runtime_error("Failed to create a new double-ended queue by copying an existing queue.");
                }
            }

            /**
             * Move constructor.
             * Creates a new double-ended queue by moving an existing queue.
             * 
             * @param other The queue to move.
             */
            DQueue(DQueue&& other) noexcept {
                dqueue = fossil_tofu_dqueue_create_move(other.dqueue);
            }

            /**
             * Destructor.
             * Destroys the double-ended queue and frees allocated memory.
             */
            ~DQueue() {
                fossil_tofu_dqueue_destroy(dqueue);
            }

            /**
             * Copy assignment operator.
             * Copies the contents of another queue into this queue.
             * 
             * @param other The queue to copy.
             * @return A reference to this queue.
             * @throws std::runtime_error if the queue copy operation fails.
             */
            DQueue& operator=(const DQueue& other) {
                if (this != &other) {
                    fossil_tofu_dqueue_destroy(dqueue);
                    dqueue = fossil_tofu_dqueue_create_copy(other.dqueue);
                    if (dqueue == nullptr) {
                        throw std::runtime_error("Failed to create a new double-ended queue by copying an existing queue.");
                    }
                }
                return *this;
            }

            /**
             * Move assignment operator.
             * Moves the contents of another queue into this queue.
             * 
             * @param other The queue to move.
             * @return A reference to this queue.
             */
            DQueue& operator=(DQueue&& other) noexcept {
                if (this != &other) {
                    fossil_tofu_dqueue_destroy(dqueue);
                    dqueue = other.dqueue;
                    other.dqueue = nullptr; // Prevent double free
                }
                return *this;
            }

            /**
             * Inserts data into the queue.
             * 
             * @param data The data to insert.
             * @throws std::runtime_error if the insertion fails.
             */
            void insert(const std::string& data) {
                if (fossil_tofu_dqueue_insert(dqueue, const_cast<char*>(data.c_str())) != 0) {
                    throw std::runtime_error("Failed to insert data into the double-ended queue.");
                }
            }

            /**
             * Removes data from the queue.
             * 
             * @throws std::runtime_error if the removal fails.
             */
            void remove() {
                if (fossil_tofu_dqueue_remove(dqueue) != 0) {
                    throw std::runtime_error("Failed to remove data from the double-ended queue.");
                }
            }

            /**
             * Gets the size of the queue.
             * 
             * @return The size of the queue.
             */
            size_t size() const {
                return fossil_tofu_dqueue_size(dqueue);
            }

            /**
             * Checks if the queue is not empty.
             * 
             * @return True if the queue is not empty, false otherwise.
             */
            bool not_empty() const {
                return fossil_tofu_dqueue_not_empty(dqueue);
            }

            /**
             * Checks if the queue is not a null pointer.
             * 
             * @return True if the queue is not a null pointer, false otherwise.
             */
            bool not_cnullptr() const {
                return fossil_tofu_dqueue_not_cnullptr(dqueue);
            }

            /**
             * Checks if the queue is empty.
             * 
             * @return True if the queue is empty, false otherwise.
             */
            bool is_empty() const {
                return fossil_tofu_dqueue_is_empty(dqueue);
            }

            /**
             * Checks if the queue is a null pointer.
             * 
             * @return True if the queue is a null pointer, false otherwise.
             */
            bool is_cnullptr() const {
                return fossil_tofu_dqueue_is_cnullptr(dqueue);
            }

            /**
             * Gets the element at the specified index in the queue.
             * 
             * @param index The index of the element to get.
             * @return The element at the specified index as std::string.
             */
            std::string get(size_t index) const {
                char* result = fossil_tofu_dqueue_get(dqueue, index);
                return result ? std::string(result) : std::string();
            }

            /**
             * Gets the first element in the queue.
             * 
             * @return The first element in the queue as std::string.
             */
            std::string get_front() const {
                char* result = fossil_tofu_dqueue_get_front(dqueue);
                return result ? std::string(result) : std::string();
            }

            /**
             * Gets the last element in the queue.
             * 
             * @return The last element in the queue as std::string.
             */
            std::string get_back() const {
                char* result = fossil_tofu_dqueue_get_back(dqueue);
                return result ? std::string(result) : std::string();
            }

            /**
             * Sets the element at the specified index in the queue.
             * 
             * @param index   The index at which to set the element.
             * @param element The element to set as std::string.
             */
            void set(size_t index, const std::string& element) {
                fossil_tofu_dqueue_set(dqueue, index, const_cast<char*>(element.c_str()));
            }

            /**
             * Sets the first element in the queue.
             * 
             * @param element The element to set as std::string.
             */
            void set_front(const std::string& element) {
                fossil_tofu_dqueue_set_front(dqueue, const_cast<char*>(element.c_str()));
            }

            /**
             * Sets the last element in the queue.
             * 
             * @param element The element to set as std::string.
             */
            void set_back(const std::string& element) {
                fossil_tofu_dqueue_set_back(dqueue, const_cast<char*>(element.c_str()));
            }

        private:
            fossil_tofu_dqueue_t* dqueue; /**< Pointer to the underlying C-style double-ended queue. */
        };

    } // namespace tofu

} // namespace fossil

#endif

#endif /* FOSSIL_TOFU_FRAMEWORK_H */

SAMPLE CODE C #

#include "fossil/tofu/dqueue.h"
#include <stdio.h>

int main() {
    fossil_dqueue_t* queue = fossil_dqueue_create_default();

    fossil_dqueue_insert(queue, "apple");
    fossil_dqueue_insert(queue, "banana");

    printf("Front: %s\n", fossil_dqueue_get_front(queue));
    printf("Back: %s\n", fossil_dqueue_get_back(queue));

    fossil_dqueue_set_front(queue, "orange");
    printf("New Front: %s\n", fossil_dqueue_get_front(queue));

    fossil_dqueue_remove(queue);
    printf("Front after removal: %s\n", fossil_dqueue_get_front(queue));

    fossil_dqueue_destroy(queue);
    return 0;
}

SAMPLE CODE C++ #

#include "fossil/tofu/dqueue.h"
#include <iostream>
using namespace fossil::tofu;

int main() {
    DQueue queue("cstr");

    queue.insert("apple");
    queue.insert("banana");

    std::cout << "Front: " << queue.get_front() << "\n";
    std::cout << "Back: " << queue.get_back() << "\n";

    queue.set_front("orange");
    std::cout << "New Front: " << queue.get_front() << "\n";

    queue.remove();
    std::cout << "Front after removal: " << queue.get_front() << "\n";

    return 0;
}

What are your feelings

Updated on September 27, 2025