/* */ #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) { int32_t offset = 0; return diggPString(src, offset); } PStringDatumHandle ParameterizedStringParser::diggPString(const std::string& src, int32_t& offset) { if(src.size() == (size_t)offset) { return 0; } 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, int32_t& 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 new PStringSegment(value, next); } PStringDatumHandle ParameterizedStringParser::createSelect(const std::string& src, int32_t& offset) { ++offset; std::string::size_type rightParenIndex = src.find("}", offset); if(rightParenIndex == std::string::npos) { throw new FatalException("Missing '}' in the parameterized string."); } std::deque values; Util::slice(values, src.substr(offset, rightParenIndex-offset), ',', true); if(values.empty()) { throw new FatalException("Empty {} is not allowed."); } offset = rightParenIndex+1; PStringDatumHandle next = diggPString(src, offset); return new PStringSelect(values, next); } PStringDatumHandle ParameterizedStringParser::createLoop(const std::string& src, int32_t& offset) { ++offset; std::string::size_type rightParenIndex = src.find("]", offset); if(rightParenIndex == std::string::npos) { throw new FatalException("Missing ']' in the parameterized string."); } std::string loopStr = src.substr(offset, rightParenIndex-offset); offset = rightParenIndex+1; int32_t 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::parseInt(stepStr); } else { throw new FatalException("A step count must be a number."); } loopStr.erase(colonIndex); } std::pair range = Util::split(loopStr, "-"); if(range.first == "" || range.second == "") { throw new FatalException("Loop range missing."); } NumberDecoratorHandle nd = 0; int32_t start; int32_t end; if(Util::isNumber(range.first) && Util::isNumber(range.second)) { nd = new FixedWidthNumberDecorator(range.first.size()); start = Util::parseInt(range.first); end = Util::parseInt(range.second); } else if(Util::isLowercase(range.first) && Util::isLowercase(range.second)) { nd = 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 = new AlphaNumberDecorator(range.first.size(), true); start = Util::alphaToNum(range.first); end = Util::alphaToNum(range.second); } else { throw new FatalException("Invalid loop range."); } PStringDatumHandle next = diggPString(src, offset); return new PStringNumLoop(start, end, step, nd, next); } } // namespace aria2