Wednesday 25 July 2018

Simple C to Tree

/*
 * File name: m_tree.h
 * Author: Seree Rakwong
 * Date: 17-SEP-2013
 *
 */

#ifndef _MTREE_H_
#define _MTREE_H_

#include <stdlib.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef void* mtree_t;
typedef void* mtree_item_t;


/*
 * create and destroy a tree
 */
mtree_t        mtree_create();
void           mtree_destroy(mtree_t tree);

/*
 * manipulate tree item functions
 */
mtree_item_t   mtree_insert_sorted_item(
    mtree_t tree,
    mtree_item_t parent,
    const void *data,
    size_t size,
    long (*pf_cmp)(const void *,const void *));
mtree_item_t   mtree_insert_item(mtree_t tree, mtree_item_t parent, const void *data, size_t size);
void           mtree_delete_item(mtree_t tree, mtree_item_t item);
void           mtree_set_item(mtree_t tree, mtree_item_t item, const void* data, size_t size);
size_t         mtree_get_item(mtree_t tree, mtree_item_t item, void* data, size_t size);
unsigned long  mtree_item_count(mtree_t tree);
unsigned long  mtree_children_count(mtree_t tree, mtree_item_t item);
long           mtree_move_item(
                    mtree_t tree, 
                    mtree_item_t movingItem, 
                    mtree_item_t newParentItem, 
                    long sorting,
                    long (*pf_cmp)(const void*, const void*));

/*
 * long (*pf_cmp)(const void* data, const void* data2)
 */
mtree_item_t   mtree_find_first_item(
    mtree_t tree,
    const void *data,
    long (*pf_cmp)(const void*, const void*));
mtree_item_t   mtree_find_next_item(
    mtree_t tree,
    mtree_item_t start,
    const void *data,
    long (*pf_cmp)(const void*, const void*));

/*
 * narrow tree item
 */
mtree_item_t   mtree_get_root_item(mtree_t tree);
mtree_item_t   mtree_get_parent_item(mtree_t tree, mtree_item_t item);
mtree_item_t   mtree_get_first_child_item(mtree_t tree, mtree_item_t item);
mtree_item_t   mtree_get_last_child_item(mtree_t tree, mtree_item_t item);
mtree_item_t   mtree_get_next_item(mtree_t tree, mtree_item_t item);
mtree_item_t   mtree_get_prev_item(mtree_t tree, mtree_item_t item);
long           mtree_is_relative_item(mtree_t tree, mtree_item_t parent, mtree_item_t item);

/*
 * traversal tree
 *   void (*pf_traversal)(const void* data, long level, long children, void* args)
 */
void mtree_preorder_traverse(
    mtree_t tree,
    mtree_item_t item,
    void* args,
    void (*pf_traversal)(const void*, long, long, void*));
void mtree_inorder_traverse(
    mtree_t tree,
    mtree_item_t item,
    void* args,
    void (*pf_traversal)(const void*, long, long, void*));
void mtree_postorder_traverse(
    mtree_t tree,
    mtree_item_t item,
    void* args,
    void (*pf_traversal)(const void*, long, long, void*));

#ifdef __cplusplus
}
#endif

#endif /* _MTREE_H_ */

/*
 * File name: m_tree.c
 * Author: Seree Rakwong
 * Date: 17-SEP-2013
 *
 */

#include "m_tree.h"

#define MTREE_SIGNATURE               0x89231a21
#define MTREE_ITEM_SIGNATURE          0x89231a20

#ifdef __cplusplus
extern "C" {
#endif

/*
* long (*pf_mtree_cmp)(const void* data1, const void* data2)
*   return:
*       < 0 if data1 is less than data2
*       = 0 if data1 is equal to data2
*       > 0 if data1 is greater than data2
*/
typedef long(*pf_mtree_cmp)(const void*, size_t, const void*, size_t);

typedef struct mtree_item_s
{
    mtree_t         owner;           /* tree owner */
    struct mtree_item_s   *parent;          /* a pointer to the parent */
    struct mtree_item_s   *first_child;     /* a pointer to the first child */
    struct mtree_item_s   *last_child;      /* a pointer to the last child */
    struct mtree_item_s   *next_sibling;    /* a pointer to the next sibling */
    struct mtree_item_s   *prev_sibling;    /* a pointer to the previous sibling */
    long            level;
    void           *data;
    size_t          size;
    unsigned long   signature;
    unsigned long   children;
} mtree_item_s, *mtree_item_sp;

typedef struct mtree_s
{
    mtree_item_sp   root;             /* there are no functions destroy root but mtree_destroy() */
    unsigned long   signature;
    unsigned long   items;
    mtree_item_sp   leaf;
} mtree_s, *mtree_sp;

/*
* ############################## BOF helper functions ##############################
*/
mtree_sp mtree_verify(mtree_t tree)
{
    mtree_sp ptree = (mtree_sp)tree;
    if (!ptree || ptree->signature != MTREE_SIGNATURE)
        return NULL;
    return ptree;
}

mtree_item_sp mtree_verify_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = (mtree_sp)tree;
    mtree_item_sp pitem = (mtree_item_sp)item;
    if (!ptree || ptree->signature != MTREE_SIGNATURE ||
        !pitem || pitem->signature != MTREE_ITEM_SIGNATURE ||
        pitem->owner != tree
        )
    {
        return NULL;
    }
    return pitem;
}

mtree_item_sp mtree_create_item(mtree_t tree, mtree_item_t parent, const void* data, size_t size)
{
    mtree_item_sp pitem = NULL;
    void* new_data = 0;

    if (!tree || !parent || !data || size == 0)
        return NULL;

    new_data = malloc(size);
    if (!new_data)
    {
        return 0;
    }

    pitem = (mtree_item_sp)malloc(sizeof(mtree_item_s));
    if (!pitem)
        return NULL;

    memset(pitem, 0, sizeof(mtree_item_s));
    pitem->owner = tree;
    pitem->parent = parent;
    pitem->signature = MTREE_ITEM_SIGNATURE;
    pitem->level = ((mtree_item_sp)parent)->level + 1;
    pitem->size = size;
    pitem->data = new_data;
    memset(pitem->data, 0, size);
    memcpy(pitem->data, data, size);

    return pitem;
}

void mtree_destroy_item(mtree_item_t item)
{
    mtree_item_sp pitem = (mtree_item_sp)item;
    if (pitem)
    {
        free(pitem->data);
        free(pitem);
        pitem = NULL;
    }
}

void mtree_delete_no_child_item(mtree_item_t item)
{
    mtree_item_sp pitem = (mtree_item_sp)item;
    mtree_item_sp pprev = NULL;
    if (pitem && pitem->first_child == NULL)
    {
        mtree_destroy_item(pitem);
        return;
    }
    if (pitem == NULL)
    {
        return;
    }
    if (pitem->last_child)
    {
        pprev = pitem->last_child->prev_sibling;
    }
    mtree_delete_no_child_item(pitem->last_child);
    mtree_delete_no_child_item(pprev);
}

/*
* ############################## BOF helper functions ##############################
*/

mtree_t mtree_create()
{
    mtree_sp ptree = (mtree_sp)malloc(sizeof(mtree_s));
    if (!ptree)
    {
        return NULL;
    }

    ptree->signature = MTREE_SIGNATURE;
    ptree->root = (mtree_item_sp)malloc(sizeof(mtree_item_s));
    if (!ptree->root)
    {
        free(ptree);
        return NULL;
    }

    memset(ptree->root, 0, sizeof(mtree_item_sp));
    ptree->root->owner = (mtree_t)ptree;
    ptree->root->signature = MTREE_ITEM_SIGNATURE;
    ptree->root->level = 0;
    ptree->items = 0;

    ptree->leaf = 0;
    return (mtree_t)ptree;
}

void mtree_destroy(mtree_t tree)
{
    mtree_sp ptree = mtree_verify(tree);
    if (ptree)
    {
        mtree_delete_item(tree, (mtree_item_t)ptree->root);
        free(ptree->root);
        free(ptree);
        ptree = NULL;
    }
}


