aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornyamatongwe <unknown>2009-07-21 09:05:43 +0000
committernyamatongwe <unknown>2009-07-21 09:05:43 +0000
commit7b7af48a7681ab335ba2c53ffa48ab053ddf4c86 (patch)
tree6039e12ca6c8f447ca34fbe3c3b0195d4c3a2372 /src
parentf20e894bd45438901560b6838cea7d4639f1e5c6 (diff)
downloadscintilla-mirror-7b7af48a7681ab335ba2c53ffa48ab053ddf4c86.tar.gz
Using a much simpler property set implementation.
Accessor objects use the PropertyGet interface to access just the property set methods they need. Removed SString.
Diffstat (limited to 'src')
-rw-r--r--src/AutoComplete.cxx2
-rw-r--r--src/CharClassify.cxx34
-rw-r--r--src/CharClassify.h14
-rw-r--r--src/Document.cxx10
-rw-r--r--src/DocumentAccessor.h5
-rw-r--r--src/KeyWords.cxx186
-rw-r--r--src/LexCaml.cxx3
-rw-r--r--src/LexCmake.cxx1
-rw-r--r--src/LexHaskell.cxx3
-rw-r--r--src/LexInno.cxx1
-rw-r--r--src/LexNsis.cxx1
-rw-r--r--src/LexOthers.cxx1
-rw-r--r--src/PropSet.cxx713
-rw-r--r--src/ScintillaBase.cxx16
-rw-r--r--src/ScintillaBase.h2
15 files changed, 321 insertions, 671 deletions
diff --git a/src/AutoComplete.cxx b/src/AutoComplete.cxx
index af6154ea1..86c64df56 100644
--- a/src/AutoComplete.cxx
+++ b/src/AutoComplete.cxx
@@ -11,7 +11,7 @@
#include "Platform.h"
-#include "PropSet.h"
+#include "CharClassify.h"
#include "AutoComplete.h"
#ifdef SCI_NAMESPACE
diff --git a/src/CharClassify.cxx b/src/CharClassify.cxx
index acab4b229..42a0ff10e 100644
--- a/src/CharClassify.cxx
+++ b/src/CharClassify.cxx
@@ -41,3 +41,37 @@ void CharClassify::SetCharClasses(const unsigned char *chars, cc newCharClass) {
}
}
}
+
+int CompareCaseInsensitive(const char *a, const char *b) {
+ while (*a && *b) {
+ if (*a != *b) {
+ char upperA = MakeUpperCase(*a);
+ char upperB = MakeUpperCase(*b);
+ if (upperA != upperB)
+ return upperA - upperB;
+ }
+ a++;
+ b++;
+ }
+ // Either *a or *b is nul
+ return *a - *b;
+}
+
+int CompareNCaseInsensitive(const char *a, const char *b, size_t len) {
+ while (*a && *b && len) {
+ if (*a != *b) {
+ char upperA = MakeUpperCase(*a);
+ char upperB = MakeUpperCase(*b);
+ if (upperA != upperB)
+ return upperA - upperB;
+ }
+ a++;
+ b++;
+ len--;
+ }
+ if (len == 0)
+ return 0;
+ else
+ // Either *a or *b is nul
+ return *a - *b;
+}
diff --git a/src/CharClassify.h b/src/CharClassify.h
index 881d3a114..d746fe02d 100644
--- a/src/CharClassify.h
+++ b/src/CharClassify.h
@@ -2,7 +2,7 @@
/** @file CharClassify.h
** Character classifications used by Document and RESearch.
**/
-// Copyright 2006 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 2006-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef CHARCLASSIFY_H
@@ -22,4 +22,16 @@ private:
enum { maxChar=256 };
unsigned char charClass[maxChar]; // not type cc to save space
};
+
+// These functions are implemented because each platform calls them something different.
+int CompareCaseInsensitive(const char *a, const char *b);
+int CompareNCaseInsensitive(const char *a, const char *b, size_t len);
+
+inline char MakeUpperCase(char ch) {
+ if (ch < 'a' || ch > 'z')
+ return ch;
+ else
+ return static_cast<char>(ch - 'a' + 'A');
+}
+
#endif
diff --git a/src/Document.cxx b/src/Document.cxx
index fdf8261d9..ab29c798a 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -1067,16 +1067,6 @@ bool Document::IsWordAt(int start, int end) {
return IsWordStartAt(start) && IsWordEndAt(end);
}
-// The comparison and case changing functions here assume ASCII
-// or extended ASCII such as the normal Windows code page.
-
-static inline char MakeUpperCase(char ch) {
- if (ch < 'a' || ch > 'z')
- return ch;
- else
- return static_cast<char>(ch - 'a' + 'A');
-}
-
static inline char MakeLowerCase(char ch) {
if (ch < 'A' || ch > 'Z')
return ch;
diff --git a/src/DocumentAccessor.h b/src/DocumentAccessor.h
index a3a939d0d..92440428e 100644
--- a/src/DocumentAccessor.h
+++ b/src/DocumentAccessor.h
@@ -14,6 +14,7 @@ class Document;
/**
*/
+
class DocumentAccessor : public Accessor {
// Private so DocumentAccessor objects can not be copied
DocumentAccessor(const DocumentAccessor &source) : Accessor(), props(source.props) {}
@@ -21,7 +22,7 @@ class DocumentAccessor : public Accessor {
protected:
Document *pdoc;
- PropSet &props;
+ PropertyGet &props;
WindowID id;
int lenDoc;
@@ -37,7 +38,7 @@ protected:
void Fill(int position);
public:
- DocumentAccessor(Document *pdoc_, PropSet &props_, WindowID id_=0) :
+ DocumentAccessor(Document *pdoc_, PropertyGet &props_, WindowID id_=0) :
Accessor(), pdoc(pdoc_), props(props_), id(id_),
lenDoc(-1), validLen(0), chFlags(0), chWhile(0),
startSeg(0), startPosStyling(0),
diff --git a/src/KeyWords.cxx b/src/KeyWords.cxx
index 2e1e82882..366cb47dc 100644
--- a/src/KeyWords.cxx
+++ b/src/KeyWords.cxx
@@ -23,6 +23,192 @@
using namespace Scintilla;
#endif
+/**
+ * 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) {
+ int prev = '\n';
+ int words = 0;
+ // For rapid determination of whether a character is a separator, build
+ // a look up table.
+ bool wordSeparator[256];
+ for (int i=0;i<256; i++) {
+ wordSeparator[i] = false;
+ }
+ wordSeparator['\r'] = true;
+ wordSeparator['\n'] = true;
+ if (!onlyLineEnds) {
+ wordSeparator[' '] = true;
+ wordSeparator['\t'] = true;
+ }
+ for (int j = 0; wordlist[j]; j++) {
+ int curr = static_cast<unsigned char>(wordlist[j]);
+ if (!wordSeparator[curr] && wordSeparator[prev])
+ words++;
+ prev = curr;
+ }
+ char **keywords = new char *[words + 1];
+ if (keywords) {
+ words = 0;
+ prev = '\0';
+ size_t slen = strlen(wordlist);
+ for (size_t k = 0; k < slen; k++) {
+ if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
+ if (!prev) {
+ keywords[words] = &wordlist[k];
+ words++;
+ }
+ } else {
+ wordlist[k] = '\0';
+ }
+ prev = wordlist[k];
+ }
+ keywords[words] = &wordlist[slen];
+ *len = words;
+ } else {
+ *len = 0;
+ }
+ return keywords;
+}
+
+void WordList::Clear() {
+ if (words) {
+ delete []list;
+ delete []words;
+ }
+ words = 0;
+ list = 0;
+ len = 0;
+ sorted = false;
+}
+
+void WordList::Set(const char *s) {
+ list = new char[strlen(s) + 1];
+ strcpy(list, s);
+ sorted = false;
+ words = ArrayFromWordList(list, &len, onlyLineEnds);
+}
+
+extern "C" int cmpString(const void *a1, const void *a2) {
+ // Can't work out the correct incantation to use modern casts here
+ return strcmp(*(char**)(a1), *(char**)(a2));
+}
+
+static void SortWordList(char **words, unsigned int len) {
+ qsort(reinterpret_cast<void*>(words), len, sizeof(*words),
+ cmpString);
+}
+
+bool WordList::InList(const char *s) {
+ if (0 == words)
+ return false;
+ if (!sorted) {
+ sorted = true;
+ SortWordList(words, len);
+ for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
+ starts[k] = -1;
+ for (int l = len - 1; l >= 0; l--) {
+ unsigned char indexChar = words[l][0];
+ starts[indexChar] = l;
+ }
+ }
+ unsigned char firstChar = s[0];
+ int j = starts[firstChar];
+ if (j >= 0) {
+ while ((unsigned char)words[j][0] == firstChar) {
+ if (s[1] == words[j][1]) {
+ const char *a = words[j] + 1;
+ const char *b = s + 1;
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ if (!*a && !*b)
+ return true;
+ }
+ j++;
+ }
+ }
+ j = starts['^'];
+ if (j >= 0) {
+ while (words[j][0] == '^') {
+ const char *a = words[j] + 1;
+ const char *b = s;
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ if (!*a)
+ return true;
+ j++;
+ }
+ }
+ return false;
+}
+
+/** similar to InList, but word s can be a substring of keyword.
+ * eg. the keyword define is defined as def~ine. This means the word must start
+ * with def to be a keyword, but also defi, defin and define are valid.
+ * The marker is ~ in this case.
+ */
+bool WordList::InListAbbreviated(const char *s, const char marker) {
+ if (0 == words)
+ return false;
+ if (!sorted) {
+ sorted = true;
+ SortWordList(words, len);
+ for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
+ starts[k] = -1;
+ for (int l = len - 1; l >= 0; l--) {
+ unsigned char indexChar = words[l][0];
+ starts[indexChar] = l;
+ }
+ }
+ unsigned char firstChar = s[0];
+ int j = starts[firstChar];
+ if (j >= 0) {
+ while (words[j][0] == firstChar) {
+ bool isSubword = false;
+ int start = 1;
+ if (words[j][1] == marker) {
+ isSubword = true;
+ start++;
+ }
+ if (s[1] == words[j][start]) {
+ const char *a = words[j] + start;
+ const char *b = s + 1;
+ while (*a && *a == *b) {
+ a++;
+ if (*a == marker) {
+ isSubword = true;
+ a++;
+ }
+ b++;
+ }
+ if ((!*a || isSubword) && !*b)
+ return true;
+ }
+ j++;
+ }
+ }
+ j = starts['^'];
+ if (j >= 0) {
+ while (words[j][0] == '^') {
+ const char *a = words[j] + 1;
+ const char *b = s;
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ if (!*a)
+ return true;
+ j++;
+ }
+ }
+ return false;
+}
+
const LexerModule *LexerModule::base = 0;
int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;
diff --git a/src/LexCaml.cxx b/src/LexCaml.cxx
index 6570dcc07..0d1162259 100644
--- a/src/LexCaml.cxx
+++ b/src/LexCaml.cxx
@@ -27,6 +27,7 @@
#include "Platform.h"
#include "PropSet.h"
+#include "PropSetSimple.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
@@ -143,7 +144,7 @@ static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length,
int initStyle, char *words[], WindowID window, char *props)
{
// create and initialize a WindowAccessor (including contained PropSet)
- PropSet ps;
+ PropSetSimple ps;
ps.SetMultiple(props);
WindowAccessor wa(window, ps);
// create and initialize WordList(s)
diff --git a/src/LexCmake.cxx b/src/LexCmake.cxx
index f63eb399f..1f51f474e 100644
--- a/src/LexCmake.cxx
+++ b/src/LexCmake.cxx
@@ -13,6 +13,7 @@
#include "Platform.h"
+#include "CharClassify.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
diff --git a/src/LexHaskell.cxx b/src/LexHaskell.cxx
index 3213bd520..b528f3f0e 100644
--- a/src/LexHaskell.cxx
+++ b/src/LexHaskell.cxx
@@ -25,6 +25,7 @@
#include "Platform.h"
#include "PropSet.h"
+#include "PropSetSimple.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
@@ -225,7 +226,7 @@ static const char* LexerName = "haskell";
void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props)
{
- PropSet ps;
+ PropSetSimple ps;
ps.SetMultiple(props);
WindowAccessor wa(window, ps);
diff --git a/src/LexInno.cxx b/src/LexInno.cxx
index 6da8548ff..6d1102c65 100644
--- a/src/LexInno.cxx
+++ b/src/LexInno.cxx
@@ -13,6 +13,7 @@
#include "Platform.h"
+#include "CharClassify.h"
#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
diff --git a/src/LexNsis.cxx b/src/LexNsis.cxx
index ab6304c42..b16cc9baf 100644
--- a/src/LexNsis.cxx
+++ b/src/LexNsis.cxx
@@ -13,6 +13,7 @@
#include "Platform.h"
+#include "CharClassify.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
diff --git a/src/LexOthers.cxx b/src/LexOthers.cxx
index 1869014f8..75458f6d5 100644
--- a/src/LexOthers.cxx
+++ b/src/LexOthers.cxx
@@ -14,6 +14,7 @@
#include "Platform.h"
+#include "CharClassify.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
diff --git a/src/PropSet.cxx b/src/PropSet.cxx
index a1c366c3b..294d08e11 100644
--- a/src/PropSet.cxx
+++ b/src/PropSet.cxx
@@ -11,370 +11,53 @@
#include <string.h>
#include <stdio.h>
+#ifdef _MSC_VER
+// Visual C++ doesn't like unreachable code or long decorated names in its own headers.
+#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702 4786)
+#endif
+
+#include <string>
+#include <map>
+
#include "Platform.h"
#include "PropSet.h"
+#include "PropSetSimple.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
-// The comparison and case changing functions here assume ASCII
-// or extended ASCII such as the normal Windows code page.
-
-static inline char MakeUpperCase(char ch) {
- if (ch < 'a' || ch > 'z')
- return ch;
- else
- return static_cast<char>(ch - 'a' + 'A');
-}
-
-static inline bool IsLetter(char ch) {
- return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
-}
-
-inline bool IsASpace(unsigned int ch) {
- return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
-}
-
-int CompareCaseInsensitive(const char *a, const char *b) {
- while (*a && *b) {
- if (*a != *b) {
- char upperA = MakeUpperCase(*a);
- char upperB = MakeUpperCase(*b);
- if (upperA != upperB)
- return upperA - upperB;
- }
- a++;
- b++;
- }
- // Either *a or *b is nul
- return *a - *b;
-}
-
-int CompareNCaseInsensitive(const char *a, const char *b, size_t len) {
- while (*a && *b && len) {
- if (*a != *b) {
- char upperA = MakeUpperCase(*a);
- char upperB = MakeUpperCase(*b);
- if (upperA != upperB)
- return upperA - upperB;
- }
- a++;
- b++;
- len--;
- }
- if (len == 0)
- return 0;
- else
- // Either *a or *b is nul
- return *a - *b;
-}
-
-bool EqualCaseInsensitive(const char *a, const char *b) {
- return 0 == CompareCaseInsensitive(a, b);
-}
-
-// Since the CaseInsensitive functions declared in SString
-// are implemented here, I will for now put the non-inline
-// implementations of the SString members here as well, so
-// that I can quickly see what effect this has.
-
-SString::SString(int i) : sizeGrowth(sizeGrowthDefault) {
- char number[32];
- sprintf(number, "%0d", i);
- s = StringAllocate(number);
- sSize = sLen = (s) ? strlen(s) : 0;
-}
-
-SString::SString(double d, int precision) : sizeGrowth(sizeGrowthDefault) {
- char number[32];
- sprintf(number, "%.*f", precision, d);
- s = StringAllocate(number);
- sSize = sLen = (s) ? strlen(s) : 0;
-}
-
-bool SString::grow(lenpos_t lenNew) {
- while (sizeGrowth * 6 < lenNew) {
- sizeGrowth *= 2;
- }
- char *sNew = new char[lenNew + sizeGrowth + 1];
- if (sNew) {
- if (s) {
- memcpy(sNew, s, sLen);
- delete []s;
- }
- s = sNew;
- s[sLen] = '\0';
- sSize = lenNew + sizeGrowth;
- }
- return sNew != 0;
-}
-
-SString &SString::assign(const char *sOther, lenpos_t sSize_) {
- if (!sOther) {
- sSize_ = 0;
- } else if (sSize_ == measure_length) {
- sSize_ = strlen(sOther);
- }
- if (sSize > 0 && sSize_ <= sSize) { // Does not allocate new buffer if the current is big enough
- if (s && sSize_) {
- memcpy(s, sOther, sSize_);
- }
- s[sSize_] = '\0';
- sLen = sSize_;
- } else {
- delete []s;
- s = StringAllocate(sOther, sSize_);
- if (s) {
- sSize = sSize_; // Allow buffer bigger than real string, thus providing space to grow
- sLen = sSize_;
- } else {
- sSize = sLen = 0;
- }
- }
- return *this;
-}
-
-bool SString::operator==(const SString &sOther) const {
- if ((s == 0) && (sOther.s == 0))
- return true;
- if ((s == 0) || (sOther.s == 0))
- return false;
- return strcmp(s, sOther.s) == 0;
-}
-
-bool SString::operator==(const char *sOther) const {
- if ((s == 0) && (sOther == 0))
- return true;
- if ((s == 0) || (sOther == 0))
- return false;
- return strcmp(s, sOther) == 0;
-}
-
-SString SString::substr(lenpos_t subPos, lenpos_t subLen) const {
- if (subPos >= sLen) {
- return SString(); // return a null string if start index is out of bounds
- }
- if ((subLen == measure_length) || (subPos + subLen > sLen)) {
- subLen = sLen - subPos; // can't substr past end of source string
- }
- return SString(s, subPos, subPos + subLen);
-}
+typedef std::map<std::string, std::string> mapss;
-SString &SString::lowercase(lenpos_t subPos, lenpos_t subLen) {
- if ((subLen == measure_length) || (subPos + subLen > sLen)) {
- subLen = sLen - subPos; // don't apply past end of string
- }
- for (lenpos_t i = subPos; i < subPos + subLen; i++) {
- if (s[i] < 'A' || s[i] > 'Z')
- continue;
- else
- s[i] = static_cast<char>(s[i] - 'A' + 'a');
- }
- return *this;
+PropSetSimple::PropSetSimple() {
+ mapss *props = new mapss;
+ impl = static_cast<void *>(props);
}
-SString &SString::uppercase(lenpos_t subPos, lenpos_t subLen) {
- if ((subLen == measure_length) || (subPos + subLen > sLen)) {
- subLen = sLen - subPos; // don't apply past end of string
- }
- for (lenpos_t i = subPos; i < subPos + subLen; i++) {
- if (s[i] < 'a' || s[i] > 'z')
- continue;
- else
- s[i] = static_cast<char>(s[i] - 'a' + 'A');
- }
- return *this;
-}
-
-SString &SString::append(const char *sOther, lenpos_t sLenOther, char sep) {
- if (!sOther) {
- return *this;
- }
- if (sLenOther == measure_length) {
- sLenOther = strlen(sOther);
- }
- int lenSep = 0;
- if (sLen && sep) { // Only add a separator if not empty
- lenSep = 1;
- }
- lenpos_t lenNew = sLen + sLenOther + lenSep;
- // Conservative about growing the buffer: don't do it, unless really needed
- if ((lenNew < sSize) || (grow(lenNew))) {
- if (lenSep) {
- s[sLen] = sep;
- sLen++;
- }
- memcpy(&s[sLen], sOther, sLenOther);
- sLen += sLenOther;
- s[sLen] = '\0';
- }
- return *this;
-}
-
-SString &SString::insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther) {
- if (!sOther || pos > sLen) {
- return *this;
- }
- if (sLenOther == measure_length) {
- sLenOther = strlen(sOther);
- }
- lenpos_t lenNew = sLen + sLenOther;
- // Conservative about growing the buffer: don't do it, unless really needed
- if ((lenNew < sSize) || grow(lenNew)) {
- lenpos_t moveChars = sLen - pos + 1;
- for (lenpos_t i = moveChars; i > 0; i--) {
- s[pos + sLenOther + i - 1] = s[pos + i - 1];
- }
- memcpy(s + pos, sOther, sLenOther);
- sLen = lenNew;
- }
- return *this;
+PropSetSimple::~PropSetSimple() {
+ mapss *props = static_cast<mapss *>(impl);
+ delete props;
+ impl = 0;
}
-/**
- * Remove @a len characters from the @a pos position, included.
- * Characters at pos + len and beyond replace characters at pos.
- * If @a len is 0, or greater than the length of the string
- * starting at @a pos, the string is just truncated at @a pos.
- */
-void SString::remove(lenpos_t pos, lenpos_t len) {
- if (pos >= sLen) {
- return;
- }
- if (len < 1 || pos + len >= sLen) {
- s[pos] = '\0';
- sLen = pos;
- } else {
- for (lenpos_t i = pos; i < sLen - len + 1; i++) {
- s[i] = s[i+len];
- }
- sLen -= len;
- }
-}
-
-bool SString::startswith(const char *prefix) {
- lenpos_t lenPrefix = strlen(prefix);
- if (lenPrefix > sLen) {
- return false;
- }
- return strncmp(s, prefix, lenPrefix) == 0;
-}
-
-bool SString::endswith(const char *suffix) {
- lenpos_t lenSuffix = strlen(suffix);
- if (lenSuffix > sLen) {
- return false;
- }
- return strncmp(s + sLen - lenSuffix, suffix, lenSuffix) == 0;
-}
-
-int SString::search(const char *sFind, lenpos_t start) const {
- if (start < sLen) {
- const char *sFound = strstr(s + start, sFind);
- if (sFound) {
- return sFound - s;
- }
- }
- return -1;
-}
-
-int SString::substitute(char chFind, char chReplace) {
- int c = 0;
- char *t = s;
- while (t) {
- t = strchr(t, chFind);
- if (t) {
- *t = chReplace;
- t++;
- c++;
- }
- }
- return c;
-}
-
-int SString::substitute(const char *sFind, const char *sReplace) {
- int c = 0;
- lenpos_t lenFind = strlen(sFind);
- lenpos_t lenReplace = strlen(sReplace);
- int posFound = search(sFind);
- while (posFound >= 0) {
- remove(posFound, lenFind);
- insert(posFound, sReplace, lenReplace);
- posFound = search(sFind, posFound + lenReplace);
- c++;
- }
- return c;
-}
-
-char *SContainer::StringAllocate(lenpos_t len) {
- if (len != measure_length) {
- return new char[len + 1];
- } else {
- return 0;
- }
-}
-
-char *SContainer::StringAllocate(const char *s, lenpos_t len) {
- if (s == 0) {
- return 0;
- }
- if (len == measure_length) {
- len = strlen(s);
- }
- char *sNew = new char[len + 1];
- if (sNew) {
- memcpy(sNew, s, len);
- sNew[len] = '\0';
- }
- return sNew;
-}
-
-// End SString functions
-
-PropSet::PropSet() {
- superPS = 0;
- for (int root = 0; root < hashRoots; root++)
- props[root] = 0;
-}
-
-PropSet::~PropSet() {
- superPS = 0;
- Clear();
-}
-
-void PropSet::Set(const char *key, const char *val, int lenKey, int lenVal) {
+void PropSetSimple::Set(const char *key, const char *val, int lenKey, int lenVal) {
+ mapss *props = static_cast<mapss *>(impl);
if (!*key) // Empty keys are not supported
return;
if (lenKey == -1)
lenKey = static_cast<int>(strlen(key));
if (lenVal == -1)
lenVal = static_cast<int>(strlen(val));
- unsigned int hash = HashString(key, lenKey);
- for (Property *p = props[hash % hashRoots]; p; p = p->next) {
- if ((hash == p->hash) &&
- ((strlen(p->key) == static_cast<unsigned int>(lenKey)) &&
- (0 == strncmp(p->key, key, lenKey)))) {
- // Replace current value
- delete [](p->val);
- p->val = StringDup(val, lenVal);
- return;
- }
- }
- // Not found
- Property *pNew = new Property;
- if (pNew) {
- pNew->hash = hash;
- pNew->key = StringDup(key, lenKey);
- pNew->val = StringDup(val, lenVal);
- pNew->next = props[hash % hashRoots];
- props[hash % hashRoots] = pNew;
- }
+ (*props)[std::string(key, lenKey)] = std::string(val, lenVal);
}
-void PropSet::Set(const char *keyVal) {
- while (IsASpace(*keyVal))
+static bool IsASpaceCharacter(unsigned int ch) {
+ return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+}
+
+void PropSetSimple::Set(const char *keyVal) {
+ while (IsASpaceCharacter(*keyVal))
keyVal++;
const char *endVal = keyVal;
while (*endVal && (*endVal != '\n'))
@@ -387,34 +70,7 @@ void PropSet::Set(const char *keyVal) {
}
}
-void PropSet::Unset(const char *key, int lenKey) {
- if (!*key) // Empty keys are not supported
- return;
- if (lenKey == -1)
- lenKey = static_cast<int>(strlen(key));
- unsigned int hash = HashString(key, lenKey);
- Property *pPrev = NULL;
- for (Property *p = props[hash % hashRoots]; p; p = p->next) {
- if ((hash == p->hash) &&
- ((strlen(p->key) == static_cast<unsigned int>(lenKey)) &&
- (0 == strncmp(p->key, key, lenKey)))) {
- if (pPrev)
- pPrev->next = p->next;
- else
- props[hash % hashRoots] = p->next;
- if (p == enumnext)
- enumnext = p->next; // Not that anyone should mix enum and Set / Unset.
- delete [](p->key);
- delete [](p->val);
- delete p;
- return;
- } else {
- pPrev = p;
- }
- }
-}
-
-void PropSet::SetMultiple(const char *s) {
+void PropSetSimple::SetMultiple(const char *s) {
const char *eol = strchr(s, '\n');
while (eol) {
Set(s);
@@ -424,16 +80,11 @@ void PropSet::SetMultiple(const char *s) {
Set(s);
}
-SString PropSet::Get(const char *key) const {
- unsigned int hash = HashString(key, strlen(key));
- for (Property *p = props[hash % hashRoots]; p; p = p->next) {
- if ((hash == p->hash) && (0 == strcmp(p->key, key))) {
- return p->val;
- }
- }
- if (superPS) {
- // Failed here, so try in base property set
- return superPS->Get(key);
+const char *PropSetSimple::Get(const char *key) const {
+ mapss *props = static_cast<mapss *>(impl);
+ mapss::const_iterator keyPos = props->find(std::string(key));
+ if (keyPos != props->end()) {
+ return keyPos->second.c_str();
} else {
return "";
}
@@ -456,300 +107,70 @@ struct VarChain {
const VarChain *link;
};
-static int ExpandAllInPlace(const PropSet &props, SString &withVars, int maxExpands, const VarChain &blankVars = VarChain()) {
- int varStart = withVars.search("$(");
- while ((varStart >= 0) && (maxExpands > 0)) {
- int varEnd = withVars.search(")", varStart+2);
- if (varEnd < 0) {
+static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, int maxExpands, const VarChain &blankVars) {
+ size_t varStart = withVars.find("$(");
+ while ((varStart != std::string::npos) && (maxExpands > 0)) {
+ size_t varEnd = withVars.find(")", varStart+2);
+ if (varEnd == std::string::npos) {
break;
}
// For consistency, when we see '$(ab$(cde))', expand the inner variable first,
// regardless whether there is actually a degenerate variable named 'ab$(cde'.
- int innerVarStart = withVars.search("$(", varStart+2);
- while ((innerVarStart > varStart) && (innerVarStart < varEnd)) {
+ size_t innerVarStart = withVars.find("$(", varStart+2);
+ while ((innerVarStart != std::string::npos) && (innerVarStart > varStart) && (innerVarStart < varEnd)) {
varStart = innerVarStart;
- innerVarStart = withVars.search("$(", varStart+2);
+ innerVarStart = withVars.find("$(", varStart+2);
}
- SString var(withVars.c_str(), varStart + 2, varEnd);
- SString val = props.Get(var.c_str());
+ std::string var(withVars.c_str(), varStart + 2, varEnd - varStart - 2);
+ std::string val = props.Get(var.c_str());
if (blankVars.contains(var.c_str())) {
- val.clear(); // treat blankVar as an empty string (e.g. to block self-reference)
+ val = ""; // treat blankVar as an empty string (e.g. to block self-reference)
}
if (--maxExpands >= 0) {
maxExpands = ExpandAllInPlace(props, val, maxExpands, VarChain(var.c_str(), &blankVars));
}
- withVars.remove(varStart, varEnd-varStart+1);
+ withVars.erase(varStart, varEnd-varStart+1);
withVars.insert(varStart, val.c_str(), val.length());
- varStart = withVars.search("$(");
+ varStart = withVars.find("$(");
}
return maxExpands;
}
-SString PropSet::GetExpanded(const char *key) const {
- SString val = Get(key);
+char *PropSetSimple::Expanded(const char *key) const {
+ std::string val = Get(key);
ExpandAllInPlace(*this, val, 100, VarChain(key));
- return val;
-}
-
-SString PropSet::Expand(const char *withVars, int maxExpands) const {
- SString val = withVars;
- ExpandAllInPlace(*this, val, maxExpands);
- return val;
-}
-
-int PropSet::GetInt(const char *key, int defaultValue) const {
- SString val = GetExpanded(key);
- if (val.length())
- return val.value();
- return defaultValue;
-}
-
-bool isprefix(const char *target, const char *prefix) {
- while (*target && *prefix) {
- if (*target != *prefix)
- return false;
- target++;
- prefix++;
- }
- if (*prefix)
- return false;
- else
- return true;
-}
-
-void PropSet::Clear() {
- for (int root = 0; root < hashRoots; root++) {
- Property *p = props[root];
- while (p) {
- Property *pNext = p->next;
- p->hash = 0;
- delete []p->key;
- p->key = 0;
- delete []p->val;
- p->val = 0;
- delete p;
- p = pNext;
- }
- props[root] = 0;
- }
-}
-
-char *PropSet::ToString() const {
- size_t len=0;
- for (int r = 0; r < hashRoots; r++) {
- for (Property *p = props[r]; p; p = p->next) {
- len += strlen(p->key) + 1;
- len += strlen(p->val) + 1;
- }
- }
- if (len == 0)
- len = 1; // Return as empty string
- char *ret = new char [len];
- if (ret) {
- char *w = ret;
- for (int root = 0; root < hashRoots; root++) {
- for (Property *p = props[root]; p; p = p->next) {
- strcpy(w, p->key);
- w += strlen(p->key);
- *w++ = '=';
- strcpy(w, p->val);
- w += strlen(p->val);
- *w++ = '\n';
- }
- }
- ret[len-1] = '\0';
- }
+ char *ret = new char [val.size() + 1];
+ strcpy(ret, val.c_str());
return ret;
}
-/**
- * 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) {
- int prev = '\n';
- int words = 0;
- // For rapid determination of whether a character is a separator, build
- // a look up table.
- bool wordSeparator[256];
- for (int i=0;i<256; i++) {
- wordSeparator[i] = false;
- }
- wordSeparator['\r'] = true;
- wordSeparator['\n'] = true;
- if (!onlyLineEnds) {
- wordSeparator[' '] = true;
- wordSeparator['\t'] = true;
- }
- for (int j = 0; wordlist[j]; j++) {
- int curr = static_cast<unsigned char>(wordlist[j]);
- if (!wordSeparator[curr] && wordSeparator[prev])
- words++;
- prev = curr;
- }
- char **keywords = new char *[words + 1];
- if (keywords) {
- words = 0;
- prev = '\0';
- size_t slen = strlen(wordlist);
- for (size_t k = 0; k < slen; k++) {
- if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
- if (!prev) {
- keywords[words] = &wordlist[k];
- words++;
- }
- } else {
- wordlist[k] = '\0';
- }
- prev = wordlist[k];
- }
- keywords[words] = &wordlist[slen];
- *len = words;
- } else {
- *len = 0;
- }
- return keywords;
-}
-
-void WordList::Clear() {
- if (words) {
- delete []list;
- delete []words;
- }
- words = 0;
- list = 0;
- len = 0;
- sorted = false;
-}
-
-void WordList::Set(const char *s) {
- list = StringDup(s);
- sorted = false;
- words = ArrayFromWordList(list, &len, onlyLineEnds);
-}
-
-extern "C" int cmpString(const void *a1, const void *a2) {
- // Can't work out the correct incantation to use modern casts here
- return strcmp(*(char**)(a1), *(char**)(a2));
-}
-
-static void SortWordList(char **words, unsigned int len) {
- qsort(reinterpret_cast<void*>(words), len, sizeof(*words),
- cmpString);
-}
-
-bool WordList::InList(const char *s) {
- if (0 == words)
- return false;
- if (!sorted) {
- sorted = true;
- SortWordList(words, len);
- for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
- starts[k] = -1;
- for (int l = len - 1; l >= 0; l--) {
- unsigned char indexChar = words[l][0];
- starts[indexChar] = l;
- }
- }
- unsigned char firstChar = s[0];
- int j = starts[firstChar];
- if (j >= 0) {
- while ((unsigned char)words[j][0] == firstChar) {
- if (s[1] == words[j][1]) {
- const char *a = words[j] + 1;
- const char *b = s + 1;
- while (*a && *a == *b) {
- a++;
- b++;
- }
- if (!*a && !*b)
- return true;
- }
- j++;
- }
- }
- j = starts['^'];
- if (j >= 0) {
- while (words[j][0] == '^') {
- const char *a = words[j] + 1;
- const char *b = s;
- while (*a && *a == *b) {
- a++;
- b++;
- }
- if (!*a)
- return true;
- j++;
- }
+char *PropSetSimple::ToString() const {
+ mapss *props = static_cast<mapss *>(impl);
+ std::string sval;
+ for (mapss::const_iterator it=props->begin(); it != props->end(); it++) {
+ sval += it->first;
+ sval += "=";
+ sval += it->second;
+ sval += "\n";
}
- return false;
+ char *ret = new char [sval.size() + 1];
+ strcpy(ret, sval.c_str());
+ return ret;
}
-/** similar to InList, but word s can be a substring of keyword.
- * eg. the keyword define is defined as def~ine. This means the word must start
- * with def to be a keyword, but also defi, defin and define are valid.
- * The marker is ~ in this case.
- */
-bool WordList::InListAbbreviated(const char *s, const char marker) {
- if (0 == words)
- return false;
- if (!sorted) {
- sorted = true;
- SortWordList(words, len);
- for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
- starts[k] = -1;
- for (int l = len - 1; l >= 0; l--) {
- unsigned char indexChar = words[l][0];
- starts[indexChar] = l;
- }
+int PropSetSimple::GetInt(const char *key, int defaultValue) const {
+ char *val = Expanded(key);
+ if (val) {
+ int retVal = atoi(val);
+ delete []val;
+ return retVal;
}
- unsigned char firstChar = s[0];
- int j = starts[firstChar];
- if (j >= 0) {
- while (words[j][0] == firstChar) {
- bool isSubword = false;
- int start = 1;
- if (words[j][1] == marker) {
- isSubword = true;
- start++;
- }
- if (s[1] == words[j][start]) {
- const char *a = words[j] + start;
- const char *b = s + 1;
- while (*a && *a == *b) {
- a++;
- if (*a == marker) {
- isSubword = true;
- a++;
- }
- b++;
- }
- if ((!*a || isSubword) && !*b)
- return true;
- }
- j++;
- }
- }
- j = starts['^'];
- if (j >= 0) {
- while (words[j][0] == '^') {
- const char *a = words[j] + 1;
- const char *b = s;
- while (*a && *a == *b) {
- a++;
- b++;
- }
- if (!*a)
- return true;
- j++;
- }
- }
- return false;
+ return defaultValue;
}
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index 5e2d9114b..3aba5fb7b 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -16,6 +16,7 @@
#include "Scintilla.h"
#include "PropSet.h"
+#include "PropSetSimple.h"
#ifdef SCI_LEXER
#include "SciLexer.h"
#include "Accessor.h"
@@ -706,24 +707,23 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
break;
case SCI_GETPROPERTY: {
- SString val = props.Get(reinterpret_cast<const char *>(wParam));
- const int n = val.length();
+ const char *val = props.Get(reinterpret_cast<const char *>(wParam));
+ const int n = strlen(val);
if (lParam != 0) {
char *ptr = reinterpret_cast<char *>(lParam);
- memcpy(ptr, val.c_str(), n);
- ptr[n] = '\0'; // terminate
+ strcpy(ptr, val);
}
return n; // Not including NUL
}
case SCI_GETPROPERTYEXPANDED: {
- SString val = props.GetExpanded(reinterpret_cast<const char *>(wParam));
- const int n = val.length();
+ char *val = props.Expanded(reinterpret_cast<const char *>(wParam));
+ const int n = strlen(val);
if (lParam != 0) {
char *ptr = reinterpret_cast<char *>(lParam);
- memcpy(ptr, val.c_str(), n);
- ptr[n] = '\0'; // terminate
+ strcpy(ptr, val);
}
+ delete []val;
return n; // Not including NUL
}
diff --git a/src/ScintillaBase.h b/src/ScintillaBase.h
index 0b414452a..15b514c2b 100644
--- a/src/ScintillaBase.h
+++ b/src/ScintillaBase.h
@@ -48,7 +48,7 @@ protected:
#ifdef SCI_LEXER
int lexLanguage;
const LexerModule *lexCurrent;
- PropSet props;
+ PropSetSimple props;
enum {numWordLists=KEYWORDSET_MAX+1};
WordList *keyWordLists[numWordLists+1];
void SetLexer(uptr_t wParam);