/* */ #include "ParameterizedStringParser.h" #include "FatalException.h" #include "Util.h" #include "PStringSegment.h" #include "PStringSelect.h" #include "PStringNumLoop.h" #include "NumberDecorator.h" #include "FixedWidthNumberDecorator.h" #include "AlphaNumberDecorator.h" #include namespace aria2 { PStringDatumHandle ParameterizedStringParser::parse(const std::string& src) { int offset = 0; return diggPString(src, offset); } PStringDatumHandle 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); } } PStringDatumHandle 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; PStringDatumHandle next = diggPString(src, offset); return SharedHandle(new PStringSegment(value, next)); } PStringDatumHandle ParameterizedStringParser::createSelect(const std::string& src, int& offset) { ++offset; std::string::size_type rightParenIndex = src.find("}", offset); if(rightParenIndex == std::string::npos) { throw FatalException("Missing '}' in the parameterized string."); } std::deque values; Util::slice(values, src.substr(offset, rightParenIndex-offset), ',', true); if(values.empty()) { throw FatalException("Empty {} is not allowed."); } offset = rightParenIndex+1; PStringDatumHandle next = diggPString(src, offset); return SharedHandle(new PStringSelect(values, next)); } PStringDatumHandle ParameterizedStringParser::createLoop(const std::string& src, int& offset) { ++offset; std::string::size_type rightParenIndex = src.find("]", offset); if(rightParenIndex == std::string::npos) { throw FatalException("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 FatalException("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 FatalException("Loop range missing."); } NumberDecoratorHandle 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 FatalException("Invalid loop range."); } PStringDatumHandle next(diggPString(src, offset)); return SharedHandle(new PStringNumLoop(start, end, step, nd, next)); } } // namespace aria2