token.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <eval/token.h>
  15. #include <eval/eval_log.h>
  16. #include <boost/lexical_cast.hpp>
  17. #include <string>
  18. using namespace isc::dhcp;
  19. using namespace std;
  20. void
  21. TokenString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
  22. // Literals only push, nothing to pop
  23. values.push(value_);
  24. }
  25. void
  26. TokenOption::evaluate(const Pkt& pkt, ValueStack& values) {
  27. OptionPtr opt = pkt.getOption(option_code_);
  28. if (opt) {
  29. values.push(opt->toString());
  30. } else {
  31. // Option not found, push empty string
  32. values.push("");
  33. }
  34. }
  35. void
  36. TokenEqual::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
  37. if (values.size() < 2) {
  38. isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
  39. "2 values for == operator, got " << values.size());
  40. }
  41. string op1 = values.top();
  42. values.pop();
  43. string op2 = values.top();
  44. values.pop(); // Dammit, std::stack interface is awkward.
  45. if (op1 == op2)
  46. values.push("true");
  47. else
  48. values.push("false");
  49. }
  50. void
  51. TokenSubstring::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
  52. if (values.size() < 3) {
  53. isc_throw(EvalBadStack, "Incorrect stack order. Expected at least "
  54. "3 values for substring operator, got " << values.size());
  55. }
  56. string len_str = values.top();
  57. values.pop();
  58. string start_str = values.top();
  59. values.pop();
  60. string string_str = values.top();
  61. values.pop();
  62. // If we have no string to start with we push an empty string and leave
  63. if (string_str.empty()) {
  64. values.push("");
  65. return;
  66. }
  67. // Convert the starting position and length from strings to numbers
  68. // the length may also be "all" in which case simply make it the
  69. // length of the string.
  70. // If we have a problem push an empty string and leave
  71. int start_pos;
  72. int length;
  73. try {
  74. start_pos = boost::lexical_cast<int>(start_str);
  75. if (len_str == "all") {
  76. length = string_str.length();
  77. } else {
  78. length = boost::lexical_cast<int>(len_str);
  79. }
  80. } catch (const boost::bad_lexical_cast&) {
  81. LOG_DEBUG(eval_logger, EVAL_DBG_TRACE,
  82. EVAL_SUBSTRING_BAD_PARAM_CONVERSION)
  83. .arg(start_str)
  84. .arg(len_str);
  85. values.push("");
  86. return;
  87. }
  88. const int string_length = string_str.length();
  89. // If the starting postion is outside of the string push an
  90. // empty string and leave
  91. if ((start_pos < -string_length) || (start_pos >= string_length)) {
  92. values.push("");
  93. return;
  94. }
  95. // Adjust the values to be something for substr. We first figure out
  96. // the starting postion, then update it and the length to get the
  97. // characters before or after it depending on the sign of length
  98. if (start_pos < 0) {
  99. start_pos = string_length + start_pos;
  100. }
  101. if (length < 0) {
  102. length = -length;
  103. if (length <= start_pos){
  104. start_pos -= length;
  105. } else {
  106. length = start_pos;
  107. start_pos = 0;
  108. }
  109. }
  110. // and finally get the substring
  111. values.push(string_str.substr(start_pos, length));
  112. }