⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stddll.c

📁 spines-ns
💻 C
字号:
/* Copyright (c) 2000, The Johns Hopkins University * All rights reserved. * * The contents of this file are subject to a license (the ``License'') * that is the exact equivalent of the BSD license as of July 23, 1999.  * You may not use this file except in compliance with the License. The * specific language governing the rights and limitations of the License * can be found in the file ``STDUTIL_LICENSE'' found in this  * distribution. * * Software distributed under the License is distributed on an AS IS  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  * * The Original Software is: *     The Stdutil Library *  * Contributors: *     Creator - John Lane Schultz (jschultz@cnds.jhu.edu) *     The Center for Networking and Distributed Systems *         (CNDS - http://www.cnds.jhu.edu) */ #include <stdlib.h>#ifdef USE_DMALLOC#include <dmalloc.h>#endif#include <string.h>#include "stdutil/stdutil.h"#include "stdutil/stderror.h"#include "stdutil/stddll.h"#ifdef STD_CONSTRUCT_CHECKS# define IS_DLL_INITED(list) ((list)->init_val == STDDLL_INITED)# define INIT_DLL(list)      ((list)->init_val = STDDLL_INITED)# define UNINIT_DLL(list)    ((list)->init_val = ~STDDLL_INITED)# define IS_IT_INITED(it)    ((it)->it_init_val == STDDLL_IT_INITED)# define INIT_IT(it)         ((it)->it_init_val = STDDLL_IT_INITED)#else# define IS_DLL_INITED(list)# define INIT_DLL(list)# define UNINIT_DLL(list)# define IS_IT_INITED(it)# define INIT_IT(it)#endif/* pointer to value appended to a list node */#define NVAL(node_ptr)   ((node_ptr)->val)/* pointer to the beginning node of a list */#define LBEGIN(list_ptr) ((list_ptr)->end_node.next)/* pointer to the end node of a list */#define LEND(list_ptr)   (&(list_ptr)->end_node)/* This fcn allocates a sequence of linked nodes of _non-zero_ length   len. It returns pointers to the first and last nodes. The sequence   is null terminated on both ends. On success it returns STD_SUCCESS.*/inline static int alloc_seq(stddll *l, size_t request_len,			    stddll_node **first, stddll_node **last) {  stddll_node *prev, *curr;  STD_SAFE_CHECK(request_len != 0);  /* append values on to end of node in memory */  if (!(curr = (stddll_node*) malloc(sizeof(stddll_node))))    return STD_MEM_FAILURE;  if (!(curr->val = malloc(l->vsize))) {    free(curr);    return STD_MEM_FAILURE;  }  *first = curr;  curr->prev = 0;  while (--request_len) {    prev = curr;    if (!(curr = (stddll_node*) malloc(sizeof(stddll_node))))      goto alloc_seq_fail;    if (!(curr->val = malloc(l->vsize))) {      free(curr);      goto alloc_seq_fail;    }    prev->next = curr;    curr->prev = prev;  }  curr->next = 0;  *last = curr;  return STD_SUCCESS; alloc_seq_fail:  while (prev) {    curr = prev->prev;    free(prev->val);    free(prev);    prev = curr;  }  return STD_MEM_FAILURE;}/* This fcn inserts a _non-empty_ sequence of linked nodes into a list before next. */inline static void linsert(stddll *l, stddll_node *next, size_t num_insert,			   stddll_node *first, stddll_node *last) {  stddll_node *prev = next->prev;  first->prev = prev;  last->next  = next;  prev->next  = first;  next->prev  = last;  l->size += num_insert;}/* This fcn allocates and inserts a sequence of linked nodes into a   list before next. It returns a pointer to the first node of the   inserted sequence, next if the sequence is empty, and 0 on failure.  */inline static stddll_node *insert_space(stddll *l, stddll_node *next, size_t num_insert) {  stddll_node *first, *last;  if (!num_insert)    return next;  if (alloc_seq(l, num_insert, &first, &last) != STD_SUCCESS)    return 0;           /* failure */  linsert(l, next, num_insert, first, last);  return first;}/* Erase a subsequence of the list starting at erase_begin of length   num_erase. It returns a pointer to the node that is shifted into    the position of erase_begin after the removal.*/inline static stddll_node *erase(stddll *l, stddll_node *erase_begin, size_t num_erase) {  stddll_node *prev, *curr = erase_begin;  erase_begin = erase_begin->prev;  /* get last node before erase region */  l->size -= num_erase;  while (num_erase--) {    STD_BOUNDS_CHECK(curr != LEND(l));  /* don't ever free end */    prev = curr;    curr = curr->next;    free(prev->val);    free(prev);  }  erase_begin->next = curr;  curr->prev        = erase_begin;  return curr;}/* Same as above, except the erase region ends just before erase_end   and is of length num_erase.*/inline static stddll_node *rerase(stddll *l, stddll_node *erase_end, size_t num_erase) {  stddll_node *prev, *curr = erase_end->prev;  l->size -= num_erase;  while (num_erase--) {    STD_BOUNDS_CHECK(curr != LEND(l)); /* don't allow a wrap around to delete end */    prev = curr;    curr = curr->prev;    free(prev->val);    free(prev);  }  curr->next      = erase_end;  erase_end->prev = curr;  return erase_end;}inline static size_t sizeof_val(const stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  return it->list->vsize;}/**************************** stddll_it interface *********************************/inline void *stddll_it_val(const stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  return NVAL(it->node);}inline stdbool stddll_it_equals(const stddll_it *it1, const stddll_it *it2) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it1) && IS_IT_INITED(it2));  STD_CONSTRUCT_CHECK(IS_DLL_INITED(it1->list) && IS_DLL_INITED(it2->list));  STD_BOUNDS_CHECK(it1->list == it2->list);  return it1->node == it2->node;}inline stdbool stddll_it_is_begin(const stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  return it->node == LBEGIN(it->list);}inline stdbool stddll_it_is_end(const stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  return it->node == LEND(it->list);}inline stddll_it *stddll_it_seek_begin(stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  it->node = LBEGIN(it->list);  return it;}inline stddll_it *stddll_it_seek_end(stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  it->node = LEND(it->list);  return it;}inline stddll_it *stddll_it_next(stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  STD_BOUNDS_CHECK(it->node != LEND(it->list));  it->node = it->node->next;  return it;}inline stddll_it *stddll_it_advance(stddll_it *it, size_t num_advance) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  while (num_advance--) {    STD_BOUNDS_CHECK(it->node != LEND(it->list));    it->node = it->node->next;  }  return it;}inline stddll_it *stddll_it_prev(stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  STD_BOUNDS_CHECK(it->node != LBEGIN(it->list));  it->node = it->node->prev;  return it;}inline stddll_it *stddll_it_retreat(stddll_it *it, size_t num_retreat) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  while (num_retreat--) {    STD_BOUNDS_CHECK(it->node != LBEGIN(it->list));    it->node = it->node->prev;  }  return it;}/***************************** stddll iterface ************************************//* Constructors, Destructor */inline int stddll_construct(stddll *l, size_t sizeof_val) {  STD_CONSTRUCT_CHECK(!IS_DLL_INITED(l));  if (!(l->vsize = sizeof_val))    return STD_ERROR(STD_ILLEGAL_PARAM);  l->size          = 0;  l->end_node.prev = &l->end_node;  l->end_node.next = &l->end_node;  l->end_node.val  = 0;  INIT_DLL(l);  return STD_SUCCESS;}inline int stddll_copy_construct(stddll *dst, const stddll *src) {  stddll_node *node1, *node2;  int ret;  STD_CONSTRUCT_CHECK(IS_DLL_INITED(src));  if ((ret = stddll_construct(dst, src->vsize)) != STD_SUCCESS)    return STD_ERROR(ret);  if (!(node1 = insert_space(dst, LEND(dst), src->size)))    return STD_ERROR(STD_MEM_FAILURE);  node2 = LBEGIN(src);  for (; node1 != LEND(dst); node1 = node1->next, node2 = node2->next)    memcpy(NVAL(node1), NVAL(node2), dst->vsize);   return STD_SUCCESS;}inline void stddll_destruct(stddll *l) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  stddll_clear(l);  UNINIT_DLL(l);}/* Iterator Interface */inline stddll_it *stddll_begin(const stddll *l, stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  it->list = (stddll*) l;  it->node = (stddll_node*) LBEGIN(l);  INIT_IT(it);  return it;}inline stddll_it *stddll_last(const stddll *l, stddll_it *it) {  return stddll_it_prev(stddll_end(l, it));}inline stddll_it *stddll_end(const stddll *l, stddll_it *it) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  it->list = (stddll*) l;  it->node = (stddll_node*) LEND(l);  INIT_IT(it);  return it;}inline stddll_it *stddll_get(const stddll *l, stddll_it *it, size_t elem_num) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  STD_BOUNDS_CHECK(elem_num <= stddll_size(l));  if (elem_num < stddll_size(l) >> 1)    return stddll_it_advance(stddll_begin(l, it), elem_num);  else    return stddll_it_retreat(stddll_end(l, it), stddll_size(l) - elem_num);}/* Size Information */inline size_t stddll_size(const stddll *l) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  return l->size;}inline stdbool stddll_empty(const stddll *l) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  return l->size == 0;}inline size_t stddll_max_size(const stddll *l) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  return STD_SIZE_T_MAX;}inline size_t stddll_val_size(const stddll *l) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  return l->vsize;}/* Size Operations */inline int stddll_resize(stddll *l, size_t num_elems) {  stdssize_t diff;  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  if ((diff = num_elems - l->size) > 0) {    if (!insert_space(l, LEND(l), (size_t) diff))      return STD_ERROR(STD_MEM_FAILURE);  } else if (diff < 0)    rerase(l, LEND(l), (size_t) -diff);   return STD_SUCCESS;}inline int stddll_clear(stddll *l) {  return stddll_resize(l, 0);}/* Stack Operations: O(1) operations */inline int stddll_push_front(stddll *l, const void *val) {  return stddll_multi_push_front(l, val, 1);}inline int stddll_pop_front(stddll *l) {  return stddll_multi_pop_front(l, 1);}inline int stddll_push_back(stddll *l, const void *val) {  return stddll_multi_push_back(l, val, 1);}inline int stddll_pop_back(stddll *l) {  return stddll_multi_pop_back(l, 1);}inline int stddll_multi_push_front(stddll *l, const void *vals, size_t num_push) {  stddll_it it;  if (stddll_multi_insert(stddll_begin(l, &it), vals, num_push))    return STD_SUCCESS;  else    return STD_ERROR(STD_MEM_FAILURE);}inline int stddll_multi_pop_front(stddll *l, size_t num_pop) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  STD_BOUNDS_CHECK(num_pop <= stddll_size(l));  erase(l, LBEGIN(l), num_pop);  return STD_SUCCESS;}inline int stddll_multi_push_back(stddll *l, const void *vals, size_t num_push) {  stddll_it it;  if (stddll_multi_insert(stddll_end(l, &it), vals, num_push))    return STD_SUCCESS;  else    return STD_ERROR(STD_MEM_FAILURE);}inline int stddll_multi_pop_back(stddll *l, size_t num_pop) {  STD_CONSTRUCT_CHECK(IS_DLL_INITED(l));  STD_BOUNDS_CHECK(num_pop <= stddll_size(l));  rerase(l, LEND(l), num_pop);  return STD_SUCCESS;}/* List Operations: O(1) operations */inline stddll_it *stddll_insert(stddll_it *it, const void *val) {  return stddll_multi_insert(it, val, 1);}inline stddll_it *stddll_erase(stddll_it *it) {  return stddll_multi_erase(it, 1);}inline stddll_it *stddll_repeat_insert(stddll_it *it, const void *val, size_t num_times) {  stddll_node *first;  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  if (!(first = insert_space(it->list, it->node, num_times)))    return (stddll_it*) STD_ERROR(STD_MEM_FAILURE2);  it->node = first;  for (; num_times--; first = first->next)    memcpy(NVAL(first), val, it->list->vsize);  return it;}inline stddll_it *stddll_multi_insert(stddll_it *it, const void *vals, size_t num_insert) {  stddll_node *first;  char *vals_ptr;  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  if (!(first = insert_space(it->list, it->node, num_insert)))    return (stddll_it*) STD_ERROR(STD_MEM_FAILURE2);  it->node = first;  for (vals_ptr = (char*) vals; num_insert--; first = first->next, vals_ptr += it->list->vsize)    memcpy(NVAL(first), vals_ptr, it->list->vsize);  return it;}inline stddll_it *stddll_multi_erase(stddll_it *it, size_t num_erase) {  STD_CONSTRUCT_CHECK(IS_IT_INITED(it) && IS_DLL_INITED(it->list));  it->node = erase(it->list, it->node, num_erase);  return it;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -