xref: /haiku/headers/private/file_systems/QueryParser.h (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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_FATAL("query value conversion to 0x%x requested!\n",
634 				(int)type);
635 			// should we fail here or just do a safety int32 conversion?
636 			return B_ERROR;
637 	}
638 
639 	fType = type;
640 
641 	// patterns are only allowed for string types
642 	if (fType != B_STRING_TYPE && fIsPattern)
643 		fIsPattern = false;
644 
645 	return B_OK;
646 }
647 
648 
649 /*!	Returns true when the key matches the equation. You have to
650 	call ConvertValue() before this one.
651 */
652 template<typename QueryPolicy>
653 bool
654 Equation<QueryPolicy>::CompareTo(const uint8* value, size_t size)
655 {
656 	int32 compare;
657 
658 	// fIsPattern is only true if it's a string type, and fOp OP_EQUAL, or
659 	// OP_UNEQUAL
660 	if (fIsPattern) {
661 		// we have already validated the pattern, so we don't check for failing
662 		// here - if something is broken, and matchString() returns an error,
663 		// we just don't match
664 		compare = matchString(fValue.String, (const char*)value) == MATCH_OK ? 0 : 1;
665 	} else
666 		compare = compareKeys(fType, value, size, Value(), fSize);
667 
668 	switch (Term<QueryPolicy>::fOp) {
669 		case OP_EQUAL:
670 			return compare == 0;
671 		case OP_UNEQUAL:
672 			return compare != 0;
673 		case OP_LESS_THAN:
674 			return compare < 0;
675 		case OP_LESS_THAN_OR_EQUAL:
676 			return compare <= 0;
677 		case OP_GREATER_THAN:
678 			return compare > 0;
679 		case OP_GREATER_THAN_OR_EQUAL:
680 			return compare >= 0;
681 	}
682 	QUERY_FATAL("Unknown/Unsupported operation: %d\n", Term<QueryPolicy>::fOp);
683 	return false;
684 }
685 
686 
687 template<typename QueryPolicy>
688 void
689 Equation<QueryPolicy>::Complement()
690 {
691 	QUERY_D(if (Term<QueryPolicy>::fOp <= OP_EQUATION || Term<QueryPolicy>::fOp > OP_LESS_THAN_OR_EQUAL) {
692 		QUERY_FATAL("op out of range!\n");
693 		return;
694 	});
695 
696 	int8 complementOp[] = {OP_UNEQUAL, OP_EQUAL, OP_LESS_THAN_OR_EQUAL,
697 			OP_GREATER_THAN_OR_EQUAL, OP_LESS_THAN, OP_GREATER_THAN};
698 	Term<QueryPolicy>::fOp = complementOp[Term<QueryPolicy>::fOp - OP_EQUAL];
699 }
700 
701 
702 /*!	Matches the node's attribute value with the equation.
703 	Returns MATCH_OK if it matches, NO_MATCH if not, < 0 if something went
704 	wrong.
705 */
706 template<typename QueryPolicy>
707 status_t
708 Equation<QueryPolicy>::Match(Entry* entry, Node* node,
709 	const char* attributeName, int32 type, const uint8* key, size_t size)
710 {
711 	// get a pointer to the attribute in question
712 	NodeHolder nodeHolder;
713 	union value<QueryPolicy> value;
714 	uint8* buffer = (uint8*)&value;
715 	const size_t bufferSize = sizeof(value);
716 
717 	// first, check if we are matching for a live query and use that value
718 	if (attributeName != NULL && !strcmp(fAttribute, attributeName)) {
719 		if (key == NULL)
720 			return NO_MATCH;
721 		buffer = const_cast<uint8*>(key);
722 	} else if (!strcmp(fAttribute, "name")) {
723 		// if not, check for "fake" attributes ("name", "size", "last_modified")
724 		if (entry == NULL)
725 			return B_ERROR;
726 		buffer = (uint8*)QueryPolicy::EntryGetNameNoCopy(nodeHolder, entry);
727 		if (buffer == NULL)
728 			return B_ERROR;
729 
730 		type = B_STRING_TYPE;
731 		size = strlen((const char*)buffer);
732 	} else if (!strcmp(fAttribute, "size")) {
733 		value.Int64 = QueryPolicy::NodeGetSize(node);
734 		type = B_INT64_TYPE;
735 	} else if (!strcmp(fAttribute, "last_modified")) {
736 		value.Int64 = QueryPolicy::NodeGetLastModifiedTime(node);
737 		type = B_INT64_TYPE;
738 	} else {
739 		// then for attributes
740 		size = bufferSize;
741 		if (QueryPolicy::NodeGetAttribute(nodeHolder, node,
742 				fAttribute, buffer, &size, &type) != B_OK) {
743 			return NO_MATCH;
744 		}
745 	}
746 
747 	// prepare own value for use, if it is possible to convert it
748 	status_t status = ConvertValue(type);
749 	if (status == B_OK)
750 		status = CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
751 
752 	QUERY_RETURN_ERROR(status);
753 }
754 
755 
756 template<typename QueryPolicy>
757 void
758 Equation<QueryPolicy>::CalculateScore(Index &index)
759 {
760 	// As always, these values could be tuned and refined.
761 	// And the code could also need some real world testing :-)
762 
763 	// do we have to operate on a "foreign" index?
764 	if (Term<QueryPolicy>::fOp == OP_UNEQUAL
765 		|| QueryPolicy::IndexSetTo(index, fAttribute) < B_OK) {
766 		fScore = 0;
767 		return;
768 	}
769 
770 	// if we have a pattern, how much does it help our search?
771 	if (fIsPattern) {
772 		fScore = getFirstPatternSymbol(fString) << 3;
773 
774 		// Even if the first pattern symbol is at position 0,
775 		// there's still an index, so don't let our score revert to zero.
776 		if (fScore == 0)
777 			fScore = 1;
778 	} else {
779 		// Score by operator
780 		if (Term<QueryPolicy>::fOp == OP_EQUAL) {
781 			// higher than pattern="255 chars+*"
782 			fScore = 2048;
783 		} else {
784 			// the pattern search is regarded cheaper when you have at
785 			// least one character to set your index to
786 			fScore = 5;
787 		}
788 	}
789 
790 	// take index size into account
791 	fScore = QueryPolicy::IndexGetWeightedScore(index, fScore);
792 }
793 
794 
795 template<typename QueryPolicy>
796 status_t
797 Equation<QueryPolicy>::PrepareQuery(Context* /*context*/, Index& index,
798 	IndexIterator** iterator, bool queryNonIndexed)
799 {
800 	status_t status = QueryPolicy::IndexSetTo(index, fAttribute);
801 
802 	// if we should query attributes without an index, we can just proceed here
803 	if (status != B_OK && !queryNonIndexed)
804 		return B_ENTRY_NOT_FOUND;
805 
806 	type_code type;
807 
808 	// Special case for OP_UNEQUAL - it will always operate through the whole
809 	// index but we need the call to the original index to get the correct type
810 	if (status != B_OK || Term<QueryPolicy>::fOp == OP_UNEQUAL) {
811 		// Try to get an index that holds all files (name)
812 		// Also sets the default type for all attributes without index
813 		// to string.
814 		type = status < B_OK ? B_STRING_TYPE : QueryPolicy::IndexGetType(index);
815 
816 		if (QueryPolicy::IndexSetTo(index, "name") != B_OK)
817 			return B_ENTRY_NOT_FOUND;
818 
819 		fHasIndex = false;
820 	} else {
821 		fHasIndex = true;
822 		type = QueryPolicy::IndexGetType(index);
823 	}
824 
825 	if (ConvertValue(type) < B_OK)
826 		return B_BAD_VALUE;
827 
828 	*iterator = QueryPolicy::IndexCreateIterator(index);
829 	if (*iterator == NULL)
830 		return B_NO_MEMORY;
831 
832 	if ((Term<QueryPolicy>::fOp == OP_EQUAL
833 			|| Term<QueryPolicy>::fOp == OP_GREATER_THAN
834 			|| Term<QueryPolicy>::fOp == OP_GREATER_THAN_OR_EQUAL || fIsPattern)
835 		&& fHasIndex) {
836 		// set iterator to the exact position
837 
838 		int32 keySize = QueryPolicy::IndexGetKeySize(index);
839 
840 		// At this point, fIsPattern is only true if it's a string type, and fOp
841 		// is either OP_EQUAL or OP_UNEQUAL
842 		if (fIsPattern) {
843 			// let's see if we can use the beginning of the key for positioning
844 			// the iterator and adjust the key size; if not, just leave the
845 			// iterator at the start and return success
846 			keySize = getFirstPatternSymbol(fString);
847 			if (keySize <= 0)
848 				return B_OK;
849 		}
850 
851 		if (keySize == 0) {
852 			// B_STRING_TYPE doesn't have a fixed length, so it was set
853 			// to 0 before - we compute the correct value here
854 			if (fType == B_STRING_TYPE) {
855 				keySize = strlen(fValue.String);
856 
857 				// The empty string is a special case - we normally don't check
858 				// for the trailing null byte, in the case for the empty string
859 				// we do it explicitly, because there can't be keys in the
860 				// B+tree with a length of zero
861 				if (keySize == 0)
862 					keySize = 1;
863 			} else
864 				QUERY_RETURN_ERROR(B_ENTRY_NOT_FOUND);
865 		}
866 
867 		status = QueryPolicy::IndexIteratorFind(*iterator, Value(), keySize);
868 		if (Term<QueryPolicy>::fOp == OP_EQUAL && !fIsPattern)
869 			return status;
870 		else if (status == B_ENTRY_NOT_FOUND
871 			&& (fIsPattern || Term<QueryPolicy>::fOp == OP_GREATER_THAN
872 				|| Term<QueryPolicy>::fOp == OP_GREATER_THAN_OR_EQUAL))
873 			return B_OK;
874 
875 		QUERY_RETURN_ERROR(status);
876 	}
877 
878 	return B_OK;
879 }
880 
881 
882 template<typename QueryPolicy>
883 status_t
884 Equation<QueryPolicy>::GetNextMatching(Context* context,
885 	IndexIterator* iterator, struct dirent* dirent, size_t bufferSize)
886 {
887 	while (true) {
888 		NodeHolder nodeHolder;
889 		union value<QueryPolicy> indexValue;
890 		size_t keyLength;
891 		size_t duplicate = 0;
892 
893 		status_t status = QueryPolicy::IndexIteratorFetchNextEntry(iterator,
894 			&indexValue, &keyLength, (size_t)sizeof(indexValue), &duplicate);
895 		if (status != B_OK)
896 			return status;
897 
898 		// only compare against the index entry when this is the correct
899 		// index for the equation
900 		if (fHasIndex && duplicate < 2 && !CompareTo((uint8*)&indexValue, keyLength)) {
901 			// They aren't equal? Let the operation decide what to do. Since
902 			// we always start at the beginning of the index (or the correct
903 			// position), only some needs to be stopped if the entry doesn't
904 			// fit.
905 			if (Term<QueryPolicy>::fOp == OP_LESS_THAN
906 				|| Term<QueryPolicy>::fOp == OP_LESS_THAN_OR_EQUAL
907 				|| (Term<QueryPolicy>::fOp == OP_EQUAL && !fIsPattern))
908 				return B_ENTRY_NOT_FOUND;
909 
910 			if (duplicate > 0)
911 				QueryPolicy::IndexIteratorSkipDuplicates(iterator);
912 			continue;
913 		}
914 
915 		Entry* entry = NULL;
916 		status = QueryPolicy::IndexIteratorGetEntry(context, iterator,
917 			nodeHolder, &entry);
918 		if (status != B_OK) {
919 			// try with next
920 			continue;
921 		}
922 
923 		// TODO: check user permissions here - but which one?!
924 		// we could filter out all those where we don't have
925 		// read access... (we should check for every parent
926 		// directory if the X_OK is allowed)
927 		// Although it's quite expensive to open all parents,
928 		// it's likely that the application that runs the
929 		// query will do something similar (and we don't have
930 		// to do it for root, either).
931 
932 		// go up in the tree until a &&-operator is found, and check if the
933 		// node matches with the rest of the expression - we don't have to
934 		// check ||-operators for that
935 		Term<QueryPolicy>* term = this;
936 		status = MATCH_OK;
937 
938 		if (!fHasIndex)
939 			status = Match(entry, QueryPolicy::EntryGetNode(entry));
940 
941 		while (term != NULL && status == MATCH_OK) {
942 			Operator<QueryPolicy>* parent
943 				= (Operator<QueryPolicy>*)term->Parent();
944 			if (parent == NULL)
945 				break;
946 
947 			if (parent->Op() == OP_AND) {
948 				// choose the other child of the parent
949 				Term<QueryPolicy>* other = parent->Right();
950 				if (other == term)
951 					other = parent->Left();
952 
953 				if (other == NULL) {
954 					QUERY_FATAL("&&-operator has only one child... "
955 						"(parent = %p)\n", parent);
956 					break;
957 				}
958 				status = other->Match(entry, QueryPolicy::EntryGetNode(entry));
959 				if (status < 0) {
960 					QUERY_REPORT_ERROR(status);
961 					status = NO_MATCH;
962 				}
963 			}
964 			term = (Term<QueryPolicy>*)parent;
965 		}
966 
967 		if (status == MATCH_OK) {
968 			ssize_t nameLength = QueryPolicy::EntryGetName(entry,
969 				dirent->d_name,
970 				(const char*)dirent + bufferSize - dirent->d_name);
971 			if (nameLength < 0) {
972 				// Invalid or unknown name.
973 				nameLength = 0;
974 			}
975 
976 			dirent->d_dev = QueryPolicy::ContextGetVolumeID(context);
977 			dirent->d_ino = QueryPolicy::EntryGetNodeID(entry);
978 			dirent->d_pdev = dirent->d_dev;
979 			dirent->d_pino = QueryPolicy::EntryGetParentID(entry);
980 			dirent->d_reclen = offsetof(struct dirent, d_name) + nameLength;
981 		}
982 
983 		if (status == MATCH_OK)
984 			return B_OK;
985 	}
986 	QUERY_RETURN_ERROR(B_ERROR);
987 }
988 
989 
990 template<typename QueryPolicy>
991 bool
992 Equation<QueryPolicy>::NeedsEntry()
993 {
994 	return strcmp(fAttribute, "name") == 0;
995 }
996 
997 
998 //	#pragma mark -
999 
1000 
1001 template<typename QueryPolicy>
1002 Operator<QueryPolicy>::Operator(Term<QueryPolicy>* left, int8 op,
1003 	Term<QueryPolicy>* right)
1004 	:
1005 	Term<QueryPolicy>(op),
1006 	fLeft(left),
1007 	fRight(right)
1008 {
1009 	if (left)
1010 		left->SetParent(this);
1011 	if (right)
1012 		right->SetParent(this);
1013 }
1014 
1015 
1016 template<typename QueryPolicy>
1017 Operator<QueryPolicy>::~Operator()
1018 {
1019 	delete fLeft;
1020 	delete fRight;
1021 }
1022 
1023 
1024 template<typename QueryPolicy>
1025 status_t
1026 Operator<QueryPolicy>::Match(Entry* entry, Node* node, const char* attribute,
1027 	int32 type, const uint8* key, size_t size)
1028 {
1029 	if (Term<QueryPolicy>::fOp == OP_AND) {
1030 		status_t status = fLeft->Match(entry, node, attribute, type, key,
1031 			size);
1032 		if (status != MATCH_OK)
1033 			return status;
1034 
1035 		return fRight->Match(entry, node, attribute, type, key, size);
1036 	} else {
1037 		// choose the term with the better score for OP_OR
1038 		Term<QueryPolicy>* first;
1039 		Term<QueryPolicy>* second;
1040 		if (fRight->Score() > fLeft->Score()) {
1041 			first = fLeft;
1042 			second = fRight;
1043 		} else {
1044 			first = fRight;
1045 			second = fLeft;
1046 		}
1047 
1048 		status_t status = first->Match(entry, node, attribute, type, key,
1049 			size);
1050 		if (status != NO_MATCH)
1051 			return status;
1052 
1053 		return second->Match(entry, node, attribute, type, key, size);
1054 	}
1055 }
1056 
1057 
1058 template<typename QueryPolicy>
1059 void
1060 Operator<QueryPolicy>::Complement()
1061 {
1062 	if (Term<QueryPolicy>::fOp == OP_AND)
1063 		Term<QueryPolicy>::fOp = OP_OR;
1064 	else
1065 		Term<QueryPolicy>::fOp = OP_AND;
1066 
1067 	fLeft->Complement();
1068 	fRight->Complement();
1069 }
1070 
1071 
1072 template<typename QueryPolicy>
1073 void
1074 Operator<QueryPolicy>::CalculateScore(Index &index)
1075 {
1076 	fLeft->CalculateScore(index);
1077 	fRight->CalculateScore(index);
1078 }
1079 
1080 
1081 template<typename QueryPolicy>
1082 int32
1083 Operator<QueryPolicy>::Score() const
1084 {
1085 	if (Term<QueryPolicy>::fOp == OP_AND) {
1086 		// return the one with the better score
1087 		if (fRight->Score() > fLeft->Score())
1088 			return fRight->Score();
1089 
1090 		return fLeft->Score();
1091 	}
1092 
1093 	// for OP_OR, be honest, and return the one with the worse score
1094 	if (fRight->Score() < fLeft->Score())
1095 		return fRight->Score();
1096 
1097 	return fLeft->Score();
1098 }
1099 
1100 
1101 template<typename QueryPolicy>
1102 status_t
1103 Operator<QueryPolicy>::InitCheck()
1104 {
1105 	if ((Term<QueryPolicy>::fOp != OP_AND && Term<QueryPolicy>::fOp != OP_OR)
1106 		|| fLeft == NULL || fLeft->InitCheck() < B_OK
1107 		|| fRight == NULL || fRight->InitCheck() < B_OK)
1108 		return B_ERROR;
1109 
1110 	return B_OK;
1111 }
1112 
1113 
1114 template<typename QueryPolicy>
1115 bool
1116 Operator<QueryPolicy>::NeedsEntry()
1117 {
1118 	return ((fLeft && fLeft->NeedsEntry()) || (fRight && fRight->NeedsEntry()));
1119 }
1120 
1121 
1122 //	#pragma mark -
1123 
1124 #ifdef DEBUG_QUERY
1125 
1126 template<typename QueryPolicy>
1127 void
1128 Operator<QueryPolicy>::PrintToStream()
1129 {
1130 	QUERY_D(__out("( "));
1131 	if (fLeft != NULL)
1132 		fLeft->PrintToStream();
1133 
1134 	const char* op;
1135 	switch (Term<QueryPolicy>::fOp) {
1136 		case OP_OR: op = "OR"; break;
1137 		case OP_AND: op = "AND"; break;
1138 		default: op = "?"; break;
1139 	}
1140 	QUERY_D(__out(" %s ", op));
1141 
1142 	if (fRight != NULL)
1143 		fRight->PrintToStream();
1144 
1145 	QUERY_D(__out(" )"));
1146 }
1147 
1148 
1149 template<typename QueryPolicy>
1150 void
1151 Equation<QueryPolicy>::PrintToStream()
1152 {
1153 	const char* symbol = "???";
1154 	switch (Term<QueryPolicy>::fOp) {
1155 		case OP_EQUAL: symbol = "=="; break;
1156 		case OP_UNEQUAL: symbol = "!="; break;
1157 		case OP_GREATER_THAN: symbol = ">"; break;
1158 		case OP_GREATER_THAN_OR_EQUAL: symbol = ">="; break;
1159 		case OP_LESS_THAN: symbol = "<"; break;
1160 		case OP_LESS_THAN_OR_EQUAL: symbol = "<="; break;
1161 	}
1162 	QUERY_D(__out("[\"%s\" %s \"%s\"]", fAttribute, symbol, fString));
1163 }
1164 
1165 #endif	// DEBUG_QUERY
1166 
1167 //	#pragma mark -
1168 
1169 
1170 template<typename QueryPolicy>
1171 Expression<QueryPolicy>::Expression()
1172 	:
1173 	fTerm(NULL)
1174 {
1175 }
1176 
1177 
1178 template<typename QueryPolicy>
1179 status_t
1180 Expression<QueryPolicy>::Init(const char* expr, const char** position)
1181 {
1182 	if (expr == NULL)
1183 		return B_BAD_VALUE;
1184 	if (fTerm != NULL)
1185 		return EALREADY;
1186 
1187 	status_t status = B_OK;
1188 	int32 equations = 0;
1189 	const int32 kMaxEquations = 32;
1190 
1191 	struct ExpressionNode {
1192 		Term<QueryPolicy>* term = NULL;
1193 		bool negated = false;
1194 		ops op = OP_NONE;
1195 	};
1196 	Stack<Stack<ExpressionNode>*> exprsTree;
1197 	Stack<ExpressionNode>* currentExpr = NULL;
1198 	ExpressionNode* current = NULL;
1199 	while (expr != NULL) {
1200 		skipWhitespace(&expr);
1201 
1202 		if (currentExpr == NULL) {
1203 			 currentExpr = new(std::nothrow) Stack<ExpressionNode>;
1204 			 if (currentExpr == NULL) {
1205 				 status = B_NO_MEMORY;
1206 				 break;
1207 			 }
1208 		}
1209 
1210 		const char c = *expr;
1211 		bool complete = false;
1212 
1213 		if (c == ')' || c == '\0') {
1214 			if (currentExpr->IsEmpty())
1215 				break; // Illegal empty expression.
1216 
1217 			complete = true;
1218 		}
1219 
1220 		if (current == NULL && !complete) {
1221 			currentExpr->Push(ExpressionNode());
1222 			current = currentExpr->Array() + (currentExpr->CountItems() - 1);
1223 		}
1224 
1225 		if (c == '(') {
1226 			exprsTree.Push(currentExpr);
1227 			currentExpr = NULL;
1228 			current = NULL;
1229 			expr++;
1230 		} else if (c == '!') {
1231 			skipWhitespace(&expr, 1);
1232 			if (*expr != '(')
1233 				break; // Not allowed.
1234 			current->negated = true;
1235 		} else if (c == '|' || c == '&') {
1236 			if (current->term == NULL)
1237 				break; // Nothing to operate on.
1238 
1239 			ops op = OP_NONE;
1240 			if (IsOperator(&expr, '|'))
1241 				op = OP_OR;
1242 			else if (IsOperator(&expr, '&'))
1243 				op = OP_AND;
1244 			else
1245 				break; // Illegal operator.
1246 
1247 			current->op = op;
1248 			current = NULL;
1249 		} else if (!complete) {
1250 			if (current->term != NULL)
1251 				break; // There already is a term.
1252 			if ((equations + 1) > kMaxEquations) {
1253 				status = E2BIG;
1254 				break;
1255 			}
1256 
1257 			Equation<QueryPolicy>* equation
1258 				= new(std::nothrow) Equation<QueryPolicy>(&expr);
1259 			if (equation == NULL) {
1260 				status = B_NO_MEMORY;
1261 				break;
1262 			}
1263 			if (equation == NULL || equation->InitCheck() != B_OK) {
1264 				status = equation->InitCheck();
1265 				delete equation;
1266 				break;
1267 			}
1268 
1269 			current->term = equation;
1270 			equations++;
1271 		}
1272 		if (!complete)
1273 			continue;
1274 
1275 		if (currentExpr->CountItems() == 1) {
1276 			if (current == NULL)
1277 				break; // Probably an anomalous operator.
1278 		}
1279 
1280 		// First pass: negation.
1281 		for (int32 i = 0; i < currentExpr->CountItems(); i++) {
1282 			current = currentExpr->Array() + i;
1283 			// If the term is negated, we just complement the tree, to get
1284 			// rid of the not, a.k.a. DeMorgan's Law.
1285 			if (current->negated) {
1286 				current->term->Complement();
1287 				current->negated = false;
1288 			}
1289 		}
1290 		// Second & third passes: && and ||.
1291 		int32 nodes = currentExpr->CountItems();
1292 		for (ops op = OP_AND; op <= OP_OR; op = (ops)(op + 1)) {
1293 			for (int32 i = 0; i < (currentExpr->CountItems() - 1); ) {
1294 				ExpressionNode* left = currentExpr->Array() + i;
1295 				if (left->op != op) {
1296 					i++;
1297 					continue;
1298 				}
1299 
1300 				// Find the right-hand expression (may have to jump over now-unused nodes.)
1301 				ExpressionNode* right = NULL;
1302 				for (int32 j = i + 1; j < currentExpr->CountItems(); j++) {
1303 					current = currentExpr->Array() + j;
1304 					if (current->term == NULL)
1305 						continue;
1306 
1307 					right = current;
1308 					break;
1309 				}
1310 				if (right == NULL)
1311 					break; // Invalid expression, somehow.
1312 
1313 				Term<QueryPolicy>* newTerm = new(std::nothrow) Operator<QueryPolicy>(
1314 					left->term, left->op, right->term);
1315 				if (newTerm == NULL) {
1316 					status = B_NO_MEMORY;
1317 					break;
1318 				}
1319 
1320 				left->term = newTerm;
1321 				left->op = right->op;
1322 				right->op = OP_NONE;
1323 				right->term = NULL;
1324 				nodes--;
1325 			}
1326 		}
1327 
1328 		// At this point we should have only one node left.
1329 		if (nodes != 1)
1330 			break;
1331 
1332 		current = currentExpr->Array();
1333 		Term<QueryPolicy>* term = current->term;
1334 
1335 		delete currentExpr;
1336 		currentExpr = NULL;
1337 		if (exprsTree.Pop(&currentExpr)) {
1338 			current = currentExpr->Array() + (currentExpr->CountItems() - 1);
1339 			if (current->term != NULL)
1340 				break; // There already is a term.
1341 			current->term = term;
1342 		} else {
1343 			if (c != '\0')
1344 				break; // Unexpected end of expression.
1345 
1346 			fTerm = term;
1347 			break;
1348 		}
1349 
1350 		expr++;
1351 	}
1352 
1353 	if (position != NULL)
1354 		*position = expr;
1355 
1356 	do {
1357 		if (currentExpr == NULL)
1358 			continue;
1359 
1360 		ExpressionNode item;
1361 		while (currentExpr->Pop(&item))
1362 			delete item.term;
1363 		delete currentExpr;
1364 	} while (exprsTree.Pop(&currentExpr));
1365 
1366 	if (fTerm == NULL && status == B_OK)
1367 		return B_BAD_VALUE;
1368 
1369 	QUERY_D(if (fTerm != NULL) {
1370 		fTerm->PrintToStream();
1371 		QUERY_D(__out("\n"));
1372 		if (*expr != '\0')
1373 			PRINT(("Unexpected end of string: \"%s\"!\n", expr));
1374 	});
1375 
1376 	return status;
1377 }
1378 
1379 
1380 template<typename QueryPolicy>
1381 Expression<QueryPolicy>::~Expression()
1382 {
1383 	delete fTerm;
1384 }
1385 
1386 
1387 template<typename QueryPolicy>
1388 bool
1389 Expression<QueryPolicy>::IsOperator(const char** expr, char op)
1390 {
1391 	const char* string = *expr;
1392 
1393 	if (*string == op && *(string + 1) == op) {
1394 		*expr += 2;
1395 		return true;
1396 	}
1397 	return false;
1398 }
1399 
1400 
1401 //	#pragma mark -
1402 
1403 
1404 template<typename QueryPolicy>
1405 Query<QueryPolicy>::Query(Context* context, Expression<QueryPolicy>* expression,
1406 	uint32 flags, port_id port, uint32 token)
1407 	:
1408 	fContext(context),
1409 	fExpression(expression),
1410 	fCurrent(NULL),
1411 	fIterator(NULL),
1412 	fIndex(context),
1413 	fFlags(flags),
1414 	fPort(port),
1415 	fToken(token),
1416 	fNeedsEntry(false)
1417 {
1418 	// If the expression has a valid root pointer, the whole tree has
1419 	// already passed the sanity check, so that we don't have to check
1420 	// every pointer
1421 	if (context == NULL || expression == NULL || expression->Root() == NULL)
1422 		return;
1423 
1424 	// create index on the stack and delete it afterwards
1425 	fExpression->Root()->CalculateScore(fIndex);
1426 	QueryPolicy::IndexUnset(fIndex);
1427 
1428 	fNeedsEntry = fExpression->Root()->NeedsEntry();
1429 
1430 	Rewind();
1431 }
1432 
1433 
1434 template<typename QueryPolicy>
1435 Query<QueryPolicy>::~Query()
1436 {
1437 	delete fExpression;
1438 }
1439 
1440 
1441 template<typename QueryPolicy>
1442 /*static*/ status_t
1443 Query<QueryPolicy>::Create(Context* context, const char* queryString,
1444 	uint32 flags, port_id port, uint32 token, Query<QueryPolicy>*& _query)
1445 {
1446 	Expression<QueryPolicy>* expression
1447 		= new(std::nothrow) Expression<QueryPolicy>;
1448 	if (expression == NULL)
1449 		QUERY_RETURN_ERROR(B_NO_MEMORY);
1450 
1451 	const char* position = NULL;
1452 	status_t status = expression->Init(queryString, &position);
1453 	if (status != B_OK) {
1454 		QUERY_INFORM("Could not parse query \"%s\", stopped at: \"%s\"\n",
1455 			queryString, position);
1456 
1457 		delete expression;
1458 		QUERY_RETURN_ERROR(status);
1459 	}
1460 
1461 	Query<QueryPolicy>* query = new(std::nothrow) Query<QueryPolicy>(context,
1462 		expression, flags, port, token);
1463 	if (query == NULL) {
1464 		delete expression;
1465 		QUERY_RETURN_ERROR(B_NO_MEMORY);
1466 	}
1467 
1468 	_query = query;
1469 	return B_OK;
1470 }
1471 
1472 
1473 template<typename QueryPolicy>
1474 status_t
1475 Query<QueryPolicy>::Rewind()
1476 {
1477 	// free previous stuff
1478 
1479 	fStack.MakeEmpty();
1480 
1481 	QueryPolicy::IndexIteratorDelete(fIterator);
1482 	fIterator = NULL;
1483 	fCurrent = NULL;
1484 
1485 	// put the whole expression on the stack
1486 
1487 	Stack<Term<QueryPolicy>*> stack;
1488 	stack.Push(fExpression->Root());
1489 
1490 	Term<QueryPolicy>* term;
1491 	while (stack.Pop(&term)) {
1492 		if (term->Op() < OP_EQUATION) {
1493 			Operator<QueryPolicy>* op = (Operator<QueryPolicy>*)term;
1494 
1495 			if (op->Op() == OP_OR) {
1496 				stack.Push(op->Left());
1497 				stack.Push(op->Right());
1498 			} else {
1499 				// For OP_AND, we can use the scoring system to decide which
1500 				// path to add
1501 				if (op->Right()->Score() > op->Left()->Score())
1502 					stack.Push(op->Right());
1503 				else
1504 					stack.Push(op->Left());
1505 			}
1506 		} else if (term->Op() == OP_EQUATION
1507 			|| fStack.Push((Equation<QueryPolicy>*)term) != B_OK)
1508 			QUERY_FATAL("Unknown term on stack or stack error\n");
1509 	}
1510 
1511 	return B_OK;
1512 }
1513 
1514 
1515 template<typename QueryPolicy>
1516 status_t
1517 Query<QueryPolicy>::GetNextEntry(struct dirent* dirent, size_t size)
1518 {
1519 	if (fIterator != NULL)
1520 		QueryPolicy::IndexIteratorResume(fIterator);
1521 
1522 	status_t error = _GetNextEntry(dirent, size);
1523 
1524 	if (fIterator != NULL)
1525 		QueryPolicy::IndexIteratorSuspend(fIterator);
1526 
1527 	return error;
1528 }
1529 
1530 
1531 template<typename QueryPolicy>
1532 void
1533 Query<QueryPolicy>::LiveUpdate(Entry* entry, Node* node, const char* attribute,
1534 	int32 type, const uint8* oldKey, size_t oldLength, const uint8* newKey,
1535 	size_t newLength)
1536 {
1537 	if (fPort < 0 || fExpression == NULL || attribute == NULL)
1538 		return;
1539 
1540 	// TODO: check if the attribute is part of the query at all...
1541 
1542 	// If no entry has been supplied, but the we need one for the evaluation
1543 	// (i.e. the "name" attribute is used), we invoke ourselves for all entries
1544 	// referring to the given node.
1545 	if (entry == NULL && fNeedsEntry) {
1546 		entry = QueryPolicy::NodeGetFirstReferrer(node);
1547 		while (entry) {
1548 			LiveUpdate(entry, node, attribute, type, oldKey, oldLength, newKey,
1549 				newLength);
1550 			entry = QueryPolicy::NodeGetNextReferrer(node, entry);
1551 		}
1552 		return;
1553 	}
1554 
1555 	status_t oldStatus = fExpression->Root()->Match(entry, node, attribute,
1556 		type, oldKey, oldLength);
1557 	status_t newStatus = fExpression->Root()->Match(entry, node, attribute,
1558 		type, newKey, newLength);
1559 
1560 	bool entryCreated = false;
1561 	bool stillInQuery = false;
1562 
1563 	if (oldStatus != MATCH_OK) {
1564 		if (newStatus != MATCH_OK) {
1565 			// nothing has changed
1566 			return;
1567 		}
1568 		entryCreated = true;
1569 	} else if (newStatus != MATCH_OK) {
1570 		// entry got removed
1571 		entryCreated = false;
1572 	} else if ((fFlags & B_ATTR_CHANGE_NOTIFICATION) != 0) {
1573 		// The entry stays in the query
1574 		stillInQuery = true;
1575 	} else
1576 		return;
1577 
1578 	// notify query listeners
1579 	status_t (*notify)(port_id, int32, dev_t, ino_t, const char*, ino_t);
1580 
1581 	if (stillInQuery)
1582 		notify = notify_query_attr_changed;
1583 	else if (entryCreated)
1584 		notify = notify_query_entry_created;
1585 	else
1586 		notify = notify_query_entry_removed;
1587 
1588 	if (entry != NULL) {
1589 		_SendEntryNotification(entry, notify);
1590 	} else {
1591 		entry = QueryPolicy::NodeGetFirstReferrer(node);
1592 		while (entry) {
1593 			_SendEntryNotification(entry, notify);
1594 			entry = QueryPolicy::NodeGetNextReferrer(node, entry);
1595 		}
1596 	}
1597 }
1598 
1599 
1600 template<typename QueryPolicy>
1601 void
1602 Query<QueryPolicy>::LiveUpdateRenameMove(Entry* entry, Node* node,
1603 	ino_t oldDirectoryID, const char* oldName, size_t oldLength,
1604 	ino_t newDirectoryID, const char* newName, size_t newLength)
1605 {
1606 	if (fPort < 0 || fExpression == NULL)
1607 		return;
1608 
1609 	// TODO: check if the attribute is part of the query at all...
1610 
1611 	status_t oldStatus = fExpression->Root()->Match(entry, node, "name",
1612 		B_STRING_TYPE, (const uint8*)oldName, oldLength);
1613 	status_t newStatus = fExpression->Root()->Match(entry, node, "name",
1614 		B_STRING_TYPE, (const uint8*)newName, newLength);
1615 
1616 	if (oldStatus != MATCH_OK || oldStatus != newStatus)
1617 		return;
1618 
1619 	// The entry stays in the query, notify query listeners about the rename
1620 	// or move
1621 
1622 	// We send a notification for the given entry, if any, or otherwise for
1623 	// all entries referring to the node;
1624 	if (entry != NULL) {
1625 		_SendEntryNotification(entry, notify_query_entry_removed);
1626 		_SendEntryNotification(entry, notify_query_entry_created);
1627 	} else {
1628 		entry = QueryPolicy::NodeGetFirstReferrer(node);
1629 		while (entry) {
1630 			_SendEntryNotification(entry, notify_query_entry_removed);
1631 			_SendEntryNotification(entry, notify_query_entry_created);
1632 			entry = QueryPolicy::NodeGetNextReferrer(node, entry);
1633 		}
1634 	}
1635 }
1636 
1637 
1638 template<typename QueryPolicy>
1639 status_t
1640 Query<QueryPolicy>::_GetNextEntry(struct dirent* dirent, size_t size)
1641 {
1642 	// If we don't have an equation to use yet/anymore, get a new one
1643 	// from the stack
1644 	while (true) {
1645 		if (fIterator == NULL) {
1646 			if (!fStack.Pop(&fCurrent)
1647 				|| fCurrent == NULL)
1648 				return B_ENTRY_NOT_FOUND;
1649 
1650 			status_t status = fCurrent->PrepareQuery(fContext, fIndex,
1651 				&fIterator, fFlags & B_QUERY_NON_INDEXED);
1652 			if (status == B_ENTRY_NOT_FOUND) {
1653 				// try next equation
1654 				continue;
1655 			}
1656 
1657 			if (status != B_OK)
1658 				return status;
1659 		}
1660 		if (fCurrent == NULL)
1661 			QUERY_RETURN_ERROR(B_ERROR);
1662 
1663 		status_t status = fCurrent->GetNextMatching(fContext, fIterator, dirent,
1664 			size);
1665 		if (status != B_OK) {
1666 			QueryPolicy::IndexIteratorDelete(fIterator);
1667 			fIterator = NULL;
1668 			fCurrent = NULL;
1669 		} else {
1670 			// only return if we have another entry
1671 			return B_OK;
1672 		}
1673 	}
1674 }
1675 
1676 
1677 template<typename QueryPolicy>
1678 void
1679 Query<QueryPolicy>::_SendEntryNotification(Entry* entry,
1680 	status_t (*notify)(port_id, int32, dev_t, ino_t, const char*, ino_t))
1681 {
1682 	NodeHolder nodeHolder;
1683 	const char* name = QueryPolicy::EntryGetNameNoCopy(nodeHolder, entry);
1684 	if (name != NULL) {
1685 		notify(fPort, fToken, QueryPolicy::ContextGetVolumeID(fContext),
1686 			QueryPolicy::EntryGetParentID(entry), name,
1687 			QueryPolicy::EntryGetNodeID(entry));
1688 	}
1689 }
1690 
1691 
1692 }	// namespace QueryParser
1693 
1694 
1695 #endif	// _FILE_SYSTEMS_QUERY_PARSER_H
1696