1 //---------------------------------------------------------------------- 2 // This software is part of the OpenBeOS distribution and is covered 3 // by the OpenBeOS license. 4 //--------------------------------------------------------------------- 5 /*! 6 \file QueryPredicate.cpp 7 BQuery predicate helper classes implementation. 8 */ 9 #include "QueryPredicate.h" 10 11 #include <ctype.h> 12 13 namespace BPrivate { 14 namespace Storage { 15 16 // QueryNode 17 18 // constructor 19 QueryNode::QueryNode() 20 { 21 } 22 23 // destructor 24 QueryNode::~QueryNode() 25 { 26 } 27 28 29 // LeafNode 30 31 // constructor 32 LeafNode::LeafNode() 33 : QueryNode() 34 { 35 } 36 37 // destructor 38 LeafNode::~LeafNode() 39 { 40 } 41 42 // Arity 43 uint32 44 LeafNode::Arity() const 45 { 46 return 0; 47 } 48 49 // SetChildAt 50 status_t 51 LeafNode::SetChildAt(QueryNode *child, int32 index) 52 { 53 return B_BAD_VALUE; 54 } 55 56 // ChildAt 57 QueryNode * 58 LeafNode::ChildAt(int32 index) 59 { 60 return NULL; 61 } 62 63 64 // UnaryNode 65 66 // constructor 67 UnaryNode::UnaryNode() 68 : QueryNode(), 69 fChild(NULL) 70 { 71 } 72 73 // destructor 74 UnaryNode::~UnaryNode() 75 { 76 delete fChild; 77 } 78 79 // Arity 80 uint32 81 UnaryNode::Arity() const 82 { 83 return 1; 84 } 85 86 // SetChildAt 87 status_t 88 UnaryNode::SetChildAt(QueryNode *child, int32 index) 89 { 90 status_t error = B_OK; 91 if (index == 0) { 92 delete fChild; 93 fChild = child; 94 } else 95 error = B_BAD_VALUE; 96 return error; 97 } 98 99 // ChildAt 100 QueryNode * 101 UnaryNode::ChildAt(int32 index) 102 { 103 QueryNode *result = NULL; 104 if (index == 0) 105 result = fChild; 106 return result; 107 } 108 109 110 // BinaryNode 111 112 // constructor 113 BinaryNode::BinaryNode() 114 : QueryNode(), 115 fChild1(NULL), 116 fChild2(NULL) 117 { 118 } 119 120 // destructor 121 BinaryNode::~BinaryNode() 122 { 123 delete fChild1; 124 delete fChild2; 125 } 126 127 // Arity 128 uint32 129 BinaryNode::Arity() const 130 { 131 return 2; 132 } 133 134 // SetChildAt 135 status_t 136 BinaryNode::SetChildAt(QueryNode *child, int32 index) 137 { 138 status_t error = B_OK; 139 if (index == 0) { 140 delete fChild1; 141 fChild1 = child; 142 } else if (index == 1) { 143 delete fChild2; 144 fChild2 = child; 145 } else 146 error = B_BAD_VALUE; 147 return error; 148 } 149 150 // ChildAt 151 QueryNode * 152 BinaryNode::ChildAt(int32 index) 153 { 154 QueryNode *result = NULL; 155 if (index == 0) 156 result = fChild1; 157 else if (index == 1) 158 result = fChild2; 159 return result; 160 } 161 162 163 // AttributeNode 164 165 // constructor 166 AttributeNode::AttributeNode(const char *attribute) 167 : LeafNode(), 168 fAttribute(attribute) 169 { 170 } 171 172 // GetString 173 status_t 174 AttributeNode::GetString(BString &predicate) 175 { 176 predicate.SetTo(fAttribute); 177 return B_OK; 178 } 179 180 181 // StringNode 182 183 // constructor 184 StringNode::StringNode(const char *value, bool caseInsensitive) 185 : LeafNode(), 186 fValue() 187 { 188 if (value) { 189 if (caseInsensitive) { 190 int32 len = strlen(value); 191 for (int32 i = 0; i < len; i++) { 192 char c = value[i]; 193 if (isalpha(c)) { 194 int lower = tolower(c); 195 int upper = toupper(c); 196 if (lower < 0 || upper < 0) 197 fValue << c; 198 else 199 fValue << "[" << (char)lower << (char)upper << "]"; 200 } else 201 fValue << c; 202 } 203 } else 204 fValue = value; 205 } 206 } 207 208 // GetString 209 status_t 210 StringNode::GetString(BString &predicate) 211 { 212 BString escaped(fValue); 213 escaped.CharacterEscape("\"\\'", '\\'); 214 predicate.SetTo(""); 215 predicate << "\"" << escaped << "\""; 216 return B_OK; 217 } 218 219 220 // DateNode 221 222 // constructor 223 DateNode::DateNode(const char *value) 224 : LeafNode(), 225 fValue(value) 226 { 227 } 228 229 // GetString 230 status_t 231 DateNode::GetString(BString &predicate) 232 { 233 BString escaped(fValue); 234 escaped.CharacterEscape("%\"\\'", '\\'); 235 predicate.SetTo(""); 236 predicate << "%" << escaped << "%"; 237 return B_OK; 238 } 239 240 241 // ValueNode 242 243 // GetString 244 // 245 // float specialization 246 template<> 247 status_t 248 ValueNode<float>::GetString(BString &predicate) 249 { 250 char buffer[32]; 251 sprintf(buffer, "0x%08lx", *(int32*)&fValue); 252 predicate.SetTo(buffer); 253 return B_OK; 254 } 255 256 // GetString 257 // 258 // double specialization 259 template<> 260 status_t 261 ValueNode<double>::GetString(BString &predicate) 262 { 263 char buffer[32]; 264 sprintf(buffer, "0x%016Lx", *(int64*)&fValue); 265 predicate.SetTo(buffer); 266 return B_OK; 267 } 268 269 270 // SpecialOpNode 271 272 // constructor 273 SpecialOpNode::SpecialOpNode(query_op op) 274 : LeafNode(), 275 fOp(op) 276 { 277 } 278 279 // GetString 280 status_t 281 SpecialOpNode::GetString(BString &predicate) 282 { 283 return B_BAD_VALUE; 284 } 285 286 287 // UnaryOpNode 288 289 // constructor 290 UnaryOpNode::UnaryOpNode(query_op op) 291 : UnaryNode(), 292 fOp(op) 293 { 294 } 295 296 // GetString 297 status_t 298 UnaryOpNode::GetString(BString &predicate) 299 { 300 status_t error = (fChild ? B_OK : B_BAD_VALUE); 301 if (error == B_OK) { 302 if (fOp == B_NOT) { 303 BString childString; 304 error = fChild->GetString(childString); 305 predicate.SetTo("(!"); 306 predicate << childString << ")"; 307 } else 308 error = B_BAD_VALUE; 309 } 310 return error; 311 } 312 313 314 // BinaryOpNode 315 316 // constructor 317 BinaryOpNode::BinaryOpNode(query_op op) 318 : BinaryNode(), 319 fOp(op) 320 { 321 } 322 323 // GetString 324 status_t 325 BinaryOpNode::GetString(BString &predicate) 326 { 327 status_t error = (fChild1 && fChild2 ? B_OK : B_BAD_VALUE); 328 BString childString1; 329 BString childString2; 330 if (error == B_OK) 331 error = fChild1->GetString(childString1); 332 if (error == B_OK) 333 error = fChild2->GetString(childString2); 334 predicate.SetTo(""); 335 if (error == B_OK) { 336 switch (fOp) { 337 case B_EQ: 338 predicate << "(" << childString1 << "==" 339 << childString2 << ")"; 340 break; 341 case B_GT: 342 predicate << "(" << childString1 << ">" 343 << childString2 << ")"; 344 break; 345 case B_GE: 346 predicate << "(" << childString1 << ">=" 347 << childString2 << ")"; 348 break; 349 case B_LT: 350 predicate << "(" << childString1 << "<" 351 << childString2 << ")"; 352 break; 353 case B_LE: 354 predicate << "(" << childString1 << "<=" 355 << childString2 << ")"; 356 break; 357 case B_NE: 358 predicate << "(" << childString1 << "!=" 359 << childString2 << ")"; 360 break; 361 case B_CONTAINS: 362 if (StringNode *strNode = dynamic_cast<StringNode*>(fChild2)) { 363 BString value; 364 value << "*" << strNode->Value() << "*"; 365 error = StringNode(value.String()).GetString(childString2); 366 } 367 if (error == B_OK) { 368 predicate << "(" << childString1 << "==" 369 << childString2 << ")"; 370 } 371 break; 372 case B_BEGINS_WITH: 373 if (StringNode *strNode = dynamic_cast<StringNode*>(fChild2)) { 374 BString value; 375 value << strNode->Value() << "*"; 376 error = StringNode(value.String()).GetString(childString2); 377 } 378 if (error == B_OK) { 379 predicate << "(" << childString1 << "==" 380 << childString2 << ")"; 381 } 382 break; 383 case B_ENDS_WITH: 384 if (StringNode *strNode = dynamic_cast<StringNode*>(fChild2)) { 385 BString value; 386 value << "*" << strNode->Value(); 387 error = StringNode(value.String()).GetString(childString2); 388 } 389 if (error == B_OK) { 390 predicate << "(" << childString1 << "==" 391 << childString2 << ")"; 392 } 393 break; 394 case B_AND: 395 predicate << "(" << childString1 << "&&" 396 << childString2 << ")"; 397 break; 398 case B_OR: 399 predicate << "(" << childString1 << "||" 400 << childString2 << ")"; 401 break; 402 default: 403 error = B_BAD_VALUE; 404 break; 405 } 406 } 407 return error; 408 } 409 410 411 // QueryStack 412 413 // constructor 414 QueryStack::QueryStack() 415 : fNodes() 416 { 417 } 418 419 // destructor 420 QueryStack::~QueryStack() 421 { 422 for (int32 i = 0; QueryNode *node = (QueryNode*)fNodes.ItemAt(i); i++) 423 delete node; 424 } 425 426 // PushNode 427 status_t 428 QueryStack::PushNode(QueryNode *node) 429 { 430 status_t error = (node ? B_OK : B_BAD_VALUE); 431 if (error == B_OK) { 432 if (!fNodes.AddItem(node)) 433 error = B_NO_MEMORY; 434 } 435 return error; 436 } 437 438 // PopNode 439 QueryNode * 440 QueryStack::PopNode() 441 { 442 return (QueryNode*)fNodes.RemoveItem(fNodes.CountItems() - 1); 443 } 444 445 // ConvertToTree 446 status_t 447 QueryStack::ConvertToTree(QueryNode *&rootNode) 448 { 449 status_t error = _GetSubTree(rootNode); 450 if (error == B_OK && !fNodes.IsEmpty()) { 451 error = B_BAD_VALUE; 452 delete rootNode; 453 rootNode = NULL; 454 } 455 return error; 456 } 457 458 // _GetSubTree 459 status_t 460 QueryStack::_GetSubTree(QueryNode *&rootNode) 461 { 462 QueryNode *node = PopNode(); 463 status_t error = (node ? B_OK : B_BAD_VALUE); 464 if (error == B_OK) { 465 uint32 arity = node->Arity(); 466 for (int32 i = (int32)arity - 1; error == B_OK && i >= 0; i--) { 467 QueryNode *child = NULL; 468 error = _GetSubTree(child); 469 if (error == B_OK) { 470 error = node->SetChildAt(child, i); 471 if (error != B_OK) 472 delete child; 473 } 474 } 475 } 476 // clean up, if something went wrong 477 if (error != B_OK && node) { 478 delete node; 479 node = NULL; 480 } 481 rootNode = node; 482 return error; 483 } 484 485 486 }; // namespace Storage 487 }; // namespace BPrivate 488 489 490 491