238 lines
7.0 KiB
C
238 lines
7.0 KiB
C
/*
|
|
* $Id: strlist.c 443 2006-05-30 04:37:13Z darren $
|
|
*
|
|
* Copyright (c) 1999-2002, Darren Hiebert
|
|
*
|
|
* This source code is released for free distribution under the terms of the
|
|
* GNU General Public License.
|
|
*
|
|
* This module contains functions managing resizable string lists.
|
|
*/
|
|
#include "third_party/ctags/general.h"
|
|
/* must always come first */
|
|
#include "third_party/ctags/debug.h"
|
|
#include "third_party/ctags/read.h"
|
|
#include "third_party/ctags/routines.h"
|
|
#include "third_party/ctags/strlist.h"
|
|
#include "third_party/musl/fnmatch.h"
|
|
|
|
/*
|
|
* FUNCTION DEFINITIONS
|
|
*/
|
|
|
|
extern stringList *stringListNew(void) {
|
|
stringList *const result = xMalloc(1, stringList);
|
|
result->max = 0;
|
|
result->count = 0;
|
|
result->list = NULL;
|
|
return result;
|
|
}
|
|
|
|
extern void stringListAdd(stringList *const current, vString *string) {
|
|
enum { incrementalIncrease = 10 };
|
|
Assert(current != NULL);
|
|
if (current->list == NULL) {
|
|
Assert(current->max == 0);
|
|
current->count = 0;
|
|
current->max = incrementalIncrease;
|
|
current->list = xMalloc(current->max, vString *);
|
|
} else if (current->count == current->max) {
|
|
current->max += incrementalIncrease;
|
|
current->list = xRealloc(current->list, current->max, vString *);
|
|
}
|
|
current->list[current->count++] = string;
|
|
}
|
|
|
|
extern void stringListRemoveLast(stringList *const current) {
|
|
Assert(current != NULL);
|
|
Assert(current->count > 0);
|
|
--current->count;
|
|
current->list[current->count] = NULL;
|
|
}
|
|
|
|
/* Combine list `from' into `current', deleting `from' */
|
|
extern void stringListCombine(stringList *const current,
|
|
stringList *const from) {
|
|
unsigned int i;
|
|
Assert(current != NULL);
|
|
Assert(from != NULL);
|
|
for (i = 0; i < from->count; ++i) {
|
|
stringListAdd(current, from->list[i]);
|
|
from->list[i] = NULL;
|
|
}
|
|
stringListDelete(from);
|
|
}
|
|
|
|
extern stringList *stringListNewFromArgv(const char *const *const argv) {
|
|
stringList *const result = stringListNew();
|
|
const char *const *p;
|
|
Assert(argv != NULL);
|
|
for (p = argv; *p != NULL; ++p) stringListAdd(result, vStringNewInit(*p));
|
|
return result;
|
|
}
|
|
|
|
extern stringList *stringListNewFromFile(const char *const fileName) {
|
|
stringList *result = NULL;
|
|
FILE *const fp = fopen(fileName, "r");
|
|
if (fp != NULL) {
|
|
result = stringListNew();
|
|
while (!feof(fp)) {
|
|
vString *const str = vStringNew();
|
|
readLine(str, fp);
|
|
vStringStripTrailing(str);
|
|
if (vStringLength(str) > 0)
|
|
stringListAdd(result, str);
|
|
else
|
|
vStringDelete(str);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
extern unsigned int stringListCount(const stringList *const current) {
|
|
Assert(current != NULL);
|
|
return current->count;
|
|
}
|
|
|
|
extern vString *stringListItem(const stringList *const current,
|
|
const unsigned int indx) {
|
|
Assert(current != NULL);
|
|
return current->list[indx];
|
|
}
|
|
|
|
extern vString *stringListLast(const stringList *const current) {
|
|
Assert(current != NULL);
|
|
Assert(current->count > 0);
|
|
return current->list[current->count - 1];
|
|
}
|
|
|
|
extern void stringListClear(stringList *const current) {
|
|
unsigned int i;
|
|
Assert(current != NULL);
|
|
for (i = 0; i < current->count; ++i) {
|
|
vStringDelete(current->list[i]);
|
|
current->list[i] = NULL;
|
|
}
|
|
current->count = 0;
|
|
}
|
|
|
|
extern void stringListDelete(stringList *const current) {
|
|
if (current != NULL) {
|
|
if (current->list != NULL) {
|
|
stringListClear(current);
|
|
eFree(current->list);
|
|
current->list = NULL;
|
|
}
|
|
current->max = 0;
|
|
current->count = 0;
|
|
eFree(current);
|
|
}
|
|
}
|
|
|
|
static boolean compareString(const char *const string, vString *const itm) {
|
|
return (boolean)(strcmp(string, vStringValue(itm)) == 0);
|
|
}
|
|
|
|
static boolean compareStringInsensitive(const char *const string,
|
|
vString *const itm) {
|
|
return (boolean)(strcasecmp(string, vStringValue(itm)) == 0);
|
|
}
|
|
|
|
static int stringListIndex(const stringList *const current,
|
|
const char *const string,
|
|
boolean (*test)(const char *s, vString *const vs)) {
|
|
int result = -1;
|
|
unsigned int i;
|
|
Assert(current != NULL);
|
|
Assert(string != NULL);
|
|
Assert(test != NULL);
|
|
for (i = 0; result == -1 && i < current->count; ++i)
|
|
if ((*test)(string, current->list[i])) result = i;
|
|
return result;
|
|
}
|
|
|
|
extern boolean stringListHas(const stringList *const current,
|
|
const char *const string) {
|
|
boolean result = FALSE;
|
|
Assert(current != NULL);
|
|
result = stringListIndex(current, string, compareString) != -1;
|
|
return result;
|
|
}
|
|
|
|
extern boolean stringListHasInsensitive(const stringList *const current,
|
|
const char *const string) {
|
|
boolean result = FALSE;
|
|
Assert(current != NULL);
|
|
Assert(string != NULL);
|
|
result = stringListIndex(current, string, compareStringInsensitive) != -1;
|
|
return result;
|
|
}
|
|
|
|
extern boolean stringListHasTest(const stringList *const current,
|
|
boolean (*test)(const char *s)) {
|
|
boolean result = FALSE;
|
|
unsigned int i;
|
|
Assert(current != NULL);
|
|
for (i = 0; !result && i < current->count; ++i)
|
|
result = (*test)(vStringValue(current->list[i]));
|
|
return result;
|
|
}
|
|
|
|
extern boolean stringListRemoveExtension(stringList *const current,
|
|
const char *const extension) {
|
|
boolean result = FALSE;
|
|
int where;
|
|
#ifdef CASE_INSENSITIVE_FILENAMES
|
|
where = stringListIndex(current, extension, compareStringInsensitive);
|
|
#else
|
|
where = stringListIndex(current, extension, compareString);
|
|
#endif
|
|
if (where != -1) {
|
|
memmove(current->list + where, current->list + where + 1,
|
|
(current->count - where) * sizeof(*current->list));
|
|
current->list[current->count - 1] = NULL;
|
|
--current->count;
|
|
result = TRUE;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
extern boolean stringListExtensionMatched(const stringList *const current,
|
|
const char *const extension) {
|
|
#ifdef CASE_INSENSITIVE_FILENAMES
|
|
return stringListHasInsensitive(current, extension);
|
|
#else
|
|
return stringListHas(current, extension);
|
|
#endif
|
|
}
|
|
|
|
static boolean fileNameMatched(const vString *const vpattern,
|
|
const char *const fileName) {
|
|
const char *const pattern = vStringValue(vpattern);
|
|
#if defined(HAVE_FNMATCH)
|
|
return (boolean)(fnmatch(pattern, fileName, 0) == 0);
|
|
#elif defined(CASE_INSENSITIVE_FILENAMES)
|
|
return (boolean)(strcasecmp(pattern, fileName) == 0);
|
|
#else
|
|
return (boolean)(strcmp(pattern, fileName) == 0);
|
|
#endif
|
|
}
|
|
|
|
extern boolean stringListFileMatched(const stringList *const current,
|
|
const char *const fileName) {
|
|
boolean result = FALSE;
|
|
unsigned int i;
|
|
for (i = 0; !result && i < stringListCount(current); ++i)
|
|
result = fileNameMatched(stringListItem(current, i), fileName);
|
|
return result;
|
|
}
|
|
|
|
extern void stringListPrint(const stringList *const current) {
|
|
unsigned int i;
|
|
Assert(current != NULL);
|
|
for (i = 0; i < current->count; ++i)
|
|
printf("%s%s", (i > 0) ? ", " : "", vStringValue(current->list[i]));
|
|
}
|
|
|
|
/* vi:set tabstop=4 shiftwidth=4: */
|