|
|
@@ -1,6 +1,8 @@
|
|
|
+#pragma once
|
|
|
|
|
|
#if __has_include(<unicode/std_string.h>)
|
|
|
#define JVALIDATE_HAS_ICU
|
|
|
+#include <unicode/brkiter.h>
|
|
|
#include <unicode/unistr.h>
|
|
|
#endif
|
|
|
|
|
|
@@ -13,4 +15,44 @@ inline size_t length(std::string_view arg) {
|
|
|
return arg.size();
|
|
|
#endif
|
|
|
}
|
|
|
+
|
|
|
+inline std::string regex_escape(std::string_view arg) {
|
|
|
+#ifdef JVALIDATE_HAS_ICU
|
|
|
+ icu::UnicodeString const ucs = icu::UnicodeString::fromUTF8(icu::StringPiece(arg));
|
|
|
+ if (ucs.countChar32() == arg.size()) {
|
|
|
+ return std::string(arg);
|
|
|
+ }
|
|
|
+
|
|
|
+ UErrorCode status = U_ZERO_ERROR;
|
|
|
+ std::unique_ptr<icu::BreakIterator> iter(
|
|
|
+ icu::BreakIterator::createCharacterInstance(NULL, status));
|
|
|
+
|
|
|
+ if (U_FAILURE(status)) {
|
|
|
+ return std::string(arg);
|
|
|
+ }
|
|
|
+
|
|
|
+ icu::UnicodeString rval;
|
|
|
+ iter->setText(ucs);
|
|
|
+ int32_t start = iter->first();
|
|
|
+ int32_t end = iter->next();
|
|
|
+ while (end != icu::BreakIterator::DONE) {
|
|
|
+ if (std::strchr("?*+", ucs.charAt(end))) {
|
|
|
+ rval.append('(');
|
|
|
+ rval.append(ucs, start, end - 1);
|
|
|
+ rval.append(')');
|
|
|
+ rval.append(ucs.char32At(end));
|
|
|
+ end = iter->next();
|
|
|
+ } else {
|
|
|
+ rval.append(ucs, start, end - 1);
|
|
|
+ }
|
|
|
+ start = end;
|
|
|
+ end = iter->next();
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string out;
|
|
|
+ return rval.toUTF8String(out);
|
|
|
+#else
|
|
|
+ return std::string(arg);
|
|
|
+#endif
|
|
|
+}
|
|
|
}
|