2 * Copyright 2002-2008, Haiku Inc.
3 * Distributed under the terms of the MIT License.
10 \file QueryPredicate.cpp
11 BQuery predicate helper classes implementation.
14 #include "QueryPredicate.h"
18 #include <UnicodeChar.h>
24 // #pragma mark - QueryNode
27 QueryNode::QueryNode()
32 QueryNode::~QueryNode()
37 // #pragma mark - LeafNode
51 LeafNode::Arity() const
58 LeafNode::SetChildAt(QueryNode
*child
, int32 index
)
65 LeafNode::ChildAt(int32 index
)
71 // #pragma mark - UnaryNode
74 UnaryNode::UnaryNode()
81 UnaryNode::~UnaryNode()
88 UnaryNode::Arity() const
95 UnaryNode::SetChildAt(QueryNode
*child
, int32 index
)
97 status_t error
= B_OK
;
108 UnaryNode::ChildAt(int32 index
)
110 QueryNode
*result
= NULL
;
117 // #pragma mark - BinaryNode
120 BinaryNode::BinaryNode()
128 BinaryNode::~BinaryNode()
136 BinaryNode::Arity() const
143 BinaryNode::SetChildAt(QueryNode
*child
, int32 index
)
145 status_t error
= B_OK
;
149 } else if (index
== 1) {
159 BinaryNode::ChildAt(int32 index
)
161 QueryNode
*result
= NULL
;
170 // #pragma mark - AttributeNode
173 AttributeNode::AttributeNode(const char *attribute
)
175 fAttribute(attribute
)
181 AttributeNode::GetString(BString
&predicate
)
183 predicate
.SetTo(fAttribute
);
188 // #pragma mark - StringNode
191 StringNode::StringNode(const char *value
, bool caseInsensitive
)
196 if (caseInsensitive
) {
197 while (uint32 codePoint
= BUnicodeChar::FromUTF8(&value
)) {
199 char *utf8
= utf8Buffer
;
200 if (BUnicodeChar::IsAlpha(codePoint
)) {
201 uint32 lower
= BUnicodeChar::ToLower(codePoint
);
202 uint32 upper
= BUnicodeChar::ToUpper(codePoint
);
203 if (lower
== upper
) {
204 BUnicodeChar::ToUTF8(codePoint
, &utf8
);
205 fValue
.Append(utf8Buffer
, utf8
- utf8Buffer
);
208 BUnicodeChar::ToUTF8(lower
, &utf8
);
209 fValue
.Append(utf8Buffer
, utf8
- utf8Buffer
);
211 BUnicodeChar::ToUTF8(upper
, &utf8
);
212 fValue
.Append(utf8Buffer
, utf8
- utf8Buffer
);
215 } else if (codePoint
== L
' ') {
218 BUnicodeChar::ToUTF8(codePoint
, &utf8
);
219 fValue
.Append(utf8Buffer
, utf8
- utf8Buffer
);
224 fValue
.ReplaceAll(' ', '*');
230 StringNode::GetString(BString
&predicate
)
232 BString
escaped(fValue
);
233 escaped
.CharacterEscape("\"\\'", '\\');
235 predicate
<< "\"" << escaped
<< "\"";
240 // #pragma mark - DateNode
243 DateNode::DateNode(const char *value
)
251 DateNode::GetString(BString
&predicate
)
253 BString
escaped(fValue
);
254 escaped
.CharacterEscape("%\"\\'", '\\');
256 predicate
<< "%" << escaped
<< "%";
261 // #pragma mark - ValueNode
266 ValueNode
<float>::GetString(BString
&predicate
)
273 value
.asFloat
= fValue
;
274 // int32 value = *reinterpret_cast<int32*>(&fValue);
275 sprintf(buffer
, "0x%08" B_PRIx32
, value
.asInteger
);
276 predicate
.SetTo(buffer
);
283 ValueNode
<double>::GetString(BString
&predicate
)
290 // int64 value = *reinterpret_cast<int64*>(&fValue);
291 value
.asFloat
= fValue
;
292 sprintf(buffer
, "0x%016" B_PRIx64
, value
.asInteger
);
293 predicate
.SetTo(buffer
);
298 // #pragma mark - SpecialOpNode
301 SpecialOpNode::SpecialOpNode(query_op op
)
309 SpecialOpNode::GetString(BString
&predicate
)
315 // #pragma mark - UnaryOpNode
318 UnaryOpNode::UnaryOpNode(query_op op
)
326 UnaryOpNode::GetString(BString
&predicate
)
328 status_t error
= (fChild
? B_OK
: B_BAD_VALUE
);
332 error
= fChild
->GetString(childString
);
333 predicate
.SetTo("(!");
334 predicate
<< childString
<< ")";
342 // #pragma mark - BinaryOpNode
345 BinaryOpNode::BinaryOpNode(query_op op
)
353 BinaryOpNode::GetString(BString
&predicate
)
355 status_t error
= (fChild1
&& fChild2
? B_OK
: B_BAD_VALUE
);
356 BString childString1
;
357 BString childString2
;
359 error
= fChild1
->GetString(childString1
);
361 error
= fChild2
->GetString(childString2
);
366 predicate
<< "(" << childString1
<< "=="
367 << childString2
<< ")";
370 predicate
<< "(" << childString1
<< ">"
371 << childString2
<< ")";
374 predicate
<< "(" << childString1
<< ">="
375 << childString2
<< ")";
378 predicate
<< "(" << childString1
<< "<"
379 << childString2
<< ")";
382 predicate
<< "(" << childString1
<< "<="
383 << childString2
<< ")";
386 predicate
<< "(" << childString1
<< "!="
387 << childString2
<< ")";
390 if (StringNode
*strNode
= dynamic_cast<StringNode
*>(fChild2
)) {
392 value
<< "*" << strNode
->Value() << "*";
393 error
= StringNode(value
.String()).GetString(childString2
);
396 predicate
<< "(" << childString1
<< "=="
397 << childString2
<< ")";
401 if (StringNode
*strNode
= dynamic_cast<StringNode
*>(fChild2
)) {
403 value
<< strNode
->Value() << "*";
404 error
= StringNode(value
.String()).GetString(childString2
);
407 predicate
<< "(" << childString1
<< "=="
408 << childString2
<< ")";
412 if (StringNode
*strNode
= dynamic_cast<StringNode
*>(fChild2
)) {
414 value
<< "*" << strNode
->Value();
415 error
= StringNode(value
.String()).GetString(childString2
);
418 predicate
<< "(" << childString1
<< "=="
419 << childString2
<< ")";
423 predicate
<< "(" << childString1
<< "&&"
424 << childString2
<< ")";
427 predicate
<< "(" << childString1
<< "||"
428 << childString2
<< ")";
439 // #pragma mark - QueryStack
442 QueryStack::QueryStack()
447 QueryStack::~QueryStack()
449 for (int32 i
= 0; QueryNode
*node
= (QueryNode
*)fNodes
.ItemAt(i
); i
++)
455 QueryStack::PushNode(QueryNode
*node
)
457 status_t error
= (node
? B_OK
: B_BAD_VALUE
);
459 if (!fNodes
.AddItem(node
))
467 QueryStack::PopNode()
469 return (QueryNode
*)fNodes
.RemoveItem(fNodes
.CountItems() - 1);
474 QueryStack::ConvertToTree(QueryNode
*&rootNode
)
476 status_t error
= _GetSubTree(rootNode
);
477 if (error
== B_OK
&& !fNodes
.IsEmpty()) {
487 QueryStack::_GetSubTree(QueryNode
*&rootNode
)
489 QueryNode
*node
= PopNode();
490 status_t error
= (node
? B_OK
: B_BAD_VALUE
);
492 uint32 arity
= node
->Arity();
493 for (int32 i
= (int32
)arity
- 1; error
== B_OK
&& i
>= 0; i
--) {
494 QueryNode
*child
= NULL
;
495 error
= _GetSubTree(child
);
497 error
= node
->SetChildAt(child
, i
);
503 // clean up, if something went wrong
504 if (error
!= B_OK
&& node
) {
513 } // namespace Storage
514 } // namespace BPrivate