Skip to content

Commit

Permalink
Use string_view for parameters to fromWide and toWide and for return …
Browse files Browse the repository at this point in the history
…from RectangularSelection_Row::text.

Make sure fromWide and toWide don't split long text between bytes of a multi-byte character.
  • Loading branch information
Coises committed Oct 16, 2023
1 parent eeb8c43 commit b3491c1
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
22 changes: 13 additions & 9 deletions src/ColumnsPlusPlus.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,20 @@ template< class T, class S > constexpr const T clamp_cast(const S& v) {
}


inline std::string fromWide(const std::wstring& s, unsigned int codepage) {
inline std::string fromWide(std::wstring_view s, unsigned int codepage) {
std::string r;
size_t inputLength = s.length();
if (!inputLength) return r;
constexpr unsigned int safeSize = std::numeric_limits<int>::max() / 8;
size_t workingPoint = 0;
while (inputLength - workingPoint > safeSize) {
int segmentLength = WideCharToMultiByte(codepage, 0, s.data() + workingPoint, safeSize, 0, 0, 0, 0);
int ss = safeSize;
if (s[ss - 1] >= 0xD800 && s[ss - 1] <= 0xDBFF) --ss; // proposed block ends with high surrogate: leave it for the next block
int segmentLength = WideCharToMultiByte(codepage, 0, s.data() + workingPoint, ss, 0, 0, 0, 0);
size_t outputPoint = r.length();
r.resize(outputPoint + segmentLength);
WideCharToMultiByte(codepage, 0, s.data() + workingPoint, safeSize, r.data() + outputPoint, segmentLength, 0, 0);
workingPoint += safeSize;
WideCharToMultiByte(codepage, 0, s.data() + workingPoint, ss, r.data() + outputPoint, segmentLength, 0, 0);
workingPoint += ss;
}
int segmentLength = WideCharToMultiByte(codepage, 0, s.data() + workingPoint, static_cast<int>(inputLength - workingPoint), 0, 0, 0, 0);
size_t outputPoint = r.length();
Expand All @@ -72,18 +74,20 @@ inline std::string fromWide(const std::wstring& s, unsigned int codepage) {
return r;
}

inline std::wstring toWide(const std::string& s, unsigned int codepage) {
inline std::wstring toWide(std::string_view s, unsigned int codepage) {
std::wstring r;
size_t inputLength = s.length();
if (!inputLength) return r;
constexpr unsigned int safeSize = std::numeric_limits<int>::max() / 2;
size_t workingPoint = 0;
while (inputLength - workingPoint > safeSize) {
int segmentLength = MultiByteToWideChar(codepage, 0, s.data() + workingPoint, safeSize, 0, 0);
int ss = safeSize;
if (codepage == CP_UTF8 && ((s[ss] & 0xC0) == 0x80)) while ((s[--ss] & 0xC0) == 0x80); // find a first byte to start the next block
int segmentLength = MultiByteToWideChar(codepage, 0, s.data() + workingPoint, ss, 0, 0);
size_t outputPoint = r.length();
r.resize(outputPoint + segmentLength);
MultiByteToWideChar(codepage, 0, s.data() + workingPoint, safeSize, r.data() + outputPoint, segmentLength);
workingPoint += safeSize;
MultiByteToWideChar(codepage, 0, s.data() + workingPoint, ss, r.data() + outputPoint, segmentLength);
workingPoint += ss;
}
int segmentLength = MultiByteToWideChar(codepage, 0, s.data() + workingPoint, static_cast<int>(inputLength - workingPoint), 0, 0);
size_t outputPoint = r.length();
Expand Down Expand Up @@ -645,7 +649,7 @@ class RectangularSelection_Row {
Scintilla::Position vsMax () const { return std::max(_vsAnchor, _vsCaret); }
Scintilla::Line line () const { return _line; }
Scintilla::Position endOfLine () const { return _endOfLine; }
std::string text () const { return _offset ? _text.substr(_offset) : _text ; }
std::string_view text () const { return std::string_view(_text).substr(_offset); }
bool isEndOfLine() const { return cpMax() == _endOfLine; }
RectangularSelection_Cell_Iterator begin() const;
RectangularSelection_Cell_Iterator end() const;
Expand Down
6 changes: 3 additions & 3 deletions src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ void ColumnsPlusPlusData::loadConfiguration() {
else if (std::regex_match(line, match, extensionsHeader )) readingSection = sectionExtensions;
else if (std::regex_match(line, match, profileHeader )) {
readingSection = sectionProfile;
profileName = toWide(match[1], CP_UTF8);
profileName = toWide(match.str(1), CP_UTF8);
}
else if (std::regex_match(line, match, dataLine)) {
if (readingSection == sectionLastSettings) {
Expand Down Expand Up @@ -272,8 +272,8 @@ void ColumnsPlusPlusData::loadConfiguration() {
}
}
else if (readingSection == sectionExtensions) {
std::wstring extension = toWide(match[1], CP_UTF8);
std::wstring profile = toWide(match[2], CP_UTF8);
std::wstring extension = toWide(match.str(1), CP_UTF8);
std::wstring profile = toWide(match.str(2), CP_UTF8);
if (extension == L"new") extensionToProfile[L"" ] = profile;
else if (extension == L"none") extensionToProfile[L"."] = profile;
else if (extension == L"default") extensionToProfile[L"*"] = profile;
Expand Down
6 changes: 4 additions & 2 deletions src/Numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,12 +644,14 @@ void ColumnsPlusPlusData::calculate() {
if (!settings.elasticEnabled || !calc.tabbed) s += std::string(maxLeft + maxRight - s.length(), ' ');
if (calc.left) {
s += calc.tabbed ? '\t' : ' ';
row.replace(s + row.text());
s += row.text();
row.replace(s);
}
else {
if (calc.tabbed) s = row.text().length() > 0 && row.text()[row.text().length() - 1] == '\t' ? s + '\t' : '\t' + s;
else s = ' ' + s;
row.replace(row.text() + s);
s.insert(0, row.text());
row.replace(s);
}
}
++resultsIndex;
Expand Down

0 comments on commit b3491c1

Please sign in to comment.