前回のポストで、REST 部分を抜き出しましたが、それ以外の部分の要素も個別に取得できるクラス Poco::URI がありますので紹介します。
class URIParser
URIParser.h
・Poco::URI の method をそのまま継承。
・前回のポストの GetKeyValues() を getQueryMap() に改名。
・PImpl イディオム(pointer to implementation idiom)を使用し、ファイルの依存関係を削減。
#include <string> #include <vector> #include <map> #include <memory> class URIParser { public: URIParser(const std::string& urlStr); ~URIParser(); int GetURL(std::string& url) const; const std::string& getScheme() const; const std::string& getUserInfo() const; const std::string& getHost() const; unsigned short getPort() const; std::string getAuthority() const; const std::string& getPath() const; std::string getQuery() const; const std::string& getFragment() const; void getPathSegments(std::vector<std::string>& segments); void getQueryMap(std::map<std::string, std::string>& keyValues) const; private: URIParser(); URIParser(const URIParser&); URIParser& operator = (const URIParser&); class URIParserImpl; std::auto_ptr<URIParserImpl> m_pImpl; };
URIParser.cpp
・URIParser::URIParserImpl クラスは Poco::URI を継承し、オリジナルの getQueryMap() だけ追加。
・getQueryMap() 内の restTokenizer で “&” 区切りで分割、さらに keyValueTokenizer で “=” 区切りで
分割。
#include "URIParser.h" #include <Poco/URI.h> #include <Poco/StringTokenizer.h> class URIParser::URIParserImpl : public Poco::URI { public: URIParserImpl(const std::string& urlStr) : Poco::URI(urlStr) { } ~URIParserImpl() { } void getQueryMap(std::map<std::string, std::string>& keyValues) const { if(empty()) return; std::string queryString(getQuery()); if("" == queryString) return; Poco::StringTokenizer restTokenizer(queryString, "&"); for(Poco::StringTokenizer::Iterator itr=restTokenizer.begin(); itr!=restTokenizer.end(); ++itr) { Poco::StringTokenizer keyValueTokenizer(*itr, "="); keyValues[keyValueTokenizer[0]] = (1 < keyValueTokenizer.count()) ? keyValueTokenizer[1]:""; } } private: URIParserImpl(); URIParserImpl(const URIParserImpl&); URIParserImpl& operator = (const URIParserImpl&); }; URIParser::URIParser(const std::string& urlStr) : m_pImpl(new URIParserImpl(urlStr)) { } URIParser::~URIParser() { } const std::string& URIParser::getScheme() const { return m_pImpl->getScheme(); } const std::string& URIParser::getUserInfo() const { return m_pImpl->getUserInfo(); } const std::string& URIParser::getHost() const { return m_pImpl->getHost(); } unsigned short URIParser::getPort() const { return m_pImpl->getPort(); } std::string URIParser::getAuthority() const { return m_pImpl->getAuthority(); } const std::string& URIParser::getPath() const { return m_pImpl->getPath(); } std::string URIParser::getQuery() const { return m_pImpl->getQuery(); } const std::string& URIParser::getFragment() const { return m_pImpl->getFragment(); } void URIParser::getPathSegments(std::vector<std::string>& segments) { m_pImpl->getPathSegments(segments); } void URIParser::getQueryMap(std::map<std::string, std::string>& keyValues) const { m_pImpl->getQueryMap(keyValues); }
URIParserTest.cpp
・ParseURI() で URIParser を使い、ログ出力。
#include <Poco/Logger.h> #include <Poco/PatternFormatter.h> #include <Poco/FormattingChannel.h> #include <Poco/ConsoleChannel.h> #include <Poco/Format.h> #include "ScopedLogMessage.h" #include "URIParser.h" void ParseURI(const std::string& sourceUri) { ScopedLogMessage msg("ParseURI ", "start", "end"); msg.Message(Poco::format(" sourceUri = %s", sourceUri)); URIParser parser(sourceUri); msg.Message(Poco::format(" scheme = %s", parser.getScheme())); msg.Message(Poco::format(" userInfo = %s", parser.getUserInfo())); msg.Message(Poco::format(" host = %s", parser.getHost())); msg.Message(Poco::format(" port = %hu", parser.getPort())); msg.Message(Poco::format(" authority = %s", parser.getAuthority())); msg.Message(Poco::format(" path = %s", parser.getPath())); std::vector<std::string> pathSegments; parser.getPathSegments(pathSegments); for(std::vector<std::string>::iterator itr=pathSegments.begin(); itr!=pathSegments.end(); ++itr) { int count = 0; msg.Message(Poco::format(" path[%d] = %s", count++, *itr)); } msg.Message(Poco::format(" query = %s", parser.getQuery())); std::map<std::string, std::string> keyValues; parser.getQueryMap(keyValues); if(0 != keyValues.size()) { int count = 0; for(std::map<std::string, std::string>::iterator itr=keyValues.begin(); itr!=keyValues.end(); ++itr) { msg.Message(Poco::format(" query[%d] = (%s, %s)", count++, itr->first, itr->second)); } } msg.Message(Poco::format(" fragment = %s", parser.getFragment())); } void PrepareConsoleLogger( const std::string& name, int level=Poco::Message::PRIO_INFORMATION) { Poco::FormattingChannel* pFCConsole = new Poco::FormattingChannel(new Poco::PatternFormatter("%t")); pFCConsole->setChannel(new Poco::ConsoleChannel); pFCConsole->open(); Poco::Logger::create(name, pFCConsole, level); } int main(int /*argc*/, char** /*argv*/) { PrepareConsoleLogger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION); ParseURI("http://www.google.co.jp/search?source=ig&hl=ja&rlz=&q=POCO+Fanatic&meta=lr%3D&aq=f&aqi=&aql=&oq=&gs_rfai="); return 0; }
Results of execution
[0] ParseURI start [0] sourceUri = http://www.google.co.jp/search?source=ig&hl=ja&rlz=&q=POCO+Fanatic&meta=lr%3D&aq=f&aqi=&aql=&oq=&gs_rfai= [0] scheme = http [0] userInfo = [0] host = www.google.co.jp [0] port = 80 [0] authority = www.google.co.jp [0] path = /search [0] path[0] = search [0] query = source=ig&hl=ja&rlz=&q=POCO+Fanatic&meta=lr=&aq=f&aqi=&aql=&oq=&gs_rfai= [0] query[0] = (aq, f) [0] query[1] = (aqi, ) [0] query[2] = (aql, ) [0] query[3] = (gs_rfai, ) [0] query[4] = (hl, ja) [0] query[5] = (meta, lr) [0] query[6] = (oq, ) [0] query[7] = (q, POCO+Fanatic) [0] query[8] = (rlz, ) [0] query[9] = (source, ig) [0] fragment = [0] ParseURI end
Downloads
・ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2010.06.05 11:53 updated)
・2010年4月27日からのダウンロード数:219
Subversion
・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。
Reference
・http://pocoproject.org にある URIandUUID のプレセンテーション。(PDF)
| Copyright © 2010 Round Square Inc. All rights reserved. |
|---|