diff options
author | nyamatongwe <devnull@localhost> | 2000-08-31 13:37:11 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2000-08-31 13:37:11 +0000 |
commit | 47217769b30c613d6772c9c992c69e250c6c6d5c (patch) | |
tree | 88bc3f11ae21230b352970c3bf8a35ba9b8e9dff /src | |
parent | 90f82072df218491195da41326ae24830156844a (diff) | |
download | scintilla-mirror-47217769b30c613d6772c9c992c69e250c6c6d5c.tar.gz |
Changes from Ferda to put the sorting and searching here rather than in
SciTEBase.
Diffstat (limited to 'src')
-rw-r--r-- | src/PropSet.cxx | 271 |
1 files changed, 267 insertions, 4 deletions
diff --git a/src/PropSet.cxx b/src/PropSet.cxx index 42c5869c9..66018544a 100644 --- a/src/PropSet.cxx +++ b/src/PropSet.cxx @@ -336,6 +336,7 @@ static bool iswordsep(char ch, bool onlyLineEnds) { // Creates an array that points into each word in the string and puts \0 terminators // after each word. static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) { +#if 0 char prev = '\n'; int words = 0; for (int j = 0; wordlist[j]; j++) { @@ -364,15 +365,49 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa } else { *len = 0; } +#else + int words = 0; // length of the returned buffer of pointers + #undef APICHUNK // how many pointers will be pre-allocated (to avoid buffer reallocation on each new pointer) + #define APICHUNK 256 + int size = APICHUNK; // real size of the returned buffer of pointers + char **keywords; // buffer for the pointers returned + int slen = strlen(wordlist); //length of the buffer with api file + keywords = (char**) malloc((size + 1) * sizeof (*keywords)); + words = 0; + for (int k = 0;;) { + while (iswordsep(wordlist[k], onlyLineEnds)) + wordlist[k++] = '\0'; + if (k >= slen) + break; + if (words >= size) { + do + size += APICHUNK; + while (size <= words); + keywords = (char**) realloc(keywords, (size + 1) * sizeof (*keywords)); + } + keywords[words++] = wordlist + k; + do + if (k < slen) + k++; + else + goto out; + while (!iswordsep(wordlist[k], onlyLineEnds)); + } +out: + keywords[words] = wordlist + slen; + *len = words; +#endif return keywords; } void WordList::Clear() { if (words) { - delete []words; delete []list; + free(words); + free(wordsNoCase); } words = 0; + wordsNoCase = 0; list = 0; len = 0; sorted = false; @@ -382,6 +417,8 @@ void WordList::Set(const char *s) { list = StringDup(s); sorted = false; words = ArrayFromWordList(list, &len, onlyLineEnds); + wordsNoCase = (char**) malloc ((len + 1) * sizeof (*wordsNoCase)); + memcpy(wordsNoCase, words, (len + 1) * sizeof (*words)); } char *WordList::Allocate(int size) { @@ -393,6 +430,8 @@ char *WordList::Allocate(int size) { void WordList::SetFromAllocated() { sorted = false; words = ArrayFromWordList(list, &len, onlyLineEnds); + wordsNoCase = (char**) malloc ((len + 1) * sizeof (*wordsNoCase)); + memcpy(wordsNoCase, words, (len + 1) * sizeof (*words)); } int cmpString(const void *a1, const void *a2) { @@ -400,17 +439,24 @@ int cmpString(const void *a1, const void *a2) { return strcmp(*(char**)(a1), *(char**)(a2)); } -static void SortWordList(char **words, unsigned int len) { +int cmpStringNoCase(const void *a1, const void *a2) { + // Can't work out the correct incantation to use modern casts here + return strcasecmp(*(char**)(a1), *(char**)(a2)); +} + +static void SortWordList(char **words, char **wordsNoCase, unsigned int len) { qsort(reinterpret_cast<void*>(words), len, sizeof(*words), cmpString); + qsort(reinterpret_cast<void*>(wordsNoCase), len, sizeof(*wordsNoCase), + cmpStringNoCase); } - + bool WordList::InList(const char *s) { if (0 == words) return false; if (!sorted) { sorted = true; - SortWordList(words, len); + SortWordList(words, wordsNoCase, len); for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++) starts[k] = -1; for (int l = len - 1; l >= 0; l--) { @@ -437,3 +483,220 @@ bool WordList::InList(const char *s) { } return false; } + +/** + * Returns an element (complete) of the wordlist array which has the beginning + * the same as the passed string. The length of the word to compare is passed + * too. Letter case can be ignored or preserved (default). + */ +const char *WordList::GetNearestWord(const char *wordStart, int searchLen /*= -1*/, bool ignoreCase /*= false*/) { + int start = 0; // lower bound of the api array block to search + int end = len - 1; // upper bound of the api array block to search + int pivot; // index of api array element just being compared + int cond; // comparison result (in the sense of strcmp() result) + const char *word; // api array element just being compared + + if (0 == words) + return NULL; + if (!sorted) { + sorted = true; + SortWordList(words, wordsNoCase, len); + } + if (ignoreCase) + while (start <= end) { // binary searching loop + pivot = (start + end) >> 1; + word = wordsNoCase[pivot]; + cond = strncasecmp(wordStart, word, searchLen); + if (!cond && nonFuncChar(word[searchLen])) // maybe there should be a "non-word character" test here? + return word; // result must not be freed with free() + else if (cond < 0) + end = pivot - 1; + else if (cond > 0) + start = pivot + 1; + } + else // preserve the letter case + while (start <= end) { // binary searching loop + pivot = (start + end) >> 1; + word = words[pivot]; + cond = strncmp(wordStart, word, searchLen); + if (!cond && nonFuncChar(word[searchLen])) // maybe there should be a "non-word character" test here? + return word; // result must not be freed with free() + else if (cond >= 0) + start = pivot + 1; + else if (cond < 0) + end = pivot - 1; + } + return NULL; +} + +/** + * Returns elements (first words of them) of the wordlist array which have + * the beginning the same as the passed string. The length of the word to + * compare is passed too. Letter case can be ignored or preserved (default). + * If there are more words meeting the condition they are returned all of + * them in the ascending order separated with spaces. + * + * NOTE: returned buffer has to be freed with a free() call. + */ +char *WordList::GetNearestWords(const char *wordStart, int searchLen /*= -1*/, bool ignoreCase /*= false*/) { + int wordlen; // length of the word part (before the '(' brace) of the api array element + int length = 0; // length of the returned buffer of words (string) + int newlength; // length of the new buffer before the reallocating itself + #undef WORDCHUNK // how many characters will be pre-allocated (to avoid buffer reallocation on each new word) + #define WORDCHUNK 100 + int size = WORDCHUNK; // real size of the returned buffer of words + char *buffer; // buffer for the words returned + int start = 0; // lower bound of the api array block to search + int end = len - 1; // upper bound of the api array block to search + int pivot; // index of api array element just being compared + int cond; // comparison result (in the sense of strcmp() result) + int oldpivot; // pivot storage to be able to browse the api array upwards and then downwards + const char *word; // api array element just being compared + const char *brace; // position of the opening brace in the api array element just being compared + + if (0 == words) + return NULL; + if (!sorted) { + sorted = true; + SortWordList(words, wordsNoCase, len); + } + buffer = (char*) malloc(size); + *buffer = '\0'; + if (ignoreCase) + while (start <= end) { // binary searching loop + pivot = (start + end) >> 1; + word = wordsNoCase[pivot]; + cond = strncasecmp(wordStart, word, searchLen); + if (!cond) { + oldpivot = pivot; + do { // browse sequentially the rest after the hit + brace = strchr(word, '('); + if (brace) + wordlen = brace - word; + else + wordlen = strlen(word); + newlength = length + wordlen; // stretch the buffer + if (length) + newlength++; + if (newlength >= size) { + do + size += WORDCHUNK; + while (size <= newlength); + buffer = (char*) realloc(buffer, size); + } + if (length) // append a new entry + buffer[length++] = ' '; + memcpy(buffer + length, word, wordlen); + length = newlength; + buffer[length] = '\0'; + if (++pivot >= end) + break; + word = wordsNoCase[pivot]; + } while (!strncasecmp(wordStart, word, searchLen)); + + pivot = oldpivot; + for (;;) { // browse sequentially the rest before the hit + if (--pivot < start) + break; + word = wordsNoCase[pivot]; + if (strncasecmp(wordStart, word, searchLen)) + break; + brace = strchr(word, '('); + if (brace) + wordlen = brace - word; + else + wordlen = strlen(word); + newlength = length + wordlen; // stretch the buffer + if (length) + newlength++; + if (newlength >= size) + { + do + size += WORDCHUNK; + while (size <= newlength); + buffer = (char*) realloc(buffer, size); + } + if (length) // append a new entry + buffer[length++] = ' '; + memcpy(buffer + length, word, wordlen); + length = newlength; + buffer[length] = '\0'; + } + return buffer; // result has to be freed with free() + } + else if (cond < 0) + end = pivot - 1; + else if (cond > 0) + start = pivot + 1; + } + else // preserve the letter case + while (start <= end) { // binary searching loop + pivot = (start + end) >> 1; + word = words[pivot]; + cond = strncmp(wordStart, word, searchLen); + if (!cond) { + oldpivot = pivot; + do { // browse sequentially the rest after the hit + brace = strchr(word, '('); + if (brace) + wordlen = brace - word; + else + wordlen = strlen(word); + newlength = length + wordlen; // stretch the buffer + if (length) + newlength++; + if (newlength >= size) + { + do + size += WORDCHUNK; + while (size <= newlength); + buffer = (char*) realloc(buffer, size); + } + if (length) // append a new entry + buffer[length++] = ' '; + memcpy(buffer + length, word, wordlen); + length = newlength; + buffer[length] = '\0'; + if (++pivot >= end) + break; + word = words[pivot]; + } while (!strncmp(wordStart, word, searchLen)); + + pivot = oldpivot; + for (;;) { // browse sequentially the rest before the hit + if (--pivot < start) + break; + word = words[pivot]; + if (strncmp(wordStart, word, searchLen)) + break; + brace = strchr(word, '('); + if (brace) + wordlen = brace - word; + else + wordlen = strlen(word); + newlength = length + wordlen; // stretch the buffer + if (length) + newlength++; + if (newlength >= size) + { + do + size += WORDCHUNK; + while (size <= newlength); + buffer = (char*) realloc(buffer, size); + } + if (length) // append a new entry + buffer[length++] = ' '; + memcpy(buffer + length, word, wordlen); + length = newlength; + buffer[length] = '\0'; + } + return buffer; // result has to be freed with free() + } + else if (cond < 0) + end = pivot - 1; + else if (cond > 0) + start = pivot + 1; + } + free(buffer); + return NULL; +} |