void CopyList(Item **dest, const Item *source) /* Copy a list. */ { if (*dest != NULL) { ProgrammingError("CopyList - list not initialized"); } if (source == NULL) { return; } const Item *ip = source; CYCLE_DECLARE(ip, slow, toggle); Item *backwards = NULL; while (ip != NULL) { PrependFullItem(&backwards, ip->name, ip->classes, ip->counter, ip->time); ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } *dest = ReverseItemList(backwards); }
void DeleteItem(Item **liststart, Item *item) { if (item != NULL) { if (item == *liststart) { *liststart = item->next; } else { Item *ip = *liststart; CYCLE_DECLARE(ip, slow, toggle); while (ip && ip->next != item) { ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } if (ip != NULL) { assert(ip->next == item); ip->next = item->next; } } free(item->name); free(item->classes); free(item); } }
/* Only intended for use in assertions. Note that its cost is O(list * length), so you don't want to call it inside a loop over the * list. */ static bool ItemIsInList(const Item *list, const Item *item) { CYCLE_DECLARE(list, slow, toggle); while (list) { if (list == item) { return true; } list = list->next; CYCLE_CHECK(list, slow, toggle); } return false; }
Item *EndOfList(Item *ip) { Item *prev = CF_UNDEFINED_ITEM; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { prev = ip; ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } return prev; }
/** * Write all strings in list to buffer #buf, separating them with * #separator. Watch out, no escaping happens. * * @return Final strlen(#buf), or #buf_size if string was truncated. * Always '\0'-terminates #buf (within #buf_size). */ size_t ItemList2CSV_bound(const Item *list, char *buf, size_t buf_size, char separator) { size_t space = buf_size - 1; /* Reserve one for a '\0' */ char *tail = buf; /* Point to end of what we've written. */ const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { size_t len = strlen(ip->name); assert(buf + buf_size == tail + space + 1); if (space < len) /* We must truncate */ { memcpy(tail, ip->name, space); tail[space] = '\0'; /* a.k.a. buf[buf_size - 1] */ return buf_size; /* This signifies truncation */ } else { memcpy(tail, ip->name, len); tail += len; space -= len; } /* Output separator if list has more entries. */ if (ip->next != NULL) { if (space > 0) { *tail = separator; tail++; space--; } else /* truncation */ { *tail = '\0'; return buf_size; } } ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } *tail = '\0'; return tail - buf; }
int ListLen(const Item *list) { int count = 0; const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { count++; ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } return count; }
int ItemListSize(const Item *list) { int size = 0; const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { if (ip->name) { size += strlen(ip->name); } ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } return size; }
/** * Checks whether list1 is a subset of list2, i.e. every entry in list1 must * be found in list2. */ bool ListSubsetOfList(const Item *list1, const Item *list2) { const Item *list1_ptr = list1; CYCLE_DECLARE(list1_ptr, slow, toggle); while (list1_ptr != NULL) { if (!IsItemIn(list2, list1_ptr->name)) { return false; } list1_ptr = list1_ptr->next; CYCLE_CHECK(list1_ptr, slow, toggle); } return true; /* all elements of list1 were found in list2 */ }
void SetItemListCounter(Item *list, const char *item, int value) { if (item == NULL || item[0] == '\0') { return; } Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { ptr->counter = value; return; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } }
bool ListsCompare(const Item *list1, const Item *list2) { if (ListLen(list1) != ListLen(list2)) { return false; } const Item *ptr = list1; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (IsItemIn(list2, ptr->name) == false) { return false; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return true; }
bool IsItemIn(const Item *list, const char *item) { if (item == NULL || item[0] == '\0') { return true; } const Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { return true; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return false; }
Item *ReturnItemIn(Item *list, const char *item) { if (item == NULL || item[0] == '\0') { return NULL; } Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { return ptr; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return NULL; }
void PrintItemList(const Item *list, Writer *w) { WriterWriteChar(w, '{'); const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { if (ip != list) { WriterWriteChar(w, ','); } WriterWriteChar(w, '\''); WriterWrite(w, ip->name); WriterWriteChar(w, '\''); ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } WriterWriteChar(w, '}'); }
int IsMatchItemIn(const Item *list, const char *item) /* Solve for possible regex/fuzzy models unified */ { if (item == NULL || item[0] == '\0') { return true; } const Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (FuzzySetMatch(ptr->name, item) == 0 || (IsRegex(ptr->name) && StringMatchFull(ptr->name, item))) { return true; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return false; }
int DeleteItemGeneral(Item **list, const char *string, ItemMatchType type) { if (list == NULL) { return false; } pcre *rx = NULL; if (type == ITEM_MATCH_TYPE_REGEX_COMPLETE_NOT || type == ITEM_MATCH_TYPE_REGEX_COMPLETE) { rx = CompileRegex(string); if (!rx) { return false; } } Item *ip = *list, *last = NULL; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { if (ip->name != NULL) { bool match = false, flip = false; switch (type) { case ITEM_MATCH_TYPE_LITERAL_START_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_LITERAL_START: match = (strncmp(ip->name, string, strlen(string)) == 0); break; case ITEM_MATCH_TYPE_LITERAL_COMPLETE_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_LITERAL_COMPLETE: match = (strcmp(ip->name, string) == 0); break; case ITEM_MATCH_TYPE_LITERAL_SOMEWHERE_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_LITERAL_SOMEWHERE: match = (strstr(ip->name, string) != NULL); break; case ITEM_MATCH_TYPE_REGEX_COMPLETE_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_REGEX_COMPLETE: match = StringMatchFullWithPrecompiledRegex(rx, ip->name); break; } if (flip) { match = !match; } if (match) { if (ip == *list) { *list = ip->next; } else { assert(ip != NULL); assert(last != NULL); assert(last->next == ip); last->next = ip->next; } free(ip->name); free(ip->classes); free(ip); if (rx) { pcre_free(rx); } return true; } } last = ip; ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } if (rx) { pcre_free(rx); } return false; }