diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index dc592ba23..d7b6a9177 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -58,6 +58,14 @@ bool cmStringCommand::InitialPass(std::vector const& args) { return this->HandleConfigureCommand(args); } + else if(subCommand == "LENGTH") + { + return this->HandleLengthCommand(args); + } + else if(subCommand == "SUBSTRING") + { + return this->HandleSubstringCommand(args); + } std::string e = "does not recognize sub-command "+subCommand; this->SetError(e.c_str()); @@ -522,3 +530,59 @@ bool cmStringCommand::HandleReplaceCommand(std::vector const& args) m_Makefile->AddDefinition(variableName.c_str(), input.c_str()); return true; } + +//---------------------------------------------------------------------------- +bool cmStringCommand::HandleSubstringCommand(std::vector const& args) +{ + if(args.size() != 5) + { + this->SetError("sub-command REPLACE requires four arguments."); + return false; + } + + const std::string& stringValue = args[1]; + int begin = atoi(args[2].c_str()); + int end = atoi(args[3].c_str()); + const std::string& variableName = args[4]; + + size_t stringLength = stringValue.size(); + int intStringLength = static_cast(stringLength); + if ( begin < 0 || begin > intStringLength ) + { + cmOStringStream ostr; + ostr << "begin index: " << begin << " is out of range 0 - " << stringLength; + this->SetError(ostr.str().c_str()); + return false; + } + int leftOverLength = intStringLength - begin; + if ( end < 0 || end > intStringLength ) + { + cmOStringStream ostr; + ostr << "end index: " << end << " is out of range " << 0 << " - " << leftOverLength; + this->SetError(ostr.str().c_str()); + return false; + } + + m_Makefile->AddDefinition(variableName.c_str(), stringValue.substr(begin, end).c_str()); + return true; +} + +//---------------------------------------------------------------------------- +bool cmStringCommand::HandleLengthCommand(std::vector const& args) +{ + if(args.size() != 3) + { + this->SetError("sub-command LENGTH requires two arguments."); + return false; + } + + const std::string& stringValue = args[1]; + const std::string& variableName = args[2]; + + size_t length = stringValue.size(); + char buffer[1024]; + sprintf(buffer, "%d", length); + + m_Makefile->AddDefinition(variableName.c_str(), buffer); + return true; +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index cbdf811f5..8c6a11ca4 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -83,6 +83,8 @@ public: " [@ONLY] [ESCAPE_QUOTES])\n" " STRING(TOUPPER )\n" " STRING(TOLOWER )\n" + " STRING(LENGTH )\n" + " STRING(SUBSTRING )\n" "REGEX MATCH will match the regular expression once and store the " "match in the output variable.\n" "REGEX MATCHALL will match the regular expression as many times as " @@ -104,7 +106,9 @@ public: "ASCII will convert all numbers into corresponding ASCII characters.\n" "CONFIGURE will transform a string like CONFIGURE_FILE transforms " "a file.\n" - "TOUPPER/TOLOWER will convert string to upper/lower characters."; + "TOUPPER/TOLOWER will convert string to upper/lower characters.\n" + "LENGTH will return a given string's length.\n" + "SUBSTRING will return a substring of a given string."; } cmTypeMacro(cmStringCommand, cmCommand); @@ -118,6 +122,8 @@ protected: bool HandleToUpperLowerCommand(std::vector const& args, bool toUpper); bool HandleCompareCommand(std::vector const& args); bool HandleReplaceCommand(std::vector const& args); + bool HandleLengthCommand(std::vector const& args); + bool HandleSubstringCommand(std::vector const& args); class RegexReplacement { diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt index 373e811ab..2cbc785b6 100644 --- a/Tests/StringFileTest/CMakeLists.txt +++ b/Tests/StringFileTest/CMakeLists.txt @@ -22,6 +22,11 @@ STRING(TOUPPER "CMake" tuvar) STRING(TOLOWER "CMake" tlvar) STRING(REPLACE "Autoconf" "CMake" repvar "People should use Autoconf") +STRING(SUBSTRING "People should use Autoconf" 7 10 substringres) +SET(substringres "Everybody ${substringres} CMake") + +STRING(LENGTH ${substringres} lengthres) + FILE(RELATIVE_PATH relpath "/usr/local/bin" "/usr/X11R6/bin/xnest") # Escaping test @@ -54,6 +59,8 @@ FOREACH(var rrepvar repvar relpath + substringres + lengthres nceqvar ceqvar cneqvar diff --git a/Tests/StringFileTest/StringFile.cxx b/Tests/StringFileTest/StringFile.cxx index 67d7c5f69..0601aa031 100644 --- a/Tests/StringFileTest/StringFile.cxx +++ b/Tests/StringFileTest/StringFile.cxx @@ -10,7 +10,9 @@ int main(int, char*[]) res += CheckMethod(rmallvar, "CMake;cmake;CMake"); res += CheckMethod(rrepvar, "People should use CMake and CMake"); res += CheckMethod(repvar, "People should use CMake"); + res += CheckMethod(substringres, "Everybody should use CMake"); res += CheckMethod(nceqvar, "0"); + res += CheckMethod(lengthres, "26"); res += CheckMethod(ceqvar, "1"); res += CheckMethod(cneqvar, "1"); res += CheckMethod(ncneqvar, "0");