searchPattern.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include <algorithm>
  2. #include <sstream>
  3. #include <regex>
  4. #include "searchPattern.hh"
  5. #include "jsonObjectEntry.hh"
  6. #include "jsonPrimitive.hh"
  7. SearchPattern::SearchPattern(const std::string &input): regex(nullptr), flags(0)
  8. {
  9. size_t pos = 0;
  10. bool escaped = false;
  11. std::stringstream ss;
  12. for (pos =0; input[pos] && (input[pos] == ' ' || input[pos] == '\t'); ++pos); //trim leading characters
  13. for (; input[pos]; ++pos)
  14. {
  15. if (escaped)
  16. {
  17. if (input[pos] == '/')
  18. ss.put(input[pos]);
  19. else
  20. ss.put('\\').put(input[pos]);
  21. escaped = false;
  22. }
  23. else if (input[pos] == '\\')
  24. escaped = true;
  25. else if (input[pos] == '/')
  26. {
  27. pattern = ss.str();
  28. evalFlags(&input[pos +1]);
  29. return;
  30. }
  31. else
  32. ss.put(input[pos]);
  33. }
  34. pattern = ss.str();
  35. }
  36. SearchPattern::~SearchPattern()
  37. {
  38. if (regex)
  39. delete regex;
  40. }
  41. void SearchPattern::evalFlags(const char *s)
  42. {
  43. while (*s)
  44. {
  45. if (*s == 'i')
  46. {
  47. flags |= SearchPattern::FLAG_CASE;
  48. std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
  49. }
  50. else if (*s == 'w')
  51. flags |= SearchPattern::FLAG_WHOLEWORD;
  52. else if (*s == 'f')
  53. flags |= SearchPattern::FLAG_WHOLESTR;
  54. else if (*s == 'e')
  55. flags |= SearchPattern::FLAG_REGEX;
  56. else if (*s == 'b')
  57. typeFlag = SearchPattern::TYPE_BOOL;
  58. else if (*s == 'n')
  59. typeFlag = SearchPattern::TYPE_NUMBER;
  60. else if (*s == 's')
  61. typeFlag = SearchPattern::TYPE_STRING;
  62. else if (*s == 'o')
  63. typeFlag = SearchPattern::TYPE_OBJKEY;
  64. s++;
  65. }
  66. if (!regex && flags & SearchPattern::FLAG_REGEX)
  67. {
  68. std::regex_constants::syntax_option_type opts = std::regex_constants::ECMAScript;
  69. if (flags & FLAG_CASE)
  70. opts |= std::regex_constants::icase;
  71. regex = new std::regex(pattern, opts);
  72. }
  73. }
  74. bool SearchPattern::isEmpty() const
  75. { return pattern.empty(); }
  76. bool SearchPattern::operator()(char a, char b)
  77. {
  78. if (a == '\t')
  79. a = ' ';
  80. if (flags & SearchPattern::FLAG_CASE)
  81. return std::tolower(a) == b;
  82. return a == b;
  83. }
  84. bool SearchPattern::match(const std::string &str, const JSonElement *type) const
  85. {
  86. if (typeFlag)
  87. {
  88. if (typeFlag == SearchPattern::TYPE_BOOL && !(dynamic_cast<const JSonPrimitive<bool> *>(type)))
  89. return false;
  90. else if (typeFlag == SearchPattern::TYPE_STRING && !(dynamic_cast<const JSonPrimitive<std::string> *>(type)))
  91. return false;
  92. else if (typeFlag == SearchPattern::TYPE_OBJKEY && !(dynamic_cast<const JSonObjectEntry *>(type)))
  93. return false;
  94. else if (typeFlag == SearchPattern::TYPE_NUMBER &&
  95. !(dynamic_cast<const JSonPrimitive<int> *>(type)) &&
  96. !(dynamic_cast<const JSonPrimitive<double> *>(type)) &&
  97. !(dynamic_cast<const JSonPrimitive<long long> *>(type)))
  98. return false;
  99. }
  100. if (flags & FLAG_REGEX)
  101. return regex_search(str, *regex);
  102. if ((flags & FLAG_WHOLESTR && str.length() != pattern.length())
  103. || pattern.length() > str.length())
  104. return false;
  105. if (flags & FLAG_WHOLEWORD && str.length() > pattern.length())
  106. {
  107. std::string pattern = " " +this->pattern +' ';
  108. return std::search(str.begin(), str.end(), pattern.begin(), pattern.end(), *this) != str.end();
  109. }
  110. return std::search(str.begin(), str.end(), pattern.begin(), pattern.end(), *this) != str.end();
  111. }
  112. const short SearchPattern::FLAG_CASE = 1;
  113. const short SearchPattern::FLAG_WHOLEWORD = 2;
  114. const short SearchPattern::FLAG_WHOLESTR = 4;
  115. const short SearchPattern::FLAG_REGEX = 8;
  116. const short SearchPattern::TYPE_BOOL = 1;
  117. const short SearchPattern::TYPE_NUMBER = 2;
  118. const short SearchPattern::TYPE_STRING = 3;
  119. const short SearchPattern::TYPE_OBJKEY = 4;