aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornyamatongwe <devnull@localhost>2000-08-31 13:37:11 +0000
committernyamatongwe <devnull@localhost>2000-08-31 13:37:11 +0000
commit47217769b30c613d6772c9c992c69e250c6c6d5c (patch)
tree88bc3f11ae21230b352970c3bf8a35ba9b8e9dff /src
parent90f82072df218491195da41326ae24830156844a (diff)
downloadscintilla-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.cxx271
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;
+}