1# - Manage String by utility functions 2# 3# Defines the following functions: 4# STRING_APPEND(<var> <str> [<separator>]) 5# - Append a string to a variable. 6# * Parameters: 7# + var: A variable that stores the result. 8# + str: A string to be appended to end of line. 9# + separator: Separator to separate between strings. 10# 11# STRING_ESCAPE_BACKSLASH(<var> <str>) 12# - Escape the backslash (\). 13# * Parameters: 14# + var: A variable that stores the result. 15# + str: A string. 16# 17# STRING_ESCAPE_DOLLAR(<var> <str>) 18# - Escape the dollar sign ($). 19# * Parameters: 20# + var: A variable that stores the result. 21# + str: A string. 22# 23# STRING_ESCAPE_QUOTE(<var> <str>) 24# - Escape the double quote ("). 25# * Parameters: 26# + var: A variable that stores the result. 27# + str: A string. 28# 29# STRING_ESCAPE_SEMICOLON(<var> <str>) 30# - Escape the semicolon (;). 31# * Parameters: 32# + var: A variable that stores the result. 33# + str: A string. 34# 35# STRING_PADDING(<var> <str> <length> [<padStr>]) 36# - Padding the string to specified length. 37# * Parameters: 38# + var: A variable that stores the result. 39# + str: A string. 40# + length: Required length. 41# + padStr: String that used in padding. Default: " " 42# 43# STRING_PREPEND(<var> <str> [<separator>]) 44# - Prepend a string to a variable. 45# * Parameters: 46# + var: A variable that stores the result. 47# + str: A string to be appended to end of line. 48# + separator: Separator to separate between strings. 49# 50# STRING_SPLIT(<var> <delimiter> <str> 51# [NOESCAPE_SEMICOLON] [ESCAPE_VARIABLE] [ALLOW_EMPTY] 52# ) 53# - Split a string into a list using a delimiter, 54# which can be in 1 or more characters long. 55# * Parameters: 56# + var: A variable that stores the result. 57# + delimiter: To separate a string. 58# + str: A string. 59# + NOESCAPE_SEMICOLON: (Optional) Do not escape semicolons. 60# + ESCAPE_VARIABLE: (Optional) Escape variables. 61# + ALLOW_EMPTY: (Optional) Allow empty element exist in the array. 62# 63# STRING_TRIM(<var> <str> [NOUNQUOTE]) 64# - Trim a string by removing the leading and trailing spaces, 65# just like STRING(STRIP ...) in CMake 2.6 and later. 66# This macro was developed as CMake 2.4 does not support 67# STRING(STRIP ..) 68# This macro also remove quote and double quote marks around 69# the string, unless NOUNQUOTE is defined. 70# * Parameters: 71# + var: A variable that stores the result. 72# + str: A string. 73# + NOUNQUOTE: (Optional) do not remove the double quote mark 74# around the string. 75# 76# STRING_UNQUOTE(<var> <str>) 77# - Remove double quote marks and quote marks around a string. 78# If the string is not quoted, then content of str is copied to var 79# * Parameters: 80# + var: A variable that stores the result. 81# + str: A string. 82# 83# Defines the following macros: 84# STRING_JOIN(<var> <delimiter> <strList> [<str> ...]) 85# - Concatenate strings, with delimiter inserted between strings. 86# * Parameters: 87# + var: A variable that stores the result. 88# + strList: A list of strings. 89# + str: (Optional) more string to be join. 90# 91 92IF(DEFINED _MANAGE_STRING_CMAKE_) 93 RETURN() 94ENDIF(DEFINED _MANAGE_STRING_CMAKE_) 95SET(_MANAGE_STRING_CMAKE_ "DEFINED") 96 97FUNCTION(STRING_APPEND var str) 98 IF(${ARGC} GREATER 2) 99 SET(_sep "${ARGV2}") 100 ELSE(${ARGC} GREATER 2) 101 SET(_sep "") 102 ENDIF(${ARGC} GREATER 2) 103 IF (POLICY CMP0054) 104 CMAKE_POLICY(PUSH) 105 CMAKE_POLICY(SET CMP0054 "NEW") 106 ENDIF() 107 IF("${${var}}" STREQUAL "") 108 SET(${var} "${str}" PARENT_SCOPE) 109 ELSE("${${var}}" STREQUAL "") 110 SET(${var} "${${var}}${_sep}${str}" PARENT_SCOPE) 111 ENDIF("${${var}}" STREQUAL "") 112 IF (POLICY CMP0054) 113 CMAKE_POLICY(POP) 114 ENDIF() 115ENDFUNCTION(STRING_APPEND var str) 116 117FUNCTION(STRING_ESCAPE_BACKSLASH var str) 118 IF(str STREQUAL "") 119 SET(${var} "" PARENT_SCOPE) 120 ELSE(str STREQUAL "") 121 STRING(REPLACE "\\" "\\\\" output "${str}") 122 SET(${var} "${output}" PARENT_SCOPE) 123 ENDIF(str STREQUAL "") 124ENDFUNCTION(STRING_ESCAPE_BACKSLASH) 125 126FUNCTION(STRING_ESCAPE_DOLLAR var str) 127 IF(str STREQUAL "") 128 SET(${var} "" PARENT_SCOPE) 129 ELSE(str STREQUAL "") 130 STRING(REPLACE "\$" "\\\$" output "${str}") 131 SET(${var} "${output}" PARENT_SCOPE) 132 ENDIF(str STREQUAL "") 133ENDFUNCTION(STRING_ESCAPE_DOLLAR) 134 135FUNCTION(STRING_ESCAPE_QUOTE var str) 136 IF(str STREQUAL "") 137 SET(${var} "" PARENT_SCOPE) 138 ELSE(str STREQUAL "") 139 STRING(REPLACE "\"" "\\\"" output "${str}") 140 SET(${var} "${output}" PARENT_SCOPE) 141 ENDIF(str STREQUAL "") 142ENDFUNCTION(STRING_ESCAPE_QUOTE) 143 144FUNCTION(STRING_ESCAPE_SEMICOLON var str) 145 IF(str STREQUAL "") 146 SET(${var} "" PARENT_SCOPE) 147 ELSE(str STREQUAL "") 148 STRING(REPLACE ";" "\\;" output "${str}") 149 SET(${var} "${output}" PARENT_SCOPE) 150 ENDIF(str STREQUAL "") 151ENDFUNCTION(STRING_ESCAPE_SEMICOLON var str) 152 153FUNCTION(STRING_PADDING var str length) 154 SET(_ret "${str}") 155 IF(${ARGN}) 156 SET(_padStr ${ARGN}) 157 ELSE(${ARGN}) 158 SET(_padStr " ") 159 ENDIF(${ARGN}) 160 STRING(LENGTH "${str}" _strLen) 161 STRING(LENGTH "${_padStr}" _padLen) 162 WHILE( _strLen LESS length) 163 SET(_ret "${_ret}${_padStr}") 164 MATH(EXPR _strLen ${_strLen}+${_padLen}) 165 ENDWHILE( _strLen LESS length) 166 SET(${var} "${_ret}" PARENT_SCOPE) 167ENDFUNCTION(STRING_PADDING var str length) 168 169FUNCTION(STRING_PREPEND var str) 170 IF(${ARGC} GREATER 2) 171 SET(_sep "${ARGV2}") 172 ELSE(${ARGC} GREATER 2) 173 SET(_sep "") 174 ENDIF(${ARGC} GREATER 2) 175 IF("${${var}}" STREQUAL "") 176 SET(${var} "${str}" PARENT_SCOPE) 177 ELSE("${${var}}" STREQUAL "") 178 SET(${var} "${str}${_sep}${${var}}" PARENT_SCOPE) 179 ENDIF("${${var}}" STREQUAL "") 180ENDFUNCTION(STRING_PREPEND var str) 181 182# Return (index of lefttmost non match character) 183# Return _strLen if all characters matches regex 184FUNCTION(STRING_LEFTMOST_NOTMATCH_INDEX var str regex) 185 STRING(LENGTH "${str}" _strLen) 186 SET(_index 0) 187 SET(_ret ${_strLen}) 188 WHILE(_index LESS _strLen) 189 STRING(SUBSTRING "${str}" ${_index} 1 _strCursor) 190 #MESSAGE("***STRING_UNQUOTE: _i=${_index} _strCursor=${_strCursor}") 191 IF(NOT "${_strCursor}" MATCHES "${regex}") 192 SET(_ret ${_index}) 193 SET(_index ${_strLen}) 194 ENDIF(NOT "${_strCursor}" MATCHES "${regex}") 195 196 MATH(EXPR _index ${_index}+1) 197 ENDWHILE(_index LESS _strLen) 198 SET(${var} ${_ret} PARENT_SCOPE) 199ENDFUNCTION(STRING_LEFTMOST_NOTMATCH_INDEX var str) 200 201# Return (index of rightmost non match character) +1 202# Return 0 if all characters matches regex 203# 204FUNCTION(STRING_RIGHTMOST_NOTMATCH_INDEX var str regex) 205 STRING(LENGTH "${str}" _strLen) 206 MATH(EXPR _index ${_strLen}) 207 SET(_ret 0) 208 WHILE(_index GREATER 0) 209 MATH(EXPR _index_1 ${_index}-1) 210 STRING(SUBSTRING "${str}" ${_index_1} 1 _strCursor) 211 #MESSAGE("***STRING_UNQUOTE: _i=${_index} _strCursor=${_strCursor}") 212 213 IF(NOT "${_strCursor}" MATCHES "${regex}") 214 SET(_ret ${_index}) 215 SET(_index 0) 216 ENDIF(NOT "${_strCursor}" MATCHES "${regex}") 217 MATH(EXPR _index ${_index}-1) 218 ENDWHILE(_index GREATER 0) 219 SET(${var} ${_ret} PARENT_SCOPE) 220ENDFUNCTION(STRING_RIGHTMOST_NOTMATCH_INDEX var str) 221 222FUNCTION(STRING_TRIM var str) 223 #_STRING_ESCAPE(_ret "${str}" ${ARGN}) 224 STRING_LEFTMOST_NOTMATCH_INDEX(_leftIndex "${str}" "[ \t\n\r]") 225 STRING_RIGHTMOST_NOTMATCH_INDEX(_rightIndex "${str}" "[ \t\n\r]") 226 # MESSAGE("_left=${_leftIndex} _rightIndex=${_rightIndex} str=|${str}|") 227 MATH(EXPR _subLen ${_rightIndex}-${_leftIndex}) 228 SET(_NOUNQUOTE 0) 229 FOREACH( _arg ${ARGN}) 230 IF(_arg STREQUAL "NOUNQUOTE") 231 SET(_NOUNQUOTE 1) 232 ENDIF(_arg STREQUAL "NOUNQUOTE") 233 ENDFOREACH( _arg ${ARGN}) 234 235 IF(_subLen GREATER 0) 236 STRING(SUBSTRING "${str}" ${_leftIndex} ${_subLen} _ret) 237 # IF _subLen > 1 238 # IF UNQUOTE; then unquote 239 # Otherwise don't touch 240 IF (_subLen GREATER 1) 241 IF(NOT _NOUNQUOTE) 242 STRING_UNQUOTE(_ret "${_ret}") 243 ENDIF(NOT _NOUNQUOTE) 244 ENDIF (_subLen GREATER 1) 245 ELSE(_subLen GREATER 0) 246 SET(_ret "") 247 ENDIF(_subLen GREATER 0) 248 SET(${var} "${_ret}" PARENT_SCOPE) 249 250 # Unencoding 251 #_STRING_UNESCAPE(${var} "${_ret}" ${ARGN}) 252ENDFUNCTION(STRING_TRIM var str) 253 254# Internal function 255# Nested Variable cannot be escaped here, as variable is already substituted 256# at the time it passes to this macro. 257FUNCTION(_STRING_ESCAPE var str) 258 # ';' and '\' are tricky, need to be encoded. 259 # '#' => '#H' 260 # '\' => '#B' 261 # ';' => '#S' 262 # '$' => '#D' 263 SET(_NOESCAPE_SEMICOLON "") 264 SET(_ESCAPE_VARIABLE "") 265 266 FOREACH(_arg ${ARGN}) 267 IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 268 SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON") 269 ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE") 270 SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE") 271 ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 272 ENDFOREACH(_arg ${ARGN}) 273 274 STRING(REGEX REPLACE "#" "#H" _ret "${str}") 275 276 STRING(REGEX REPLACE "\\\\" "#B" _ret "${_ret}") 277 278 IF(NOT _ESCAPE_VARIABLE STREQUAL "") 279 STRING(REGEX REPLACE "$" "#D" _ret "${_ret}") 280 ENDIF(NOT _ESCAPE_VARIABLE STREQUAL "") 281 282 IF(_NOESCAPE_SEMICOLON STREQUAL "") 283 STRING(REGEX REPLACE ";" "#S" _ret "${_ret}") 284 ENDIF(_NOESCAPE_SEMICOLON STREQUAL "") 285 #MESSAGE("_STRING_ESCAPE:_ret=${_ret}") 286 SET(${var} "${_ret}" PARENT_SCOPE) 287ENDFUNCTION(_STRING_ESCAPE var str) 288 289FUNCTION(_STRING_UNESCAPE var str) 290 # '#B' => '\' 291 # '#H' => '#' 292 # '#D' => '$' 293 # '#S' => ';' 294 SET(_ESCAPE_VARIABLE "") 295 SET(_NOESCAPE_SEMICOLON "") 296 SET(_ret "${str}") 297 FOREACH(_arg ${ARGN}) 298 IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 299 SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON") 300 ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE") 301 SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE") 302 STRING(REGEX REPLACE "#D" "$" _ret "${_ret}") 303 ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 304 ENDFOREACH(_arg ${ARGN}) 305 #MESSAGE("###_STRING_UNESCAPE: var=${var} _ret=${_ret} _NOESCAPE_SEMICOLON=${_NOESCAPE_SEMICOLON} ESCAPE_VARIABLE=${_ESCAPE_VARIABLE}") 306 307 STRING(REGEX REPLACE "#B" "\\\\" _ret "${_ret}") 308 IF("${_NOESCAPE_SEMICOLON}" STREQUAL "") 309 # ESCAPE_SEMICOLON 310 STRING(REGEX REPLACE "#S" "\\\\;" _ret "${_ret}") 311 ELSE("${_NOESCAPE_SEMICOLON}" STREQUAL "") 312 # Don't ESCAPE_SEMICOLON 313 STRING(REGEX REPLACE "#S" ";" _ret "${_ret}") 314 ENDIF("${_NOESCAPE_SEMICOLON}" STREQUAL "") 315 316 IF(NOT _ESCAPE_VARIABLE STREQUAL "") 317 # '#D' => '$' 318 STRING(REGEX REPLACE "#D" "$" _ret "${_ret}") 319 ENDIF(NOT _ESCAPE_VARIABLE STREQUAL "") 320 STRING(REGEX REPLACE "#H" "#" _ret "${_ret}") 321 SET(${var} "${_ret}" PARENT_SCOPE) 322 #MESSAGE("*** _STRING_UNESCAPE: ${var}=${${var}}") 323ENDFUNCTION(_STRING_UNESCAPE var str) 324 325FUNCTION(STRING_UNQUOTE var str) 326 SET(_ret "${str}") 327 STRING(LENGTH "${str}" _strLen) 328 329 # IF _strLen > 1 330 # IF lCh and rCh are both "\"" 331 # Remove _lCh and _rCh 332 # ELSEIF lCh and rCh are both "'" 333 # Remove _lCh and _rCh 334 # Otherwise don't touch 335 IF(_strLen GREATER 1) 336 STRING(SUBSTRING "${str}" 0 1 _lCh) 337 MATH(EXPR _strLen_1 ${_strLen}-1) 338 MATH(EXPR _strLen_2 ${_strLen_1}-1) 339 STRING(SUBSTRING "${str}" ${_strLen_1} 1 _rCh) 340 #MESSAGE("_lCh=${_lCh} _rCh=${_rCh} _ret=|${_ret}|") 341 IF("${_lCh}" STREQUAL "\"" AND "${_rCh}" STREQUAL "\"") 342 STRING(SUBSTRING "${_ret}" 1 ${_strLen_2} _ret) 343 ELSEIF("${_lCh}" STREQUAL "'" AND "${_rCh}" STREQUAL "'") 344 STRING(SUBSTRING "${_ret}" 1 ${_strLen_2} _ret) 345 ENDIF("${_lCh}" STREQUAL "\"" AND "${_rCh}" STREQUAL "\"") 346 ENDIF (_strLen GREATER 1) 347 SET(${var} "${_ret}" PARENT_SCOPE) 348ENDFUNCTION(STRING_UNQUOTE var str) 349 350MACRO(STRING_JOIN var delimiter) 351 SET(_ret "") 352 FOREACH(_str ${ARGN}) 353 STRING_APPEND(_ret "${_str}" "${delimiter}") 354 ENDFOREACH(_str ${ARGN}) 355 SET(${var} "${_ret}") 356ENDMACRO(STRING_JOIN var delimiter) 357 358FUNCTION(STRING_FIND var str search_str) 359 STRING(LENGTH "${str}" _str_len) 360 STRING(LENGTH "${search_str}" _search_len) 361 MATH(EXPR _str_end ${_str_len}-${_search_len}+1) 362 363 SET(_index 0) 364 SET(_str_remain "") 365 SET(_result -1) 366 WHILE(_index LESS _str_end) 367 STRING(SUBSTRING "${str}" ${_index} ${_search_len} _str_window) 368 IF(_str_window STREQUAL search_str) 369 SET(_result ${_index}) 370 BREAK() 371 ELSE(_str_window STREQUAL search_str) 372 MATH(EXPR _index ${_index}+1) 373 ENDIF(_str_window STREQUAL search_str) 374 ENDWHILE(_index LESS _str_end) 375 SET(${var} ${_result} PARENT_SCOPE) 376ENDFUNCTION(STRING_FIND var str search) 377 378FUNCTION(STRING_SPLIT_2 var str_remain has_delimiter delimiter str) 379 STRING_FIND(_index "${str}" "${delimiter}") 380 IF(_index EQUAL -1) 381 SET(${has_delimiter} "0" PARENT_SCOPE) 382 SET(${var} "${str}" PARENT_SCOPE) 383 SET(${str_remain} "" PARENT_SCOPE) 384 ELSE(_index EQUAL -1) 385 SET(${has_delimiter} "1" PARENT_SCOPE) 386 STRING(SUBSTRING "${str}" 0 ${_index} _var) 387 SET(${var} "${_var}" PARENT_SCOPE) 388 389 STRING(LENGTH "${str}" _str_len) 390 STRING(LENGTH "${delimiter}" _delimiter_len) 391 MATH(EXPR _str_2_start ${_index}+${_delimiter_len}) 392 MATH(EXPR _str_2_len ${_str_len}-${_index}-${_delimiter_len}) 393 STRING(SUBSTRING "${str}" ${_str_2_start} ${_str_2_len} _str_remain) 394 SET(${str_remain} "${_str_remain}" PARENT_SCOPE) 395 ENDIF(_index EQUAL -1) 396ENDFUNCTION(STRING_SPLIT_2 var str_remain has_delimiter delimiter str) 397 398FUNCTION(STRING_SPLIT var delimiter str) 399 #MESSAGE("***STRING_SPLIT: var=${var} str=${str}") 400 SET(_max_tokens "") 401 SET(_NOESCAPE_SEMICOLON "") 402 SET(_ESCAPE_VARIABLE "") 403 SET(_ALLOW_EMPTY "") 404 FOREACH(_arg ${ARGN}) 405 IF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 406 SET(_NOESCAPE_SEMICOLON "NOESCAPE_SEMICOLON") 407 ELSEIF(${_arg} STREQUAL "ESCAPE_VARIABLE") 408 SET(_ESCAPE_VARIABLE "ESCAPE_VARIABLE") 409 ELSEIF(${_arg} STREQUAL "ALLOW_EMPTY") 410 SET(_ALLOW_EMPTY "ALLOW_EMPTY") 411 ELSE(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 412 SET(_max_tokens ${_arg}) 413 ENDIF(${_arg} STREQUAL "NOESCAPE_SEMICOLON") 414 ENDFOREACH(_arg ${ARGN}) 415 416 IF(NOT _max_tokens) 417 SET(_max_tokens -1) 418 ENDIF(NOT _max_tokens) 419 420 _STRING_ESCAPE(_str "${str}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE}) 421 _STRING_ESCAPE(_delimiter "${delimiter}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE}) 422 SET(_str_list "") 423 SET(_token_count 1) 424 425 WHILE(NOT _token_count EQUAL _max_tokens) 426 STRING_SPLIT_2(_token _str _has_delimiter "${_delimiter}" "${_str}") 427 #MESSAGE("_token_count=${_token_count} _max_tokens=${_max_tokens} _token=|${_token}| _str=${_str}") 428 MATH(EXPR _token_count ${_token_count}+1) 429 # Use length check to avoid the reserved word like "type" 430 STRING(LENGTH "${_token}" _token_len) 431 432 IF(_token_len GREATER 0 OR _ALLOW_EMPTY) 433 LIST(APPEND _str_list "${_token}") 434 ENDIF(_token_len GREATER 0 OR _ALLOW_EMPTY) 435 IF(_has_delimiter EQUAL 0) 436 ## No more tokens 437 BREAK() 438 ENDIF(_has_delimiter EQUAL 0) 439 ENDWHILE(NOT _token_count EQUAL _max_tokens) 440 441 IF(_has_delimiter EQUAL 1) 442 LIST(APPEND _str_list "${_str}") 443 ENDIF(_has_delimiter EQUAL 1) 444 445 # Unencoding 446 _STRING_UNESCAPE(_var "${_str_list}" ${_NOESCAPE_SEMICOLON} ${_ESCAPE_VARIABLE}) 447 #MESSAGE("***STRING_SPLIT: tokens=${${var}}") 448 SET(${var} "${_var}" PARENT_SCOPE) 449ENDFUNCTION(STRING_SPLIT var delimiter str) 450 451