Poco::StringTokenizer

Poco::StringTokenizer は、元になる文字列を、その中に含まれる文字(列)で複数のトークンに分解し、インデックスまたはイテレータでのアクセスを可能にします。

例えば、Google で “POCO Fanatic” を検索すると、URL 欄に:

http://www.google.co.jp/search?source=ig&hl=ja&rlz=&q=POCO+Fanatic&meta=lr%3D&aq=f&aqi=&aql=&oq=&gs_rfai=

と出ますが、この REST (Representational State Transfer) 形式の文字列を Poco::StringTokenizer を使って解析するクラスを紹介します。
(このクラスを POCO::Net ライブラリによる組み込み Web サーバの実装と合わせて使えば、そこそこ使える Web サーバが作れると思います)

class RestParser

RestParser.h

・”?” より前を取得する GetURL() と、REST の Key-Value ペアの map を取得する GetKeyValues()
 とを備える。
PImpl イディオム(pointer to implementation idiom)を使用し、ファイルの依存関係を削減。

#include <string>
#include <map>
#include <memory>
 
class RestParser
{
public:
	RestParser(const std::string& urlStr);
	~RestParser();
	int GetURL(std::string& url) const;
	int GetKeyValues(std::map<std::string, std::string>& keyValues) const;
 
private:
	RestParser();
	RestParser(const RestParser&);
	RestParser& operator = (const RestParser&);
 
	class RestParserImpl;
	std::auto_ptr<RestParserImpl>	m_pImpl;
};

RestParser.cpp

・RestParser::RestParserImpl クラスは Poco::StringTokenizer を継承し、urlStr を “?” の前後で分ける。
・GetKeyValues() 内の restTokenizer で “&” 区切りで分割、さらに keyValueTokenizer で “=” 区切りで
 分割。

#include "RestParser.h"
 
#include <Poco/StringTokenizer.h>
 
class RestParser::RestParserImpl : public Poco::StringTokenizer
{
public:
	RestParserImpl(const std::string& urlStr) :
		Poco::StringTokenizer(urlStr, "?")
	{
	}
	~RestParserImpl()
	{
	}
	int GetURL(std::string& url) const
	{
		if(!IsValidUrlWithRest())	return -1;
 
		url = (*this)[0];
		return 0;
	}
	int GetKeyValues(std::map<std::string, std::string>& keyValues) const
	{
		if(!IsValidUrlWithRest())	return -1;
 
		Poco::StringTokenizer restTokenizer((*this)[1], "&");
		for(Poco::StringTokenizer::Iterator itr=restTokenizer.begin(); itr!=restTokenizer.end(); ++itr)
		{
			Poco::StringTokenizer keyValueTokenizer(*itr, "=");
			keyValues[keyValueTokenizer[0]] = (1 < keyValueTokenizer.count()) ? keyValueTokenizer[1]:"";
		}
		return 0;
	}
 
private:
	RestParserImpl();
	RestParserImpl(const RestParserImpl&);
	RestParserImpl& operator = (const RestParserImpl&);
 
	bool IsValidUrlWithRest(void) const
	{
		return (2 == count());
	}
};
 
RestParser::RestParser(const std::string& urlStr) :
	m_pImpl(new RestParserImpl(urlStr))
{
}
 
RestParser::~RestParser()
{
}
 
int RestParser::GetURL(std::string& url) const
{
	return m_pImpl->GetURL(url);
}
 
int RestParser::GetKeyValues(std::map<std::string, std::string>& keyValues) const
{
	return m_pImpl->GetKeyValues(keyValues);
}

RestParserTest.cpp

・ParseRest() で RestParser を使い、ログ出力。

#include <Poco/Format.h>
 
#include "ScopedLogMessage.h"
#include "PrepareConsoleLogger.h"
#include "RestParser.h"
 
void ParseRest(const std::string& sourceUrl)
{
	ScopedLogMessage msg("ParseRest ", "start", "end");
 
	msg.Message(Poco::format(" sourceUrl = %s", sourceUrl));
 
	RestParser parser(sourceUrl);
 
	std::string url;
	if(0 == parser.GetURL(url))
	{
		msg.Message(Poco::format("  url = %s", url));
	}
 
	std::map<std::string, std::string> keyValues;
	if(0 == parser.GetKeyValues(keyValues))
	{
		int count = 0;
		for(std::map<std::string, std::string>::iterator itr=keyValues.begin(); itr!=keyValues.end(); ++itr)
		{
			msg.Message(Poco::format("  (key, value)[%d] = (%s, %s)", count++, itr->first, itr->second));
		}
	}
}
 
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);
 
	ParseRest("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] ParseRest start
[0]  sourceUrl = 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]   url = http://www.google.co.jp/search
[0]   (key, value)[0] = (aq, f)
[0]   (key, value)[1] = (aqi, )
[0]   (key, value)[2] = (aql, )
[0]   (key, value)[3] = (gs_rfai, )
[0]   (key, value)[4] = (hl, ja)
[0]   (key, value)[5] = (meta, lr%3D)
[0]   (key, value)[6] = (oq, )
[0]   (key, value)[7] = (q, POCO+Fanatic)
[0]   (key, value)[8] = (rlz, )
[0]   (key, value)[9] = (source, ig)
[0] ParseRest end

Downloads

ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年4月25日からのダウンロード数:961

Subversion

・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。

Reference

http://pocoproject.org にある StringsAndFormatting のプレセンテーション。(PDF)

Powered by POCO Copyright © 2010 Round Square Inc. All rights reserved.


Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>