/* Copyright (c) 1993 Stephen F. White */ #include "cool.h" #include "proto.h" static List *doinsert (List * list, Var value, int pos); static int sort_up(const void *a, const void *b); static int sort_down(const void *a, const void *b); List *list_new (int size) { List *new; new = MALLOC (List, 1); new->len = size; new->ref = 1; if (size) { new->el = MALLOC (Var, size); } else { new->el = 0; } new->mem = size; return new; } List *list_setadd (List * list, Var value) { List *ret; ret = list; if (list_ismember (value, list)) { var_free (value); return ret; } return list_append (list, value, 0); } List *list_setremove (List * list, Var value) { List *ret; int t; ret = list; if ((t = list_ismember (value, list))) { ret = list_delete (list, t); } return ret; } int list_ismember (Var element, List * list) { int i; for (i = 0; i < list->len; i++) { if (var_eq (element, list->el[i])) { return i + 1; } } return 0; } List *list_assign (List * list, Var value, int pos) { List *new; int i; if (list->ref == 1) { var_free (list->el[pos - 1]); list->el[pos - 1] = value; return list; } new = list_new(list->len); for (i = 0; i < list->len; i++) { if (i == pos - 1) { new->el[i] = value; } else { new->el[i] = var_dup (list->el[i]); } } list_free (list); return new; } static List *doinsert (List * list, Var value, int pos) { List *new; int i; new = list_new (list->len + 1); for (i = 0; i < pos - 1; i++) { new->el[i] = var_dup (list->el[i]); } new->el[pos - 1] = value; for (i = pos; i < new->len; i++) { new->el[i] = var_dup (list->el[i - 1]); } list_free (list); return new; } List *list_insert (List * list, Var value, int pos) { if (pos < 1 || pos > list->len) { pos = 1; } return (doinsert (list, value, pos)); } List *list_append (List * list, Var value, int pos) { if (pos < 1 || pos > list->len) { pos = list->len; } return (doinsert (list, value, pos + 1)); } List *list_delete (List * list, int pos) { List *new; int i; new = list_new (list->len - 1); for (i = 0; i < pos - 1; i++) { new->el[i] = var_dup (list->el[i]); } for (i = pos - 1; i < new->len; i++) { new->el[i] = var_dup (list->el[i + 1]); } list_free (list); /* free old list */ return new; } List *list_subset (List * list, int lower, int upper) { List *r; int i; r = list_new (upper - lower + 1); for (i = lower - 1; i < upper; i++) { r->el[i - lower + 1] = var_dup (list->el[i]); } return r; } #ifdef INLINE void list__free (List * list) { int i; for (i = 0; i < list->len; i++) { var_free (list->el[i]); } if (list->len) { FREE (list->el); } FREE (list); } #else /* !INLINE */ void list_free (List * list) { int i; if (!--list->ref) { for (i = 0; i < list->len; i++) { var_free (list->el[i]); } if (list->len) { FREE (list->el); } FREE (list); } } List *list_dup (List * list) { list->ref++; return list; } #endif /* !INLINE */ List *explode (const char *str, const char *sep, int nwords) { const char *word_start; List *list = list_new (nwords); int i; for (i = 0; i < nwords; i++) { while ( *str && strncmp( str, sep, strlen( sep ) ) == 0 ) { str += strlen( sep ); } word_start = str; /* skip to next separator */ while (*str && strncmp( str, sep, strlen( sep ) ) != 0 ) { str++; } list->el[i].type = STR; list->el[i].v.str = string_ncpy (word_start, str - word_start); } return list; } List * list_sort(List *list, int reverse) { List *ret; int i; if (list->ref == 1) { ret = list; } else { ret = list_new(list->len); for (i = 0; i < list->len; i++) { ret->el[i] = var_dup(list->el[i]); } list_free(list); } qsort(ret->el, ret->len, sizeof(Var), (reverse ? sort_down : sort_up)); return ret; } static int sort_up(const void *a, const void *b) { return var_compare(*((const Var *) a), *((const Var *) b)); } static int sort_down(const void *a, const void *b) { return var_compare(*((const Var *) b), *((const Var *) a)); }