From 1fdd0b8dc8f2895c5942b23410f11ea21dd4e3f4 Mon Sep 17 00:00:00 2001
From: Neil
Date: Thu, 10 Jun 2021 16:03:47 +1000
Subject: Use string_view for PositionCache methods. Replace custom hash code
with standard library hash. Drop standard methods that are not needed.
Restrict representations to 200 bytes. Improve documentation.
---
doc/ScintillaDoc.html | 8 ++++---
src/EditView.cxx | 7 +++---
src/PositionCache.cxx | 63 ++++++++++++++++++++++-----------------------------
src/PositionCache.h | 17 +++++---------
4 files changed, 42 insertions(+), 53 deletions(-)
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 300ae0208..d972c99a7 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -3861,20 +3861,22 @@ struct Sci_TextToFind {
SCI_GETREPRESENTATION(const char *encodedCharacter, char *representation NUL-terminated) → int
SCI_CLEARREPRESENTATION(const char *encodedCharacter)
Any character, including those normally displayed as mnemonics may be represented by a
- string inverted in a rounded rectangle.
+ Unicode string inverted in a rounded rectangle.
For example, the Ohm sign Ω U+2126 looks very similar to the Greek Omega character Ω U+03C9 so,
for the UTF-8 encoding, to distinguish the Ohm sign as "U+2126 Ω" this call could be made:
SCI_SETREPRESENTATION("\xe2\x84\xa6", "U+2126 \xe2\x84\xa6")
- The encodedCharacter parameter is a NUL-terminated string of the bytes for one character in the
+
The encodedCharacter parameter is a NUL-terminated string of the bytes for one character in the
current encoding. This can not be used to set a representation for multiple-character strings.
+ The representation parameter is a NUL-terminated UTF-8 string with a maximum length of 200 bytes.
+
One exception to the single character restriction is that the two character sequence "\r\n" (Carriage Return + Line Feed)
can have a representation that is visible in line end viewing (SCI_SETVIEWEOL) mode.
If there is no representation for "\r\n" then the individual '\r' and '\n' representations will be seen.
- The NUL (0) character is a special case since the encodedCharacter parameter is NUL terminated, the NUL
+
The NUL (0) character is a special case since the encodedCharacter parameter is NUL terminated, the NUL
character is specified as an empty string.
SCI_CLEARALLREPRESENTATIONS
diff --git a/src/EditView.cxx b/src/EditView.cxx
index 5d69c1345..92c1450cc 100644
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -473,7 +473,8 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
representationWidth = NextTabstopPos(line, x, vstyle.tabWidth) - ll->positions[ts.start];
} else {
if (representationWidth <= 0.0) {
- XYPOSITION positionsRepr[256]; // Should expand when needed
+ assert(ts.representation->stringRep.length() <= Representation::maxLength);
+ XYPOSITION positionsRepr[Representation::maxLength+1];
surface->MeasureWidthsUTF8(vstyle.styles[StyleControlChar].font.get(), ts.representation->stringRep, positionsRepr);
representationWidth = positionsRepr[ts.representation->stringRep.length() - 1];
if (FlagSet(ts.representation->appearance, RepresentationAppearance::Blob)) {
@@ -488,8 +489,8 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
// Over half the segments are single characters and of these about half are space characters.
ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth;
} else {
- posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], &ll->chars[ts.start],
- ts.length, &ll->positions[ts.start + 1]);
+ posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start],
+ std::string_view(&ll->chars[ts.start], ts.length), &ll->positions[ts.start + 1]);
}
}
lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic);
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx
index 7ea3055d4..d3347248b 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -546,7 +546,7 @@ static unsigned int KeyFromString(std::string_view charBytes) noexcept {
}
void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std::string_view value) {
- if (charBytes.length() <= 4) {
+ if ((charBytes.length() <= 4) && (value.length() <= Representation::maxLength)) {
const unsigned int key = KeyFromString(charBytes);
MapRepresentation::iterator it = mapReprs.find(key);
if (it == mapReprs.end()) {
@@ -754,12 +754,12 @@ bool BreakFinder::More() const noexcept {
}
PositionCacheEntry::PositionCacheEntry() noexcept :
- styleNumber(0), len(0), clock(0), positions(nullptr) {
+ styleNumber(0), len(0), clock(0) {
}
// Copy constructor not currently used, but needed for being element in std::vector.
PositionCacheEntry::PositionCacheEntry(const PositionCacheEntry &other) :
- styleNumber(other.styleNumber), len(other.styleNumber), clock(other.styleNumber), positions(nullptr) {
+ styleNumber(other.styleNumber), len(other.len), clock(other.clock) {
if (other.positions) {
const size_t lenData = len + (len / sizeof(XYPOSITION)) + 1;
positions = std::make_unique(lenData);
@@ -767,18 +767,18 @@ PositionCacheEntry::PositionCacheEntry(const PositionCacheEntry &other) :
}
}
-void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_,
- unsigned int len_, const XYPOSITION *positions_, unsigned int clock_) {
+void PositionCacheEntry::Set(unsigned int styleNumber_, std::string_view sv,
+ const XYPOSITION *positions_, unsigned int clock_) {
Clear();
styleNumber = styleNumber_;
- len = len_;
+ len = static_cast(sv.length());
clock = clock_;
- if (s_ && positions_) {
+ if (sv.data() && positions_) {
positions = std::make_unique(len + (len / sizeof(XYPOSITION)) + 1);
for (unsigned int i=0; i{}(sv);
+ const size_t h2 = std::hash{}(styleNumber_);
+ return h1 ^ (h2 << 1);
}
bool PositionCacheEntry::NewerThan(const PositionCacheEntry &other) const noexcept {
@@ -835,10 +827,6 @@ PositionCache::PositionCache() {
allClear = true;
}
-PositionCache::~PositionCache() {
- Clear();
-}
-
void PositionCache::Clear() noexcept {
if (!allClear) {
for (PositionCacheEntry &pce : pces) {
@@ -854,23 +842,26 @@ void PositionCache::SetSize(size_t size_) {
pces.resize(size_);
}
-void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
- const char *s, unsigned int len, XYPOSITION *positions) {
+size_t PositionCache::GetSize() const noexcept {
+ return pces.size();
+}
+void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
+ std::string_view sv, XYPOSITION *positions) {
allClear = false;
size_t probe = pces.size(); // Out of bounds
- if ((!pces.empty()) && (len < 30)) {
+ if ((!pces.empty()) && (sv.length() < 30)) {
// Only store short strings in the cache so it doesn't churn with
// long comments with only a single comment.
// Two way associative: try two probe positions.
- const unsigned int hashValue = PositionCacheEntry::Hash(styleNumber, s, len);
+ const size_t hashValue = PositionCacheEntry::Hash(styleNumber, sv);
probe = hashValue % pces.size();
- if (pces[probe].Retrieve(styleNumber, s, len, positions)) {
+ if (pces[probe].Retrieve(styleNumber, sv, positions)) {
return;
}
- const unsigned int probe2 = (hashValue * 37) % pces.size();
- if (pces[probe2].Retrieve(styleNumber, s, len, positions)) {
+ const size_t probe2 = (hashValue * 37) % pces.size();
+ if (pces[probe2].Retrieve(styleNumber, sv, positions)) {
return;
}
// Not found. Choose the oldest of the two slots to replace
@@ -879,7 +870,7 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns
}
}
const Font *fontStyle = vstyle.styles[styleNumber].font.get();
- surface->MeasureWidths(fontStyle, std::string_view(s, len), positions);
+ surface->MeasureWidths(fontStyle, sv, positions);
if (probe < pces.size()) {
// Store into cache
clock++;
@@ -891,6 +882,6 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns
}
clock = 2;
}
- pces[probe].Set(styleNumber, s, len, positions, clock);
+ pces[probe].Set(styleNumber, sv, positions, clock);
}
}
diff --git a/src/PositionCache.h b/src/PositionCache.h
index 030b16504..b628b0421 100644
--- a/src/PositionCache.h
+++ b/src/PositionCache.h
@@ -188,16 +188,17 @@ public:
void operator=(const PositionCacheEntry &) = delete;
void operator=(PositionCacheEntry &&) = delete;
~PositionCacheEntry();
- void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, const XYPOSITION *positions_, unsigned int clock_);
+ void Set(unsigned int styleNumber_, std::string_view sv, const XYPOSITION *positions_, unsigned int clock_);
void Clear() noexcept;
- bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const noexcept;
- static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len_) noexcept;
+ bool Retrieve(unsigned int styleNumber_, std::string_view sv, XYPOSITION *positions_) const noexcept;
+ static size_t Hash(unsigned int styleNumber_, std::string_view sv) noexcept;
bool NewerThan(const PositionCacheEntry &other) const noexcept;
void ResetClock() noexcept;
};
class Representation {
public:
+ static constexpr size_t maxLength = 200;
std::string stringRep;
RepresentationAppearance appearance;
ColourRGBA colour;
@@ -271,17 +272,11 @@ class PositionCache {
bool allClear;
public:
PositionCache();
- // Deleted so PositionCache objects can not be copied.
- PositionCache(const PositionCache &) = delete;
- PositionCache(PositionCache &&) = delete;
- void operator=(const PositionCache &) = delete;
- void operator=(PositionCache &&) = delete;
- ~PositionCache();
void Clear() noexcept;
void SetSize(size_t size_);
- size_t GetSize() const noexcept { return pces.size(); }
+ size_t GetSize() const noexcept;
void MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
- const char *s, unsigned int len, XYPOSITION *positions);
+ std::string_view sv, XYPOSITION *positions);
};
}
--
cgit v1.2.3