- Не то чтобы я об этом знал, и я ничего не мог найти об этом.
- Да. Это не красиво, но в следующем примере проверяется входная строка на наличие недопустимых символов и возникает ошибка сборки, если она находит. В этом простом примере это позволяет
A-Z, a-z, 0-9, '\', '/', '-', '_', ':' and ' ' (space)
.
Пошаговое описание этого конкретного решения может быть:
- Установить допустимые специальные символы (это действительно должно быть указано пользователем через параметр)
- Получить длину ввода и вычесть 1 (индекс с нуля)
- итерируйте
[i..length-of-string - 1]
и получите соответствующий символ в этой позиции из _name
- попробуйте сопоставить символ с
A-Z
или a-z
, если найден, перейдите к следующему символу
- попробуйте сопоставить символ с
0-9
, если найден, перейдите к следующему символу
- попробуйте сопоставить символ с любым из указанных специальных символов, если он найден, перейти к следующему символу
- повысить ошибку сборки, поскольку текущий символ недопустим
#
# validate_name(<name>)
# Checks if the specified string consists of legal ASCII characters.
# If an illegal character is found, then a build error is produced.
# Legal characters are: A-Z, a-z, 0-9 and '\', '/', '-', '_', ':' and ' '.
#
# _name: The string to examine
#
# Example: validate_name("C:\\foo\\bar")
# validate_name("/home/user/code/project")
#
function(validate_name _name)
# For simplicity, set all valid special characters here.
set(valid_specials "\\\\/-_: ")
string(LENGTH "${_name}" name_length)
math(EXPR name_length "${name_length}-1")
foreach(i RANGE 0 ${name_length})
# Get next character.
string(SUBSTRING "${_name}" ${i} 1 current_char)
# Convert said character to lowercase. This way we don't have to consider
# A-Z explicitly.
string(TOLOWER ${current_char} current_char)
# Is it A-Z or a-z?
if (NOT (("${current_char}" STRLESS "a") OR ("${current_char}" STRGREATER "z")))
# It's A-Z or a-z.
continue()
endif()
# Is it a number?
if (NOT (("${current_char}" STRLESS "0") OR ("${current_char}" STRGREATER "9")))
# It's a number.
continue()
endif()
# Is it a valid "special" character?
string(FIND "${valid_specials}" "${current_char}" valid_special_found)
if (valid_special_found GREATER -1)
continue()
endif()
message(FATAL_ERROR "'${current_char}' is not a legal character in this context.")
endforeach()
endfunction()
Если вы хотите уменьшить размер кода, вы можете поместить все разрешенные символы в одну строку и использовать string(FIND ...)
, очень похоже на то, что делается со специальными символами. В любом случае производительность не будет иметь большого значения. Я сделал это так, чтобы вы знали о STRLESS
и т. Д.
Наконец, в вашем случае вы бы назвали его с помощью: validate_name(${CMAKE_CURRENT_LIST_DIR})
Другое возможное решение - просто использовать регулярное выражение:
set(NAME "home/user/path")
string(REGEX MATCH "[A-Za-z0-9 \\\\/:_-]*" MATCH "${NAME}")
if (NOT "${MATCH}" STREQUAL "${NAME}")
message(FATAL_ERROR "Illegal character(s) found.")
endif()
Будет получена другая строка, если найдены какие-либо символы, не определенные правилом. Если строка верна, то MATCH == NAME
. Обратите внимание, что если первый символ недопустим, CMake
выдаст свою ошибку. Я далеко не эксперт по регулярным выражениям, поэтому уверен, что есть более элегантное решение.
Во всяком случае, я думаю, что это должно как минимум начать. Дайте мне знать, если вам нужны дальнейшие разъяснения.