file_systems: Backport changes to QueryParser from BFS.

* 3e818f2075
 * 711e2dc05b
 * 6609c1a03a
 * f79179975d
 * 0ed0f5cb35 (tweaked for 64-bit)
 * a2eb6bbda4

Change-Id: I11d9946b475449b7b5aeed956e3ae8a776a0b20a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7704
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Augustin Cavalier
2024-06-24 19:40:08 +00:00
committed by waddlesplash
parent 3a17bd3545
commit 7da55c7296
+44 -37
View File
@@ -249,6 +249,8 @@ public:
status_t ParseQuotedString(char** _start, char** _end); status_t ParseQuotedString(char** _start, char** _end);
char* CopyString(char* start, char* end); char* CopyString(char* start, char* end);
inline bool _IsEquationChar(char c) const;
inline bool _IsOperatorChar(char c) const;
virtual status_t Match(Entry* entry, Node* node, virtual status_t Match(Entry* entry, Node* node,
const char* attribute = NULL, int32 type = 0, const char* attribute = NULL, int32 type = 0,
@@ -278,7 +280,6 @@ private:
status_t ConvertValue(type_code type); status_t ConvertValue(type_code type);
bool CompareTo(const uint8* value, size_t size); bool CompareTo(const uint8* value, size_t size);
uint8* Value() const { return (uint8*)&fValue; } uint8* Value() const { return (uint8*)&fValue; }
status_t MatchEmptyString();
char* fAttribute; char* fAttribute;
char* fString; char* fString;
@@ -401,16 +402,17 @@ Equation<QueryPolicy>::Equation(char** expr)
// set string to a valid start of the equation symbol // set string to a valid start of the equation symbol
string = end + 2; string = end + 2;
skipWhitespace(&string); skipWhitespace(&string);
if (*string != '=' && *string != '<' && *string != '>' if (!_IsEquationChar(string[0])) {
&& *string != '!') {
*expr = string; *expr = string;
return; return;
} }
} else { } else {
// search the (in)equation for the actual equation symbol (and for other operators // search the (in)equation for the actual equation symbol (and for other operators
// in case the equation is malformed) // in case the equation is malformed)
while (*string && *string != '=' && *string != '<' && *string != '>' while (string[0] != 0 && !_IsOperatorChar(string[0])
&& *string != '!' && *string != '&' && *string != '|') { && !_IsEquationChar(string[0])) {
if (string[0] == '\\' && string[1] != 0)
string++;
string++; string++;
} }
@@ -474,7 +476,7 @@ Equation<QueryPolicy>::Equation(char** expr)
string = end + 2; string = end + 2;
skipWhitespace(&string); skipWhitespace(&string);
} else { } else {
while (*string && *string != '&' && *string != '|' && *string != ')') while (string[0] && !_IsOperatorChar(string[0]) && string[0] != ')')
string++; string++;
end = string - 1; end = string - 1;
@@ -564,13 +566,38 @@ Equation<QueryPolicy>::CopyString(char* start, char* end)
if (copy == NULL) if (copy == NULL)
return NULL; return NULL;
memcpy(copy, start, length - 1); // Filter out remaining escaping slashes
for (int32 i = 0; i < length; i++) {
char c = start++[0];
if (c == '\\' && i < length) {
length--;
i--;
continue;
}
copy[i] = c;
}
copy[length - 1] = '\0'; copy[length - 1] = '\0';
return copy; return copy;
} }
template<typename QueryPolicy>
bool
Equation<QueryPolicy>::_IsEquationChar(char c) const
{
return c == '=' || c == '<' || c == '>' || c == '!';
}
template<typename QueryPolicy>
bool
Equation<QueryPolicy>::_IsOperatorChar(char c) const
{
return c == '&' || c == '|';
}
template<typename QueryPolicy> template<typename QueryPolicy>
status_t status_t
Equation<QueryPolicy>::ConvertValue(type_code type) Equation<QueryPolicy>::ConvertValue(type_code type)
@@ -598,6 +625,9 @@ Equation<QueryPolicy>::ConvertValue(type_code type)
fValue.Int32 = strtoul(string, &string, 0); fValue.Int32 = strtoul(string, &string, 0);
fSize = sizeof(uint32); fSize = sizeof(uint32);
break; break;
case B_TIME_TYPE:
type = B_INT64_TYPE;
// supposed to fall through
case B_INT64_TYPE: case B_INT64_TYPE:
fValue.Int64 = strtoll(string, &string, 0); fValue.Int64 = strtoll(string, &string, 0);
fSize = sizeof(int64); fSize = sizeof(int64);
@@ -684,27 +714,6 @@ Equation<QueryPolicy>::Complement()
} }
template<typename QueryPolicy>
status_t
Equation<QueryPolicy>::MatchEmptyString()
{
// There is no matching attribute, we will just bail out if we
// already know that our value is not of a string type.
// If not, it will be converted to a string - and then be compared with "".
// That's why we have to call ConvertValue() here - but it will be
// a cheap call for the next time
// TODO: Should we do this only for OP_UNEQUAL?
if (fType != 0 && fType != B_STRING_TYPE)
return NO_MATCH;
status_t status = ConvertValue(B_STRING_TYPE);
if (status == B_OK)
status = CompareTo((const uint8*)"", fSize) ? MATCH_OK : NO_MATCH;
return status;
}
/*! Matches the node's attribute value with the equation. /*! Matches the node's attribute value with the equation.
Returns MATCH_OK if it matches, NO_MATCH if not, < 0 if something went Returns MATCH_OK if it matches, NO_MATCH if not, < 0 if something went
wrong. wrong.
@@ -722,12 +731,8 @@ Equation<QueryPolicy>::Match(Entry* entry, Node* node,
// first, check if we are matching for a live query and use that value // first, check if we are matching for a live query and use that value
if (attributeName != NULL && !strcmp(fAttribute, attributeName)) { if (attributeName != NULL && !strcmp(fAttribute, attributeName)) {
if (key == NULL) { if (key == NULL)
if (type == B_STRING_TYPE)
return MatchEmptyString();
return NO_MATCH; return NO_MATCH;
}
buffer = const_cast<uint8*>(key); buffer = const_cast<uint8*>(key);
} else if (!strcmp(fAttribute, "name")) { } else if (!strcmp(fAttribute, "name")) {
// if not, check for "fake" attributes ("name", "size", "last_modified") // if not, check for "fake" attributes ("name", "size", "last_modified")
@@ -750,7 +755,7 @@ Equation<QueryPolicy>::Match(Entry* entry, Node* node,
size = bufferSize; size = bufferSize;
if (QueryPolicy::NodeGetAttribute(nodeHolder, node, if (QueryPolicy::NodeGetAttribute(nodeHolder, node,
fAttribute, buffer, &size, &type) != B_OK) { fAttribute, buffer, &size, &type) != B_OK) {
return MatchEmptyString(); return NO_MATCH;
} }
} }
@@ -973,14 +978,16 @@ Equation<QueryPolicy>::GetNextMatching(Context* context,
ssize_t nameLength = QueryPolicy::EntryGetName(entry, ssize_t nameLength = QueryPolicy::EntryGetName(entry,
dirent->d_name, dirent->d_name,
(const char*)dirent + bufferSize - dirent->d_name); (const char*)dirent + bufferSize - dirent->d_name);
if (nameLength < 0) if (nameLength < 0) {
QUERY_RETURN_ERROR(nameLength); // Invalid or unknown name.
nameLength = 0;
}
dirent->d_dev = QueryPolicy::ContextGetVolumeID(context); dirent->d_dev = QueryPolicy::ContextGetVolumeID(context);
dirent->d_ino = QueryPolicy::EntryGetNodeID(entry); dirent->d_ino = QueryPolicy::EntryGetNodeID(entry);
dirent->d_pdev = dirent->d_dev; dirent->d_pdev = dirent->d_dev;
dirent->d_pino = QueryPolicy::EntryGetParentID(entry); dirent->d_pino = QueryPolicy::EntryGetParentID(entry);
dirent->d_reclen = sizeof(struct dirent) + strlen(dirent->d_name) + 1; dirent->d_reclen = offsetof(struct dirent, d_name) + nameLength;
} }
if (status == MATCH_OK) if (status == MATCH_OK)