diff --git a/core/parser/ParsingCaret.cpp b/core/parser/ParsingCaret.cpp index b47abe9e..727ea043 100644 --- a/core/parser/ParsingCaret.cpp +++ b/core/parser/ParsingCaret.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace oatpp { namespace parser { @@ -507,6 +508,11 @@ namespace oatpp { namespace parser { } + bool ParsingCaret::findText(p_char8 text, v_int32 textSize) { + m_pos = (v_int32)(std::search(&m_data[m_pos], &m_data[m_size], text, text + textSize) - m_data); + return m_pos != m_size; + } + std::shared_ptr ParsingCaret::findTextFromList(const std::shared_ptr>>& list){ while(m_pos < m_size){ diff --git a/core/parser/ParsingCaret.hpp b/core/parser/ParsingCaret.hpp index 623e3875..6f147768 100644 --- a/core/parser/ParsingCaret.hpp +++ b/core/parser/ParsingCaret.hpp @@ -52,7 +52,12 @@ public: , m_end(-1) {} - void end(){ + void start() { + m_start = m_caret.m_pos; + m_end = -1; + } + + void end() { m_end = m_caret.m_pos; } @@ -61,6 +66,9 @@ public: } v_int32 getSize(){ + if(m_end == -1) { + return m_caret.m_pos - m_start; + } return m_end - m_start; } @@ -156,6 +164,8 @@ public: std::shared_ptr parseStringEnclosed(char openChar, char closeChar, char escapeChar, bool saveAsOwnData); std::shared_ptr parseName(bool saveAsOwnData); + bool findText(p_char8 text, v_int32 textSize); + std::shared_ptr findTextFromList(const std::shared_ptr>>& list); bool notAtCharFromSet(const char* set) const; diff --git a/network/Url.cpp b/network/Url.cpp new file mode 100644 index 00000000..5b0525dc --- /dev/null +++ b/network/Url.cpp @@ -0,0 +1,160 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#include "Url.hpp" + +#include + +namespace oatpp { namespace network { + +std::shared_ptr Url::Parser::parseScheme(oatpp::parser::ParsingCaret& caret) { + v_int32 pos0 = caret.getPosition(); + caret.findChar(':'); + v_int32 size = caret.getPosition() - pos0; + if(size > 0) { + v_char8 buff[size]; + std::memcpy(buff, &caret.getData()[pos0], size); + oatpp::base::String::lowerCase(buff, size); + return oatpp::base::String::createShared(buff, size, true); + } + return nullptr; +} + +Url::Authority Url::Parser::parseAuthority(oatpp::parser::ParsingCaret& caret) { + + p_char8 data = caret.getData(); + v_int32 pos0 = caret.getPosition(); + v_int32 pos = pos0; + + v_int32 hostPos = pos0; + v_int32 atPos = -1; + v_int32 portPos = -1; + + while (pos < caret.getSize()) { + v_char8 a = data[pos]; + if(a == '@') { + atPos = pos; + pos ++; + hostPos = pos; + } else if(a == ':') { + pos ++; + portPos = pos; // last ':' in authority proceeds port in case it goes after '@' + } else if(a == '/' || a == '?' || a == '#') { + if(pos == pos0) { + return Url::Authority(); + } + break; + } else { + pos ++; + } + } + + caret.setPosition(pos); + + Url::Authority result; + + if(atPos > -1) { + result.userInfo = oatpp::base::String::createShared(&data[pos0], atPos - pos0, true); + } + + if(portPos > hostPos) { + result.host = oatpp::base::String::createShared(&data[hostPos], portPos - 1 - hostPos, true); + char* end; + result.port = (v_int32) std::strtol((const char*)&data[portPos], &end, 10); + bool success = (((v_int64)end - (v_int64)&data[portPos]) == pos - portPos); + if(!success) { + caret.setError("Invalid port string"); + } + } else { + result.host = oatpp::base::String::createShared(&data[hostPos], pos - pos0, true); + } + + return result; + +} + +std::shared_ptr Url::Parser::parsePath(oatpp::parser::ParsingCaret& caret) { + oatpp::parser::ParsingCaret::Label label(caret); + caret.findCharFromSet((p_char8)"?#", 2); + if(label.getSize() > 0) { + return label.toString(true); + } + return nullptr; +} + +void Url::Parser::parseQueryParamsToMap(Url::Parameters& params, oatpp::parser::ParsingCaret& caret) { + + if(caret.findChar('?')) { + + do { + caret.inc(); + oatpp::parser::ParsingCaret::Label nameLabel(caret); + if(caret.findChar('=')) { + nameLabel.end(); + caret.inc(); + oatpp::parser::ParsingCaret::Label valueLabel(caret); + caret.findChar('&'); + params.put(nameLabel.toString(), valueLabel.toString()); + } + } while (caret.canContinueAtChar('&')); + + } + +} + +void Url::Parser::parseQueryParamsToMap(Url::Parameters& params, const oatpp::base::String::PtrWrapper& str) { + oatpp::parser::ParsingCaret caret(str.getPtr()); + parseQueryParamsToMap(params, caret); +} + +std::shared_ptr Url::Parser::parseQueryParams(oatpp::parser::ParsingCaret& caret) { + auto params = Url::Parameters::createShared(); + parseQueryParamsToMap(*params, caret); + return params; +} + +std::shared_ptr Url::Parser::parseQueryParams(const oatpp::base::String::PtrWrapper& str) { + auto params = Url::Parameters::createShared(); + parseQueryParamsToMap(*params, str); + return params; +} + +Url Url::Parser::parseUrl(oatpp::parser::ParsingCaret& caret) { + Url result; + result.scheme = parseScheme(caret); + if(caret.canContinueAtChar(':', 1)) { + if(caret.proceedIfFollowsText((p_char8)"//", 2)) { + if(!caret.isAtChar('/')) { + result.authority = parseAuthority(caret); + } + result.path = parsePath(caret); + result.queryParams = parseQueryParams(caret); + } else { + result.authority = parseAuthority(caret); + } + } + return result; +} + +}} diff --git a/network/Url.hpp b/network/Url.hpp new file mode 100644 index 00000000..62fcb5d2 --- /dev/null +++ b/network/Url.hpp @@ -0,0 +1,113 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#ifndef oatpp_network_Url_hpp +#define oatpp_network_Url_hpp + +#include "oatpp/core/parser/ParsingCaret.hpp" +#include "oatpp/core/collection/ListMap.hpp" +#include "oatpp/core/base/String.hpp" + +namespace oatpp { namespace network { + +class Url : public oatpp::base::Controllable { +public: + typedef oatpp::collection::ListMap Parameters; +public: + + struct Authority { + std::shared_ptr userInfo; + std::shared_ptr host; + v_int32 port = -1; + }; + +public: + + class Parser { + public: + + /** + * parse ":" + * example "http", "https", "ftp" + * returns lowercase string before ':' char + * caret should be at the first char of the scheme + */ + static std::shared_ptr parseScheme(oatpp::parser::ParsingCaret& caret); + + /** + * parse utl authority components. + * userinfo is not parsed into login and password separately as + * inclusion of password in userinfo is deprecated and ignored here + * caret should be at the first char of the authority (not at "//") + */ + static Url::Authority parseAuthority(oatpp::parser::ParsingCaret& caret); + + /** + * parse path of the url + * caret should be at the first char of the path + */ + static std::shared_ptr parsePath(oatpp::parser::ParsingCaret& caret); + + /** + * parse query params in form of "?=&=..." referred by ParsingCaret + * and put that params to Parameters map + */ + static void parseQueryParamsToMap(Url::Parameters& params, oatpp::parser::ParsingCaret& caret); + + /** + * parse query params in form of "?=&=..." referred by str + * and put that params to Parameters map + */ + static void parseQueryParamsToMap(Url::Parameters& params, const oatpp::base::String::PtrWrapper& str); + + /** + * parse query params in form of "?=&=..." referred by ParsingCaret + */ + static std::shared_ptr parseQueryParams(oatpp::parser::ParsingCaret& caret); + + /** + * parse query params in form of "?=&=..." referred by str + */ + static std::shared_ptr parseQueryParams(const oatpp::base::String::PtrWrapper& str); + + /** + * parse Url + */ + static Url parseUrl(oatpp::parser::ParsingCaret& caret); + + + }; + +public: + + std::shared_ptr scheme; + Authority authority; + std::shared_ptr path; + std::shared_ptr queryParams; + +}; + +}} + +#endif /* oatpp_network_url_Url_hpp */ diff --git a/web/url/Parser.cpp b/web/url/Parser.cpp deleted file mode 100644 index 0bad2634..00000000 --- a/web/url/Parser.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** - * - * Project _____ __ ____ _ _ - * ( _ ) /__\ (_ _)_| |_ _| |_ - * )(_)( /(__)\ )( (_ _)(_ _) - * (_____)(__)(__)(__) |_| |_| - * - * - * Copyright 2018-present, Leonid Stryzhevskyi, - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ***************************************************************************/ - -#include "Parser.hpp" - -namespace oatpp { namespace web { namespace url { - -void Parser::parseQueryParamsToMap(Parameters& params, oatpp::parser::ParsingCaret& caret) { - - if(caret.findChar('?')) { - - do { - caret.inc(); - oatpp::parser::ParsingCaret::Label nameLabel(caret); - if(caret.findChar('=')) { - nameLabel.end(); - caret.inc(); - oatpp::parser::ParsingCaret::Label valueLabel(caret); - caret.findChar('&'); - params.put(nameLabel.toString(), valueLabel.toString()); - } - } while (caret.canContinueAtChar('&')); - - } - -} - -void Parser::parseQueryParamsToMap(Parameters& params, const oatpp::base::String::PtrWrapper& str) { - oatpp::parser::ParsingCaret caret(str.getPtr()); - parseQueryParamsToMap(params, caret); -} - -std::shared_ptr Parser::parseQueryParams(oatpp::parser::ParsingCaret& caret) { - auto params = Parameters::createShared(); - parseQueryParamsToMap(*params, caret); - return params; -} - -std::shared_ptr Parser::parseQueryParams(const oatpp::base::String::PtrWrapper& str) { - auto params = Parameters::createShared(); - parseQueryParamsToMap(*params, str); - return params; -} - -}}} diff --git a/web/url/Parser.hpp b/web/url/Parser.hpp deleted file mode 100644 index 82aa335e..00000000 --- a/web/url/Parser.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************** - * - * Project _____ __ ____ _ _ - * ( _ ) /__\ (_ _)_| |_ _| |_ - * )(_)( /(__)\ )( (_ _)(_ _) - * (_____)(__)(__)(__) |_| |_| - * - * - * Copyright 2018-present, Leonid Stryzhevskyi, - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ***************************************************************************/ - -#ifndef oatpp_web_url_Parser_hpp -#define oatpp_web_url_Parser_hpp - -#include "oatpp/core/collection/ListMap.hpp" -#include "oatpp/core/parser/ParsingCaret.hpp" - -namespace oatpp { namespace web { namespace url { - -class Parser { -public: - typedef oatpp::collection::ListMap Parameters; -public: - - /** - * parse query params in form of "?=&=..." referred by ParsingCaret - * and put that params to Parameters map - */ - static void parseQueryParamsToMap(Parameters& params, oatpp::parser::ParsingCaret& caret); - - /** - * parse query params in form of "?=&=..." referred by str - * and put that params to Parameters map - */ - static void parseQueryParamsToMap(Parameters& params, const oatpp::base::String::PtrWrapper& str); - - /** - * parse query params in form of "?=&=..." referred by ParsingCaret - */ - static std::shared_ptr parseQueryParams(oatpp::parser::ParsingCaret& caret); - - /** - * parse query params in form of "?=&=..." referred by str - */ - static std::shared_ptr parseQueryParams(const oatpp::base::String::PtrWrapper& str); - -}; - -}}} - -#endif /* oatpp_web_url_Parser_hpp */