summaryrefslogtreecommitdiff
path: root/plugins/Dbx_kyoto/src/kyotocabinet/kcregex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_kyoto/src/kyotocabinet/kcregex.cc')
-rw-r--r--plugins/Dbx_kyoto/src/kyotocabinet/kcregex.cc195
1 files changed, 195 insertions, 0 deletions
diff --git a/plugins/Dbx_kyoto/src/kyotocabinet/kcregex.cc b/plugins/Dbx_kyoto/src/kyotocabinet/kcregex.cc
new file mode 100644
index 0000000000..e3e56e8a6e
--- /dev/null
+++ b/plugins/Dbx_kyoto/src/kyotocabinet/kcregex.cc
@@ -0,0 +1,195 @@
+/*************************************************************************************************
+ * Regular expression
+ * Copyright (C) 2009-2012 FAL Labs
+ * This file is part of Kyoto Cabinet.
+ * This program is free software: you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation, either version
+ * 3 of the License, or any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *************************************************************************************************/
+
+
+#include "kcregex.h"
+#include "myconf.h"
+
+#if _KC_PXREGEX
+extern "C" {
+#include <regex.h>
+}
+#else
+#include <regex>
+#endif
+
+
+namespace kyotocabinet { // common namespace
+
+
+/**
+ * Regex internal.
+ */
+struct RegexCore {
+#if _KC_PXREGEX
+ ::regex_t rbuf;
+ bool alive;
+ bool nosub;
+#else
+ std::regex* rbuf;
+#endif
+};
+
+
+/**
+ * Default constructor.
+ */
+Regex::Regex() : opq_(NULL) {
+#if _KC_PXREGEX
+ _assert_(true);
+ RegexCore* core = new RegexCore;
+ core->alive = false;
+ core->nosub = false;
+ opq_ = (void*)core;
+#else
+ _assert_(true);
+ RegexCore* core = new RegexCore;
+ core->rbuf = NULL;
+ opq_ = (void*)core;
+#endif
+}
+
+
+/**
+ * Destructor.
+ */
+Regex::~Regex() {
+#if _KC_PXREGEX
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (core->alive) ::regfree(&core->rbuf);
+ delete core;
+#else
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ delete core->rbuf;
+ delete core;
+#endif
+}
+
+
+/**
+ * Compile a string of regular expression.
+ */
+bool Regex::compile(const std::string& regex, uint32_t opts) {
+#if _KC_PXREGEX
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (core->alive) {
+ ::regfree(&core->rbuf);
+ core->alive = false;
+ }
+ int32_t cflags = REG_EXTENDED;
+ if (opts & IGNCASE) cflags |= REG_ICASE;
+ if ((opts & MATCHONLY) || regex.empty()) {
+ cflags |= REG_NOSUB;
+ core->nosub = true;
+ }
+ if (::regcomp(&core->rbuf, regex.c_str(), cflags) != 0) return false;
+ core->alive = true;
+ return true;
+#else
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (core->rbuf) {
+ delete core->rbuf;
+ core->rbuf = NULL;
+ }
+ int32_t cflags = std::regex::ECMAScript;
+ if (opts & IGNCASE) cflags |= std::regex::icase;
+ if ((opts & MATCHONLY) || regex.empty()) cflags |= std::regex::nosubs;
+ try {
+ core->rbuf = new std::regex(regex, (std::regex::flag_type)cflags);
+ } catch (...) {
+ core->rbuf = NULL;
+ return false;
+ }
+ return true;
+#endif
+}
+
+
+/**
+ * Check whether a string matches the regular expression.
+ */
+bool Regex::match(const std::string& str) {
+#if _KC_PXREGEX
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (!core->alive) return false;
+ if (core->nosub) return ::regexec(&core->rbuf, str.c_str(), 0, NULL, 0) == 0;
+ ::regmatch_t subs[1];
+ return ::regexec(&core->rbuf, str.c_str(), 1, subs, 0) == 0;
+#else
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (!core->rbuf) return false;
+ std::smatch res;
+ return std::regex_search(str, res, *core->rbuf);
+#endif
+}
+
+
+/**
+ * Check whether a string matches the regular expression.
+ */
+std::string Regex::replace(const std::string& str, const std::string& alt) {
+#if _KC_PXREGEX
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (!core->alive || core->nosub) return str;
+ regmatch_t subs[256];
+ if (::regexec(&core->rbuf, str.c_str(), sizeof(subs) / sizeof(*subs), subs, 0) != 0)
+ return str;
+ const char* sp = str.c_str();
+ std::string xstr;
+ bool first = true;
+ while (sp[0] != '\0' && ::regexec(&core->rbuf, sp, 10, subs, first ? 0 : REG_NOTBOL) == 0) {
+ first = false;
+ if (subs[0].rm_so == -1) break;
+ xstr.append(sp, subs[0].rm_so);
+ for (const char* rp = alt.c_str(); *rp != '\0'; rp++) {
+ if (*rp == '$') {
+ if (rp[1] >= '0' && rp[1] <= '9') {
+ int32_t num = rp[1] - '0';
+ if (subs[num].rm_so != -1 && subs[num].rm_eo != -1)
+ xstr.append(sp + subs[num].rm_so, subs[num].rm_eo - subs[num].rm_so);
+ ++rp;
+ } else if (rp[1] == '&') {
+ xstr.append(sp + subs[0].rm_so, subs[0].rm_eo - subs[0].rm_so);
+ ++rp;
+ } else if (rp[1] != '\0') {
+ xstr.append(++rp, 1);
+ }
+ } else {
+ xstr.append(rp, 1);
+ }
+ }
+ sp += subs[0].rm_eo;
+ if (subs[0].rm_eo < 1) break;
+ }
+ xstr.append(sp);
+ return xstr;
+#else
+ _assert_(true);
+ RegexCore* core = (RegexCore*)opq_;
+ if (!core->rbuf) return str;
+ return std::regex_replace(str, *core->rbuf, alt);
+#endif
+}
+
+
+} // common namespace
+
+// END OF FILE