// $Id: RparseUrl.cpp 1070 2018-11-17 09:48:04Z mueller $ // // Copyright 2013-2018 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for complete details. // // Revision History: // Date Rev Version Comment // 2018-11-16 1070 1.1.1 use auto; use emplace,make_pair; use range loop // 2017-04-15 875 1.1 add Set() with default scheme handling // 2015-06-04 686 1.0.2 Set(): add check that optlist is enclosed by '|' // 2013-02-23 492 1.0.1 add static FindScheme(); allow no or empty scheme // 2013-02-03 481 1.0 Initial version, extracted from RlinkPort // --------------------------------------------------------------------------- /*! \file \brief Implemenation of RparseUrl. */ #include #include "RparseUrl.hpp" #include "RosFill.hpp" #include "RosPrintf.hpp" using namespace std; /*! \class Retro::RparseUrl \brief FIXME_docs */ // all method definitions in namespace Retro namespace Retro { //------------------------------------------+----------------------------------- //! Default constructor RparseUrl::RparseUrl() : fUrl(), fScheme(), fPath(), fOptMap() {} //------------------------------------------+----------------------------------- //! Destructor RparseUrl::~RparseUrl() {} //------------------------------------------+----------------------------------- //! FIXME_docs bool RparseUrl::Set(const std::string& url, const std::string& optlist, RerrMsg& emsg) { fUrl = url; fScheme = FindScheme(url); fPath.clear(); fOptMap.clear(); // check that optlist is empty or starts and ends with '|' if (optlist.length() > 0 && (optlist.length()<2 || optlist[0]!='|' || optlist[optlist.length()-1]!='|') ) { emsg.Init("RparseUrl::Set()", string("optlist \"") + optlist + "\" not enclosed in '|'"); return false; } size_t pdel = fScheme.length(); if (pdel == 0 && url.length()>0 && url[0] != ':') pdel = -1; size_t odel = url.find_first_of('?', fScheme.length()); if (odel == string::npos) { // no options if (url.length() > pdel+1) fPath = url.substr(pdel+1); } else { // options to process fPath = url.substr(pdel+1,odel-(pdel+1)); string key; string val; bool hasval = false; for (size_t i=odel+1; i= url.length()) { emsg.Init("RparseUrl::Set()", string("invalid trailing \\ in url '") + url + "'"); return false; } i += 1; switch (url[i]) { case '\\' : c = '\\'; break; case ';' : c = ';'; break; default : emsg.Init("RparseUrl::Set()", string("invalid \\ escape in url '") + url + "'"); return false; } } val.push_back(c); } } } if (key.length() || hasval) { if (!AddOpt(key, val, hasval, optlist, emsg)) return false; } } return true; } //------------------------------------------+----------------------------------- //! FIXME_docs bool RparseUrl::Set(const std::string& url, const std::string& optlist, const std::string& scheme, RerrMsg& emsg) { if (FindScheme(url).length() == 0 && scheme.length() > 0) { string url1 = scheme + string(":") + url; return Set(url1, optlist, emsg); } return Set(url, optlist, emsg); } //------------------------------------------+----------------------------------- //! FIXME_docs void RparseUrl::Clear() { fUrl.clear(); fScheme.clear(); fPath.clear(); fOptMap.clear(); return; } //------------------------------------------+----------------------------------- //! FIXME_docs bool RparseUrl::FindOpt(const std::string& name) const { auto it = fOptMap.find(name); if (it == fOptMap.end()) return false; return true; } //------------------------------------------+----------------------------------- //! FIXME_docs bool RparseUrl::FindOpt(const std::string& name, std::string& value) const { auto it = fOptMap.find(name); if (it == fOptMap.end()) return false; value = it->second; return true; } //------------------------------------------+----------------------------------- //! FIXME_docs void RparseUrl::Dump(std::ostream& os, int ind, const char* text) const { RosFill bl(ind); os << bl << (text?text:"--") << "RparseUrl @ " << this << endl; os << bl << " fUrl: " << fUrl << endl; os << bl << " fScheme: " << fScheme << endl; os << bl << " fPath: " << fPath << endl; os << bl << " fOptMap: " << endl; for (auto& o: fOptMap) { os << bl << " " << RosPrintf(o.first.c_str(), "-s",8) << " : " << o.second << endl; } return; } //------------------------------------------+----------------------------------- //! FIXME_docs std::string RparseUrl::FindScheme(const std::string& url, const std::string& def) { size_t pdel = url.find_first_of(':'); if (pdel == string::npos) { // no : found return def; } size_t odel = url.find_first_of('?'); if (odel != string::npos && odel < pdel) { // : after ? return def; } return url.substr(0, pdel); } //------------------------------------------+----------------------------------- //! FIXME_docs bool RparseUrl::AddOpt(const std::string& key, const std::string& val, bool hasval, const std::string& optlist, RerrMsg& emsg) { string lkey = "|"; lkey += key; if (hasval) lkey += "="; lkey += "|"; if (optlist.find(lkey) == string::npos) { emsg.Init("RparseUrl::AddOpt()", string("invalid field name '") + lkey + "'; allowed: '" + optlist + "'"); return false; } fOptMap.emplace(make_pair(key, hasval ? val : "1")); return true; } } // end namespace Retro