From 5d2c2b27a6323e2666378b986129b2a7c2c39e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 6 Feb 2022 16:04:24 +0100 Subject: New upstream version 5.2.2GA --- app/bin/partcatalog.c | 1250 +++++++++++++++++++++++++++++-------------------- 1 file changed, 752 insertions(+), 498 deletions(-) (limited to 'app/bin/partcatalog.c') diff --git a/app/bin/partcatalog.c b/app/bin/partcatalog.c index a1db09c..25ae024 100644 --- a/app/bin/partcatalog.c +++ b/app/bin/partcatalog.c @@ -1,7 +1,7 @@ /** \file partcatalog.c * Manage the catalog of track parameter files */ -/* XTrkCad - Model Railroad CAD +/* XTrackCAD - Model Railroad CAD * Copyright (C) 2019 Martin Fischer * * This program is free software; you can redistribute it and/or modify @@ -19,41 +19,27 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include -#ifdef HAVE_MALLOC_H -#include -#endif -#include -#include -#include -#include -#include - -#include -#include - -#ifdef WINDOWS - #include "include/dirent.h" -#else - #include -#endif +#include "dynstring.h" #include "fileio.h" +#include "include/levenshtein.h" #include "misc.h" +#include "misc2.h" #include "include/paramfile.h" #include "include/partcatalog.h" #include "paths.h" #include "include/stringxtc.h" #include "include/utf8convert.h" - -#if _MSC_VER > 1300 - #define strnicmp _strnicmp - #define strdup _strdup -#endif +#include "include/utlist.h" #define PUNCTUATION "+-*/.,&%=#" +#define SEARCHDELIMITER " \t\n\r/" +#define LDISTANCELIMIT (2) +static char *stopwords = { + "scale", +}; +static int log_params; /** * Create and initialize the linked list for the catalog entries @@ -61,22 +47,46 @@ * \return pointer to first element */ -CatalogEntry * +Catalog * InitCatalog(void) { - CatalogEntry *head; - CatalogEntry *tail; - - /* allocate two pseudo nodes for beginning and end of list */ - head = (CatalogEntry *)malloc(sizeof(CatalogEntry)); - tail = (CatalogEntry *)malloc(sizeof(CatalogEntry)); - - head->next = tail; - tail->next = tail; + Catalog *newCatalog = MyMalloc(sizeof(Catalog)); + if (newCatalog) { + newCatalog->head = NULL; + } + return (newCatalog); +} +/** + * Destroys the catalog + * + * \param [in] catalog + */ +void +DestroyCatalog(Catalog *catalog) +{ + CatalogEntry *current = catalog->head; + CatalogEntry *entry = NULL; + CatalogEntry *tmp = NULL, *old = NULL; + DL_FOREACH_SAFE(current, entry, tmp) + { + //if (old) MyFree(old); + old = NULL; + for (unsigned int i = 0; i < entry->files; i++) { + MyFree(entry->fullFileName[i]); + entry->fullFileName[i] = NULL; + } + entry->files = 0; + MyFree(entry->contents); + entry->contents = NULL; + MyFree(entry->tag); + entry->tag = NULL; + old = entry; + DL_DELETE(catalog->head,entry); + } - return (head); + catalog->head = NULL; } /** @@ -90,32 +100,30 @@ InitCatalog(void) static CatalogEntry * InsertIntoCatalogAfter(CatalogEntry *entry) { - CatalogEntry *newEntry = (CatalogEntry *)malloc(sizeof(CatalogEntry)); + CatalogEntry *newEntry = (CatalogEntry *)MyMalloc(sizeof(CatalogEntry)); newEntry->next = entry->next; + newEntry->prev = entry; entry->next = newEntry; newEntry->files = 0; newEntry->contents = NULL; + newEntry->tag = NULL; return (newEntry); } /** - * Count the elements in the linked list ignoring dummy elements + * Count the elements in the linked list * - * \param listHeader IN the linked list - * \return the numberof elements + * \param catalog IN + * \return the number of elements */ unsigned -CountCatalogEntries(CatalogEntry *listHeader) +CountCatalogEntries(Catalog *catalog) { - CatalogEntry *currentEntry = listHeader->next; + CatalogEntry * entry; unsigned count = 0; - - while (currentEntry != currentEntry->next) { - count++; - currentEntry = currentEntry->next; - } + DL_COUNT(catalog->head, entry, count); return (count); } @@ -125,70 +133,96 @@ CountCatalogEntries(CatalogEntry *listHeader) * \param listHeader IN the list */ -void -EmptyCatalog(CatalogEntry *listHeader) +EXPORT void +CatalogDiscard(Catalog *catalog) { - CatalogEntry *current = listHeader; - - while (current->next != current->next->next) { - CatalogEntry *removedElement; - removedElement = current->next; - current->next = current->next->next; - if (removedElement->contents) { - free(removedElement->contents); - } - for (unsigned int i = 0; i < removedElement->files; i++) { - free(removedElement->fullFileName[i]); - } - free(removedElement); + CatalogEntry *current = catalog->head; + CatalogEntry *element; + CatalogEntry *tmp,*old = NULL; + + DL_FOREACH_SAFE(current, element, tmp) { + //if (old) MyFree(old); + old = NULL; + MyFree(element->contents); + element->contents = NULL; + MyFree(element->tag); + element->tag = NULL; + for (unsigned int i = 0; i < element->files; i++) { + MyFree(element->fullFileName[i]); + element->fullFileName[i] = NULL; + } + element->files = 0; + old = element; + DL_DELETE(catalog->head,element); } + + catalog->head = NULL; } /** - * Find the position in the list and add + * Compare entries * - * \param listHeader IN start of list - * \param contents IN contents to include + * \param [in] a If non-null, a CatalogEntry to compare. + * \param [in] b If non-null, a CatalogEntry to compare. * - * \return CatalogEntry if found, NULL otherwise + * \returns An int. */ -static CatalogEntry * -InsertInOrder(CatalogEntry *listHeader, const char *contents) +static int +CompareEntries(CatalogEntry *a, CatalogEntry *b) { - CatalogEntry *currentEntry = listHeader; + return XtcStricmp(a->contents, b->contents); +} - while (currentEntry->next != currentEntry->next->next) { - CatalogEntry *nextEntry = currentEntry->next; - if (XtcStricmp(nextEntry->contents, contents)>0) { - return InsertIntoCatalogAfter(currentEntry); - } - currentEntry = nextEntry; - } - return InsertIntoCatalogAfter(currentEntry); +/** + * Create a new CatalogEntry and insert it keeping the list sorted + * + * \param [in] catalog + * \param [in] contents to include. + * \param [in] tag + * + * \returns CatalogEntry + */ + +EXPORT CatalogEntry * +InsertInOrder(Catalog *catalog, const char *contents, const char *tag) +{ + CatalogEntry *newEntry = MyMalloc(sizeof(CatalogEntry)); + newEntry->files = 0; + + if (contents) + newEntry->contents = MyStrdup(contents); + if (tag) + newEntry->tag = MyStrdup(tag); + + DL_INSERT_INORDER(catalog->head, newEntry, CompareEntries); + + return newEntry; } + /** - * Get the existing list element for a content + * Find an existing list element for a given content * - * \param listHeader IN start of list - * \param contents IN contents to search - * \param Do we log error messages or not + * \param [in] catalog + * \param [in] contents contents to search. + * \param [in] silent we log error messages or not. * - * \return CatalogEntry if found, NULL otherwise + * \returns CatalogEntry if found, NULL otherwise. */ static CatalogEntry * -IsExistingContents(CatalogEntry *listHeader, const char *contents, BOOL_T silent) +IsExistingContents(Catalog *catalog, const char *contents, BOOL_T silent) { - CatalogEntry *currentEntry = listHeader->next; + CatalogEntry *head = catalog->head; + CatalogEntry *currentEntry; - while (currentEntry != currentEntry->next) { + DL_FOREACH(head, currentEntry) { if (!XtcStricmp(currentEntry->contents, contents)) { - if (!silent) - printf("%s already exists in %s\n", contents, currentEntry->fullFileName[0]); + if (!silent) { + printf("%s already exists in %s\n", contents, currentEntry->fullFileName[0]); + } return (currentEntry); } - currentEntry = currentEntry->next; } return (NULL); } @@ -203,49 +237,36 @@ IsExistingContents(CatalogEntry *listHeader, const char *contents, BOOL_T silent * \param contents contents description */ -static void -UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents) +EXPORT void +UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents, char *tag) { if (!entry->contents) { - entry->contents = strdup(contents); + MyFree(entry->contents); + entry->contents = NULL; } + if (contents) + entry->contents = MyStrdup(contents); + + if (!entry->tag) { + MyFree(entry->tag); + entry->tag = NULL; + } + if (tag) + entry->tag = MyStrdup(tag); if (entry->files < MAXFILESPERCONTENT) { - entry->fullFileName[entry->files++] = strdup(path); + entry->fullFileName[entry->files++] = MyStrdup(path); } else { - AbortProg("Number of file with same content too large!", NULL); + AbortProg("Number of files with same content too large!", NULL); } } -/** - * Create the list for the catalog entries - * - * \return - */ - -static CatalogEntry * -CreateCatalog() -{ - CatalogEntry *catalog = InitCatalog(); - - return (catalog); -} - - -static IndexEntry * -CreateIndexTable(unsigned int capacity) -{ - IndexEntry *index = (IndexEntry *)malloc(capacity * sizeof(IndexEntry)); - - return (index); -} - /** * Scan opened directory for the next parameter file * * \param dir IN opened directory handle * \param dirName IN name of directory - * \param fileName OUT fully qualified filename + * \param fileName OUT fully qualified filename, must be free()'d by caller * * \return TRUE if file found, FALSE if not */ @@ -289,391 +310,347 @@ GetNextParameterFile(DIR *dir, const char *dirName, char **fileName) return (res); } -/** - * Scan a directory for parameter files. For each file found the CONTENTS is - * read and added to the list * - * - * \param insertAfter IN starting point for the list of files - * \param dirName IN directory to be scanned +/*! + * Filter keywords. Current rules: + * - single character string that only consist of a punctuation char * - * \return pointer to the last element(?) + * \param word IN keyword + * \return true if any rule applies, false otherwise */ -static CatalogEntry * -ScanDirectory(CatalogEntry *catalog, const char *dirName) +bool +FilterKeyword(char *word) { - DIR *d; - CatalogEntry *newEntry = catalog; - - d = opendir(dirName); - if (d) { - char *fileName = NULL; + if (strlen(word) == 1 && strpbrk(word, PUNCTUATION)) { + return (true); + } - while (GetNextParameterFile(d, dirName, &fileName)) { - CatalogEntry *existingEntry; - char *contents = GetParameterFileContent(fileName); - if ((existingEntry = IsExistingContents(catalog, contents,FALSE))) { - printf("Duplicate CONTENTS record in parameter file %s\n", fileName); - if (strcmp(existingEntry->fullFileName[existingEntry->files-1],fileName)) - UpdateCatalogEntry(existingEntry, fileName, contents); - } else { - newEntry = InsertInOrder(catalog,contents); - UpdateCatalogEntry(newEntry, fileName, contents); - } - free(contents); - free(fileName); - fileName = NULL; + for (int i = 0; i < sizeof(stopwords) / sizeof(char *); i++) { + if (!XtcStricmp(word, stopwords+i)) { + return (true); } - closedir(d); } + return (false); +} - return (newEntry); +int KeyWordCmp(void *a, void *b) +{ + return XtcStricmp(((IndexEntry *)a)->keyWord,((IndexEntry *)b)->keyWord); } + /** - * Comparison function for IndexEntries used by qsort() + * Standardize spelling: remove some typical spelling problems. It is assumed that the word + * has already been converted to lower case * - * \param entry1 IN - * \param entry2 IN - * \return per C runtime conventions + * \param [in,out] word If non-null, the word. */ -static int -CompareIndex(const void *entry1, const void *entry2) +void +StandardizeSpelling(char *word) { - IndexEntry index1 = *(IndexEntry *)entry1; - IndexEntry index2 = *(IndexEntry *)entry2; - return (strcoll(index1.keyWord, index2.keyWord)); -} + char *p = strchr(word, '-'); + // remove the word 'scale' from combinations like N-scale + if (p) { + if (!XtcStricmp(p+1, "scale")) { + *p = '\0'; + } + } -/*! - * Filter keywords. Current rules: - * - single character string that only consist of a punctuation char - * - * \param word IN keyword - * \return true if any rule applies, false otherwise - */ + if (!strncasecmp(word, "h0", 2)) { + strncpy(word, "ho", 2); + } -bool -FilterKeyword(char *word) -{ - if (strlen(word) == 1 && strpbrk(word, PUNCTUATION )) { - return(true); - } - return(false); + if (!strncasecmp(word, "00", 2)) { + strncpy(word, "oo", 2); + } + + if (word[0] == '0') { + word[0] = 'o'; + } } /** * Create the keyword index from a list of parameter files * - * \param catalog IN list of parameter files - * \param index IN index table to be filled - * \param pointer IN/OUT array of words that are indexed - * \param capacityOfIndex IN total maximum of keywords - * \return number of indexed keywords + * \param [in] library initialized library + * + * \returns number of indexed keywords. */ + static unsigned -CreateContentsIndex(CatalogEntry *catalog, IndexEntry *index, void** words_array, - unsigned capacityOfIndex) +CreateKeywordIndex(ParameterLib *library) { - CatalogEntry *currentEntry = catalog->next; - unsigned totalMemory = 0; + CatalogEntry *listOfEntries = library->catalog->head; + CatalogEntry *curParamFile; + size_t totalMemory = 0; size_t wordCount = 0; char *wordList; char *wordListPtr; + IndexEntry *index = library->index; - while (currentEntry != currentEntry->next) { - totalMemory += strlen(currentEntry->contents) + 1; - currentEntry = currentEntry->next; + // allocate a buffer for the complete set of keywords + DL_FOREACH(listOfEntries, curParamFile) { + totalMemory += strlen(curParamFile->contents) + 1; } - - wordList = malloc((totalMemory + 1) * sizeof(char)); - *words_array = (void*)wordList; + wordList = MyMalloc((totalMemory + 1) * sizeof(char)); wordListPtr = wordList; - currentEntry = catalog->next; - while (currentEntry != currentEntry->next) { + DL_FOREACH(listOfEntries, curParamFile) { char *word; - char *content = strdup(currentEntry->contents); + char *content = strdup(curParamFile->contents); - word = strtok(content, " \t\n\r"); - while (word && wordCount < capacityOfIndex) { + word = strtok(content, SEARCHDELIMITER); + while (word) { strcpy(wordListPtr, word); - char *p = wordListPtr; - for (; *p; ++p) { - *p = tolower(*p); + XtcStrlwr(wordListPtr); + if (!FilterKeyword(wordListPtr)) { + IndexEntry *searchEntry = MyMalloc(sizeof(IndexEntry)); + IndexEntry *existingEntry = NULL; + searchEntry->keyWord = wordListPtr; + StandardizeSpelling(wordListPtr); + + if (index) { + DL_SEARCH(index, existingEntry, searchEntry, KeyWordCmp); + } + if (existingEntry) { + DYNARR_APPEND(CatalogEntry *, *(existingEntry->references), 5); + DYNARR_LAST(CatalogEntry *, *(existingEntry->references)) = curParamFile; + MyFree(searchEntry); + } else { + searchEntry->references = calloc(1, sizeof(dynArr_t)); + DYNARR_APPEND(CatalogEntry *, *(searchEntry->references), 5); + DYNARR_LAST(CatalogEntry *, *(searchEntry->references)) = curParamFile; + DL_APPEND(index, searchEntry); + LOG1(log_params, ("Index Entry: <%s>\n", searchEntry->keyWord)) + } + + wordListPtr += strlen(word) + 1; + wordCount++; } - if (!FilterKeyword(wordListPtr)) { - index[wordCount].value = currentEntry; - index[wordCount].keyWord = wordListPtr; - wordListPtr += strlen(word) + 1; - wordCount++; - if (wordCount >= capacityOfIndex) { - AbortProg("Too many keywords were used!", NULL); - } - } - word = strtok(NULL, " \t\n\r"); + word = strtok(NULL, SEARCHDELIMITER); } free(content); - currentEntry = currentEntry->next; } *wordListPtr = '\0'; - qsort((void*)index, wordCount, sizeof(IndexEntry), CompareIndex); + DL_SORT(index, KeyWordCmp); + library->index = index; + library->words = wordList; - return (wordCount); + IndexEntry *existingEntry; + DL_FOREACH(index, existingEntry) { + LOG1(log_params, ("Index Entry: <%s> Count: %d\n", existingEntry->keyWord, + existingEntry->references->cnt)); + } + return (unsigned)(wordCount); } /** -* A recursive binary search function. It returns location of x in -* given array arr[l..r] is present, otherwise -1 -* Taken from http://www.geeksforgeeks.org/binary-search/ and modified -* -* \param arr IN array to search -* \param l IN starting index -* \param r IN highest index in array -* \param key IN key to search -* \return index if found, -1 otherwise -*/ + * Search the index for a keyword. The index is assumed to be sorted. Each + * keyword has one entry in the index list. + * + * \param [in] index index list. + * \param length number of entries index. + * \param [in] search search string. + * \param [out] entries array of found entry. + * + * \returns TRUE if found, FALSE otherwise. + */ -static int SearchInIndex(IndexEntry arr[], int l, int r, char *key) +unsigned int +FindWord(IndexEntry *index, int length, char *search, IndexEntry **entries) { - if (r >= l) { - int mid = l + (r - l) / 2; - int res = XtcStricmp(key, arr[mid].keyWord); + IndexEntry *result = NULL; - // If the element is present at the middle itself - if (!res) { - return mid; - } - - // If the array size is 1 - if (r == 0) { - return -1; - } + IndexEntry searchWord; + searchWord.keyWord = search; - // If element is smaller than mid, then it can only be present - // in left subarray - if (res < 0) { - return SearchInIndex(arr, l, mid - 1, key); - } + *entries = NULL; - // Else the element can only be present in right subarray - return SearchInIndex(arr, mid + 1, r, key); - } + DL_SEARCH(index, result, &searchWord, KeyWordCmp); + if (!result) { + int maxdistance = 1; + while (maxdistance <= LDISTANCELIMIT && !result ) { + IndexEntry *current; + size_t minDistance = LDISTANCELIMIT + 1; + int maxProbability = 0; + LOG1(log_params, ("Close match for: <%s> maxdistance: %d\n", search, maxdistance)); + + DL_FOREACH(index, current) + { + size_t ldist = levenshtein(search, current->keyWord); + LOG1(log_params, ("Distance of: <%s> is %d\n", current->keyWord, ldist)); + if (ldist == maxdistance) { + if (current->references->cnt > maxProbability) { + if (!result) { + result = MyMalloc(sizeof(IndexEntry)); + } + memcpy(result, current, sizeof(IndexEntry)); + maxProbability = current->references->cnt; + } + } + } - // We reach here when element is not present in array - return -1; + maxdistance++; + } + } + + *entries = result; + return (result != NULL); } /** - * Inserts a key in arr[] of given capacity. n is current - * size of arr[]. This function returns n+1 if insertion - * is successful, else n. - * Taken from http ://www.geeksforgeeks.org/search-insert-and-delete-in-a-sorted-array/ and modified + * Create and initialize the data structure for the track library + * + * \param trackLibrary OUT the newly allocated track library + * \return TRUE on success */ -int InsertSorted(CatalogEntry *arr[], int n, CatalogEntry *key, int capacity) +ParameterLib * +InitLibrary(void) { - // Cannot insert more elements if n is already - // more than or equal to capcity - if (n >= capacity) { - return n; - } + ParameterLib *trackLib = MyMalloc(sizeof(ParameterLib)); - int i; - for (i = n - 1; (i >= 0 && arr[i] > key); i--) { - arr[i + 1] = arr[i]; + if (trackLib) { + trackLib->catalog = InitCatalog(); + trackLib->index = NULL; + trackLib->wordCount = 0; + trackLib->parameterFileCount = 0; } - arr[i + 1] = key; - - return (n + 1); + return (trackLib); } /** - * Comparison function for CatalogEntries used by qsort() + * Destroys the library freeing all associated memory * - * \param entry1 IN - * \param entry2 IN - * \return per C runtime conventions + * \param [in] library If non-null, the library. */ -static int -CompareResults(const void *entry1, const void *entry2) +void +DestroyLibrary(ParameterLib *library) { - CatalogEntry * index1 = *(CatalogEntry **)entry1; - CatalogEntry * index2 = *(CatalogEntry **)entry2; - return (strcoll(index1->contents, index2->contents)); + if (library) { + DestroyCatalog(library->catalog); + MyFree(library); + } } /** - * Search the index for a keyword. The index is assumed to be sorted. So after one entry - * is found, neighboring entries up and down are checked as well. The total result set - * is placed into an array and returned. This array has to be free'd by the caller. - * - * \param index IN index list - * \param length IN number of entries index - * \param search IN search string - * \param resultCount OUT count of found entries - * \return array of found catalog entries, NULL if none found + * Scan directory and add all parameter files found to the catalog + * + * \param trackLib IN the catalog + * \param directory IN directory to scan + * \return number of files found */ -static int findAll = 1; - -unsigned int -FindWord(IndexEntry *index, int length, char *search, CatalogEntry ***entries) +bool +CreateCatalogFromDir(ParameterLib *paramLib, char *directory) { - CatalogEntry **result; //Array of pointers to Catalog Entries - int found; - int foundElements = 0; - *entries = NULL; - - //Get all the entries back for generic search or if "generic find" - if (findAll || !search || (search[0] == '*') || (search[0] == '\0')) { - result = malloc((length) * sizeof(CatalogEntry *)); - for (int i = 0; i < length; i++) { - result[i] = index[i].value; - } - *entries = result; - return length; - } - - found = SearchInIndex(index, 0, length, search); + DIR *d; + Catalog *catalog = paramLib->catalog; - if (found >= 0) { - int lower = found; - int upper = found; - int i; + d = opendir(directory); + if (d) { + char *fileName = NULL; - while (lower > 0 && !XtcStricmp(index[lower-1].keyWord, search)) { - lower--; - } + while (GetNextParameterFile(d, directory, &fileName)) { + CatalogEntry *existingEntry; - while (upper < length - 1 && !XtcStricmp(index[upper + 1].keyWord, search)) { - upper++; - } + char *contents = GetParameterFileContent(fileName); - foundElements = 1 + upper - lower; + char *scale = GetParameterFileScale(fileName); - result = malloc((foundElements) * sizeof(CatalogEntry *)); - for (i = 0; i < foundElements; i++) { - result[i] = index[i+lower].value; + if ((existingEntry = IsExistingContents(catalog, contents, FALSE))) { + UpdateCatalogEntry(existingEntry, fileName, contents, scale); + } else { + CatalogEntry *newEntry; + newEntry = InsertInOrder(catalog, contents, scale); + UpdateCatalogEntry(newEntry, fileName, contents, scale); + } + MyFree(contents); + MyFree(scale); + free(fileName); + fileName = NULL; } - - qsort((void*)result, foundElements, sizeof(void *), CompareResults); - - *entries = result; + closedir(d); } - return (foundElements); + paramLib->parameterFileCount = CountCatalogEntries(paramLib->catalog); + return (paramLib->parameterFileCount); } /** - * Create and initialize the data structure for the track library + * Discard the complete catalog from a library * - * \param trackLibrary OUT the newly allocated track library - * \return TRUE on success + * \param [in] library */ -TrackLibrary * -InitLibrary(void) +void +DiscardCatalog(ParameterLib *library) { - TrackLibrary *trackLib = malloc(sizeof(TrackLibrary)); - - if (trackLib) { - trackLib->catalog = CreateCatalog(); - trackLib->index = NULL; - trackLib->wordCount = 0; - trackLib->trackTypeCount = 0; + CatalogEntry *entry; + CatalogEntry *temp; + + DL_FOREACH_SAFE(library->catalog->head, entry, temp) { + MyFree(entry->contents); + MyFree(entry->tag); + for (unsigned int i = 0; i < entry->files; i++) { + MyFree(entry->fullFileName[i]); + } + DL_DELETE(library->catalog->head, entry); + MyFree(entry); } - return (trackLib); } -/** - * Scan directory and all parameter files found to the catalog - * - * \param trackLib IN the catalog - * \param directory IN directory to scan - * \return number of files found - */ - -bool -GetTrackFiles(TrackLibrary *trackLib, char *directory) -{ - ScanDirectory(trackLib->catalog, directory); - trackLib->trackTypeCount = CountCatalogEntries(trackLib->catalog); - return (trackLib->trackTypeCount); -} /** - * Add a list of parameters files to a catalog. This function is - * called when the user selects files in the file selector. + * Create the search index from the contents description for the whole + * catalog. + * + * \param [in] parameterLib IN the catalog. * - * \param files IN count of files - * \param fileName IN array of filenames - * \param data IN pointer to the catalog - * \return alwqys TRUE + * \returns the number of words indexed. */ -int GetParameterFileInfo( - int files, - char ** fileName, - void * data) +unsigned +CreateLibraryIndex(ParameterLib *parameterLib) { - CatalogEntry *catalog = (CatalogEntry *)data; + parameterLib->index = NULL; - assert(fileName != NULL); - assert(files > 0); - assert(data != NULL); + parameterLib->wordCount = CreateKeywordIndex(parameterLib); - for (int i = 0; i < files; i++) { - CatalogEntry *newEntry; - char *contents = GetParameterFileContent(fileName[i]); - - if (!(newEntry = IsExistingContents(catalog, contents,TRUE))) { - newEntry = InsertIntoCatalogAfter(catalog); - } - UpdateCatalogEntry(newEntry, fileName[i], contents); - free(contents); - } - return (TRUE); + return (parameterLib->wordCount); } /** - * Create the search index from the contents description for the whole catalog. - * A fixed number of words are added to the index. See ESTIMATED_CONTENTS_WORDS + * Discard library index freeing all memory used + * references were created using MakeFullPath. These were allocated using malloc and + * not MyMalloc * - * \param trackLib IN the catalog - * \return the number of words indexed + * \param [in] trackLib the track library. */ -unsigned -CreateLibraryIndex(TrackLibrary *trackLib) -{ - trackLib->index = CreateIndexTable(trackLib->trackTypeCount * - ESTIMATED_CONTENTS_WORDS); - - trackLib->wordCount = CreateContentsIndex(trackLib->catalog, trackLib->index, - &trackLib->words_array, - ESTIMATED_CONTENTS_WORDS * trackLib->trackTypeCount); - - return (trackLib->wordCount); -} - void -DeleteLibraryIndex(TrackLibrary *trackLib) +DiscardLibraryIndex(ParameterLib *trackLib) { - free(trackLib->index); - trackLib->index = NULL; - - free(trackLib->words_array); - - trackLib->wordCount = 0; + IndexEntry *indexEntry; + IndexEntry *tmp; + + DL_FOREACH_SAFE(trackLib->index, indexEntry, tmp) { + DYNARR_FREE(CatalogEntry *, *(indexEntry->references)); + free(indexEntry->references); + DL_DELETE(trackLib->index, indexEntry); + MyFree(indexEntry); + } + MyFree(trackLib->words); + trackLib->index = NULL; + trackLib->wordCount = 0; } @@ -684,14 +661,16 @@ DeleteLibraryIndex(TrackLibrary *trackLib) * \return NULL if error or empty directory, else library handle */ -TrackLibrary * +ParameterLib * CreateLibrary(char *directory) { - TrackLibrary *library; + ParameterLib *library; + + log_params = LogFindIndex("params"); library = InitLibrary(); if (library) { - if (!GetTrackFiles(library, directory)) { + if (!CreateCatalogFromDir(library, directory)) { return (NULL); } @@ -700,112 +679,288 @@ CreateLibrary(char *directory) return (library); } +/** + * Discard library freeing all memory used + * + * \param [in,out] library If non-null, the library. + */ + void -DeleteLibrary(TrackLibrary* library) +DiscardLibrary(ParameterLib* library) { - DeleteLibraryIndex(library); + CatalogEntry *entry = library->catalog->head; + CatalogEntry *element; + CatalogEntry *tmp; + DiscardLibraryIndex(library); - free(library); + DL_FOREACH_SAFE(entry, element, tmp) { + MyFree(element->contents); + MyFree(element->tag); + for (unsigned int i = 0; i < element->files; i++) { + MyFree(element->fullFileName[i]); + } + DL_DELETE(entry, element); + MyFree(element); + } + MyFree(library->words); + MyFree(library); } -// Case insensitive comparison -char* stristr( const char* haystack, const char* needle ) +/** + * Create a statistic for a finished search. The returned string has to be MyFreed() after usage + * + * \param [in] result the finished search + * + * \returns Null if it fails, else the found statistics. + */ + +char * +SearchStatistics(SearchResult *result) { - int c = tolower((unsigned char)*needle); - if (c == '\0') - return (char *)haystack; - for (; *haystack; haystack++) { - if (tolower((unsigned char)*haystack) == c) { - for (size_t i = 0;;) { - if (needle[++i] == '\0') - return (char *)haystack; - if (tolower((unsigned char)haystack[i]) != tolower((unsigned char)needle[i])) - break; - } - } - } - return NULL; + DynString buffer; + DynString subStats[STATE_COUNT]; + + unsigned searched = 0; + unsigned discarded = 0; + unsigned notfound = 0; + unsigned close = 0; + + char *resStat; + DynStringMalloc(&buffer, 16); + + for (int i = SEARCHED; i < STATE_COUNT; i++) { + DynStringMalloc(subStats + i, 16); + } + + DynStringCatCStr(subStats + SEARCHED, _("Found: ")); + DynStringCatCStr(subStats + CLOSE, _("Similar: ")); + DynStringCatCStr(subStats + DISCARDED, _("Ignored: ")); + DynStringCatCStr(subStats + NOTFOUND, _("Not found: ")); + + for (unsigned int i = 0; i < result->words; i++) { + switch (result->kw[i].state) { + case SEARCHED: + DynStringPrintf(&buffer, "%s (%d) ", result->kw[i].keyWord, + result->kw[i].count); + searched++; + break; + case DISCARDED: + DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); + discarded++; + break; + case NOTFOUND: + DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); + notfound++; + break; + case CLOSE: + DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); + close++; + break; + default: + break; + } + DynStringCatStr(subStats + result->kw[i].state, &buffer); + } + + DynStringReset(&buffer); + if (searched) { + DynStringCatStr(&buffer, subStats + SEARCHED); + } + if (close) { + DynStringCatStr(&buffer, subStats + CLOSE); + } + if (notfound) { + DynStringCatStr(&buffer, subStats + NOTFOUND); + } + if (discarded) { + DynStringCatStr(&buffer, subStats + DISCARDED); + } + + resStat = MyStrdup(DynStringToCStr(&buffer)); + DynStringFree(&buffer); + for (int i = SEARCHED; i < STATE_COUNT; i++) { + DynStringFree(subStats + i); + } + return (resStat); } /** - * Search the library for a keyword string and return the result list + * returns number of words in str. * - * First the index is searched for the first word and then each "hit" is matched - * to the entire search string + * \param [in] str the string. * - * Null, Blank and "*" match all entries + * \returns The total number of words. + */ + +unsigned countWords(char *str) +{ + int state = FALSE; + unsigned wc = 0; // word count + + // Scan all characters one by one + while (*str) { + // If next character is a separator, set the + // state as FALSE + if (*str == ' ' || *str == '\n' || *str == '\t' || *str == '\r' || *str == '/') { + state = FALSE; + } + + // If next character is not a word separator and + // state is OUT, then set the state as IN and + // increment word count + else if (state == FALSE) { + state = TRUE; + ++wc; + } + + // Move to next character + ++str; + } + + return wc; +} + +/** + * Search the library for a keyword string and return the result list * - * The list is de-duped of repeat of filenames as the same file might appear in - * more than once + * Each key word exists only once in the index. * * \param library IN the library * \param searchExpression IN keyword to search for * \param resultEntries IN list header for result list * \return number of found entries */ + unsigned -SearchLibrary(TrackLibrary *library, char *searchExpression, - CatalogEntry *resultEntries) +SearchLibrary(ParameterLib *library, char *searchExpression, + SearchResult *results) { - CatalogEntry **entries; - CatalogEntry * newEntry = resultEntries; - unsigned entryCount; - - char * word; - - word = strdup(searchExpression); - - //word = strtok(word," \t"); + CatalogEntry *element; + IndexEntry *entries; + unsigned entryCount = 0; + char *searchWord; + unsigned words = countWords(searchExpression); + char *searchExp = MyStrdup(searchExpression); + unsigned i = 0; if (library->index == NULL || library->wordCount == 0) { return (0); } - entryCount = FindWord(library->index, library->wordCount, word, - &entries); - int count= 0; - if (entryCount) { - unsigned int i = 0; - while (i < entryCount) { - char * match; - //Check if entire String Matches - if (!searchExpression || !word || (word[0] == '*') || (word[0] == '\0') || - (match = stristr(entries[i]->contents,searchExpression))) { - CatalogEntry * existingEntry; - existingEntry = IsExistingContents(resultEntries, entries[i]->contents, TRUE); - //Same FileName already in one of the entries? - BOOL_T found = FALSE; - if (existingEntry) { - for (unsigned int j=0;jfiles;j++) { - if (!strcmp(existingEntry->fullFileName[j],entries[i]->fullFileName[entries[i]->files-1])) { - found=TRUE; - break; - } - } - if (found == TRUE ) { - i++; - continue; - } - UpdateCatalogEntry(existingEntry, entries[i]->fullFileName[(entries[i]->files- 1)], - entries[i]->contents); - } else { - newEntry = InsertInOrder(resultEntries,entries[i]->contents); - UpdateCatalogEntry(newEntry, entries[i]->fullFileName[(entries[i]->files- 1)], - entries[i]->contents); - } - count++; - } + + results->kw = MyMalloc(words * sizeof(struct sSingleResult)); + results->subCatalog.head = NULL; + + searchWord = strtok(searchExp, SEARCHDELIMITER); + while (searchWord) { + XtcStrlwr(searchWord); + if (!FilterKeyword(searchWord)) { + StandardizeSpelling(searchWord); + results->kw[i].state = SEARCHED; + } else { + results->kw[i].state = DISCARDED; + } + results->kw[i++].keyWord = MyStrdup(searchWord); + searchWord = strtok(NULL, SEARCHDELIMITER); + } + results->words = words; + + i = 0; + while (i < words) { + if (results->kw[i].state == DISCARDED) { i++; + continue; } + FindWord(library->index, library->wordCount, results->kw[i].keyWord, &entries); + if (entries) { + results->kw[i].count = entries->references->cnt; + if (XtcStricmp(results->kw[i].keyWord, entries->keyWord)) { + results->kw[i].state = CLOSE; + MyFree(results->kw[i].keyWord); + results->kw[i].keyWord = MyStrdup(entries->keyWord); + } + + if (results->subCatalog.head == NULL) { + // if first keyword -> initialize result set + for (int j = 0; j < entries->references->cnt; j++) { + CatalogEntry *newEntry = MyMalloc(sizeof(CatalogEntry)); + CatalogEntry *foundEntry = DYNARR_N(CatalogEntry *, *(entries->references), j); + newEntry->contents = MyStrdup(foundEntry->contents); + newEntry->tag = MyStrdup(foundEntry->tag); + newEntry->files = foundEntry->files; + for (unsigned int i=0;ifiles;i++) { + newEntry->fullFileName[i] = MyStrdup(foundEntry->fullFileName[i]); + } + + DL_APPEND(results->subCatalog.head, newEntry); + } + } else { + // follow up keyword, create intersection with current result set + CatalogEntry *current; + CatalogEntry *temp; + + DL_FOREACH_SAFE(results->subCatalog.head, current, temp) { + int found = 0; + for (int j = 0; j < entries->references->cnt; j++) { + CatalogEntry *foundEntry = DYNARR_N(CatalogEntry *, *(entries->references), j); + + if (strcmp(foundEntry->contents,current->contents)==0) { + found = TRUE; + break; + } + } + if (!found) { + DL_DELETE(results->subCatalog.head, current); + MyFree(current->contents); + MyFree(current->tag); + for (unsigned int i=0;ifiles;i++) { + MyFree(current->fullFileName[i]); + } + MyFree(current); + } + } + } + } else { + // Searches that don't yield a result are ignored + results->kw[i].state = NOTFOUND; + results->kw[i].count = 0; + } + i++; } - free(word); - if (entries) - free(entries); //Clean-up after search - return (count); + + DL_COUNT(results->subCatalog.head, element, results->totalFound); + MyFree(searchExp); + return (results->totalFound); } /** - * Get the contents description from a parameter file. Returned string has to be freed after use. + * Discard results. The memory allocated with the search is freed + * + * \param [in] res If non-null, the results. + */ + +void +SearchDiscardResult(SearchResult *res) +{ + if (res) { + CatalogEntry *current = res->subCatalog.head; + CatalogEntry *element; + CatalogEntry *tmp; + + DL_FOREACH_SAFE(current, element, tmp) { + DL_DELETE(current, element); + MyFree(element); + } + + for (unsigned int i = 0; i < res->words; i++) { + MyFree(res->kw[i].keyWord); + } + MyFree(res->kw); + } +} + +/** + * Get the contents description from a parameter file. Returned string has to be MyFree'd after use. * * \param file IN xtpfile * \return pointer to found contents or NULL if not present @@ -814,33 +969,132 @@ SearchLibrary(TrackLibrary *library, char *searchExpression, char * GetParameterFileContent(char *file) { - FILE *fh; - char *result = NULL; - - fh = fopen(file, "rt"); - if (fh) { - bool found = false; - - while (!found) { - char buffer[512]; - if (fgets(buffer, sizeof(buffer), fh)) { - char *ptr = strtok(buffer, " \t"); - if (!XtcStricmp(ptr, CONTENTSCOMMAND)) { - /* if found, store the rest of the line and the filename */ - ptr = ptr+strlen(CONTENTSCOMMAND)+1; - ptr = strtok(ptr, "\r\n"); - result = strdup(ptr); -#ifdef WINDOWS - ConvertUTF8ToSystem(result); -#endif // WINDOWS - found = true; - } - } else { - fprintf(stderr, "Nothing found in %s\n", file); - found = true; - } - } - fclose(fh); - } - return(result); + FILE *fh; + char *result = NULL; + + fh = fopen(file, "rt"); + if (fh) { + bool found = false; + + while (!found) { + char buffer[512]; + if (fgets(buffer, sizeof(buffer), fh)) { + char *ptr = strtok(buffer, " \t"); + if (!XtcStricmp(ptr, CONTENTSCOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(CONTENTSCOMMAND)+1; + ptr = strtok(ptr, "\r\n"); + result = MyStrdup(ptr); +#ifdef UTFCONVERT + ConvertUTF8ToSystem(result); +#endif // UTFCONVERT + found = true; + } + } else { + fprintf(stderr, "Nothing found in %s\n", file); + found = true; + } + } + fclose(fh); + } + return (result); +} + +/** + * Get the first scale values from a parameter file. Returned strings have to be MyFreed after use + * + * \param file IN xtpfile + * \param array of one of three char results (Track, Structure and Car) + */ + +char * +GetParameterFileScale(char *file) +{ + FILE *fh; + char *scale = NULL; + + + fh = fopen(file, "rt"); + if (fh) { + bool found = FALSE, found_Turnout = FALSE, found_Structure = FALSE, found_Car = FALSE; + + while (!found) { + char buffer[512]; + if (fgets(buffer, sizeof(buffer), fh)) { + char *ptr = strtok(buffer, " \t"); + if (!found_Turnout && !XtcStricmp(ptr, TURNOUTCOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(TURNOUTCOMMAND)+1; + ptr = strtok(ptr, " \t"); + scale = MyMalloc(strlen(TURNOUTCOMMAND)+2+strlen(ptr)); + strcpy(scale,TURNOUTCOMMAND); + char * cp = scale + strlen(TURNOUTCOMMAND); + cp[0] = ' '; + cp++; + strcpy(cp,ptr); + found_Turnout = true; + } else if (!found_Structure && !XtcStricmp(ptr, STRUCTURECOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(STRUCTURECOMMAND)+1; + ptr = strtok(ptr, " \t"); + scale = MyMalloc(strlen(STRUCTURECOMMAND)+2+strlen(ptr)); + strcpy(scale,STRUCTURECOMMAND); + char * cp = scale + strlen(STRUCTURECOMMAND)+1; + cp[-1] = ' '; + strcpy(cp,ptr); + found_Structure = true; + } else if (!found_Car && !XtcStricmp(ptr, CARCOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(CARCOMMAND)+1; + ptr = strtok(ptr, " \t"); + scale = MyMalloc(strlen(CARCOMMAND)+2+strlen(ptr)); + strcpy(scale,CARCOMMAND); + char * cp = scale + strlen(CARCOMMAND)+1; + cp[-1] = ' '; + strcpy(cp,ptr); + found_Car = true; + } else if (!found_Car && !XtcStricmp(ptr, CARPROTOCOMMAND)) { + /* if found, store the rest of the line and the filename */ + scale = MyMalloc(strlen(CARPROTOCOMMAND)+3); + strcpy(scale,CARPROTOCOMMAND); + char * cp = scale + strlen(CARPROTOCOMMAND); + strcpy(cp," *"); + found_Car = true; + } + } else { + if (!found_Turnout && !found_Structure && !found_Car) { + fprintf(stderr, "Nothing found in %s\n", file); + found = true; + } + } + if (found_Turnout || found_Structure || found_Car) found = TRUE; + } + fclose(fh); + } + return scale; + +} + +#ifdef MEMWATCH +/** this is used to test for memory leaks. It should show no leaks from functions in this source file */ +RunMemoryTest(char *directory) +{ + ParameterLib *library; + SearchResult *results; + + mwInit(); + library = InitLibrary(); + if (library) { + CreateCatalogFromDir(library, directory); + CreateLibraryIndex(library); + results = MyMalloc(sizeof(SearchResult)); + SearchLibrary(library, "peco", results); + SearchDiscardResult(results); + MyFree(results); + DiscardLibraryIndex(library); + DiscardCatalog(library); + } + DestroyLibrary(library); + mwTerm(); } +#endif //MEMWATCH -- cgit v1.2.3 From a14a7a0ccc9de76aeab0b2e4bbf58f1a79deedc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Wed, 3 Jul 2024 10:19:30 +0200 Subject: New upstream version 5.3.0GA --- app/bin/partcatalog.c | 1209 +++++++++++++++++++++++++------------------------ 1 file changed, 607 insertions(+), 602 deletions(-) (limited to 'app/bin/partcatalog.c') diff --git a/app/bin/partcatalog.c b/app/bin/partcatalog.c index 25ae024..205ae50 100644 --- a/app/bin/partcatalog.c +++ b/app/bin/partcatalog.c @@ -16,14 +16,13 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "dynstring.h" #include "fileio.h" #include "include/levenshtein.h" #include "misc.h" -#include "misc2.h" #include "include/paramfile.h" #include "include/partcatalog.h" #include "paths.h" @@ -36,7 +35,7 @@ #define LDISTANCELIMIT (2) static char *stopwords = { - "scale", + "scale", }; static int log_params; @@ -50,11 +49,11 @@ static int log_params; Catalog * InitCatalog(void) { - Catalog *newCatalog = MyMalloc(sizeof(Catalog)); - if (newCatalog) { - newCatalog->head = NULL; - } - return (newCatalog); + Catalog *newCatalog = MyMalloc(sizeof(Catalog)); + if (newCatalog) { + newCatalog->head = NULL; + } + return (newCatalog); } /** @@ -68,27 +67,28 @@ DestroyCatalog(Catalog *catalog) { CatalogEntry *current = catalog->head; CatalogEntry *entry = NULL; - CatalogEntry *tmp = NULL, *old = NULL; - DL_FOREACH_SAFE(current, entry, tmp) - { + CatalogEntry *tmp = NULL; +// CatalogEntry *old = NULL; + DL_FOREACH_SAFE(current, entry, tmp) { //if (old) MyFree(old); - old = NULL; +// old = NULL; for (unsigned int i = 0; i < entry->files; i++) { - MyFree(entry->fullFileName[i]); - entry->fullFileName[i] = NULL; + MyFree(entry->fullFileName[i]); + entry->fullFileName[i] = NULL; } entry->files = 0; MyFree(entry->contents); entry->contents = NULL; MyFree(entry->tag); entry->tag = NULL; - old = entry; +// old = entry; DL_DELETE(catalog->head,entry); } catalog->head = NULL; } +#if 0 /** * Create a new CatalogEntry and add it to the linked list. The newly * created entry is inserted into the list after the given position @@ -100,16 +100,17 @@ DestroyCatalog(Catalog *catalog) static CatalogEntry * InsertIntoCatalogAfter(CatalogEntry *entry) { - CatalogEntry *newEntry = (CatalogEntry *)MyMalloc(sizeof(CatalogEntry)); - newEntry->next = entry->next; - newEntry->prev = entry; - entry->next = newEntry; - newEntry->files = 0; - newEntry->contents = NULL; - newEntry->tag = NULL; - - return (newEntry); + CatalogEntry *newEntry = (CatalogEntry *)MyMalloc(sizeof(CatalogEntry)); + newEntry->next = entry->next; + newEntry->prev = entry; + entry->next = newEntry; + newEntry->files = 0; + newEntry->contents = NULL; + newEntry->tag = NULL; + + return (newEntry); } +#endif /** * Count the elements in the linked list @@ -121,10 +122,10 @@ InsertIntoCatalogAfter(CatalogEntry *entry) unsigned CountCatalogEntries(Catalog *catalog) { - CatalogEntry * entry; - unsigned count = 0; - DL_COUNT(catalog->head, entry, count); - return (count); + CatalogEntry * entry; + unsigned count = 0; + DL_COUNT(catalog->head, entry, count); + return (count); } /** @@ -136,27 +137,28 @@ CountCatalogEntries(Catalog *catalog) EXPORT void CatalogDiscard(Catalog *catalog) { - CatalogEntry *current = catalog->head; - CatalogEntry *element; - CatalogEntry *tmp,*old = NULL; - - DL_FOREACH_SAFE(current, element, tmp) { - //if (old) MyFree(old); - old = NULL; - MyFree(element->contents); - element->contents = NULL; - MyFree(element->tag); - element->tag = NULL; - for (unsigned int i = 0; i < element->files; i++) { - MyFree(element->fullFileName[i]); - element->fullFileName[i] = NULL; - } - element->files = 0; - old = element; - DL_DELETE(catalog->head,element); - } - - catalog->head = NULL; + CatalogEntry *current = catalog->head; + CatalogEntry *element; + CatalogEntry *tmp; +// CatalogEntry *old = NULL; + + DL_FOREACH_SAFE(current, element, tmp) { + //if (old) MyFree(old); +// old = NULL; + MyFree(element->contents); + element->contents = NULL; + MyFree(element->tag); + element->tag = NULL; + for (unsigned int i = 0; i < element->files; i++) { + MyFree(element->fullFileName[i]); + element->fullFileName[i] = NULL; + } + element->files = 0; +// old = element; + DL_DELETE(catalog->head,element); + } + + catalog->head = NULL; } /** @@ -171,7 +173,7 @@ CatalogDiscard(Catalog *catalog) static int CompareEntries(CatalogEntry *a, CatalogEntry *b) { - return XtcStricmp(a->contents, b->contents); + return XtcStricmp(a->contents, b->contents); } /** @@ -187,17 +189,19 @@ CompareEntries(CatalogEntry *a, CatalogEntry *b) EXPORT CatalogEntry * InsertInOrder(Catalog *catalog, const char *contents, const char *tag) { - CatalogEntry *newEntry = MyMalloc(sizeof(CatalogEntry)); - newEntry->files = 0; + CatalogEntry *newEntry = MyMalloc(sizeof(CatalogEntry)); + newEntry->files = 0; - if (contents) - newEntry->contents = MyStrdup(contents); - if (tag) - newEntry->tag = MyStrdup(tag); + if (contents) { + newEntry->contents = MyStrdup(contents); + } + if (tag) { + newEntry->tag = MyStrdup(tag); + } - DL_INSERT_INORDER(catalog->head, newEntry, CompareEntries); + DL_INSERT_INORDER(catalog->head, newEntry, CompareEntries); - return newEntry; + return newEntry; } /** @@ -213,18 +217,18 @@ InsertInOrder(Catalog *catalog, const char *contents, const char *tag) static CatalogEntry * IsExistingContents(Catalog *catalog, const char *contents, BOOL_T silent) { - CatalogEntry *head = catalog->head; - CatalogEntry *currentEntry; - - DL_FOREACH(head, currentEntry) { - if (!XtcStricmp(currentEntry->contents, contents)) { - if (!silent) { - printf("%s already exists in %s\n", contents, currentEntry->fullFileName[0]); - } - return (currentEntry); - } - } - return (NULL); + CatalogEntry *head = catalog->head; + CatalogEntry *currentEntry; + + DL_FOREACH(head, currentEntry) { + if (!XtcStricmp(currentEntry->contents, contents)) { + if (!silent) { + printf("%s already exists in %s\n", contents, currentEntry->fullFileName[0]); + } + return (currentEntry); + } + } + return (NULL); } /** @@ -240,25 +244,24 @@ IsExistingContents(Catalog *catalog, const char *contents, BOOL_T silent) EXPORT void UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents, char *tag) { - if (!entry->contents) { - MyFree(entry->contents); - entry->contents = NULL; - } - if (contents) - entry->contents = MyStrdup(contents); - - if (!entry->tag) { - MyFree(entry->tag); - entry->tag = NULL; - } - if (tag) - entry->tag = MyStrdup(tag); - - if (entry->files < MAXFILESPERCONTENT) { - entry->fullFileName[entry->files++] = MyStrdup(path); - } else { - AbortProg("Number of files with same content too large!", NULL); - } + if (!entry->contents) { + MyFree(entry->contents); + entry->contents = NULL; + } + if (contents) { + entry->contents = MyStrdup(contents); + } + + if (!entry->tag) { + MyFree(entry->tag); + entry->tag = NULL; + } + if (tag) { + entry->tag = MyStrdup(tag); + } + + CHECK( entry->files < MAXFILESPERCONTENT ); + entry->fullFileName[entry->files++] = MyStrdup(path); } /** @@ -274,40 +277,40 @@ UpdateCatalogEntry(CatalogEntry *entry, char *path, char *contents, char *tag) static bool GetNextParameterFile(DIR *dir, const char *dirName, char **fileName) { - bool done = false; - bool res = false; - - /* - * get all files from the directory - */ - while (!done) { - struct stat fileState; - struct dirent *ent; - - ent = readdir(dir); - - if (ent) { - if (!XtcStricmp(FindFileExtension(ent->d_name), "xtp")) { - /* create full file name and get the state for that file */ - MakeFullpath(fileName, dirName, ent->d_name, NULL); - - if (stat(*fileName, &fileState) == -1) { - fprintf(stderr, "Error getting file state for %s\n", *fileName); - continue; - } - - /* ignore any directories */ - if (!(fileState.st_mode & S_IFDIR)) { - done = true; - res = true; - } - } - } else { - done = true; - res = false; - } - } - return (res); + bool done = false; + bool res = false; + + /* + * get all files from the directory + */ + while (!done) { + struct stat fileState; + struct dirent *ent; + + ent = readdir(dir); + + if (ent) { + if (!XtcStricmp(FindFileExtension(ent->d_name), "xtp")) { + /* create full file name and get the state for that file */ + MakeFullpath(fileName, dirName, ent->d_name, NULL); + + if (stat(*fileName, &fileState) == -1) { + fprintf(stderr, "Error getting file state for %s\n", *fileName); + continue; + } + + /* ignore any directories */ + if (!(fileState.st_mode & S_IFDIR)) { + done = true; + res = true; + } + } + } else { + done = true; + res = false; + } + } + return (res); } /*! @@ -321,21 +324,21 @@ GetNextParameterFile(DIR *dir, const char *dirName, char **fileName) bool FilterKeyword(char *word) { - if (strlen(word) == 1 && strpbrk(word, PUNCTUATION)) { - return (true); - } - - for (int i = 0; i < sizeof(stopwords) / sizeof(char *); i++) { - if (!XtcStricmp(word, stopwords+i)) { - return (true); - } - } - return (false); + if (strlen(word) == 1 && strpbrk(word, PUNCTUATION)) { + return (true); + } + + for (int i = 0; i < sizeof(stopwords) / sizeof(char *); i++) { + if (!XtcStricmp(word, stopwords+i)) { + return (true); + } + } + return (false); } int KeyWordCmp(void *a, void *b) { - return XtcStricmp(((IndexEntry *)a)->keyWord,((IndexEntry *)b)->keyWord); + return XtcStricmp(((IndexEntry *)a)->keyWord,((IndexEntry *)b)->keyWord); } @@ -349,25 +352,25 @@ int KeyWordCmp(void *a, void *b) void StandardizeSpelling(char *word) { - char *p = strchr(word, '-'); - // remove the word 'scale' from combinations like N-scale - if (p) { - if (!XtcStricmp(p+1, "scale")) { - *p = '\0'; - } - } - - if (!strncasecmp(word, "h0", 2)) { - strncpy(word, "ho", 2); - } - - if (!strncasecmp(word, "00", 2)) { - strncpy(word, "oo", 2); - } - - if (word[0] == '0') { - word[0] = 'o'; - } + char *p = strchr(word, '-'); + // remove the word 'scale' from combinations like N-scale + if (p) { + if (!XtcStricmp(p+1, "scale")) { + *p = '\0'; + } + } + + if (!strncasecmp(word, "h0", 2)) { + strcpy(word, "ho"); + } + + if (!strncasecmp(word, "00", 2)) { + strcpy(word, "oo"); + } + + if (word[0] == '0') { + word[0] = 'o'; + } } /** @@ -381,71 +384,71 @@ StandardizeSpelling(char *word) static unsigned CreateKeywordIndex(ParameterLib *library) { - CatalogEntry *listOfEntries = library->catalog->head; - CatalogEntry *curParamFile; - size_t totalMemory = 0; - size_t wordCount = 0; - char *wordList; - char *wordListPtr; - IndexEntry *index = library->index; - - // allocate a buffer for the complete set of keywords - DL_FOREACH(listOfEntries, curParamFile) { - totalMemory += strlen(curParamFile->contents) + 1; - } - wordList = MyMalloc((totalMemory + 1) * sizeof(char)); - - wordListPtr = wordList; - - DL_FOREACH(listOfEntries, curParamFile) { - char *word; - char *content = strdup(curParamFile->contents); - - word = strtok(content, SEARCHDELIMITER); - while (word) { - strcpy(wordListPtr, word); - - XtcStrlwr(wordListPtr); - if (!FilterKeyword(wordListPtr)) { - IndexEntry *searchEntry = MyMalloc(sizeof(IndexEntry)); - IndexEntry *existingEntry = NULL; - searchEntry->keyWord = wordListPtr; - StandardizeSpelling(wordListPtr); - - if (index) { - DL_SEARCH(index, existingEntry, searchEntry, KeyWordCmp); - } - if (existingEntry) { - DYNARR_APPEND(CatalogEntry *, *(existingEntry->references), 5); - DYNARR_LAST(CatalogEntry *, *(existingEntry->references)) = curParamFile; - MyFree(searchEntry); - } else { - searchEntry->references = calloc(1, sizeof(dynArr_t)); - DYNARR_APPEND(CatalogEntry *, *(searchEntry->references), 5); - DYNARR_LAST(CatalogEntry *, *(searchEntry->references)) = curParamFile; - DL_APPEND(index, searchEntry); - LOG1(log_params, ("Index Entry: <%s>\n", searchEntry->keyWord)) - } - - wordListPtr += strlen(word) + 1; - wordCount++; - } - word = strtok(NULL, SEARCHDELIMITER); - } - free(content); - } - *wordListPtr = '\0'; + CatalogEntry *listOfEntries = library->catalog->head; + CatalogEntry *curParamFile; + size_t totalMemory = 0; + size_t wordCount = 0; + char *wordList; + char *wordListPtr; + IndexEntry *index = library->index; + + // allocate a buffer for the complete set of keywords + DL_FOREACH(listOfEntries, curParamFile) { + totalMemory += strlen(curParamFile->contents) + 1; + } + wordList = MyMalloc((totalMemory + 1) * sizeof(char)); + + wordListPtr = wordList; + + DL_FOREACH(listOfEntries, curParamFile) { + char *word; + char *content = strdup(curParamFile->contents); + + word = strtok(content, SEARCHDELIMITER); + while (word) { + strcpy(wordListPtr, word); + + XtcStrlwr(wordListPtr); + if (!FilterKeyword(wordListPtr)) { + IndexEntry *searchEntry = MyMalloc(sizeof(IndexEntry)); + IndexEntry *existingEntry = NULL; + searchEntry->keyWord = wordListPtr; + StandardizeSpelling(wordListPtr); + + if (index) { + DL_SEARCH(index, existingEntry, searchEntry, KeyWordCmp); + } + if (existingEntry) { + DYNARR_APPEND(CatalogEntry *, *(existingEntry->references), 5); + DYNARR_LAST(CatalogEntry *, *(existingEntry->references)) = curParamFile; + MyFree(searchEntry); + } else { + searchEntry->references = calloc(1, sizeof(dynArr_t)); + DYNARR_APPEND(CatalogEntry *, *(searchEntry->references), 5); + DYNARR_LAST(CatalogEntry *, *(searchEntry->references)) = curParamFile; + DL_APPEND(index, searchEntry); + LOG1(log_params, ("Index Entry: <%s>\n", searchEntry->keyWord)) + } + + wordListPtr += strlen(word) + 1; + wordCount++; + } + word = strtok(NULL, SEARCHDELIMITER); + } + free(content); + } + *wordListPtr = '\0'; DL_SORT(index, KeyWordCmp); - library->index = index; - library->words = wordList; - - IndexEntry *existingEntry; - DL_FOREACH(index, existingEntry) { - LOG1(log_params, ("Index Entry: <%s> Count: %d\n", existingEntry->keyWord, - existingEntry->references->cnt)); - } - return (unsigned)(wordCount); + library->index = index; + library->words = wordList; + + IndexEntry *existingEntry; + DL_FOREACH(index, existingEntry) { + LOG1(log_params, ("Index Entry: <%s> Count: %d\n", existingEntry->keyWord, + existingEntry->references->cnt)); + } + return (unsigned)(wordCount); } /** @@ -463,24 +466,24 @@ CreateKeywordIndex(ParameterLib *library) unsigned int FindWord(IndexEntry *index, int length, char *search, IndexEntry **entries) { - IndexEntry *result = NULL; + IndexEntry *result = NULL; - IndexEntry searchWord; - searchWord.keyWord = search; + IndexEntry searchWord; + searchWord.keyWord = search; - *entries = NULL; + *entries = NULL; - DL_SEARCH(index, result, &searchWord, KeyWordCmp); + DL_SEARCH(index, result, &searchWord, KeyWordCmp); if (!result) { int maxdistance = 1; while (maxdistance <= LDISTANCELIMIT && !result ) { IndexEntry *current; - size_t minDistance = LDISTANCELIMIT + 1; +// size_t minDistance = LDISTANCELIMIT + 1; int maxProbability = 0; - LOG1(log_params, ("Close match for: <%s> maxdistance: %d\n", search, maxdistance)); - - DL_FOREACH(index, current) - { + LOG1(log_params, ("Close match for: <%s> maxdistance: %d\n", search, + maxdistance)); + + DL_FOREACH(index, current) { size_t ldist = levenshtein(search, current->keyWord); LOG1(log_params, ("Distance of: <%s> is %d\n", current->keyWord, ldist)); if (ldist == maxdistance) { @@ -497,9 +500,9 @@ FindWord(IndexEntry *index, int length, char *search, IndexEntry **entries) maxdistance++; } } - - *entries = result; - return (result != NULL); + + *entries = result; + return (result != NULL); } /** @@ -512,16 +515,16 @@ FindWord(IndexEntry *index, int length, char *search, IndexEntry **entries) ParameterLib * InitLibrary(void) { - ParameterLib *trackLib = MyMalloc(sizeof(ParameterLib)); + ParameterLib *trackLib = MyMalloc(sizeof(ParameterLib)); - if (trackLib) { - trackLib->catalog = InitCatalog(); - trackLib->index = NULL; - trackLib->wordCount = 0; - trackLib->parameterFileCount = 0; - } + if (trackLib) { + trackLib->catalog = InitCatalog(); + trackLib->index = NULL; + trackLib->wordCount = 0; + trackLib->parameterFileCount = 0; + } - return (trackLib); + return (trackLib); } /** @@ -533,10 +536,10 @@ InitLibrary(void) void DestroyLibrary(ParameterLib *library) { - if (library) { - DestroyCatalog(library->catalog); - MyFree(library); - } + if (library) { + DestroyCatalog(library->catalog); + MyFree(library); + } } /** @@ -550,37 +553,37 @@ DestroyLibrary(ParameterLib *library) bool CreateCatalogFromDir(ParameterLib *paramLib, char *directory) { - DIR *d; - Catalog *catalog = paramLib->catalog; - - d = opendir(directory); - if (d) { - char *fileName = NULL; - - while (GetNextParameterFile(d, directory, &fileName)) { - CatalogEntry *existingEntry; - - char *contents = GetParameterFileContent(fileName); - - char *scale = GetParameterFileScale(fileName); - - - if ((existingEntry = IsExistingContents(catalog, contents, FALSE))) { - UpdateCatalogEntry(existingEntry, fileName, contents, scale); - } else { - CatalogEntry *newEntry; - newEntry = InsertInOrder(catalog, contents, scale); - UpdateCatalogEntry(newEntry, fileName, contents, scale); - } - MyFree(contents); - MyFree(scale); - free(fileName); - fileName = NULL; - } - closedir(d); - } - paramLib->parameterFileCount = CountCatalogEntries(paramLib->catalog); - return (paramLib->parameterFileCount); + DIR *d; + Catalog *catalog = paramLib->catalog; + + d = opendir(directory); + if (d) { + char *fileName = NULL; + + while (GetNextParameterFile(d, directory, &fileName)) { + CatalogEntry *existingEntry; + + char *contents = GetParameterFileContent(fileName); + + char *scale = GetParameterFileScale(fileName); + + + if ((existingEntry = IsExistingContents(catalog, contents, FALSE))) { + UpdateCatalogEntry(existingEntry, fileName, contents, scale); + } else { + CatalogEntry *newEntry; + newEntry = InsertInOrder(catalog, contents, scale); + UpdateCatalogEntry(newEntry, fileName, contents, scale); + } + MyFree(contents); + MyFree(scale); + free(fileName); + fileName = NULL; + } + closedir(d); + } + paramLib->parameterFileCount = CountCatalogEntries(paramLib->catalog); + return (paramLib->parameterFileCount); } /** @@ -592,18 +595,18 @@ CreateCatalogFromDir(ParameterLib *paramLib, char *directory) void DiscardCatalog(ParameterLib *library) { - CatalogEntry *entry; - CatalogEntry *temp; - - DL_FOREACH_SAFE(library->catalog->head, entry, temp) { - MyFree(entry->contents); - MyFree(entry->tag); - for (unsigned int i = 0; i < entry->files; i++) { - MyFree(entry->fullFileName[i]); - } - DL_DELETE(library->catalog->head, entry); - MyFree(entry); - } + CatalogEntry *entry; + CatalogEntry *temp; + + DL_FOREACH_SAFE(library->catalog->head, entry, temp) { + MyFree(entry->contents); + MyFree(entry->tag); + for (unsigned int i = 0; i < entry->files; i++) { + MyFree(entry->fullFileName[i]); + } + DL_DELETE(library->catalog->head, entry); + MyFree(entry); + } } @@ -620,11 +623,11 @@ DiscardCatalog(ParameterLib *library) unsigned CreateLibraryIndex(ParameterLib *parameterLib) { - parameterLib->index = NULL; + parameterLib->index = NULL; - parameterLib->wordCount = CreateKeywordIndex(parameterLib); + parameterLib->wordCount = CreateKeywordIndex(parameterLib); - return (parameterLib->wordCount); + return (parameterLib->wordCount); } /** @@ -638,19 +641,19 @@ CreateLibraryIndex(ParameterLib *parameterLib) void DiscardLibraryIndex(ParameterLib *trackLib) { - IndexEntry *indexEntry; - IndexEntry *tmp; - - DL_FOREACH_SAFE(trackLib->index, indexEntry, tmp) { - DYNARR_FREE(CatalogEntry *, *(indexEntry->references)); - free(indexEntry->references); - DL_DELETE(trackLib->index, indexEntry); - MyFree(indexEntry); - } - - MyFree(trackLib->words); - trackLib->index = NULL; - trackLib->wordCount = 0; + IndexEntry *indexEntry; + IndexEntry *tmp; + + DL_FOREACH_SAFE(trackLib->index, indexEntry, tmp) { + DYNARR_FREE(CatalogEntry *, *(indexEntry->references)); + free(indexEntry->references); + DL_DELETE(trackLib->index, indexEntry); + MyFree(indexEntry); + } + + MyFree(trackLib->words); + trackLib->index = NULL; + trackLib->wordCount = 0; } @@ -664,19 +667,19 @@ DiscardLibraryIndex(ParameterLib *trackLib) ParameterLib * CreateLibrary(char *directory) { - ParameterLib *library; + ParameterLib *library; - log_params = LogFindIndex("params"); + log_params = LogFindIndex("params"); - library = InitLibrary(); - if (library) { - if (!CreateCatalogFromDir(library, directory)) { - return (NULL); - } + library = InitLibrary(); + if (library) { + if (!CreateCatalogFromDir(library, directory)) { + return (NULL); + } - CreateLibraryIndex(library); - } - return (library); + CreateLibraryIndex(library); + } + return (library); } /** @@ -688,23 +691,23 @@ CreateLibrary(char *directory) void DiscardLibrary(ParameterLib* library) { - CatalogEntry *entry = library->catalog->head; - CatalogEntry *element; - CatalogEntry *tmp; - - DiscardLibraryIndex(library); - - DL_FOREACH_SAFE(entry, element, tmp) { - MyFree(element->contents); - MyFree(element->tag); - for (unsigned int i = 0; i < element->files; i++) { - MyFree(element->fullFileName[i]); - } - DL_DELETE(entry, element); - MyFree(element); - } - MyFree(library->words); - MyFree(library); + CatalogEntry *entry = library->catalog->head; + CatalogEntry *element; + CatalogEntry *tmp; + + DiscardLibraryIndex(library); + + DL_FOREACH_SAFE(entry, element, tmp) { + MyFree(element->contents); + MyFree(element->tag); + for (unsigned int i = 0; i < element->files; i++) { + MyFree(element->fullFileName[i]); + } + DL_DELETE(entry, element); + MyFree(element); + } + MyFree(library->words); + MyFree(library); } /** @@ -718,71 +721,71 @@ DiscardLibrary(ParameterLib* library) char * SearchStatistics(SearchResult *result) { - DynString buffer; - DynString subStats[STATE_COUNT]; + DynString buffer; + DynString subStats[STATE_COUNT]; - unsigned searched = 0; - unsigned discarded = 0; - unsigned notfound = 0; + unsigned searched = 0; + unsigned discarded = 0; + unsigned notfound = 0; unsigned close = 0; - char *resStat; - DynStringMalloc(&buffer, 16); + char *resStat; + DynStringMalloc(&buffer, 16); - for (int i = SEARCHED; i < STATE_COUNT; i++) { - DynStringMalloc(subStats + i, 16); - } + for (int i = SEARCHED; i < STATE_COUNT; i++) { + DynStringMalloc(subStats + i, 16); + } - DynStringCatCStr(subStats + SEARCHED, _("Found: ")); + DynStringCatCStr(subStats + SEARCHED, _("Found: ")); DynStringCatCStr(subStats + CLOSE, _("Similar: ")); - DynStringCatCStr(subStats + DISCARDED, _("Ignored: ")); - DynStringCatCStr(subStats + NOTFOUND, _("Not found: ")); - - for (unsigned int i = 0; i < result->words; i++) { - switch (result->kw[i].state) { - case SEARCHED: - DynStringPrintf(&buffer, "%s (%d) ", result->kw[i].keyWord, - result->kw[i].count); - searched++; - break; - case DISCARDED: - DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); - discarded++; - break; - case NOTFOUND: - DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); - notfound++; - break; + DynStringCatCStr(subStats + DISCARDED, _("Ignored: ")); + DynStringCatCStr(subStats + NOTFOUND, _("Not found: ")); + + for (unsigned int i = 0; i < result->words; i++) { + switch (result->kw[i].state) { + case SEARCHED: + DynStringPrintf(&buffer, "%s (%d) ", result->kw[i].keyWord, + result->kw[i].count); + searched++; + break; + case DISCARDED: + DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); + discarded++; + break; + case NOTFOUND: + DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); + notfound++; + break; case CLOSE: DynStringPrintf(&buffer, "%s ", result->kw[i].keyWord); close++; break; - default: - break; - } - DynStringCatStr(subStats + result->kw[i].state, &buffer); - } - - DynStringReset(&buffer); - if (searched) { - DynStringCatStr(&buffer, subStats + SEARCHED); - } + default: + break; + } + DynStringCatStr(subStats + result->kw[i].state, &buffer); + } + + DynStringReset(&buffer); + if (searched) { + DynStringCatStr(&buffer, subStats + SEARCHED); + } if (close) { DynStringCatStr(&buffer, subStats + CLOSE); } - if (notfound) { - DynStringCatStr(&buffer, subStats + NOTFOUND); - } - if (discarded) { - DynStringCatStr(&buffer, subStats + DISCARDED); - } - - resStat = MyStrdup(DynStringToCStr(&buffer)); - DynStringFree(&buffer); + if (notfound) { + DynStringCatStr(&buffer, subStats + NOTFOUND); + } + if (discarded) { + DynStringCatStr(&buffer, subStats + DISCARDED); + } + + resStat = MyStrdup(DynStringToCStr(&buffer)); + DynStringFree(&buffer); for (int i = SEARCHED; i < STATE_COUNT; i++) { DynStringFree(subStats + i); } - return (resStat); + return (resStat); } /** @@ -795,30 +798,31 @@ SearchStatistics(SearchResult *result) unsigned countWords(char *str) { - int state = FALSE; - unsigned wc = 0; // word count - - // Scan all characters one by one - while (*str) { - // If next character is a separator, set the - // state as FALSE - if (*str == ' ' || *str == '\n' || *str == '\t' || *str == '\r' || *str == '/') { - state = FALSE; - } - - // If next character is not a word separator and - // state is OUT, then set the state as IN and - // increment word count - else if (state == FALSE) { - state = TRUE; - ++wc; - } - - // Move to next character - ++str; - } - - return wc; + int state = FALSE; + unsigned wc = 0; // word count + + // Scan all characters one by one + while (*str) { + // If next character is a separator, set the + // state as FALSE + if (*str == ' ' || *str == '\n' || *str == '\t' || *str == '\r' + || *str == '/') { + state = FALSE; + } + + // If next character is not a word separator and + // state is OUT, then set the state as IN and + // increment word count + else if (state == FALSE) { + state = TRUE; + ++wc; + } + + // Move to next character + ++str; + } + + return wc; } /** @@ -836,101 +840,101 @@ unsigned SearchLibrary(ParameterLib *library, char *searchExpression, SearchResult *results) { - CatalogEntry *element; - IndexEntry *entries; - unsigned entryCount = 0; - char *searchWord; - unsigned words = countWords(searchExpression); - char *searchExp = MyStrdup(searchExpression); - unsigned i = 0; - - if (library->index == NULL || library->wordCount == 0) { - return (0); - } - - results->kw = MyMalloc(words * sizeof(struct sSingleResult)); - results->subCatalog.head = NULL; - - searchWord = strtok(searchExp, SEARCHDELIMITER); - while (searchWord) { - XtcStrlwr(searchWord); - if (!FilterKeyword(searchWord)) { - StandardizeSpelling(searchWord); - results->kw[i].state = SEARCHED; - } else { - results->kw[i].state = DISCARDED; - } - results->kw[i++].keyWord = MyStrdup(searchWord); - searchWord = strtok(NULL, SEARCHDELIMITER); - } - results->words = words; - - i = 0; - while (i < words) { - if (results->kw[i].state == DISCARDED) { - i++; - continue; - } - FindWord(library->index, library->wordCount, results->kw[i].keyWord, &entries); - if (entries) { - results->kw[i].count = entries->references->cnt; + CatalogEntry *element; + IndexEntry *entries; +// unsigned entryCount = 0; + char *searchWord; + unsigned words = countWords(searchExpression); + char *searchExp = MyStrdup(searchExpression); + unsigned i = 0; + + if (library->index == NULL || library->wordCount == 0) { + return (0); + } + + results->kw = MyMalloc(words * sizeof(struct sSingleResult)); + results->subCatalog.head = NULL; + + searchWord = strtok(searchExp, SEARCHDELIMITER); + while (searchWord) { + XtcStrlwr(searchWord); + if (!FilterKeyword(searchWord)) { + StandardizeSpelling(searchWord); + results->kw[i].state = SEARCHED; + } else { + results->kw[i].state = DISCARDED; + } + results->kw[i++].keyWord = MyStrdup(searchWord); + searchWord = strtok(NULL, SEARCHDELIMITER); + } + results->words = words; + + i = 0; + while (i < words) { + if (results->kw[i].state == DISCARDED) { + i++; + continue; + } + FindWord(library->index, library->wordCount, results->kw[i].keyWord, &entries); + if (entries) { + results->kw[i].count = entries->references->cnt; if (XtcStricmp(results->kw[i].keyWord, entries->keyWord)) { results->kw[i].state = CLOSE; MyFree(results->kw[i].keyWord); results->kw[i].keyWord = MyStrdup(entries->keyWord); } - if (results->subCatalog.head == NULL) { - // if first keyword -> initialize result set - for (int j = 0; j < entries->references->cnt; j++) { - CatalogEntry *newEntry = MyMalloc(sizeof(CatalogEntry)); - CatalogEntry *foundEntry = DYNARR_N(CatalogEntry *, *(entries->references), j); - newEntry->contents = MyStrdup(foundEntry->contents); - newEntry->tag = MyStrdup(foundEntry->tag); - newEntry->files = foundEntry->files; - for (unsigned int i=0;ifiles;i++) { - newEntry->fullFileName[i] = MyStrdup(foundEntry->fullFileName[i]); - } - - DL_APPEND(results->subCatalog.head, newEntry); - } - } else { - // follow up keyword, create intersection with current result set - CatalogEntry *current; - CatalogEntry *temp; - - DL_FOREACH_SAFE(results->subCatalog.head, current, temp) { - int found = 0; - for (int j = 0; j < entries->references->cnt; j++) { - CatalogEntry *foundEntry = DYNARR_N(CatalogEntry *, *(entries->references), j); - - if (strcmp(foundEntry->contents,current->contents)==0) { - found = TRUE; - break; - } - } - if (!found) { - DL_DELETE(results->subCatalog.head, current); - MyFree(current->contents); - MyFree(current->tag); - for (unsigned int i=0;ifiles;i++) { - MyFree(current->fullFileName[i]); - } - MyFree(current); - } - } - } - } else { - // Searches that don't yield a result are ignored - results->kw[i].state = NOTFOUND; - results->kw[i].count = 0; - } - i++; - } - - DL_COUNT(results->subCatalog.head, element, results->totalFound); - MyFree(searchExp); - return (results->totalFound); + if (results->subCatalog.head == NULL) { + // if first keyword -> initialize result set + for (int j = 0; j < entries->references->cnt; j++) { + CatalogEntry *newEntry = MyMalloc(sizeof(CatalogEntry)); + CatalogEntry *foundEntry = DYNARR_N(CatalogEntry *, *(entries->references), j); + newEntry->contents = MyStrdup(foundEntry->contents); + newEntry->tag = MyStrdup(foundEntry->tag); + newEntry->files = foundEntry->files; + for (unsigned int i=0; ifiles; i++) { + newEntry->fullFileName[i] = MyStrdup(foundEntry->fullFileName[i]); + } + + DL_APPEND(results->subCatalog.head, newEntry); + } + } else { + // follow up keyword, create intersection with current result set + CatalogEntry *current; + CatalogEntry *temp; + + DL_FOREACH_SAFE(results->subCatalog.head, current, temp) { + int found = 0; + for (int j = 0; j < entries->references->cnt; j++) { + CatalogEntry *foundEntry = DYNARR_N(CatalogEntry *, *(entries->references), j); + + if (strcmp(foundEntry->contents,current->contents)==0) { + found = TRUE; + break; + } + } + if (!found) { + DL_DELETE(results->subCatalog.head, current); + MyFree(current->contents); + MyFree(current->tag); + for (unsigned int i=0; ifiles; i++) { + MyFree(current->fullFileName[i]); + } + MyFree(current); + } + } + } + } else { + // Searches that don't yield a result are ignored + results->kw[i].state = NOTFOUND; + results->kw[i].count = 0; + } + i++; + } + + DL_COUNT(results->subCatalog.head, element, results->totalFound); + MyFree(searchExp); + return (results->totalFound); } /** @@ -942,21 +946,21 @@ SearchLibrary(ParameterLib *library, char *searchExpression, void SearchDiscardResult(SearchResult *res) { - if (res) { - CatalogEntry *current = res->subCatalog.head; - CatalogEntry *element; - CatalogEntry *tmp; - - DL_FOREACH_SAFE(current, element, tmp) { - DL_DELETE(current, element); - MyFree(element); - } - - for (unsigned int i = 0; i < res->words; i++) { - MyFree(res->kw[i].keyWord); - } - MyFree(res->kw); - } + if (res) { + CatalogEntry *current = res->subCatalog.head; + CatalogEntry *element; + CatalogEntry *tmp; + + DL_FOREACH_SAFE(current, element, tmp) { + DL_DELETE(current, element); + MyFree(element); + } + + for (unsigned int i = 0; i < res->words; i++) { + MyFree(res->kw[i].keyWord); + } + MyFree(res->kw); + } } /** @@ -969,35 +973,35 @@ SearchDiscardResult(SearchResult *res) char * GetParameterFileContent(char *file) { - FILE *fh; - char *result = NULL; - - fh = fopen(file, "rt"); - if (fh) { - bool found = false; - - while (!found) { - char buffer[512]; - if (fgets(buffer, sizeof(buffer), fh)) { - char *ptr = strtok(buffer, " \t"); - if (!XtcStricmp(ptr, CONTENTSCOMMAND)) { - /* if found, store the rest of the line and the filename */ - ptr = ptr+strlen(CONTENTSCOMMAND)+1; - ptr = strtok(ptr, "\r\n"); - result = MyStrdup(ptr); + FILE *fh; + char *result = NULL; + + fh = fopen(file, "rt"); + if (fh) { + bool found = false; + + while (!found) { + char buffer[512]; + if (fgets(buffer, sizeof(buffer), fh)) { + char *ptr = strtok(buffer, " \t"); + if (!XtcStricmp(ptr, CONTENTSCOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(CONTENTSCOMMAND)+1; + ptr = strtok(ptr, "\r\n"); + result = MyStrdup(ptr); #ifdef UTFCONVERT - ConvertUTF8ToSystem(result); + ConvertUTF8ToSystem(result); #endif // UTFCONVERT - found = true; - } - } else { - fprintf(stderr, "Nothing found in %s\n", file); - found = true; - } - } - fclose(fh); - } - return (result); + found = true; + } + } else { + fprintf(stderr, "Nothing found in %s\n", file); + found = true; + } + } + fclose(fh); + } + return (result); } /** @@ -1010,68 +1014,69 @@ GetParameterFileContent(char *file) char * GetParameterFileScale(char *file) { - FILE *fh; - char *scale = NULL; - - - fh = fopen(file, "rt"); - if (fh) { - bool found = FALSE, found_Turnout = FALSE, found_Structure = FALSE, found_Car = FALSE; - - while (!found) { - char buffer[512]; - if (fgets(buffer, sizeof(buffer), fh)) { - char *ptr = strtok(buffer, " \t"); - if (!found_Turnout && !XtcStricmp(ptr, TURNOUTCOMMAND)) { - /* if found, store the rest of the line and the filename */ - ptr = ptr+strlen(TURNOUTCOMMAND)+1; - ptr = strtok(ptr, " \t"); - scale = MyMalloc(strlen(TURNOUTCOMMAND)+2+strlen(ptr)); - strcpy(scale,TURNOUTCOMMAND); - char * cp = scale + strlen(TURNOUTCOMMAND); - cp[0] = ' '; - cp++; - strcpy(cp,ptr); - found_Turnout = true; - } else if (!found_Structure && !XtcStricmp(ptr, STRUCTURECOMMAND)) { - /* if found, store the rest of the line and the filename */ - ptr = ptr+strlen(STRUCTURECOMMAND)+1; - ptr = strtok(ptr, " \t"); - scale = MyMalloc(strlen(STRUCTURECOMMAND)+2+strlen(ptr)); - strcpy(scale,STRUCTURECOMMAND); + FILE *fh; + char *scale = NULL; + + + fh = fopen(file, "rt"); + if (fh) { + bool found = FALSE, found_Turnout = FALSE, found_Structure = FALSE, + found_Car = FALSE; + + while (!found) { + char buffer[512]; + if (fgets(buffer, sizeof(buffer), fh)) { + char *ptr = strtok(buffer, " \t"); + if (!found_Turnout && !XtcStricmp(ptr, TURNOUTCOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(TURNOUTCOMMAND)+1; + ptr = strtok(ptr, " \t"); + scale = MyMalloc(strlen(TURNOUTCOMMAND)+2+strlen(ptr)); + strcpy(scale,TURNOUTCOMMAND); + char * cp = scale + strlen(TURNOUTCOMMAND); + cp[0] = ' '; + cp++; + strcpy(cp,ptr); + found_Turnout = true; + } else if (!found_Structure && !XtcStricmp(ptr, STRUCTURECOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(STRUCTURECOMMAND)+1; + ptr = strtok(ptr, " \t"); + scale = MyMalloc(strlen(STRUCTURECOMMAND)+2+strlen(ptr)); + strcpy(scale,STRUCTURECOMMAND); char * cp = scale + strlen(STRUCTURECOMMAND)+1; cp[-1] = ' '; strcpy(cp,ptr); - found_Structure = true; - } else if (!found_Car && !XtcStricmp(ptr, CARCOMMAND)) { - /* if found, store the rest of the line and the filename */ - ptr = ptr+strlen(CARCOMMAND)+1; - ptr = strtok(ptr, " \t"); - scale = MyMalloc(strlen(CARCOMMAND)+2+strlen(ptr)); - strcpy(scale,CARCOMMAND); + found_Structure = true; + } else if (!found_Car && !XtcStricmp(ptr, CARCOMMAND)) { + /* if found, store the rest of the line and the filename */ + ptr = ptr+strlen(CARCOMMAND)+1; + ptr = strtok(ptr, " \t"); + scale = MyMalloc(strlen(CARCOMMAND)+2+strlen(ptr)); + strcpy(scale,CARCOMMAND); char * cp = scale + strlen(CARCOMMAND)+1; cp[-1] = ' '; strcpy(cp,ptr); - found_Car = true; - } else if (!found_Car && !XtcStricmp(ptr, CARPROTOCOMMAND)) { - /* if found, store the rest of the line and the filename */ - scale = MyMalloc(strlen(CARPROTOCOMMAND)+3); - strcpy(scale,CARPROTOCOMMAND); + found_Car = true; + } else if (!found_Car && !XtcStricmp(ptr, CARPROTOCOMMAND)) { + /* if found, store the rest of the line and the filename */ + scale = MyMalloc(strlen(CARPROTOCOMMAND)+3); + strcpy(scale,CARPROTOCOMMAND); char * cp = scale + strlen(CARPROTOCOMMAND); strcpy(cp," *"); - found_Car = true; - } - } else { - if (!found_Turnout && !found_Structure && !found_Car) { - fprintf(stderr, "Nothing found in %s\n", file); - found = true; - } - } - if (found_Turnout || found_Structure || found_Car) found = TRUE; - } - fclose(fh); - } - return scale; + found_Car = true; + } + } else { + if (!found_Turnout && !found_Structure && !found_Car) { + fprintf(stderr, "Nothing found in %s\n", file); + found = true; + } + } + if (found_Turnout || found_Structure || found_Car) { found = TRUE; } + } + fclose(fh); + } + return scale; } @@ -1079,22 +1084,22 @@ GetParameterFileScale(char *file) /** this is used to test for memory leaks. It should show no leaks from functions in this source file */ RunMemoryTest(char *directory) { - ParameterLib *library; - SearchResult *results; - - mwInit(); - library = InitLibrary(); - if (library) { - CreateCatalogFromDir(library, directory); - CreateLibraryIndex(library); - results = MyMalloc(sizeof(SearchResult)); - SearchLibrary(library, "peco", results); - SearchDiscardResult(results); - MyFree(results); - DiscardLibraryIndex(library); - DiscardCatalog(library); - } - DestroyLibrary(library); - mwTerm(); + ParameterLib *library; + SearchResult *results; + + mwInit(); + library = InitLibrary(); + if (library) { + CreateCatalogFromDir(library, directory); + CreateLibraryIndex(library); + results = MyMalloc(sizeof(SearchResult)); + SearchLibrary(library, "peco", results); + SearchDiscardResult(results); + MyFree(results); + DiscardLibraryIndex(library); + DiscardCatalog(library); + } + DestroyLibrary(library); + mwTerm(); } #endif //MEMWATCH -- cgit v1.2.3