VirtualBox

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

Last change on this file since 94348 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette