xref: /haiku/headers/private/file_systems/QueryParser.h (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
1 /*
2  * Copyright 2001-2014, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
4  * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
5  * This file may be used under the terms of the MIT License.
6  */
7 #ifndef _FILE_SYSTEMS_QUERY_PARSER_H
8 #define _FILE_SYSTEMS_QUERY_PARSER_H
9 
10 
11 /*!	Query parsing and evaluation. */
12 
13 
14 // The operator precedence is =,!=,>,<,>=,<= .. && .. ||.
15 // Apparently, the "!" (not) can only be used with parentheses.
16 //
17 // If you think that there are too few NULL pointer checks in some places
18 // of the code, just read the beginning of the query constructor.
19 // The API is not fully available, just the Query and the Expression class
20 // are.
21 
22 #ifdef FS_SHELL
23 #	include <new>
24 
25 #	include "fssh_api_wrapper.h"
26 #	include "fssh_auto_deleter.h"
27 #else
28 #	include <dirent.h>
29 #	include <stdlib.h>
30 #	include <string.h>
31 
32 #	include <algorithm>
33 #	include <new>
34 
35 #	include <fs_interface.h>
36 #	include <fs_query.h>
37 #	include <TypeConstants.h>
38 
39 #	include <util/SinglyLinkedList.h>
40 #	include <util/Stack.h>
41 
42 #	include <query_private.h>
43 #endif	// !FS_SHELL
44 
45 #include <file_systems/QueryParserUtils.h>
46 
47 
48 //#define DEBUG_QUERY
49 
50 #ifndef QUERY_RETURN_ERROR
51 #	define QUERY_RETURN_ERROR(error)	return (error)
52 #endif
53 
54 #ifndef QUERY_REPORT_ERROR
55 #	define QUERY_REPORT_ERROR(error)	do {} while (false)
56 #endif
57 
58 #ifndef QUERY_FATAL
59 #	define QUERY_FATAL(message...)		panic(message)
60 #endif
61 
62 #ifndef QUERY_INFORM
63 #	define QUERY_INFORM(message...)		dprintf(message)
64 #endif
65 
66 #ifndef QUERY_D
67 #	define QUERY_D(block)
68 #endif
69 
70 
71 namespace QueryParser {
72 
73 
74 template<typename QueryPolicy> class Equation;
75 template<typename QueryPolicy> class Expression;
76 template<typename QueryPolicy> class Term;
77 template<typename QueryPolicy> class Query;
78 
79 
80 enum ops {
81 	OP_NONE,
82 
83 	OP_AND,
84 	OP_OR,
85 
86 	OP_EQUATION,
87 		// is only used for invalid equations
88 
89 	OP_EQUAL,
90 	OP_UNEQUAL,
91 	OP_GREATER_THAN,
92 	OP_LESS_THAN,
93 	OP_GREATER_THAN_OR_EQUAL,
94 	OP_LESS_THAN_OR_EQUAL,
95 };
96 
97 
98 template<typename QueryPolicy>
99 union value {
100 	int64	Int64;
101 	uint64	Uint64;
102 	int32	Int32;
103 	uint32	Uint32;
104 	float	Float;
105 	double	Double;
106 	char	String[QueryPolicy::kMaxFileNameLength];
107 };
108 
109 
110 template<typename QueryPolicy>
111 class Query {
112 public:
113 			typedef typename QueryPolicy::Entry Entry;
114 			typedef typename QueryPolicy::Index Index;
115 			typedef typename QueryPolicy::IndexIterator IndexIterator;
116 			typedef typename QueryPolicy::Node Node;
117 			typedef typename QueryPolicy::NodeHolder NodeHolder;
118 			typedef typename QueryPolicy::Context Context;
119 
120 public:
121 							Query(Context* context,
122 								Expression<QueryPolicy>* expression,
123 								uint32 flags, port_id port, uint32 token);
124 							~Query();
125 
126 	static	status_t		Create(Context* context, const char* queryString,
127 								uint32 flags, port_id port, uint32 token,
128 								Query<QueryPolicy>*& _query);
129 
130 			status_t		Rewind();
131 	inline	status_t		GetNextEntry(struct dirent* dirent, size_t size);
132 
133 			void			LiveUpdate(Entry* entry, Node* node,
134 								const char* attribute, int32 type,
135 								const uint8* oldKey, size_t oldLength,
136 								const uint8* newKey, size_t newLength);
137 			void			LiveUpdateRenameMove(Entry* entry, Node* node,
138 								ino_t oldDirectoryID, const char* oldName,
139 								size_t oldLength, ino_t newDirectoryID,
140 								const char* newName, size_t newLength);
141 
142 			Expression<QueryPolicy>* GetExpression() const
143 								{ return fExpression; }
144 
145 			uint32			Flags() const
146 								{ return fFlags; }
147 
148 private:
149 			status_t		_GetNextEntry(struct dirent* dirent, size_t size);
150 			void			_SendEntryNotification(Entry* entry,
151 								status_t (*notify)(port_id, int32, dev_t, ino_t,
152 									const char*, ino_t));
153 
154 private:
155 			Context*		fContext;
156 			Expression<QueryPolicy>* fExpression;
157 			Equation<QueryPolicy>* fCurrent;
158 			IndexIterator*	fIterator;
159 			Index			fIndex;
160 			Stack<Equation<QueryPolicy>*> fStack;
161 
162 			uint32			fFlags;
163 			port_id			fPort;
164 			int32			fToken;
165 			bool			fNeedsEntry;
166 };
167 
168 
169 /*!	Abstract base class for the operator/equation classes.
170 */
171 template<typename QueryPolicy>
172 class Term {
173 public:
174 			typedef typename QueryPolicy::Entry Entry;
175 			typedef typename QueryPolicy::Index Index;
176 			typedef typename QueryPolicy::IndexIterator IndexIterator;
177 			typedef typename QueryPolicy::Node Node;
178 			typedef typename QueryPolicy::NodeHolder NodeHolder;
179 			typedef typename QueryPolicy::Context Context;
180 
181 public:
182 						Term(int8 op) : fOp(op), fParent(NULL) {}
183 	virtual				~Term() {}
184 
185 			int8		Op() const { return fOp; }
186 
187 			void		SetParent(Term<QueryPolicy>* parent)
188 							{ fParent = parent; }
189 			Term<QueryPolicy>* Parent() const { return fParent; }
190 
191 	virtual	status_t	Match(Entry* entry, Node* node,
192 							const char* attribute = NULL, int32 type = 0,
193 							const uint8* key = NULL, size_t size = 0) = 0;
194 	virtual	void		Complement() = 0;
195 
196 	virtual	void		CalculateScore(Index& index) = 0;
197 	virtual	int32		Score() const = 0;
198 
199 	virtual	status_t	InitCheck() = 0;
200 
201 	virtual	bool		NeedsEntry() = 0;
202 
203 #ifdef DEBUG_QUERY
204 	virtual	void		PrintToStream() = 0;
205 #endif
206 
207 protected:
208 			int8		fOp;
209 			Term<QueryPolicy>* fParent;
210 };
211 
212 
213 /*!	An Equation object represents an "attribute-equation operator-value" pair.
214 
215 	Although an Equation object is quite independent from the volume on which
216 	the query is run, there are some dependencies that are produced while
217 	querying:
218 	The type/size of the value, the score, and if it has an index or not.
219 	So you could run more than one query on the same volume, but it might return
220 	wrong values when it runs concurrently on another volume.
221 	That's not an issue right now, because we run single-threaded and don't use
222 	queries more than once.
223 */
224 template<typename QueryPolicy>
225 class Equation : public Term<QueryPolicy> {
226 public:
227 			typedef typename QueryPolicy::Entry Entry;
228 			typedef typename QueryPolicy::Index Index;
229 			typedef typename QueryPolicy::IndexIterator IndexIterator;
230 			typedef typename QueryPolicy::Node Node;
231 			typedef typename QueryPolicy::NodeHolder NodeHolder;
232 			typedef typename QueryPolicy::Context Context;
233 
234 public:
235 						Equation(const char** expression);
236 	virtual				~Equation();
237 
238 	virtual	status_t	InitCheck();
239 
240 			status_t	ParseQuotedString(const char** _start, const char** _end);
241 			char*		CopyString(const char* start, const char* end);
242 	inline	bool		_IsEquationChar(char c) const;
243 	inline	bool		_IsOperatorChar(char c) const;
244 
245 	virtual	status_t	Match(Entry* entry, Node* node,
246 							const char* attribute = NULL, int32 type = 0,
247 							const uint8* key = NULL, size_t size = 0);
248 	virtual void		Complement();
249 
250 			status_t	PrepareQuery(Context* context, Index& index,
251 							IndexIterator** iterator, bool queryNonIndexed);
252 			status_t	GetNextMatching(Context* context,
253 							IndexIterator* iterator, struct dirent* dirent,
254 							size_t bufferSize);
255 
256 	virtual	void		CalculateScore(Index &index);
257 	virtual	int32		Score() const { return fScore; }
258 
259 	virtual	bool		NeedsEntry();
260 
261 #ifdef DEBUG_QUERY
262 	virtual	void		PrintToStream();
263 #endif
264 
265 private:
266 						Equation(const Equation& other);
267 						Equation& operator=(const Equation& other);
268 							// no implementation
269 
270 			status_t	ConvertValue(type_code type);
271 			bool		CompareTo(const uint8* value, size_t size);
272 			uint8*		Value() const { return (uint8*)&fValue; }
273 
274 			char*		fAttribute;
275 			char*		fString;
276 			union value<QueryPolicy> fValue;
277 			type_code	fType;
278 			size_t		fSize;
279 			bool		fIsPattern;
280 
281 			int32		fScore;
282 			bool		fHasIndex;
283 };
284 
285 
286 /*!	The Operator class does not represent a generic operator, but only those
287 	that combine two equations, namely "or", and "and".
288 */
289 template<typename QueryPolicy>
290 class Operator : public Term<QueryPolicy> {
291 public:
292 			typedef typename QueryPolicy::Entry Entry;
293 			typedef typename QueryPolicy::Index Index;
294 			typedef typename QueryPolicy::IndexIterator IndexIterator;
295 			typedef typename QueryPolicy::Node Node;
296 			typedef typename QueryPolicy::Context Context;
297 
298 public:
299 						Operator(Term<QueryPolicy>* left, int8 op,
300 							Term<QueryPolicy>* right);
301 	virtual				~Operator();
302 
303 			Term<QueryPolicy>* Left() const { return fLeft; }
304 			Term<QueryPolicy>* Right() const { return fRight; }
305 
306 	virtual	status_t	Match(Entry* entry, Node* node,
307 							const char* attribute = NULL, int32 type = 0,
308 							const uint8* key = NULL, size_t size = 0);
309 	virtual	void		Complement();
310 
311 	virtual	void		CalculateScore(Index& index);
312 	virtual	int32		Score() const;
313 
314 	virtual	status_t	InitCheck();
315 
316 	virtual	bool		NeedsEntry();
317 
318 #ifdef DEBUG_QUERY
319 	virtual	void		PrintToStream();
320 #endif
321 
322 private:
323 						Operator(const Operator& other);
324 						Operator& operator=(const Operator& other);
325 							// no implementation
326 
327 			Term<QueryPolicy>* fLeft;
328 			Term<QueryPolicy>* fRight;
329 };
330 
331 
332 template<typename QueryPolicy>
333 class Expression {
334 public:
335 			typedef typename QueryPolicy::Entry Entry;
336 			typedef typename QueryPolicy::Index Index;
337 			typedef typename QueryPolicy::IndexIterator IndexIterator;
338 			typedef typename QueryPolicy::Node Node;
339 			typedef typename QueryPolicy::Context Context;
340 
341 public:
342 							Expression();
343 							~Expression();
344 
345 			status_t		Init(const char* expr, const char** position);
346 
347 			Term<QueryPolicy>* Root() const { return fTerm; }
348 
349 protected:
350 			bool			IsOperator(const char** expr, char op);
351 
352 private:
353 							Expression(const Expression& other);
354 							Expression& operator=(const Expression& other);
355 								// no implementation
356 
357 			Term<QueryPolicy>* fTerm;
358 };
359 
360 
361 //	#pragma mark -
362 
363 
364 template<typename QueryPolicy>
365 Equation<QueryPolicy>::Equation(const char** expr)
366 	:
367 	Term<QueryPolicy>(OP_EQUATION),
368 	fAttribute(NULL),
369 	fString(NULL),
370 	fType(0),
371 	fIsPattern(false)
372 {
373 	const char* string = *expr;
374 	const char* start = string;
375 	const char* end = NULL;
376 
377 	// Since the equation is the integral part of any query, we're just parsing
378 	// the whole thing here.
379 	// The whitespace at the start is already removed in
380 	// Expression::ParseEquation()
381 
382 	if (*start == '"' || *start == '\'') {
383 		// string is quoted (start has to be on the beginning of a string)
384 		if (ParseQuotedString(&start, &end) < B_OK)
385 			return;
386 
387 		// set string to a valid start of the equation symbol
388 		string = end + 2;
389 		skipWhitespace(&string);
390 		if (!_IsEquationChar(string[0])) {
391 			*expr = string;
392 			return;
393 		}
394 	} else {
395 		// search the (in)equation for the actual equation symbol (and for other operators
396 		// in case the equation is malformed)
397 		while (string[0] != 0 && !_IsOperatorChar(string[0])
398 			&& !_IsEquationChar(string[0])) {
399 			if (string[0] == '\\' && string[1] != 0)
400 				string++;
401 			string++;
402 		}
403 
404 		// get the attribute string	(and trim whitespace), in case
405 		// the string was not quoted
406 		end = string - 1;
407 		skipWhitespaceReverse(&end, start);
408 	}
409 
410 	// attribute string is empty (which is not allowed)
411 	if (start > end)
412 		return;
413 
414 	// At this point, "start" points to the beginning of the string, "end"
415 	// points to the last character of the string, and "string" points to the
416 	// first character of the equation symbol
417 
418 	// test for the right symbol (as this doesn't need any memory)
419 	switch (*string) {
420 		case '=':
421 			Term<QueryPolicy>::fOp = OP_EQUAL;
422 			break;
423 		case '>':
424 			Term<QueryPolicy>::fOp = *(string + 1) == '='
425 				? OP_GREATER_THAN_OR_EQUAL : OP_GREATER_THAN;
426 			break;
427 		case '<':
428 			Term<QueryPolicy>::fOp = *(string + 1) == '='
429 				? OP_LESS_THAN_OR_EQUAL : OP_LESS_THAN;
430 			break;
431 		case '!':
432 			if (*(string + 1) != '=')
433 				return;
434 			Term<QueryPolicy>::fOp = OP_UNEQUAL;
435 			break;
436 
437 		// any invalid characters will be rejected
438 		default:
439 			*expr = string;
440 			return;
441 	}
442 
443 	// lets change "start" to point to the first character after the symbol
444 	if (*(string + 1) == '=')
445 		string++;
446 	string++;
447 	skipWhitespace(&string);
448 
449 	// allocate & copy the attribute string
450 
451 	fAttribute = CopyString(start, end);
452 	if (fAttribute == NULL)
453 		return;
454 
455 	start = string;
456 	if (*start == '"' || *start == '\'') {
457 		// string is quoted (start has to be on the beginning of a string)
458 		if (ParseQuotedString(&start, &end) < B_OK)
459 			return;
460 
461 		string = end + 2;
462 		skipWhitespace(&string);
463 	} else {
464 		while (string[0] && !_IsOperatorChar(string[0]) && string[0] != ')')
465 			string++;
466 
467 		end = string - 1;
468 		skipWhitespaceReverse(&end, start);
469 	}
470 
471 	// at this point, "start" will point to the first character of the value,
472 	// "end" will point to its last character, and "start" to the first non-
473 	// whitespace character after the value string
474 
475 	fString = CopyString(start, end);
476 	if (fString == NULL)
477 		return;
478 
479 	// patterns are only allowed for these operations (and strings)
480 	if (Term<QueryPolicy>::fOp == OP_EQUAL
481 		|| Term<QueryPolicy>::fOp == OP_UNEQUAL) {
482 		fIsPattern = isPattern(fString);
483 		if (fIsPattern && isValidPattern(fString) < B_OK) {
484 			// we only want to have valid patterns; setting fString
485 			// to NULL will cause InitCheck() to fail
486 			free(fString);
487 			fString = NULL;
488 		}
489 	}
490 
491 	*expr = string;
492 }
493 
494 
495 template<typename QueryPolicy>
496 Equation<QueryPolicy>::~Equation()
497 {
498 	free(fAttribute);
499 	free(fString);
500 }
501 
502 
503 template<typename QueryPolicy>
504 status_t
505 Equation<QueryPolicy>::InitCheck()
506 {
507 	if (fAttribute == NULL || fString == NULL
508 		|| Term<QueryPolicy>::fOp == OP_NONE) {
509 		return B_BAD_VALUE;
510 	}
511 
512 	return B_OK;
513 }
514 
515 
516 template<typename QueryPolicy>
517 status_t
518 Equation<QueryPolicy>::ParseQuotedString(const char** _start, const char** _end)
519 {
520 	const char* start = *_start;
521 	const char quote = *start++;
522 	const char* end = start;
523 
524 	for (; *end && *end != quote; end++) {
525 		if (*end == '\\')
526 			end++;
527 	}
528 	if (*end == '\0')
529 		return B_BAD_VALUE;
530 
531 	*_start = start;
532 	*_end = end - 1;
533 
534 	return B_OK;
535 }
536 
537 
538 template<typename QueryPolicy>
539 char*
540 Equation<QueryPolicy>::CopyString(const char* start, const char* end)
541 {
542 	// end points to the last character of the string - and the length
543 	// also has to include the null-termination
544 	int32 length = end + 2 - start;
545 	// just to make sure; since that's the max. attribute name length and
546 	// the max. string in an index, it make sense to have it that way
547 	if (length > QueryPolicy::kMaxFileNameLength || length <= 0)
548 		return NULL;
549 
550 	char* copy = (char*)malloc(length);
551 	if (copy == NULL)
552 		return NULL;
553 
554 	// Filter out remaining escaping slashes
555 	for (int32 i = 0; i < length; i++) {
556 		char c = start++[0];
557 		if (c == '\\' && i < length) {
558 			length--;
559 			i--;
560 			continue;
561 		}
562 		copy[i] = c;
563 	}
564 	copy[length - 1] = '\0';
565 
566 	return copy;
567 }
568 
569 
570 template<typename QueryPolicy>
571 bool
572 Equation<QueryPolicy>::_IsEquationChar(char c) const
573 {
574 	return c == '=' || c == '<' || c == '>' || c == '!';
575 }
576 
577 
578 template<typename QueryPolicy>
579 bool
580 Equation<QueryPolicy>::_IsOperatorChar(char c) const
581 {
582 	return c == '&' || c == '|';
583 }
584 
585 
586 template<typename QueryPolicy>
587 status_t
588 Equation<QueryPolicy>::ConvertValue(type_code type)
589 {
590 	// Has the type already been converted?
591 	if (type == fType)
592 		return B_OK;
593 
594 	char* string = fString;
595 
596 	switch (type) {
597 		case B_MIME_STRING_TYPE:
598 			type = B_STRING_TYPE;
599 			// supposed to fall through
600 		case B_STRING_TYPE:
601 			strncpy(fValue.String, string, QueryPolicy::kMaxFileNameLength);
602 			fValue.String[QueryPolicy::kMaxFileNameLength - 1] = '\0';
603 			fSize = strlen(fValue.String);
604 			break;
605 		case B_INT32_TYPE:
606 			fValue.Int32 = strtol(string, &string, 0);
607 			fSize = sizeof(int32);
608 			break;
609 		case B_UINT32_TYPE:
610 			fValue.Int32 = strtoul(string, &string, 0);
611 			fSize = sizeof(uint32);
612 			break;
613 		case B_TIME_TYPE:
614 			type = B_INT64_TYPE;
615 			// supposed to fall through
616 		case B_INT64_TYPE:
617 			fValue.Int64 = strtoll(string, &string, 0);
618 			fSize = sizeof(int64);
619 			break;
620 		case B_UINT64_TYPE:
621 			fValue.Uint64 = strtoull(string, &string, 0);
622 			fSize = sizeof(uint64);
623 			break;
624 		case B_FLOAT_TYPE:
625 			fValue.Float = strtod(string, &string);
626 			fSize = sizeof(float);
627 			break;
628 		case B_DOUBLE_TYPE:
629 			fValue.Double = strtod(string, &string);
630 			fSize = sizeof(double);
631 			break;
632 		default:
633 			QUERY_INFORM("query attribute '%s': unsupported value conversion to 0x%x requested!\n",
634 				fAttribute, (int)type);
635 			return B_BAD_TYPE;
636 	}
637 
638 	fType = type;
639 
640 	// patterns are only allowed for string types
641 	if (fType != B_STRING_TYPE && fIsPattern)
642 		fIsPattern = false;
643 
644 	return B_OK;
645 }
646 
647 
648 /*!	Returns true when the key matches the equation. You have to
649 	call ConvertValue() before this one.
650 */
651 template<typename QueryPolicy>
652 bool
653 Equation<QueryPolicy>::CompareTo(const uint8* value, size_t size)
654 {
655 	int32 compare;
656 
657 	// fIsPattern is only true if it's a string type, and fOp OP_EQUAL, or
658 	// OP_UNEQUAL
659 	if (fIsPattern) {
660 		// we have already validated the pattern, so we don't check for failing
661 		// here - if something is broken, and matchString() returns an error,
662 		// we just don't match
663 		compare = matchString(fValue.String, (const char*)value) == MATCH_OK ? 0 : 1;
664 	} else
665 		compare = compareKeys(fType, value, size, Value(), fSize);
666 
667 	switch (Term<QueryPolicy>::fOp) {
668 		case OP_EQUAL:
669 			return compare == 0;
670 		case OP_UNEQUAL:
671 			return compare != 0;
672 		case OP_LESS_THAN:
673 			return compare < 0;
674 		case OP_LESS_THAN_OR_EQUAL:
675 			return compare <= 0;
676 		case OP_GREATER_THAN:
677 			return compare > 0;
678 		case OP_GREATER_THAN_OR_EQUAL:
679 			return compare >= 0;
680 	}
681 	QUERY_FATAL("Unknown/Unsupported operation: %d\n", Term<QueryPolicy>::fOp);
682 	return false;
683 }
684 
685 
686 template<typename QueryPolicy>
687 void
688 Equation<QueryPolicy>::Complement()
689 {
690 	QUERY_D(if (Term<QueryPolicy>::fOp <= OP_EQUATION || Term<QueryPolicy>::fOp > OP_LESS_THAN_OR_EQUAL) {
691 		QUERY_FATAL("op out of range!\n");
692 		return;
693 	});
694 
695 	int8 complementOp[] = {OP_UNEQUAL, OP_EQUAL, OP_LESS_THAN_OR_EQUAL,
696 			OP_GREATER_THAN_OR_EQUAL, OP_LESS_THAN, OP_GREATER_THAN};
697 	Term<QueryPolicy>::fOp = complementOp[Term<QueryPolicy>::fOp - OP_EQUAL];
698 }
699 
700 
701 /*!	Matches the node's attribute value with the equation.
702 	Returns MATCH_OK if it matches, NO_MATCH if not, < 0 if something went
703 	wrong.
704 */
705 template<typename QueryPolicy>
706 status_t
707 Equation<QueryPolicy>::Match(Entry* entry, Node* node,
708 	const char* attributeName, int32 type, const uint8* key, size_t size)
709 {
710 	// get a pointer to the attribute in question
711 	NodeHolder nodeHolder;
712 	union value<QueryPolicy> value;
713 	uint8* buffer = (uint8*)&value;
714 	const size_t bufferSize = sizeof(value);
715 
716 	// first, check if we are matching for a live query and use that value
717 	if (attributeName != NULL && !strcmp(fAttribute, attributeName)) {
718 		if (key == NULL)
719 			return NO_MATCH;
720 		buffer = const_cast<uint8*>(key);
721 	} else if (!strcmp(fAttribute, "name")) {
722 		// if not, check for "fake" attributes ("name", "size", "last_modified")
723 		if (entry == NULL)
724 			return B_ERROR;
725 		buffer = (uint8*)QueryPolicy::EntryGetNameNoCopy(nodeHolder, entry);
726 		if (buffer == NULL)
727 			return B_ERROR;
728 
729 		type = B_STRING_TYPE;
730 		size = strlen((const char*)buffer);
731 	} else if (!strcmp(fAttribute, "size")) {
732 		value.Int64 = QueryPolicy::NodeGetSize(node);
733 		type = B_INT64_TYPE;
734 	} else if (!strcmp(fAttribute, "last_modified")) {
735 		value.Int64 = QueryPolicy::NodeGetLastModifiedTime(node);
736 		type = B_INT64_TYPE;
737 	} else {
738 		// then for attributes
739 		size = bufferSize;
740 		if (QueryPolicy::NodeGetAttribute(nodeHolder, node,
741 				fAttribute, buffer, &size, &type) != B_OK) {
742 			return NO_MATCH;
743 		}
744 	}
745 
746 	// prepare own value for use, if it is possible to convert it
747 	status_t status = ConvertValue(type);
748 	if (status == B_OK)
749 		status = CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
750 
751 	QUERY_RETURN_ERROR(status);
752 }
753 
754 
755 template<typename QueryPolicy>
756 void
757 Equation<QueryPolicy>::CalculateScore(Index &index)
758 {
759 	// As always, these values could be tuned and refined.
760 	// And the code could also need some real world testing :-)
761 
762 	// do we have to operate on a "foreign" index?
763 	if (Term<QueryPolicy>::fOp == OP_UNEQUAL
764 		|| QueryPolicy::IndexSetTo(index, fAttribute) < B_OK) {
765 		fScore = 0;
766 		return;
767 	}
768 
769 	// if we have a pattern, how much does it help our search?
770 	if (fIsPattern) {
771 		fScore = getFirstPatternSymbol(fString) << 3;
772 
773 		// Even if the first pattern symbol is at position 0,
774 		// there's still an index, so don't let our score revert to zero.
775 		if (fScore == 0)
776 			fScore = 1;
777 	} else {
778 		// Score by operator
779 		if (Term<QueryPolicy>::fOp == OP_EQUAL) {
780 			// higher than pattern="255 chars+*"
781 			fScore = 2048;
782 		} else {
783 			// the pattern search is regarded cheaper when you have at
784 			// least one character to set your index to
785 			fScore = 5;
786 		}
787 	}
788 
789 	// take index size into account
790 	fScore = QueryPolicy::IndexGetWeightedScore(index, fScore);
791 }
792 
793 
794 template<typename QueryPolicy>
795 status_t
796 Equation<QueryPolicy>::PrepareQuery(Context* /*context*/, Index& index,
797 	IndexIterator** iterator, bool queryNonIndexed)
798 {
799 	status_t status = QueryPolicy::IndexSetTo(index, fAttribute);
800 
801 	// if we should query attributes without an index, we can just proceed here
802 	if (status != B_OK && !queryNonIndexed)
803 		return B_ENTRY_NOT_FOUND;
804 
805 	type_code type;
806 
807 	// Special case for OP_UNEQUAL - it will always operate through the whole
808 	// index but we need the call to the original index to get the correct type
809 	if (status != B_OK || Term<QueryPolicy>::fOp == OP_UNEQUAL) {
810 		// Try to get an index that holds all files (name)
811 		// Also sets the default type for all attributes without index
812 		// to string.
813 		type = status < B_OK ? B_STRING_TYPE : QueryPolicy::IndexGetType(index);
814 
815 		if (QueryPolicy::IndexSetTo(index, "name") != B_OK)
816 			return B_ENTRY_NOT_FOUND;
817 
818 		fHasIndex = false;
819 	} else {
820 		fHasIndex = true;
821 		type = QueryPolicy::IndexGetType(index);
822 	}
823 
824 	if (ConvertValue(type) < B_OK)
825 		return B_BAD_VALUE;
826 
827 	*iterator = QueryPolicy::IndexCreateIterator(index);
828 	if (*iterator == NULL)
829 		return B_NO_MEMORY;
830 
831 	if ((Term<QueryPolicy>::fOp == OP_EQUAL
832 			|| Term<QueryPolicy>::fOp == OP_GREATER_THAN
833 			|| Term<QueryPolicy>::fOp == OP_GREATER_THAN_OR_EQUAL || fIsPattern)
834 		&& fHasIndex) {
835 		// set iterator to the exact position
836 
837 		int32 keySize = QueryPolicy::IndexGetKeySize(index);
838 
839 		// At this point, fIsPattern is only true if it's a string type, and fOp
840 		// is either OP_EQUAL or OP_UNEQUAL
841 		if (fIsPattern) {
842 			// let's see if we can use the beginning of the key for positioning
843 			// the iterator and adjust the key size; if not, just leave the
844 			// iterator at the start and return success
845 			keySize = getFirstPatternSymbol(fString);
846 			if (keySize <= 0)
847 				return B_OK;
848 		}
849 
850 		if (keySize == 0) {
851 			// B_STRING_TYPE doesn't have a fixed length, so it was set
852 			// to 0 before - we compute the correct value here
853 			if (fType == B_STRING_TYPE) {
854 				keySize = strlen(fValue.String);
855 
856 				// The empty string is a special case - we normally don't check
857 				// for the trailing null byte, in the case for the empty string
858 				// we do it explicitly, because there can't be keys in the
859 				// B+tree with a length of zero
860 				if (keySize == 0)
861 					keySize = 1;
862 			} else
863 				QUERY_RETURN_ERROR(B_ENTRY_NOT_FOUND);
864 		}
865 
866 		status = QueryPolicy::IndexIteratorFind(*iterator, Value(), keySize);
867 		if (Term<QueryPolicy>::fOp == OP_EQUAL && !fIsPattern)
868 			return status;
869 		else if (status == B_ENTRY_NOT_FOUND
870 			&& (fIsPattern || Term<QueryPolicy>::fOp == OP_GREATER_THAN
871 				|| Term<QueryPolicy>::fOp == OP_GREATER_THAN_OR_EQUAL))
872 			return B_OK;
873 
874 		QUERY_RETURN_ERROR(status);
875 	}
876 
877 	return B_OK;
878 }
879 
880 
881 template<typename QueryPolicy>
882 status_t
883 Equation<QueryPolicy>::GetNextMatching(Context* context,
884 	IndexIterator* iterator, struct dirent* dirent, size_t bufferSize)
885 {
886 	while (true) {
887 		NodeHolder nodeHolder;
888 		union value<QueryPolicy> indexValue;
889 		size_t keyLength;
890 		size_t duplicate = 0;
891 
892 		status_t status = QueryPolicy::IndexIteratorFetchNextEntry(iterator,
893 			&indexValue, &keyLength, (size_t)sizeof(indexValue), &duplicate);
894 		if (status != B_OK)
895 			return status;
896 
897 		// only compare against the index entry when this is the correct
898 		// index for the equation
899 		if (fHasIndex && duplicate < 2 && !CompareTo((uint8*)&indexValue, keyLength)) {
900 			// They aren't equal? Let the operation decide what to do. Since
901 			// we always start at the beginning of the index (or the correct
902 			// position), only some needs to be stopped if the entry doesn't
903 			// fit.
904 			if (Term<QueryPolicy>::fOp == OP_LESS_THAN
905 				|| Term<QueryPolicy>::fOp == OP_LESS_THAN_OR_EQUAL
906 				|| (Term<QueryPolicy>::fOp == OP_EQUAL && !fIsPattern))
907 				return B_ENTRY_NOT_FOUND;
908 
909 			if (duplicate > 0)
910 				QueryPolicy::IndexIteratorSkipDuplicates(iterator);
911 			continue;
912 		}
913 
914 		Entry* entry = NULL;
915 		status = QueryPolicy::IndexIteratorGetEntry(context, iterator,
916 			nodeHolder, &entry);
917 		if (status != B_OK) {
918 			// try with next
919 			continue;
920 		}
921 
922 		// TODO: check user permissions here - but which one?!
923 		// we could filter out all those where we don't have
924 		// read access... (we should check for every parent
925 		// directory if the X_OK is allowed)
926 		// Although it's quite expensive to open all parents,
927 		// it's likely that the application that runs the
928 		// query will do something similar (and we don't have
929 		// to do it for root, either).
930 
931 		// go up in the tree until a &&-operator is found, and check if the
932 		// node matches with the rest of the expression - we don't have to
933 		// check ||-operators for that
934 		Term<QueryPolicy>* term = this;
935 		status = MATCH_OK;
936 
937 		if (!fHasIndex)
938 			status = Match(entry, QueryPolicy::EntryGetNode(entry));
939 
940 		while (term != NULL && status == MATCH_OK) {
941 			Operator<QueryPolicy>* parent
942 				= (Operator<QueryPolicy>*)term->Parent();
943 			if (parent == NULL)
944 				break;
945 
946 			if (parent->Op() == OP_AND) {
947 				// choose the other child of the parent
948 				Term<QueryPolicy>* other = parent->Right();
949 				if (other == term)
950 					other = parent->Left();
951 
952 				if (other == NULL) {
953 					QUERY_FATAL("&&-operator has only one child... "
954 						"(parent = %p)\n", parent);
955 					break;
956 				}
957 				status = other->Match(entry, QueryPolicy::EntryGetNode(entry));
958 				if (status < 0) {
959 					QUERY_REPORT_ERROR(status);
960 					status = NO_MATCH;
961 				}
962 			}
963 			term = (Term<QueryPolicy>*)parent;
964 		}
965 
966 		if (status == MATCH_OK) {
967 			ssize_t nameLength = QueryPolicy::EntryGetName(entry,
968 				dirent->d_name,
969 				(const char*)dirent + bufferSize - dirent->d_name);
970 			if (nameLength < 0) {
971 				// Invalid or unknown name.
972 				nameLength = 0;
973 			}
974 
975 			dirent->d_dev = QueryPolicy::ContextGetVolumeID(context);
976 			dirent->d_ino = QueryPolicy::EntryGetNodeID(entry);
977 			dirent->d_pdev = dirent->d_dev;
978 			dirent->d_pino = QueryPolicy::EntryGetParentID(entry);
979 			dirent->d_reclen = offsetof(struct dirent, d_name) + nameLength;
980 		}
981 
982 		if (status == MATCH_OK)
983 			return B_OK;
984 	}
985 	QUERY_RETURN_ERROR(B_ERROR);
986 }
987 
988 
989 template<typename QueryPolicy>
990 bool
991 Equation<QueryPolicy>::NeedsEntry()
992 {
993 	return strcmp(fAttribute, "name") == 0;
994 }
995 
996 
997 //	#pragma mark -
998 
999 
1000 template<typename QueryPolicy>
1001 Operator<QueryPolicy>::Operator(Term<QueryPolicy>* left, int8 op,
1002 	Term<QueryPolicy>* right)
1003 	:
1004 	Term<QueryPolicy>(op),
1005 	fLeft(left),
1006 	fRight(right)
1007 {
1008 	if (left)
1009 		left->SetParent(this);
1010 	if (right)
1011 		right->SetParent(this);
1012 }
1013 
1014 
1015 template<typename QueryPolicy>
1016 Operator<QueryPolicy>::~Operator()
1017 {
1018 	delete fLeft;
1019 	delete fRight;
1020 }
1021 
1022 
1023 template<typename QueryPolicy>
1024 status_t
1025 Operator<QueryPolicy>::Match(Entry* entry, Node* node, const char* attribute,
1026 	int32 type, const uint8* key, size_t size)
1027 {
1028 	if (Term<QueryPolicy>::fOp == OP_AND) {
1029 		status_t status = fLeft->Match(entry, node, attribute, type, key,
1030 			size);
1031 		if (status != MATCH_OK)
1032 			return status;
1033 
1034 		return fRight->Match(entry, node, attribute, type, key, size);
1035 	} else {
1036 		// choose the term with the better score for OP_OR
1037 		Term<QueryPolicy>* first;
1038 		Term<QueryPolicy>* second;
1039 		if (fRight->Score() > fLeft->Score()) {
1040 			first = fLeft;
1041 			second = fRight;
1042 		} else {
1043 			first = fRight;
1044 			second = fLeft;
1045 		}
1046 
1047 		status_t status = first->Match(entry, node, attribute, type, key,
1048 			size);
1049 		if (status != NO_MATCH)
1050 			return status;
1051 
1052 		return second->Match(entry, node, attribute, type, key, size);
1053 	}
1054 }
1055 
1056 
1057 template<typename QueryPolicy>
1058 void
1059 Operator<QueryPolicy>::Complement()
1060 {
1061 	if (Term<QueryPolicy>::fOp == OP_AND)
1062 		Term<QueryPolicy>::fOp = OP_OR;
1063 	else
1064 		Term<QueryPolicy>::fOp = OP_AND;
1065 
1066 	fLeft->Complement();
1067 	fRight->Complement();
1068 }
1069 
1070 
1071 template<typename QueryPolicy>
1072 void
1073 Operator<QueryPolicy>::CalculateScore(Index &index)
1074 {
1075 	fLeft->CalculateScore(index);
1076 	fRight->CalculateScore(index);
1077 }
1078 
1079 
1080 template<typename QueryPolicy>
1081 int32
1082 Operator<QueryPolicy>::Score() const
1083 {
1084 	if (Term<QueryPolicy>::fOp == OP_AND) {
1085 		// return the one with the better score
1086 		if (fRight->Score() > fLeft->Score())
1087 			return fRight->Score();
1088 
1089 		return fLeft->Score();
1090 	}
1091 
1092 	// for OP_OR, be honest, and return the one with the worse score
1093 	if (fRight->Score() < fLeft->Score())
1094 		return fRight->Score();
1095 
1096 	return fLeft->Score();
1097 }
1098 
1099 
1100 template<typename QueryPolicy>
1101 status_t
1102 Operator<QueryPolicy>::InitCheck()
1103 {
1104 	if ((Term<QueryPolicy>::fOp != OP_AND && Term<QueryPolicy>::fOp != OP_OR)
1105 		|| fLeft == NULL || fLeft->InitCheck() < B_OK
1106 		|| fRight == NULL || fRight->InitCheck() < B_OK)
1107 		return B_ERROR;
1108 
1109 	return B_OK;
1110 }
1111 
1112 
1113 template<typename QueryPolicy>
1114 bool
1115 Operator<QueryPolicy>::NeedsEntry()
1116 {
1117 	return ((fLeft && fLeft->NeedsEntry()) || (fRight && fRight->NeedsEntry()));
1118 }
1119 
1120 
1121 //	#pragma mark -
1122 
1123 #ifdef DEBUG_QUERY
1124 
1125 template<typename QueryPolicy>
1126 void
1127 Operator<QueryPolicy>::PrintToStream()
1128 {
1129 	QUERY_D(__out("( "));
1130 	if (fLeft != NULL)
1131 		fLeft->PrintToStream();
1132 
1133 	const char* op;
1134 	switch (Term<QueryPolicy>::fOp) {
1135 		case OP_OR: op = "OR"; break;
1136 		case OP_AND: op = "AND"; break;
1137 		default: op = "?"; break;
1138 	}
1139 	QUERY_D(__out(" %s ", op));
1140 
1141 	if (fRight != NULL)
1142 		fRight->PrintToStream();
1143 
1144 	QUERY_D(__out(" )"));
1145 }
1146 
1147 
1148 template<typename QueryPolicy>
1149 void
1150 Equation<QueryPolicy>::PrintToStream()
1151 {
1152 	const char* symbol = "???";
1153 	switch (Term<QueryPolicy>::fOp) {
1154 		case OP_EQUAL: symbol = "=="; break;
1155 		case OP_UNEQUAL: symbol = "!="; break;
1156 		case OP_GREATER_THAN: symbol = ">"; break;
1157 		case OP_GREATER_THAN_OR_EQUAL: symbol = ">="; break;
1158 		case OP_LESS_THAN: symbol = "<"; break;
1159 		case OP_LESS_THAN_OR_EQUAL: symbol = "<="; break;
1160 	}
1161 	QUERY_D(__out("[\"%s\" %s \"%s\"]", fAttribute, symbol, fString));
1162 }
1163 
1164 #endif	// DEBUG_QUERY
1165 
1166 //	#pragma mark -
1167 
1168 
1169 template<typename QueryPolicy>
1170 Expression<QueryPolicy>::Expression()
1171 	:
1172 	fTerm(NULL)
1173 {
1174 }
1175 
1176 
1177 template<typename QueryPolicy>
1178 status_t
1179 Expression<QueryPolicy>::Init(const char* expr, const char** position)
1180 {
1181 	if (expr == NULL)
1182 		return B_BAD_VALUE;
1183 	if (fTerm != NULL)
1184 		return EALREADY;
1185 
1186 	status_t status = B_OK;
1187 	int32 equations = 0;
1188 	const int32 kMaxEquations = 32;
1189 
1190 	struct ExpressionNode {
1191 		Term<QueryPolicy>* term = NULL;
1192 		bool negated = false;
1193 		ops op = OP_NONE;
1194 	};
1195 	Stack<Stack<ExpressionNode>*> exprsTree;
1196 	Stack<ExpressionNode>* currentExpr = NULL;
1197 	ExpressionNode* current = NULL;
1198 	while (expr != NULL) {
1199 		skipWhitespace(&expr);
1200 
1201 		if (currentExpr == NULL) {
1202 			 currentExpr = new(std::nothrow) Stack<ExpressionNode>;
1203 			 if (currentExpr == NULL) {
1204 				 status = B_NO_MEMORY;
1205 				 break;
1206 			 }
1207 		}
1208 
1209 		const char c = *expr;
1210 		bool complete = false;
1211 
1212 		if (c == ')' || c == '\0') {
1213 			if (currentExpr->IsEmpty())
1214 				break; // Illegal empty expression.
1215 
1216 			complete = true;
1217 		}
1218 
1219 		if (current == NULL && !complete) {
1220 			currentExpr->Push(ExpressionNode());
1221 			current = currentExpr->Array() + (currentExpr->CountItems() - 1);
1222 		}
1223 
1224 		if (c == '(') {
1225 			exprsTree.Push(currentExpr);
1226 			currentExpr = NULL;
1227 			current = NULL;
1228 			expr++;
1229 		} else if (c == '!') {
1230 			skipWhitespace(&expr, 1);
1231 			if (*expr != '(')
1232 				break; // Not allowed.
1233 			current->negated = true;
1234 		} else if (c == '|' || c == '&') {
1235 			if (current->term == NULL)
1236 				break; // Nothing to operate on.
1237 
1238 			ops op = OP_NONE;
1239 			if (IsOperator(&expr, '|'))
1240 				op = OP_OR;
1241 			else if (IsOperator(&expr, '&'))
1242 				op = OP_AND;
1243 			else
1244 				break; // Illegal operator.
1245 
1246 			current->op = op;
1247 			current = NULL;
1248 		} else if (!complete) {
1249 			if (current->term != NULL)
1250 				break; // There already is a term.
1251 			if ((equations + 1) > kMaxEquations) {
1252 				status = E2BIG;
1253 				break;
1254 			}
1255 
1256 			Equation<QueryPolicy>* equation
1257 				= new(std::nothrow) Equation<QueryPolicy>(&expr);
1258 			if (equation == NULL) {
1259 				status = B_NO_MEMORY;
1260 				break;
1261 			}
1262 			if (equation == NULL || equation->InitCheck() != B_OK) {
1263 				status = equation->InitCheck();
1264 				delete equation;
1265 				break;
1266 			}
1267 
1268 			current->term = equation;
1269 			equations++;
1270 		}
1271 		if (!complete)
1272 			continue;
1273 
1274 		if (currentExpr->CountItems() == 1) {
1275 			if (current == NULL)
1276 				break; // Probably an anomalous operator.
1277 		}
1278 
1279 		// First pass: negation.
1280 		for (int32 i = 0; i < currentExpr->CountItems(); i++) {
1281 			current = currentExpr->Array() + i;
1282 			// If the term is negated, we just complement the tree, to get
1283 			// rid of the not, a.k.a. DeMorgan's Law.
1284 			if (current->negated) {
1285 				current->term->Complement();
1286 				current->negated = false;
1287 			}
1288 		}
1289 		// Second & third passes: && and ||.
1290 		int32 nodes = currentExpr->CountItems();
1291 		for (ops op = OP_AND; op <= OP_OR; op = (ops)(op + 1)) {
1292 			for (int32 i = 0; i < (currentExpr->CountItems() - 1); ) {
1293 				ExpressionNode* left = currentExpr->Array() + i;
1294 				if (left->op != op) {
1295 					i++;
1296 					continue;
1297 				}
1298 
1299 				// Find the right-hand expression (may have to jump over now-unused nodes.)
1300 				ExpressionNode* right = NULL;
1301 				for (int32 j = i + 1; j < currentExpr->CountItems(); j++) {
1302 					current = currentExpr->Array() + j;
1303 					if (current->term == NULL)
1304 						continue;
1305 
1306 					right = current;
1307 					break;
1308 				}
1309 				if (right == NULL)
1310 					break; // Invalid expression, somehow.
1311 
1312 				Term<QueryPolicy>* newTerm = new(std::nothrow) Operator<QueryPolicy>(
1313 					left->term, left->op, right->term);
1314 				if (newTerm == NULL) {
1315 					status = B_NO_MEMORY;
1316 					break;
1317 				}
1318 
1319 				left->term = newTerm;
1320 				left->op = right->op;
1321 				right->op = OP_NONE;
1322 				right->term = NULL;
1323 				nodes--;
1324 			}
1325 		}
1326 
1327 		// At this point we should have only one node left.
1328 		if (nodes != 1)
1329 			break;
1330 
1331 		current = currentExpr->Array();
1332 		Term<QueryPolicy>* term = current->term;
1333 
1334 		delete currentExpr;
1335 		currentExpr = NULL;
1336 		if (exprsTree.Pop(&currentExpr)) {
1337 			current = currentExpr->Array() + (currentExpr->CountItems() - 1);
1338 			if (current->term != NULL)
1339 				break; // There already is a term.
1340 			current->term = term;
1341 		} else {
1342 			if (c != '\0')
1343 				break; // Unexpected end of expression.
1344 
1345 			fTerm = term;
1346 			break;
1347 		}
1348 
1349 		expr++;
1350 	}
1351 
1352 	if (position != NULL)
1353 		*position = expr;
1354 
1355 	do {
1356 		if (currentExpr == NULL)
1357 			continue;
1358 
1359 		ExpressionNode item;
1360 		while (currentExpr->Pop(&item))
1361 			delete item.term;
1362 		delete currentExpr;
1363 	} while (exprsTree.Pop(&currentExpr));
1364 
1365 	if (fTerm == NULL && status == B_OK)
1366 		return B_BAD_VALUE;
1367 
1368 	QUERY_D(if (fTerm != NULL) {
1369 		fTerm->PrintToStream();
1370 		QUERY_D(__out("\n"));
1371 		if (*expr != '\0')
1372 			PRINT(("Unexpected end of string: \"%s\"!\n", expr));
1373 	});
1374 
1375 	return status;
1376 }
1377 
1378 
1379 template<typename QueryPolicy>
1380 Expression<QueryPolicy>::~Expression()
1381 {
1382 	delete fTerm;
1383 }
1384 
1385 
1386 template<typename QueryPolicy>
1387 bool
1388 Expression<QueryPolicy>::IsOperator(const char** expr, char op)
1389 {
1390 	const char* string = *expr;
1391 
1392 	if (*string == op && *(string + 1) == op) {
1393 		*expr += 2;
1394 		return true;
1395 	}
1396 	return false;
1397 }
1398 
1399 
1400 //	#pragma mark -
1401 
1402 
1403 template<typename QueryPolicy>
1404 Query<QueryPolicy>::Query(Context* context, Expression<QueryPolicy>* expression,
1405 	uint32 flags, port_id port, uint32 token)
1406 	:
1407 	fContext(context),
1408 	fExpression(expression),
1409 	fCurrent(NULL),
1410 	fIterator(NULL),
1411 	fIndex(context),
1412 	fFlags(flags),
1413 	fPort(port),
1414 	fToken(token),
1415 	fNeedsEntry(false)
1416 {
1417 	// If the expression has a valid root pointer, the whole tree has
1418 	// already passed the sanity check, so that we don't have to check
1419 	// every pointer
1420 	if (context == NULL || expression == NULL || expression->Root() == NULL)
1421 		return;
1422 
1423 	// create index on the stack and delete it afterwards
1424 	fExpression->Root()->CalculateScore(fIndex);
1425 	QueryPolicy::IndexUnset(fIndex);
1426 
1427 	fNeedsEntry = fExpression->Root()->NeedsEntry();
1428 
1429 	Rewind();
1430 }
1431 
1432 
1433 template<typename QueryPolicy>
1434 Query<QueryPolicy>::~Query()
1435 {
1436 	delete fExpression;
1437 }
1438 
1439 
1440 template<typename QueryPolicy>
1441 /*static*/ status_t
1442 Query<QueryPolicy>::Create(Context* context, const char* queryString,
1443 	uint32 flags, port_id port, uint32 token, Query<QueryPolicy>*& _query)
1444 {
1445 	Expression<QueryPolicy>* expression
1446 		= new(std::nothrow) Expression<QueryPolicy>;
1447 	if (expression == NULL)
1448 		QUERY_RETURN_ERROR(B_NO_MEMORY);
1449 
1450 	const char* position = NULL;
1451 	status_t status = expression->Init(queryString, &position);
1452 	if (status != B_OK) {
1453 		QUERY_INFORM("Could not parse query \"%s\", stopped at: \"%s\"\n",
1454 			queryString, position);
1455 
1456 		delete expression;
1457 		QUERY_RETURN_ERROR(status);
1458 	}
1459 
1460 	Query<QueryPolicy>* query = new(std::nothrow) Query<QueryPolicy>(context,
1461 		expression, flags, port, token);
1462 	if (query == NULL) {
1463 		delete expression;
1464 		QUERY_RETURN_ERROR(B_NO_MEMORY);
1465 	}
1466 
1467 	_query = query;
1468 	return B_OK;
1469 }
1470 
1471 
1472 template<typename QueryPolicy>
1473 status_t
1474 Query<QueryPolicy>::Rewind()
1475 {
1476 	// free previous stuff
1477 
1478 	fStack.MakeEmpty();
1479 
1480 	QueryPolicy::IndexIteratorDelete(fIterator);
1481 	fIterator = NULL;
1482 	fCurrent = NULL;
1483 
1484 	// put the whole expression on the stack
1485 
1486 	Stack<Term<QueryPolicy>*> stack;
1487 	stack.Push(fExpression->Root());
1488 
1489 	Term<QueryPolicy>* term;
1490 	while (stack.Pop(&term)) {
1491 		if (term->Op() < OP_EQUATION) {
1492 			Operator<QueryPolicy>* op = (Operator<QueryPolicy>*)term;
1493 
1494 			if (op->Op() == OP_OR) {
1495 				stack.Push(op->Left());
1496 				stack.Push(op->Right());
1497 			} else {
1498 				// For OP_AND, we can use the scoring system to decide which
1499 				// path to add
1500 				if (op->Right()->Score() > op->Left()->Score())
1501 					stack.Push(op->Right());
1502 				else
1503 					stack.Push(op->Left());
1504 			}
1505 		} else if (term->Op() == OP_EQUATION
1506 			|| fStack.Push((Equation<QueryPolicy>*)term) != B_OK)
1507 			QUERY_FATAL("Unknown term on stack or stack error\n");
1508 	}
1509 
1510 	return B_OK;
1511 }
1512 
1513 
1514 template<typename QueryPolicy>
1515 status_t
1516 Query<QueryPolicy>::GetNextEntry(struct dirent* dirent, size_t size)
1517 {
1518 	if (fIterator != NULL)
1519 		QueryPolicy::IndexIteratorResume(fIterator);
1520 
1521 	status_t error = _GetNextEntry(dirent, size);
1522 
1523 	if (fIterator != NULL)
1524 		QueryPolicy::IndexIteratorSuspend(fIterator);
1525 
1526 	return error;
1527 }
1528 
1529 
1530 template<typename QueryPolicy>
1531 void
1532 Query<QueryPolicy>::LiveUpdate(Entry* entry, Node* node, const char* attribute,
1533 	int32 type, const uint8* oldKey, size_t oldLength, const uint8* newKey,
1534 	size_t newLength)
1535 {
1536 	if (fPort < 0 || fExpression == NULL || attribute == NULL)
1537 		return;
1538 
1539 	// TODO: check if the attribute is part of the query at all...
1540 
1541 	// If no entry has been supplied, but the we need one for the evaluation
1542 	// (i.e. the "name" attribute is used), we invoke ourselves for all entries
1543 	// referring to the given node.
1544 	if (entry == NULL && fNeedsEntry) {
1545 		entry = QueryPolicy::NodeGetFirstReferrer(node);
1546 		while (entry) {
1547 			LiveUpdate(entry, node, attribute, type, oldKey, oldLength, newKey,
1548 				newLength);
1549 			entry = QueryPolicy::NodeGetNextReferrer(node, entry);
1550 		}
1551 		return;
1552 	}
1553 
1554 	status_t oldStatus = fExpression->Root()->Match(entry, node, attribute,
1555 		type, oldKey, oldLength);
1556 	status_t newStatus = fExpression->Root()->Match(entry, node, attribute,
1557 		type, newKey, newLength);
1558 
1559 	bool entryCreated = false;
1560 	bool stillInQuery = false;
1561 
1562 	if (oldStatus != MATCH_OK) {
1563 		if (newStatus != MATCH_OK) {
1564 			// nothing has changed
1565 			return;
1566 		}
1567 		entryCreated = true;
1568 	} else if (newStatus != MATCH_OK) {
1569 		// entry got removed
1570 		entryCreated = false;
1571 	} else if ((fFlags & B_ATTR_CHANGE_NOTIFICATION) != 0) {
1572 		// The entry stays in the query
1573 		stillInQuery = true;
1574 	} else
1575 		return;
1576 
1577 	// notify query listeners
1578 	status_t (*notify)(port_id, int32, dev_t, ino_t, const char*, ino_t);
1579 
1580 	if (stillInQuery)
1581 		notify = notify_query_attr_changed;
1582 	else if (entryCreated)
1583 		notify = notify_query_entry_created;
1584 	else
1585 		notify = notify_query_entry_removed;
1586 
1587 	if (entry != NULL) {
1588 		_SendEntryNotification(entry, notify);
1589 	} else {
1590 		entry = QueryPolicy::NodeGetFirstReferrer(node);
1591 		while (entry) {
1592 			_SendEntryNotification(entry, notify);
1593 			entry = QueryPolicy::NodeGetNextReferrer(node, entry);
1594 		}
1595 	}
1596 }
1597 
1598 
1599 template<typename QueryPolicy>
1600 void
1601 Query<QueryPolicy>::LiveUpdateRenameMove(Entry* entry, Node* node,
1602 	ino_t oldDirectoryID, const char* oldName, size_t oldLength,
1603 	ino_t newDirectoryID, const char* newName, size_t newLength)
1604 {
1605 	if (fPort < 0 || fExpression == NULL)
1606 		return;
1607 
1608 	// TODO: check if the attribute is part of the query at all...
1609 
1610 	status_t oldStatus = fExpression->Root()->Match(entry, node, "name",
1611 		B_STRING_TYPE, (const uint8*)oldName, oldLength);
1612 	status_t newStatus = fExpression->Root()->Match(entry, node, "name",
1613 		B_STRING_TYPE, (const uint8*)newName, newLength);
1614 
1615 	if (oldStatus != MATCH_OK || oldStatus != newStatus)
1616 		return;
1617 
1618 	// The entry stays in the query, notify query listeners about the rename
1619 	// or move
1620 
1621 	// We send a notification for the given entry, if any, or otherwise for
1622 	// all entries referring to the node;
1623 	if (entry != NULL) {
1624 		_SendEntryNotification(entry, notify_query_entry_removed);
1625 		_SendEntryNotification(entry, notify_query_entry_created);
1626 	} else {
1627 		entry = QueryPolicy::NodeGetFirstReferrer(node);
1628 		while (entry) {
1629 			_SendEntryNotification(entry, notify_query_entry_removed);
1630 			_SendEntryNotification(entry, notify_query_entry_created);
1631 			entry = QueryPolicy::NodeGetNextReferrer(node, entry);
1632 		}
1633 	}
1634 }
1635 
1636 
1637 template<typename QueryPolicy>
1638 status_t
1639 Query<QueryPolicy>::_GetNextEntry(struct dirent* dirent, size_t size)
1640 {
1641 	// If we don't have an equation to use yet/anymore, get a new one
1642 	// from the stack
1643 	while (true) {
1644 		if (fIterator == NULL) {
1645 			if (!fStack.Pop(&fCurrent)
1646 				|| fCurrent == NULL)
1647 				return B_ENTRY_NOT_FOUND;
1648 
1649 			status_t status = fCurrent->PrepareQuery(fContext, fIndex,
1650 				&fIterator, fFlags & B_QUERY_NON_INDEXED);
1651 			if (status == B_ENTRY_NOT_FOUND) {
1652 				// try next equation
1653 				continue;
1654 			}
1655 
1656 			if (status != B_OK)
1657 				return status;
1658 		}
1659 		if (fCurrent == NULL)
1660 			QUERY_RETURN_ERROR(B_ERROR);
1661 
1662 		status_t status = fCurrent->GetNextMatching(fContext, fIterator, dirent,
1663 			size);
1664 		if (status != B_OK) {
1665 			QueryPolicy::IndexIteratorDelete(fIterator);
1666 			fIterator = NULL;
1667 			fCurrent = NULL;
1668 		} else {
1669 			// only return if we have another entry
1670 			return B_OK;
1671 		}
1672 	}
1673 }
1674 
1675 
1676 template<typename QueryPolicy>
1677 void
1678 Query<QueryPolicy>::_SendEntryNotification(Entry* entry,
1679 	status_t (*notify)(port_id, int32, dev_t, ino_t, const char*, ino_t))
1680 {
1681 	NodeHolder nodeHolder;
1682 	const char* name = QueryPolicy::EntryGetNameNoCopy(nodeHolder, entry);
1683 	if (name != NULL) {
1684 		notify(fPort, fToken, QueryPolicy::ContextGetVolumeID(fContext),
1685 			QueryPolicy::EntryGetParentID(entry), name,
1686 			QueryPolicy::EntryGetNodeID(entry));
1687 	}
1688 }
1689 
1690 
1691 }	// namespace QueryParser
1692 
1693 
1694 #endif	// _FILE_SYSTEMS_QUERY_PARSER_H
1695