Skip to content

Instantly share code, notes, and snippets.

@maddinat0r
Created June 4, 2017 21:44
Show Gist options
  • Save maddinat0r/99b64c46e0ec75848971d10f5790bc42 to your computer and use it in GitHub Desktop.
Save maddinat0r/99b64c46e0ec75848971d10f5790bc42 to your computer and use it in GitHub Desktop.
small cpp string parser based on boost::spirit
#include <string>
#include <vector>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
template<char Delimiter = ' ', typename... Args>
bool sscanfpp(std::string const &input, Args &...args)
{
std::vector<std::string> params;
if (!qi::parse(input.begin(), input.end(),
+~qi::char_(Delimiter) % Delimiter,
params))
{
return false;
}
return sscanfpp_parse(params, std::forward<Args&>(args)...);
}
bool sscanfpp_parse(std::vector<std::string> &params)
{
return params.size() == 0;
}
// int overload
template<typename... Args>
bool sscanfpp_parse(std::vector<std::string> &params, int &arg, Args& ...args)
{
std::string const &param = params.front();
bool res = qi::parse(param.begin(), param.end(), qi::int_, arg);
params.erase(params.begin());
return res && sscanfpp_parse(params, std::forward<Args&>(args)...);
}
// float overload
template<typename... Args>
bool sscanfpp_parse(std::vector<std::string> &params, float &arg, Args& ...args)
{
std::string const &param = params.front();
bool res = qi::parse(param.begin(), param.end(), qi::float_, arg);
params.erase(params.begin());
return res && sscanfpp_parse(params, std::forward<Args&>(args)...);
}
// string overload
template<typename... Args>
bool sscanfpp_parse(std::vector<std::string> &params, std::string &arg, Args& ...args)
{
std::string const &param = params.front();
//number as first char is not allowed to distinguish string from int/float
bool res = qi::parse(param.begin(), param.end(), qi::alpha >> *qi::char_, arg);
params.erase(params.begin());
return sscanfpp_parse(params, std::forward<Args&>(args)...);
}
// optional int overload
template<typename... Args>
bool sscanfpp_parse(std::vector<std::string> &params, boost::optional<int> &arg, Args& ...args)
{
std::string const &param = params.front();
bool res = qi::parse(param.begin(), param.end(), -qi::int_, arg);
if (arg)
params.erase(params.begin());
return sscanfpp_parse(params, std::forward<Args&>(args)...);
}
// optional string overload
template<typename... Args>
bool sscanfpp_parse(std::vector<std::string> &params, boost::optional<std::string> &arg, Args& ...args)
{
std::string const &param = params.front();
//number as first char is not allowed to distinguish string from int/float
bool res = qi::parse(param.begin(), param.end(), -(qi::alpha >> *qi::char_), arg);
if (arg)
params.erase(params.begin());
return sscanfpp_parse(params, std::forward<Args&>(args)...);
}
int main()
{
std::string const input{ "text 123 32.2421" };
std::string text1;
boost::optional<std::string> text2;
int number = -1;
float flt = -1.f;
bool res = sscanfpp(input, text1, number, text2, flt);
std::cout << "result: " << res << std::endl;
std::cout << "text1: " << text1 << std::endl;
std::cout << "text2: " << text2 << std::endl;
std::cout << "number: " << number << std::endl;
std::cout << "float: " << flt << std::endl;
std::cin.get();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment