U0 LinkedListDel(U8 **_list)
{//Free entire linked-list.
        U8 **tmpl;

        while (_list)
        {
                tmpl = *_list;
                Free(_list);
                _list = tmpl;
        }
}

U8 *LinkedListCopy(U8 **_list, CTask *mem_task=NULL)
{//MAlloc ident copy of entire linked-list.
        U8 *res = NULL, **tmpl = &res;

        while (_list)
        {
                tmpl = *tmpl = MAllocIdent(_list, mem_task);
                _list = *_list;
        }

        return res;
}

I64 LinkedListCount(U8 **_list)
{//Count of nodes in linked-list.
        I64 res = 0;

        while (_list)
        {
                res++;
                _list = *_list;
        }

        return res;
}

I64 LinkedListSize(U8 **_list)
{//Mem size of all nodes in linked-list.
        I64 res = 0;

        while (_list)
        {
                res += MSize2(_list);
                _list = *_list;
        }

        return res;
}

U0 QueueDel(CQueue *head, Bool querem=FALSE)
{//Free entries in queue, not head.
        CQueue *tmpq = head->next, *tmpq1;

        while (tmpq != head)
        {
                tmpq1 = tmpq->next;
                if (querem)
                        QueueRemove(tmpq);
                Free(tmpq);
                tmpq = tmpq1;
        }
}

CQueue *QueueCopy(CQueue *head, CTask *mem_task=NULL)
{//MAlloc ident copy of entire queue and head.
        CQueue *res = MAllocIdent(head, mem_task), *tmpq = head->next, *tmpq1;

        QueueInit(res);
        while (tmpq != head)
        {
                tmpq1 = MAllocIdent(tmpq, mem_task);
                QueueInsert(tmpq1, res->last);
                tmpq = tmpq->next;
        }

        return res;
}

I64 QueueCount(CQueue *head)
{//Count of nodes in queue, not head.
        CQueue  *tmpq = head->next;
        I64              res = 0;

        while (tmpq != head)
        {
                res++;
                tmpq = tmpq->next;
        }

        return res;
}

I64 QueueSize(CQueue *head)
{//Mem size of all nodes in queue, not head.
        CQueue  *tmpq = head->next;
        I64              res = 0;

        while (tmpq != head)
        {
                res += MSize2(tmpq);
                tmpq = tmpq->next;
        }

        return res;
}

CQueueVectU8 *QueueVectU8New(I64 min_idx=0)
{//Create new queue vecter.
        CQueueVectU8 *res = MAlloc(sizeof(CQueueVectU8));

        QueueInit(res);
        res->total_count = res->node_count = 0;
        res->min_idx = min_idx;

        return res;
}

U0 QueueVectU8Put(CQueueVectU8 *v, I64 idx, U8 ch)
{//Put U8 at idx i.
        CQueueVectU8 *tmpv;

        idx -= v->min_idx;
        if (idx<0)
                return;
        if (idx<v->total_count)
        {
                tmpv = v;
                do
                {
                        idx -= tmpv->node_count;
                        if (idx < 0)
                        {
                                tmpv->body[idx + tmpv->node_count] = ch;
                                return;
                        }
                        tmpv = tmpv->next;
                }
                while (tmpv != v);

        }
        else
                idx -= v->total_count;

        while (TRUE)
        {
                tmpv = v->last;
                if (tmpv->node_count >= QUE_VECT_U8_COUNT)
                {
                        tmpv = MAlloc(sizeof(CQueueVectU8));
                        tmpv->node_count = 0;
                        QueueInsert(tmpv, v->last);
                }
                if (idx--)
                {
                        tmpv->body[tmpv->node_count++] = 0;
                        v->total_count++;
                }
                else
                {
                        tmpv->body[tmpv->node_count++] = ch;
                        v->total_count++;
                        break;
                }
        }
}

U0 QueueVectU8Del(CQueueVectU8 *v)
{//Free entire queue vector.
        if (v)
        {
                QueueDel(v);
                Free(v);
        }
}

I64 QueueVectU8Get(CQueueVectU8 *v, I64 idx)
{//Get U8 at idx i.
        CQueueVectU8 *tmpv;

        idx -= v->min_idx;
        if (!(0 <= idx<v->total_count))
                return 0;
        tmpv = v;
        do
        {
                idx -= tmpv->node_count;
                if (idx < 0)
                        return tmpv->body[idx + tmpv->node_count];
                tmpv = tmpv->next;
        }
        while (tmpv != v);

        return 0;
}

CFifoU8 *FifoU8New(I64 size, CTask *mem_task=NULL)
{//Create new fifo.
        CFifoU8 *f;

        if (!mem_task)
                mem_task = Fs;

        f = MAlloc(sizeof(CFifoU8), mem_task);
        f->buf          = MAlloc(size, mem_task);
        f->mask         = size - 1;
        f->in_ptr       = 0;
        f->out_ptr      = 0;

        return f;
}

U0 FifoU8Del(CFifoU8 *f)
{//Free fifo.
        Free(f->buf);
        Free(f);
}

Bool FifoU8Insert(CFifoU8 *f, U8 b)
{//Insert U8 into fifo.
        I64 new_in_ptr;

        PUSHFD
        CLI
        new_in_ptr = (f->in_ptr + 1) & f->mask;
        if (new_in_ptr == f->out_ptr)
        {
                POPFD
                return FALSE;
        }
        else
        {
                f->buf[f->in_ptr] = b;
                f->in_ptr = new_in_ptr;
                POPFD
                return TRUE;
        }
}

Bool FifoU8Remove(CFifoU8 *f, U8 *_b)
{//Remove U8 from fifo.
        PUSHFD
        CLI
        if (f->in_ptr == f->out_ptr)
        {
                POPFD
                return FALSE;
        }
        else
        {
                *_b = f->buf[f->out_ptr];
                f->out_ptr = (f->out_ptr + 1) & f->mask;
                POPFD
                return TRUE;
        }
}

Bool FifoU8Peek(CFifoU8 *f, U8 *_b)
{//Peek at front of fifo and don't remove.
        PUSHFD
        CLI
        if (f->in_ptr == f->out_ptr)
        {
                POPFD
                return FALSE;
        }
        else
        {
                *_b = f->buf[f->out_ptr];
                POPFD
                return TRUE;
        }
}

U0 FifoU8Flush(CFifoU8 *f)
{//Flush fifo getting rid of all U8's.
        PUSHFD
        CLI
        f->out_ptr = f->in_ptr;
        POPFD
}

I64 FifoU8Count(CFifoU8 *f)
{//Count of U8's in fifo.
        I64 res;

        PUSHFD
        CLI
        if (f->out_ptr > f->in_ptr)
                res = f->mask + 1 - (f->out_ptr - f->in_ptr);
        else
                res = f->in_ptr - f->out_ptr;
        POPFD

        return res;
}

CFifoI64 *FifoI64New(I64 size, CTask *mem_task=NULL)
{//Create new fifo.
        CFifoI64 *f;

        if (!mem_task)
                mem_task = Fs;

        f = MAlloc(sizeof(CFifoI64), mem_task);
        f->buf          = MAlloc(size * sizeof(I64), mem_task);
        f->mask         = size - 1;
        f->in_ptr       = 0;
        f->out_ptr      = 0;

        return f;
}

U0 FifoI64Del(CFifoI64 *f)
{//Free fifo.
        Free(f->buf);
        Free(f);
}

Bool FifoI64Ins(CFifoI64 *f, I64 q)
{//Insert I64 into fifo.
        I64 new_in_ptr;

        PUSHFD
        CLI
        new_in_ptr = (f->in_ptr + 1) & f->mask;
        if (new_in_ptr == f->out_ptr)
        {
                POPFD
                return FALSE;
        }
        else
        {
                f->buf[f->in_ptr] = q;
                f->in_ptr = new_in_ptr;
                POPFD
                return TRUE;
        }
}

Bool FifoI64Remove(CFifoI64 *f, I64 *_q)
{//Remove I64 from fifo.
        PUSHFD
        CLI
        if (f->in_ptr == f->out_ptr)
        {
                POPFD
                return FALSE;
        }
        else
        {
                *_q = f->buf[f->out_ptr];
                f->out_ptr = (f->out_ptr + 1) & f->mask;
                POPFD
                return TRUE;
        }
}

Bool FifoI64Peek(CFifoI64 *f, I64 *_q)
{//Peek at front of fifo and don't remove.
        PUSHFD
        CLI
        if (f->in_ptr == f->out_ptr)
        {
                POPFD
                return FALSE;
        }
        else
        {
                *_q = f->buf[f->out_ptr];
                POPFD
                return TRUE;
        }
}

U0 FifoI64Flush(CFifoI64 *f)
{//Flush fifo getting rid of all I64's.
        PUSHFD
        CLI
        f->out_ptr = f->in_ptr;
        POPFD
}

I64 FifoI64Count(CFifoI64 *f)
{//Count of I64's in fifo.
        I64 res;

        PUSHFD
        CLI
        if (f->out_ptr > f->in_ptr)
                res = f->mask + 1 - (f->out_ptr - f->in_ptr);
        else
                res = f->in_ptr - f->out_ptr;
        POPFD

        return res;
}