Mercurial > hg > svcore
changeset 1851:91056142abd0
Add function (cribbed from Rosegarden source) to check whether a string is valid UTF-8
author | Chris Cannam |
---|---|
date | Thu, 30 Apr 2020 14:45:24 +0100 |
parents | e830b252267e |
children | a454c7477b4f |
files | base/StringBits.cpp base/StringBits.h |
diffstat | 2 files changed, 81 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/base/StringBits.cpp Wed Apr 29 13:25:19 2020 +0100 +++ b/base/StringBits.cpp Thu Apr 30 14:45:24 2020 +0100 @@ -168,3 +168,75 @@ return s; } +bool +StringBits::isValidUtf8(const std::string &bytes, bool isTruncated) +{ + size_t len = bytes.length(); + size_t mblen = 0; + unsigned char first = '\0'; + + for (size_t i = 0; i < len; ++i) { + + unsigned char c = bytes[i]; + + if (((c & 0xc0) == 0xc0) || !(c & 0x80)) { + + // 11xxxxxx or 0xxxxxxx: first byte of a character sequence + + if (mblen > 0) { + + // have we seen a valid sequence? + size_t length = + (!(first & 0x20)) ? 2 : + (!(first & 0x10)) ? 3 : + (!(first & 0x08)) ? 4 : + (!(first & 0x04)) ? 5 : 0; + + if (length != 0 && mblen != length) { + // previous multibyte sequence had invalid length + return false; + } + } + + mblen = 0; + first = c; + + } else { + + // second or subsequent byte + + if (mblen == 0) { + // ... without a first byte! + return false; + } + } + } + + // at the end + + if (isTruncated) { + // can't trust any errors arising now + return true; + } + + if (mblen > 0) { + + // have we seen a valid sequence? + size_t length = + (!(first & 0x20)) ? 2 : + (!(first & 0x10)) ? 3 : + (!(first & 0x08)) ? 4 : + (!(first & 0x04)) ? 5 : 0; + + if (length != 0 && mblen != length) { + // final multibyte sequence had invalid length + return false; + } + } + + return true; +} + + + +
--- a/base/StringBits.h Wed Apr 29 13:25:19 2020 +0100 +++ b/base/StringBits.h Thu Apr 30 14:45:24 2020 +0100 @@ -65,6 +65,15 @@ * Comma-Separated Values (CSV) Files. */ static QString joinDelimited(QVector<QString> row, QString delimiter); + + /** + * Return true if the given byte array contains a valid UTF-8 + * sequence, false if not. If isTruncated is true, the byte array + * will be treated as the prefix of a longer byte sequence, and + * any errors resulting from a multibyte code ending prematurely + * at the end of the array will be ignored. + */ + static bool isValidUtf8(const std::string &bytes, bool isTruncated); }; #endif