mtree_item_t mtree_get_root_item(mtree_t tree)
{
    mtree_sp ptree = mtree_verify(tree);
    if (ptree)
    {
        return (mtree_item_t)ptree->root;
    }
    return NULL;
}

unsigned long  mtree_item_count(mtree_t tree)
{
    mtree_sp ptree = mtree_verify(tree);
    if (ptree)
    {
        return ptree->items;
    }
    return 0;
}

unsigned long  mtree_children_count(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (ptree && pitem)
    {
        return pitem->children;
    }
    return 0;
}

mtree_item_t mtree_get_parent_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (ptree && pitem)
    {
        return (mtree_item_t)pitem->parent;
    }
    return NULL;
}

mtree_item_t mtree_get_first_child_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (ptree && pitem)
    {
        return (mtree_item_t)pitem->first_child;
    }
    return NULL;
}

mtree_item_t mtree_get_last_child_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (ptree && pitem)
    {
        return (mtree_item_t)pitem->last_child;
    }
    return NULL;
}

mtree_item_t mtree_get_next_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (ptree && pitem)
    {
        return (mtree_item_t)pitem->next_sibling;
    }
    return NULL;
}

mtree_item_t mtree_get_prev_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (ptree && pitem)
    {
        return (mtree_item_t)pitem->prev_sibling;
    }
    return NULL;
}

mtree_item_t mtree_insert_item(mtree_t tree, mtree_item_t parent, const void *data, size_t size)
{
    mtree_sp      ptree = mtree_verify(tree);
    mtree_item_sp pparent = mtree_verify_item(tree, parent);
    mtree_item_sp pitem = NULL;
    if (!ptree)
    {
        return NULL;
    }
    if (!pparent)
    {
        pparent = ptree->root;
    }
    pitem = mtree_create_item(tree, (mtree_item_t)pparent, data, size);
    if (!pitem)
    {
        return NULL;
    }

    /* attach the new item to the tree */
    if (!pparent->first_child)
    {
        /* it's the first child of the parent */
        pparent->first_child = pitem;
    }
    else
    {
        /* attach to the last child */
        pitem->prev_sibling = pparent->last_child;
        pparent->last_child->next_sibling = pitem;
    }
    pparent->last_child = pitem;
    /* increase children count */
    ++pparent->children;
    ++ptree->items;

    return (mtree_item_t)pitem;
}

mtree_item_t mtree_insert_sorted_item(
    mtree_t tree,
    mtree_item_t parent,
    const void *data,
    size_t size,
    long (*pf_cmp)(const void*, const void*))
{
    mtree_sp      ptree = mtree_verify(tree);
    mtree_item_sp pparent = mtree_verify_item(tree, parent);
    mtree_item_sp pitem = NULL;
    mtree_item_sp it = NULL;
    mtree_item_sp prev = NULL;

    if (!ptree)
    {
        return NULL;
    }
    if (!pparent)
    {
        pparent = ptree->root;
    }
    pitem = mtree_create_item(tree, (mtree_item_t)pparent, data, size);
    if (!pitem)
    {
        return NULL;
    }

    /* attach the new item to the tree */
    if (!pparent->first_child)
    {
        /* it's the first child of the parent */
        pparent->first_child = pitem;
        pparent->last_child = pitem;
    }
    else
    {
        /* insert between the right position */
        it = pparent->first_child;
        while (it != NULL && pf_cmp && pf_cmp(data, it->data) > 0)
        {
            it = it->next_sibling;
        }

        /* attached the new item */
        if (it == NULL)
        {
            pitem->prev_sibling = pparent->last_child;
            pparent->last_child->next_sibling = pitem;
            pparent->last_child = pitem;
        }
        else if (it == pparent->first_child)
        {
            pitem->next_sibling = pparent->first_child;
            pparent->first_child->prev_sibling = pitem;
            pparent->first_child = pitem;
        }
        else
        {
            prev = it->prev_sibling;

            pitem->prev_sibling = prev;
            pitem->next_sibling = it;
            it->prev_sibling = pitem;
            if (prev)
            {
                prev->next_sibling = pitem;
            }            
        }
    }
    /* increase children count */
    ++pparent->children;
    ++ptree->items;

    return (mtree_item_t)pitem;
}

void mtree_delete_item(mtree_t tree, mtree_item_t item)
{
    mtree_sp      ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    mtree_item_sp pparent = NULL;
    mtree_item_sp pnext = NULL;
    mtree_item_sp pprev = NULL;

    if (!ptree || !pitem)
    {
        return;
    }

    /* save the current information of its links */
    pparent = pitem->parent;
    pnext = pitem->next_sibling;
    pprev = pitem->prev_sibling;

    if (pparent && pparent->first_child == pitem)
    {
        /* delete at the first child */
        pparent->first_child = pparent->first_child->next_sibling;
        if (pparent->first_child)
        {
            pparent->first_child->prev_sibling = NULL;
        }
    }
    else if (pparent && pparent->last_child == pitem)
    {
        /* delete at the last child */
        pparent->last_child = pparent->last_child->prev_sibling;
        if (pparent->last_child)
        {
            pparent->last_child->next_sibling = NULL;
        }
    }
    else
    {
        /* otherwise, delete any position of its child parent */
        if (pnext)
        {
            pnext->prev_sibling = pprev;
        }
        if (pprev)
        {
            pprev->next_sibling = pnext;
        }
    }
    /* prompt to delete the item */
    mtree_delete_no_child_item(pitem);
    /* decrease children count */
    --pparent->children;
    --ptree->items;
}

void mtree_preorder_traverse(
    mtree_t tree,
    mtree_item_t item,
    void* args,
    void (*pf_traversal)(const void*, long, long, void*))
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (!ptree || !pitem || !pf_traversal)
    {
        return;
    }

    pf_traversal(pitem->data, pitem->level, pitem->children, args);
    mtree_preorder_traverse(tree, (mtree_item_t)pitem->first_child, args, pf_traversal);
    mtree_preorder_traverse(tree, (mtree_item_t)pitem->next_sibling, args, pf_traversal);
}

void mtree_inorder_traverse(
    mtree_t tree,
    mtree_item_t item,
    void* args,
    void (*pf_traversal)(const void*, long, long, void*))
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (!ptree || !pitem || !pf_traversal)
    {
        return;
    }

    mtree_preorder_traverse(tree, (mtree_item_t)pitem->first_child, args, pf_traversal);
    pf_traversal(pitem->data, pitem->level, pitem->children, args);
    mtree_preorder_traverse(tree, (mtree_item_t)pitem->next_sibling, args, pf_traversal);
}

void mtree_postorder_traverse(
    mtree_t tree,
    mtree_item_t item,
    void* args,
    void (*pf_traversal)(const void*, long, long, void*))
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (!ptree || !pitem || !pf_traversal)
    {
        return;
    }

    mtree_preorder_traverse(tree, (mtree_item_t)pitem->first_child, args, pf_traversal);
    mtree_preorder_traverse(tree, (mtree_item_t)pitem->next_sibling, args, pf_traversal);
    pf_traversal(pitem->data, pitem->level, pitem->children, args);
}

void mtree_set_item(
    mtree_t tree,
    mtree_item_t item,
    const void* data,
    size_t size)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    void* pdata = NULL;
    if (!ptree || !pitem || !data || size == 0)
    {
        return;
    }

    pdata = malloc(size);
    if (!pdata)
    {
        return;
    }
    memset(pdata, 0, size);
    memcpy(pdata, data, size);

    free(pitem->data);
    pitem->data = pdata;
    pitem->size = size;
}

size_t mtree_get_item(
    mtree_t tree,
    mtree_item_t item,
    void* data,
    size_t size)
{
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    if (!ptree || !pitem || !data)
    {
        return 0;
    }

    if (size > pitem->size)
    {
        size = pitem->size;
    }
    memset(data, 0, size);
    memcpy(data, pitem->data, pitem->size);
    return size;
}

