/* Copyright 2016, Michele Santullo * This file is part of "dindexer". * * "dindexer" is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * "dindexer" 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 more details. * * You should have received a copy of the GNU General Public License * along with "dindexer". If not, see . */ #include "genericpath.hpp" #include "helpers/infix_iterator.hpp" #include #include #include #include #include namespace qi = boost::spirit::qi; namespace din { namespace { typedef std::vector StringList; std::string hex_to_str (unsigned int parChara) { const char curr = static_cast(parChara); return std::string(&curr, 1); } template struct PathGrammar : public qi::grammar { PathGrammar ( void ); qi::rule start; qi::rule diritem; qi::rule escape; qi::rule hex_code; qi::uint_parser hex_chara; }; template PathGrammar::PathGrammar() : PathGrammar::base_type(start) { namespace px = boost::phoenix; using boost::spirit::qi::lit; using boost::spirit::qi::char_; using boost::spirit::qi::_val; using boost::spirit::_1; start %= *lit("/") >> *(diritem >> *lit("/")); diritem %= +(escape | (char_ - '/' - '\\' - ' ')); escape %= lit("\\") >> (hex_code | char_); hex_code = lit("x") >> hex_chara[_val += px::bind(&hex_to_str, _1)]; } } //unnamed namespace void GenericPath::push_piece (const std::string& parPiece) { using boost::spirit::qi::parse; PathGrammar gramm; auto piece_begin = parPiece.begin(); const std::string::const_iterator piece_end = parPiece.end(); StringList result; const bool parse_result = parse( piece_begin, piece_end, gramm, result ); if (not parPiece.empty() and parPiece[0] == '/') { m_stack.clear(); } for (auto&& itm : result) { if (itm == "..") { if (not m_stack.empty()) { m_stack.pop_back(); } } else if (itm == ".") { } else { m_stack.push_back(std::move(itm)); } } assert(parse_result); } std::string GenericPath::to_string() const { std::ostringstream oss; oss << '/'; boost::copy(m_stack, infix_ostream_iterator(oss, "/")); return oss.str(); } } //namespace din