VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/Matching.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.1 KB
Line 
1/* $Id: Matching.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * @todo r=bird: brief description, please.
4 *
5 * Definition of template classes that provide simple API to
6 * do matching between values and value filters constructed from strings.
7 */
8
9/*
10 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
11 *
12 * This file is part of VirtualBox base platform packages, as
13 * available from https://www.virtualbox.org.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, in version 3 of the
18 * License.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <https://www.gnu.org/licenses>.
27 *
28 * SPDX-License-Identifier: GPL-3.0-only
29 */
30
31#define LOG_GROUP LOG_GROUP_MAIN
32#include "Matching.h"
33
34#include "LoggingNew.h"
35
36#include <stdlib.h>
37
38#include <iprt/errcore.h>
39
40namespace matching
41{
42
43// static
44void ParsedIntervalFilter_base::parse (const char *aFilter,
45 ParsedIntervalFilter_base *that)
46{
47 // initially null and valid
48 that->mNull = true;
49 that->mValid = true;
50 that->mErrorPosition = 0;
51
52 if (!aFilter || strncmp(aFilter, RT_STR_TUPLE("int:")) != 0)
53 return;
54
55 that->mNull = false;
56
57 size_t len = strlen (aFilter);
58
59 Mode mode = Single; // what's expected next
60 size_t start = 4, end = 4;
61 size_t err = 0; // less than 4 indicates success
62
63 do
64 {
65 end = strcspn(aFilter + start, ",-");
66 end += start;
67
68 char delim = aFilter[end];
69
70 if (delim == '-')
71 {
72 if (mode == End)
73 {
74 err = end;
75 break;
76 }
77 else
78 mode = Start;
79 }
80
81 // skip spaces around numbers
82 size_t s = start;
83 while (s < end && aFilter[s] == ' ') ++s;
84 size_t e = end - 1;
85 while (e > s && aFilter[e] == ' ') --e;
86 ++e;
87
88 that->parseValue(aFilter, s, e, mode);
89 if (!that->mValid)
90 return;
91
92 if (mode == Start)
93 mode = End;
94 else if (mode == End)
95 mode = Single;
96
97 start = end + 1;
98 }
99 while (start <= len);
100
101 if (err >= 4)
102 {
103 that->mValid = false;
104 that->mErrorPosition = err;
105 }
106}
107
108// static
109size_t ParsedIntervalFilter_base::parseValue (
110 const char *aFilter, size_t aStart, size_t aEnd,
111 bool aIsSigned, const Limits &aLimits,
112 Widest &val)
113{
114 char *endptr = NULL;
115
116 int vrc = 0;
117 if (aIsSigned)
118 vrc = RTStrToInt64Ex(aFilter + aStart, &endptr, 0, &val.ll);
119 else
120 vrc = RTStrToUInt64Ex(aFilter + aStart, &endptr, 0, &val.ull);
121
122 AssertReturn(endptr, 0);
123
124 size_t parsed = (size_t)(endptr - aFilter);
125
126 // return parsed if not able to parse to the end
127 if (parsed != aEnd)
128 return parsed;
129
130 // return aStart if out if range
131 if (vrc == VWRN_NUMBER_TOO_BIG ||
132 (aIsSigned &&
133 (val.ll < aLimits.min.ll ||
134 val.ll > aLimits.max.ll)) ||
135 (!aIsSigned &&
136 (val.ull < aLimits.min.ull ||
137 val.ull > aLimits.max.ull)))
138 return aStart;
139
140 return parsed;
141}
142
143void ParsedBoolFilter::parse (const Bstr &aFilter)
144{
145 mNull = false;
146 mValid = true;
147 mErrorPosition = 0;
148
149 if (aFilter.isEmpty())
150 {
151 mValueAny = true;
152 mValue = false;
153 }
154 else
155 {
156 mValueAny = false;
157 if (aFilter == L"true" || aFilter == L"yes" || aFilter == L"1")
158 mValue = true;
159 else
160 if (aFilter == L"false" || aFilter == L"no" || aFilter == L"0")
161 mValue = false;
162 else
163 mValid = false;
164 }
165}
166
167void ParsedRegexpFilter_base::parse (const Bstr &aFilter)
168{
169 /// @todo (dmik) parse "rx:<regexp>" string
170 // note, that min/max checks must not be done, when the string
171 // begins with "rx:". These limits are for exact matching only!
172
173 // empty or null string means any match (see #isMatch() below),
174 // so we don't apply Min/Max restrictions in this case
175
176 if (!aFilter.isEmpty())
177 {
178 size_t len = aFilter.length();
179
180 if (mMinLen > 0 && len < mMinLen)
181 {
182 mNull = mValid = false;
183 mErrorPosition = len;
184 return;
185 }
186
187 if (mMaxLen > 0 && len > mMaxLen)
188 {
189 mNull = mValid = false;
190 mErrorPosition = mMaxLen;
191 return;
192 }
193 }
194
195 mSimple = aFilter;
196 mNull = false;
197 mValid = true;
198 mErrorPosition = 0;
199}
200
201bool ParsedRegexpFilter_base::isMatch (const Bstr &aValue) const
202{
203 /// @todo (dmik) do regexp matching
204
205 // empty or null mSimple matches any match
206 return mSimple.isEmpty()
207 || (mIgnoreCase && mSimple.compare(aValue, Bstr::CaseInsensitive) == 0)
208 || (!mIgnoreCase && mSimple.compare(aValue) == 0);
209}
210
211} /* namespace matching */
212/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use