mtree_item_t mtree_find_first_item(
    mtree_t tree,
    const void *data,
    long (*pf_cmp)(const void*, const void*))
{
    mtree_sp ptree = mtree_verify(tree);
    if (!ptree || !pf_cmp)
    {
        return NULL;
    }
    return  mtree_find_next_item(
                tree, 
                (mtree_item_t)ptree->root->first_child, 
                data, 
                pf_cmp);
}

mtree_item_t mtree_find_next_item(
    mtree_t tree,
    mtree_item_t item,
    const void *data, 
    long (*pf_cmp)(const void*, const void*))
{
    long rc = -1;
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    mtree_item_t  found = NULL;
    if (!ptree || !pitem || !pf_cmp)
    {
        return NULL;
    }
    rc = pf_cmp(data, pitem->data);
    if (rc == 0)
    {
        return item;
    }
    found = mtree_find_next_item(
                tree, 
                (mtree_item_t)pitem->first_child, 
                data, 
                pf_cmp);
    if (found)
    {
        return found;
    }
    found = mtree_find_next_item(
                tree, 
                (mtree_item_t)pitem->next_sibling, 
                data, 
                pf_cmp);
    if (found)
    {
        return found;
    }
    return NULL;
}

long mtree_move_item(
    mtree_t tree, 
    mtree_item_t item, 
    mtree_item_t newParent, 
    long sorting,
    long (*pf_cmp)(const void*, const void*))
{
    long rc = 0;
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    mtree_item_sp pNewParent = mtree_verify_item(tree, newParent);
    mtree_item_sp pOldParent = 0;

    /* invalid tree or item */
    if (!ptree || !pitem)
    {
        rc = -1;
        return rc;
    }
    /* not allowed moving root item */
    if (item == mtree_get_root_item(tree))
    {
        rc = -2;
        return rc;
    }
    /* no moving because its parent already */
    if (pitem->parent == pNewParent)
    {
        rc = 1;
        return rc;
    }
    /* not allowed moving to new parent if it is a child or nephew */
    if (mtree_is_relative_item(tree, (mtree_item_t)pitem , newParent))
    {
        rc = 2;
        return rc;
    }

    /* cut the current link from the old parent */
    pOldParent = pitem->parent;
    if (pitem == pOldParent->first_child)
    {
        pOldParent->first_child = pitem->next_sibling;
        if (pOldParent->first_child)
        {
            pOldParent->first_child->prev_sibling = 0;
        }
    }
    else if (pitem == pOldParent->last_child)
    {
        pOldParent->last_child = pitem->prev_sibling;
        if (pOldParent->last_child)
        {
            pOldParent->last_child->next_sibling = 0;
        }
    }
    else
    {
        mtree_item_sp prev = pitem->prev_sibling;
        mtree_item_sp next = pitem->next_sibling;
        
        prev->next_sibling = next;
        next->prev_sibling = prev;
    }

    /* insert the new link to the new parent */
    if (sorting && pf_cmp)
    {
        mtree_item_sp it = pNewParent->first_child;
        while (it != NULL && pf_cmp(pitem->data, it->data) > 0)
        {
            it = it->next_sibling;
        }

        /* attached the new item */
        if (it == NULL)
        {
            pitem->prev_sibling = pNewParent->last_child;
            pNewParent->last_child->next_sibling = pitem;
            pNewParent->last_child = pitem;
        }
        else if (it == pNewParent->first_child)
        {
            pitem->next_sibling = pNewParent->first_child;
            pNewParent->first_child->prev_sibling = pitem;
            pNewParent->first_child = pitem;
        }
        else
        {
            mtree_item_sp prev = it->prev_sibling;

            pitem->prev_sibling = prev;
            pitem->next_sibling = it;
            it->prev_sibling = pitem;
            if (prev)
            {
                prev->next_sibling = pitem;
            }            
        }
    }
    else
    {
        mtree_item_sp last = pNewParent->last_child;
        if (last)
        {
            last->prev_sibling = pitem;            
        }
        pitem->prev_sibling = last;
        pitem->next_sibling = 0;

        pNewParent->last_child = pitem;
    }
    return rc;
}

