Pattern.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #include "Pattern.hpp"
  25. #include "oatpp/core/data/stream/BufferStream.hpp"
  26. namespace oatpp { namespace web { namespace url { namespace mapping {
  27. const char* Pattern::Part::FUNCTION_CONST = "const";
  28. const char* Pattern::Part::FUNCTION_VAR = "var";
  29. const char* Pattern::Part::FUNCTION_ANY_END = "tail";
  30. std::shared_ptr<Pattern> Pattern::parse(p_char8 data, v_buff_size size){
  31. if(size <= 0){
  32. return nullptr;
  33. }
  34. auto result = Pattern::createShared();
  35. v_buff_size lastPos = 0;
  36. v_buff_size i = 0;
  37. while(i < size){
  38. v_char8 a = data[i];
  39. if(a == '/'){
  40. if(i - lastPos > 0){
  41. auto part = Part::createShared(Part::FUNCTION_CONST, oatpp::String((const char*)&data[lastPos], i - lastPos));
  42. result->m_parts->push_back(part);
  43. }
  44. lastPos = i + 1;
  45. } else if(a == '*'){
  46. lastPos = i + 1;
  47. if(size > lastPos){
  48. auto part = Part::createShared(Part::FUNCTION_ANY_END, oatpp::String((const char*)&data[lastPos], size - lastPos));
  49. result->m_parts->push_back(part);
  50. }else{
  51. auto part = Part::createShared(Part::FUNCTION_ANY_END, oatpp::String((v_buff_size)0));
  52. result->m_parts->push_back(part);
  53. }
  54. return result;
  55. } else if(a == '{'){
  56. lastPos = i + 1;
  57. while(i < size && data[i] != '}'){
  58. i++;
  59. }
  60. if(i > lastPos){
  61. auto part = Part::createShared(Part::FUNCTION_VAR, oatpp::String((const char*)&data[lastPos], i - lastPos));
  62. result->m_parts->push_back(part);
  63. }else{
  64. auto part = Part::createShared(Part::FUNCTION_VAR, oatpp::String((v_buff_size)0));
  65. result->m_parts->push_back(part);
  66. }
  67. lastPos = i + 1;
  68. }
  69. i++;
  70. }
  71. if(i - lastPos > 0){
  72. auto part = Part::createShared(Part::FUNCTION_CONST, oatpp::String((const char*)&data[lastPos], i - lastPos));
  73. result->m_parts->push_back(part);
  74. }
  75. return result;
  76. }
  77. std::shared_ptr<Pattern> Pattern::parse(const char* data){
  78. return parse((p_char8) data, std::strlen(data));
  79. }
  80. std::shared_ptr<Pattern> Pattern::parse(const oatpp::String& data){
  81. return parse((p_char8) data->data(), data->size());
  82. }
  83. v_char8 Pattern::findSysChar(oatpp::parser::Caret& caret) {
  84. auto data = caret.getData();
  85. for (v_buff_size i = caret.getPosition(); i < caret.getDataSize(); i++) {
  86. v_char8 a = data[i];
  87. if(a == '/' || a == '?') {
  88. caret.setPosition(i);
  89. return a;
  90. }
  91. }
  92. caret.setPosition(caret.getDataSize());
  93. return 0;
  94. }
  95. bool Pattern::match(const StringKeyLabel& url, MatchMap& matchMap) {
  96. oatpp::parser::Caret caret((const char*) url.getData(), url.getSize());
  97. if (m_parts->empty()) {
  98. return !caret.skipChar('/');
  99. }
  100. auto curr = std::begin(*m_parts);
  101. const auto end = std::end(*m_parts);
  102. while(curr != end){
  103. const std::shared_ptr<Part>& part = *curr;
  104. ++curr;
  105. caret.skipChar('/');
  106. if(part->function == Part::FUNCTION_CONST){
  107. if(!caret.isAtText(part->text->data(), part->text->size(), true)) {
  108. return false;
  109. }
  110. if(caret.canContinue() && !caret.isAtChar('/')){
  111. if(caret.isAtChar('?') && (curr == end || (*curr)->function == Part::FUNCTION_ANY_END)) {
  112. matchMap.m_tail = StringKeyLabel(url.getMemoryHandle(), caret.getCurrData(), caret.getDataSize() - caret.getPosition());
  113. return true;
  114. }
  115. return false;
  116. }
  117. }else if(part->function == Part::FUNCTION_ANY_END){
  118. if(caret.getDataSize() > caret.getPosition()){
  119. matchMap.m_tail = StringKeyLabel(url.getMemoryHandle(), caret.getCurrData(), caret.getDataSize() - caret.getPosition());
  120. }
  121. return true;
  122. }else if(part->function == Part::FUNCTION_VAR){
  123. if(!caret.canContinue()){
  124. return false;
  125. }
  126. auto label = caret.putLabel();
  127. v_char8 a = findSysChar(caret);
  128. if(a == '?') {
  129. if(curr == end || (*curr)->function == Part::FUNCTION_ANY_END) {
  130. matchMap.m_variables[part->text] = StringKeyLabel(url.getMemoryHandle(), label.getData(), label.getSize());
  131. matchMap.m_tail = StringKeyLabel(url.getMemoryHandle(), caret.getCurrData(), caret.getDataSize() - caret.getPosition());
  132. return true;
  133. }
  134. caret.findChar('/');
  135. }
  136. matchMap.m_variables[part->text] = StringKeyLabel(url.getMemoryHandle(), label.getData(), label.getSize());
  137. }
  138. }
  139. caret.skipChar('/');
  140. return !caret.canContinue();
  141. }
  142. oatpp::String Pattern::toString() {
  143. oatpp::data::stream::BufferOutputStream stream;
  144. for (const std::shared_ptr<Part>& part : *m_parts) {
  145. if(part->function == Part::FUNCTION_CONST) {
  146. stream.writeSimple("/", 1);
  147. stream.writeSimple(part->text);
  148. } else if(part->function == Part::FUNCTION_VAR) {
  149. stream.writeSimple("/{", 2);
  150. stream.writeSimple(part->text);
  151. stream.writeSimple("}", 1);
  152. } else if(part->function == Part::FUNCTION_ANY_END) {
  153. stream.writeSimple("/*", 2);
  154. }
  155. }
  156. return stream.toString();
  157. }
  158. }}}}