/* */ #include "ParameterizedStringParser.h" #include #include "DlAbortEx.h" #include "util.h" #include "PStringSegment.h" #include "PStringSelect.h" #include "PStringNumLoop.h" #include "NumberDecorator.h" #include "FixedWidthNumberDecorator.h" #include "AlphaNumberDecorator.h" namespace aria2 { SharedHandle ParameterizedStringParser::parse(const std::string& src) { int offset = 0; return diggPString(src, offset); } SharedHandle ParameterizedStringParser::diggPString(const std::string& src, int& offset) { if(src.size() == (size_t)offset) { return SharedHandle(); } switch(src[offset]) { case '[': return createLoop(src, offset); case '{': return createSelect(src, offset); default: return createSegment(src, offset); } } SharedHandle ParameterizedStringParser::createSegment(const std::string& src, int& offset) { std::string::size_type nextDelimiterIndex = src.find_first_of("[{", offset); if(nextDelimiterIndex == std::string::npos) { nextDelimiterIndex = src.size(); } std::string value = src.substr(offset, nextDelimiterIndex-offset); offset = nextDelimiterIndex; SharedHandle next = diggPString(src, offset); return SharedHandle(new PStringSegment(value, next)); } SharedHandle ParameterizedStringParser::createSelect(const std::string& src, int& offset) { ++offset; std::string::size_type rightParenIndex = src.find("}", offset); if(rightParenIndex == std::string::npos) { throw DL_ABORT_EX("Missing '}' in the parameterized string."); } std::vector values; util::split(src.substr(offset, rightParenIndex-offset), std::back_inserter(values), ",", true); if(values.empty()) { throw DL_ABORT_EX("Empty {} is not allowed."); } offset = rightParenIndex+1; SharedHandle next = diggPString(src, offset); return SharedHandle(new PStringSelect(values, next)); } SharedHandle ParameterizedStringParser::createLoop(const std::string& src, int& offset) { ++offset; std::string::size_type rightParenIndex = src.find("]", offset); if(rightParenIndex == std::string::npos) { throw DL_ABORT_EX("Missing ']' in the parameterized string."); } std::string loopStr = src.substr(offset, rightParenIndex-offset); offset = rightParenIndex+1; unsigned int step = 1; std::string::size_type colonIndex = loopStr.find(":"); if(colonIndex != std::string::npos) { std::string stepStr = loopStr.substr(colonIndex+1); if(util::isNumber(stepStr)) { step = util::parseUInt(stepStr); } else { throw DL_ABORT_EX("A step count must be a positive number."); } loopStr.erase(colonIndex); } std::pair range = util::split(loopStr, "-"); if(range.first.empty() || range.second.empty()) { throw DL_ABORT_EX("Loop range missing."); } SharedHandle nd; unsigned int start; unsigned int end; if(util::isNumber(range.first) && util::isNumber(range.second)) { nd.reset(new FixedWidthNumberDecorator(range.first.size())); start = util::parseUInt(range.first); end = util::parseUInt(range.second); } else if(util::isLowercase(range.first) && util::isLowercase(range.second)) { nd.reset(new AlphaNumberDecorator(range.first.size())); start = util::alphaToNum(range.first); end = util::alphaToNum(range.second); } else if(util::isUppercase(range.first) && util::isUppercase(range.second)) { nd.reset(new AlphaNumberDecorator(range.first.size(), true)); start = util::alphaToNum(range.first); end = util::alphaToNum(range.second); } else { throw DL_ABORT_EX("Invalid loop range."); } SharedHandle next(diggPString(src, offset)); return SharedHandle(new PStringNumLoop(start, end, step, nd, next)); } } // namespace aria2