long mtree_is_relative_item(
    mtree_t tree, 
    mtree_item_t parent, 
    mtree_item_t item)
{
    long rc = 0;
    mtree_sp ptree = mtree_verify(tree);
    mtree_item_sp pitem = mtree_verify_item(tree, item);
    mtree_item_sp pparent = mtree_verify_item(tree, parent);

    if (!ptree || !pitem || !pparent)
    {
        return rc;
    }

    if (pitem->parent == pparent)
    {
        rc = 1;
    }
    if (rc != 1)
    {
        rc = mtree_is_relative_item(
                tree,
                parent,
                (mtree_item_t)pitem->first_child);
    }
    if (rc != 1)
    {
        rc = mtree_is_relative_item(
                tree,
                parent,
                (mtree_item_t)pitem->next_sibling);
    }
    return rc;
}

#ifdef __cplusplus
}
#endif

Simple C to Que by using Doubly-Linked List

/*
 * File name: m_que.h
 * Author: Seree Rakwong
 * Date: 16-SEP-2013
 *
 */

#ifndef _MQUE_H_
#define _MQUE_H_

#include "m_list.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef void* mque_t;

long    mque_init();
void    mque_release();

mque_t  mque_create();
void    mque_destroy(mque_t que);

int     mque_enque(mque_t que, const void *data, size_t size);
size_t  mque_get_que(mque_t que, void *data, size_t size);
int     mque_deque(mque_t que);
int     mque_get_count(mque_t que);
int     mque_is_empty(mque_t que);

#ifdef __cplusplus
}
#endif

#endif /* _MQUE_H_ */

/*
 * File name: m_que.c
 * Author: Seree Rakwong
 * Date: 16-SEP-2013
 *
 */
#include "m_que.h"

#define MQUE_SIGNATURE         0x51554500


#ifdef __cplusplus
extern "C" {
#endif

typedef struct mque_s
{
    mlist_t        list;
    unsigned long  signature;
} mque_s, *mque_sp;

/*
* #################### BOF helper functions ####################
*/
mque_sp mque_verify_que(mque_t que)
{
    mque_sp pque = (mque_sp)que;
    if (!pque || pque->signature != MQUE_SIGNATURE)
        return 0;

    return pque;
}

/*
#################### EOF helper functions ####################
*/
long    mque_init()
{
    return mlist_init();
}

void    mque_release()
{
    mlist_init();
}

mque_t mque_create()
{
    mque_sp pque = (mque_sp)malloc(sizeof(mque_s));
    if (!pque)
        return 0;

    pque->list = mlist_create();
    pque->signature = MQUE_SIGNATURE;

    return (mque_t)pque;
}

void mque_destroy(mque_t que)
{
    mque_sp pque = mque_verify_que(que);
    if (!pque)
        return;

    mlist_destroy(pque->list);
    free(pque);
    pque = 0;
}

int mque_enque(mque_t que, const void *data, size_t size)
{
    mque_sp pque = mque_verify_que(que);
    if (!pque)
        return 1;

    if (0 == mlist_insert_last(pque->list, data, size))
        return -1;
    return 0;
}

size_t mque_get_que(mque_t que, void *data, size_t size)
{
    mque_sp pque = mque_verify_que(que);
    if (!pque)
        return -1;
    return mlist_get_item(mlist_get_begin(pque->list), data, size);
}

int mque_deque(mque_t que)
{
    mque_sp pque = mque_verify_que(que);
    if (!pque)
        return 1;

    return mlist_remove_first(pque->list);
}

int mque_get_count(mque_t que)
{
    mque_sp pque = mque_verify_que(que);
    if (!pque)
        return -1;

    return mlist_get_count(pque->list);
}

int mque_is_empty(mque_t que)
{
    return (mque_get_count(que) == 0);
}

#ifdef __cplusplus
}
#endif