summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/src-server/Matching.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Main/src-server/Matching.cpp
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Main/src-server/Matching.cpp')
-rw-r--r--src/VBox/Main/src-server/Matching.cpp212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/Matching.cpp b/src/VBox/Main/src-server/Matching.cpp
new file mode 100644
index 00000000..dfddc96c
--- /dev/null
+++ b/src/VBox/Main/src-server/Matching.cpp
@@ -0,0 +1,212 @@
+/* $Id: Matching.cpp $ */
+/** @file
+ * @todo r=bird: brief description, please.
+ *
+ * Definition of template classes that provide simple API to
+ * do matching between values and value filters constructed from strings.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * 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, in version 3 of the
+ * License.
+ *
+ * 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 <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#define LOG_GROUP LOG_GROUP_MAIN
+#include "Matching.h"
+
+#include "LoggingNew.h"
+
+#include <stdlib.h>
+
+#include <iprt/errcore.h>
+
+namespace matching
+{
+
+// static
+void ParsedIntervalFilter_base::parse (const char *aFilter,
+ ParsedIntervalFilter_base *that)
+{
+ // initially null and valid
+ that->mNull = true;
+ that->mValid = true;
+ that->mErrorPosition = 0;
+
+ if (!aFilter || strncmp(aFilter, RT_STR_TUPLE("int:")) != 0)
+ return;
+
+ that->mNull = false;
+
+ size_t len = strlen (aFilter);
+
+ Mode mode = Single; // what's expected next
+ size_t start = 4, end = 4;
+ size_t err = 0; // less than 4 indicates success
+
+ do
+ {
+ end = strcspn(aFilter + start, ",-");
+ end += start;
+
+ char delim = aFilter[end];
+
+ if (delim == '-')
+ {
+ if (mode == End)
+ {
+ err = end;
+ break;
+ }
+ else
+ mode = Start;
+ }
+
+ // skip spaces around numbers
+ size_t s = start;
+ while (s < end && aFilter[s] == ' ') ++s;
+ size_t e = end - 1;
+ while (e > s && aFilter[e] == ' ') --e;
+ ++e;
+
+ that->parseValue(aFilter, s, e, mode);
+ if (!that->mValid)
+ return;
+
+ if (mode == Start)
+ mode = End;
+ else if (mode == End)
+ mode = Single;
+
+ start = end + 1;
+ }
+ while (start <= len);
+
+ if (err >= 4)
+ {
+ that->mValid = false;
+ that->mErrorPosition = err;
+ }
+}
+
+// static
+size_t ParsedIntervalFilter_base::parseValue (
+ const char *aFilter, size_t aStart, size_t aEnd,
+ bool aIsSigned, const Limits &aLimits,
+ Widest &val)
+{
+ char *endptr = NULL;
+
+ int vrc = 0;
+ if (aIsSigned)
+ vrc = RTStrToInt64Ex(aFilter + aStart, &endptr, 0, &val.ll);
+ else
+ vrc = RTStrToUInt64Ex(aFilter + aStart, &endptr, 0, &val.ull);
+
+ AssertReturn(endptr, 0);
+
+ size_t parsed = (size_t)(endptr - aFilter);
+
+ // return parsed if not able to parse to the end
+ if (parsed != aEnd)
+ return parsed;
+
+ // return aStart if out if range
+ if (vrc == VWRN_NUMBER_TOO_BIG ||
+ (aIsSigned &&
+ (val.ll < aLimits.min.ll ||
+ val.ll > aLimits.max.ll)) ||
+ (!aIsSigned &&
+ (val.ull < aLimits.min.ull ||
+ val.ull > aLimits.max.ull)))
+ return aStart;
+
+ return parsed;
+}
+
+void ParsedBoolFilter::parse (const Bstr &aFilter)
+{
+ mNull = false;
+ mValid = true;
+ mErrorPosition = 0;
+
+ if (aFilter.isEmpty())
+ {
+ mValueAny = true;
+ mValue = false;
+ }
+ else
+ {
+ mValueAny = false;
+ if (aFilter == L"true" || aFilter == L"yes" || aFilter == L"1")
+ mValue = true;
+ else
+ if (aFilter == L"false" || aFilter == L"no" || aFilter == L"0")
+ mValue = false;
+ else
+ mValid = false;
+ }
+}
+
+void ParsedRegexpFilter_base::parse (const Bstr &aFilter)
+{
+ /// @todo (dmik) parse "rx:<regexp>" string
+ // note, that min/max checks must not be done, when the string
+ // begins with "rx:". These limits are for exact matching only!
+
+ // empty or null string means any match (see #isMatch() below),
+ // so we don't apply Min/Max restrictions in this case
+
+ if (!aFilter.isEmpty())
+ {
+ size_t len = aFilter.length();
+
+ if (mMinLen > 0 && len < mMinLen)
+ {
+ mNull = mValid = false;
+ mErrorPosition = len;
+ return;
+ }
+
+ if (mMaxLen > 0 && len > mMaxLen)
+ {
+ mNull = mValid = false;
+ mErrorPosition = mMaxLen;
+ return;
+ }
+ }
+
+ mSimple = aFilter;
+ mNull = false;
+ mValid = true;
+ mErrorPosition = 0;
+}
+
+bool ParsedRegexpFilter_base::isMatch (const Bstr &aValue) const
+{
+ /// @todo (dmik) do regexp matching
+
+ // empty or null mSimple matches any match
+ return mSimple.isEmpty()
+ || (mIgnoreCase && mSimple.compare(aValue, Bstr::CaseInsensitive) == 0)
+ || (!mIgnoreCase && mSimple.compare(aValue) == 0);
+}
+
+} /* namespace matching */
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */