diff options
author | Zufu Liu <unknown> | 2021-07-29 09:23:11 +1000 |
---|---|---|
committer | Zufu Liu <unknown> | 2021-07-29 09:23:11 +1000 |
commit | ff085a4ce95380e9d981e0170e2d1eeaa93fdb88 (patch) | |
tree | a290341caea8722cd045d676ae5347aa50ec03a5 /src | |
parent | 884df029d33db4f93557885fb5020e5cdc9e8a9d (diff) | |
download | scintilla-mirror-ff085a4ce95380e9d981e0170e2d1eeaa93fdb88.tar.gz |
Feature [feature-requests:#1413] Decrease cost of representation for \r\n.
Diffstat (limited to 'src')
-rw-r--r-- | src/PositionCache.cxx | 58 | ||||
-rw-r--r-- | src/PositionCache.h | 8 |
2 files changed, 50 insertions, 16 deletions
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index 285bf2816..1497adee7 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -533,8 +533,10 @@ std::shared_ptr<LineLayout> LineLayoutCache::Retrieve(Sci::Line lineNumber, Sci: return std::make_shared<LineLayout>(lineNumber, maxChars); } +namespace { + // Simply pack the (maximum 4) character bytes into an int -static unsigned int KeyFromString(std::string_view charBytes) noexcept { +constexpr unsigned int KeyFromString(std::string_view charBytes) noexcept { PLATFORM_ASSERT(charBytes.length() <= 4); unsigned int k=0; for (size_t i=0; i < charBytes.length(); i++) { @@ -545,6 +547,10 @@ static unsigned int KeyFromString(std::string_view charBytes) noexcept { return k; } +constexpr unsigned int representationKeyCrLf = KeyFromString("\r\n"); + +} + void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std::string_view value) { if ((charBytes.length() <= 4) && (value.length() <= Representation::maxLength)) { const unsigned int key = KeyFromString(charBytes); @@ -553,6 +559,9 @@ void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std:: // New entry so increment for first byte const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0]; startByteHasReprs[ucStart]++; + if (key == representationKeyCrLf) { + crlf = true; + } } mapReprs[key] = Representation(value); } @@ -585,24 +594,33 @@ void SpecialRepresentations::SetRepresentationColour(std::string_view charBytes, void SpecialRepresentations::ClearRepresentation(std::string_view charBytes) { if (charBytes.length() <= 4) { - MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes)); + const unsigned int key = KeyFromString(charBytes); + MapRepresentation::iterator it = mapReprs.find(key); if (it != mapReprs.end()) { mapReprs.erase(it); const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0]; startByteHasReprs[ucStart]--; + if (key == representationKeyCrLf) { + crlf = false; + } } } } +const Representation *SpecialRepresentations::GetRepresentation(std::string_view charBytes) const { + MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes)); + if (it != mapReprs.end()) { + return &(it->second); + } + return nullptr; +} + const Representation *SpecialRepresentations::RepresentationFromCharacter(std::string_view charBytes) const { if (charBytes.length() <= 4) { const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0]; if (!startByteHasReprs[ucStart]) return nullptr; - MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes)); - if (it != mapReprs.end()) { - return &(it->second); - } + return GetRepresentation(charBytes); } return nullptr; } @@ -620,6 +638,7 @@ void SpecialRepresentations::Clear() { mapReprs.clear(); constexpr short none = 0; std::fill(startByteHasReprs, std::end(startByteHasReprs), none); + crlf = false; } void BreakFinder::Insert(Sci::Position val) { @@ -694,16 +713,23 @@ TextSegment BreakFinder::Next() { const int prev = nextBreak; while (nextBreak < lineRange.end) { int charWidth = 1; - if (encodingFamily == EncodingFamily::unicode) - charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(&ll->chars[nextBreak]), - static_cast<int>(lineRange.end - nextBreak)); - else if (encodingFamily == EncodingFamily::dbcs) - charWidth = pdoc->DBCSDrawBytes( - std::string_view(&ll->chars[nextBreak], lineRange.end - nextBreak)); - // Special case \r\n line ends if there is a representation - if (preprs->Contains("\r\n") && ll->chars[nextBreak] == '\r' && ll->chars[nextBreak + 1] == '\n') - charWidth = 2; - const Representation *repr = preprs->RepresentationFromCharacter(std::string_view(&ll->chars[nextBreak], charWidth)); + const char * const chars = &ll->chars[nextBreak]; + const unsigned char ch = chars[0]; + if (!UTF8IsAscii(ch) && encodingFamily != EncodingFamily::eightBit) { + if (encodingFamily == EncodingFamily::unicode) { + charWidth = UTF8DrawBytes(reinterpret_cast<const unsigned char *>(chars), static_cast<int>(lineRange.end - nextBreak)); + } else { + charWidth = pdoc->DBCSDrawBytes(std::string_view(chars, lineRange.end - nextBreak)); + } + } + const Representation *repr = nullptr; + if (preprs->MayContain(ch)) { + // Special case \r\n line ends if there is a representation + if (ch == '\r' && preprs->ContainsCrLf() && chars[1] == '\n') { + charWidth = 2; + } + repr = preprs->GetRepresentation(std::string_view(chars, charWidth)); + } if (((nextBreak > 0) && (ll->styles[nextBreak] != ll->styles[nextBreak - 1])) || repr || (nextBreak == saeNext)) { diff --git a/src/PositionCache.h b/src/PositionCache.h index b628b0421..0eefaca78 100644 --- a/src/PositionCache.h +++ b/src/PositionCache.h @@ -212,13 +212,21 @@ typedef std::map<unsigned int, Representation> MapRepresentation; class SpecialRepresentations { MapRepresentation mapReprs; short startByteHasReprs[0x100] {}; + bool crlf = false; public: void SetRepresentation(std::string_view charBytes, std::string_view value); void SetRepresentationAppearance(std::string_view charBytes, RepresentationAppearance appearance); void SetRepresentationColour(std::string_view charBytes, ColourRGBA colour); void ClearRepresentation(std::string_view charBytes); + const Representation *GetRepresentation(std::string_view charBytes) const; const Representation *RepresentationFromCharacter(std::string_view charBytes) const; bool Contains(std::string_view charBytes) const; + bool ContainsCrLf() const noexcept { + return crlf; + } + bool MayContain(unsigned char ch) const noexcept { + return startByteHasReprs[ch] != 0; + } void Clear(); }; |