229 if (propValue.empty()) {
243 std::smatch invalid_substring;
244 if (!
m_allowEmptyTokens && std::regex_search(propValue, invalid_substring, REGEX_INVALID))
245 return "Unable to parse filename due to an empty token.";
246 if (!isASCII(propValue))
247 return "Unable to parse filename due to an unsupported non-ASCII character being found.";
249 std::vector<std::vector<std::string>> fileNames;
252 std::sregex_token_iterator end;
253 std::sregex_token_iterator commaToken(propValue.begin(), propValue.end(), REGEX_COMMA_OPERATORS, -1);
255 for (; commaToken != end; ++commaToken) {
256 const std::string commaTokenString = commaToken->str();
259 std::sregex_token_iterator plusToken(commaTokenString.begin(), commaTokenString.end(), REGEX_PLUS_OPERATORS, -1);
261 std::vector<std::vector<std::string>> temp;
265 std::vector<std::string> plusTokenStrings;
266 for (; plusToken != end; ++plusToken)
267 plusTokenStrings.emplace_back(plusToken->str());
270 for (
auto &plusTokenString : plusTokenStrings) {
273 }
catch (
const std::range_error &re) {
276 }
catch (
const std::runtime_error &) {
289 f.emplace_back(1, plusTokenString);
291 if (plusTokenStrings.size() > 1) {
297 return "Adding a range of files to another file(s) is not currently "
301 temp.emplace_back(f[0]);
303 for (
auto &parsedFile : f[0])
304 temp[0].emplace_back(parsedFile);
307 temp.insert(temp.end(), f.begin(), f.end());
311 fileNames.insert(fileNames.end(), std::make_move_iterator(temp.begin()), std::make_move_iterator(temp.end()));
314 std::vector<std::vector<std::string>> allUnresolvedFileNames = fileNames;
315 std::vector<std::vector<std::string>> allFullFileNames;
320 std::string defaultExt;
321 for (
const auto &unresolvedFileName : flattenedAllUnresolvedFileNames) {
324 std::filesystem::path path(unresolvedFileName);
325 if (path.has_extension()) {
326 defaultExt = path.extension().string();
330 }
catch (
const std::exception &) {
338 for (
const auto &unresolvedFileNames : allUnresolvedFileNames) {
339 const auto hasWildCard = [](
const std::string &
name) {
return name.find(
'*') != std::string::npos; };
340 if (std::any_of(unresolvedFileNames.cbegin(), unresolvedFileNames.cend(), hasWildCard))
341 return "Searching for files by wildcards is not currently supported.";
347 std::vector<std::string> filesToResolveWithExtension;
348 std::vector<size_t> resolutionIndices;
349 std::vector<std::string> resolvedFiles(unresolvedFileNames.size());
351 for (
size_t i = 0; i < unresolvedFileNames.size(); ++i) {
352 const auto &unresolvedFileName = unresolvedFileNames[i];
357 std::filesystem::path path(unresolvedFileName);
359 useDefaultExt = !path.has_extension();
360 }
catch (
const std::exception &) {
363 useDefaultExt =
false;
366 if (!useDefaultExt) {
368 std::string
error = slaveFileProp.
setValue(unresolvedFileName);
371 if (!
error.empty()) {
372 throw std::runtime_error(
error);
375 resolvedFiles[i] = slaveFileProp();
378 filesToResolveWithExtension.emplace_back(unresolvedFileName);
379 resolutionIndices.emplace_back(i);
389 if (!filesToResolveWithExtension.empty()) {
390 const auto extsToUse = !defaultExt.empty() ? std::vector<std::string>(1, defaultExt) :
m_exts;
391 bool batchSucceeded =
false;
393 auto resolvedPaths = FileFinder::Instance().findRuns(filesToResolveWithExtension, extsToUse);
394 for (
size_t i = 0; i < resolvedPaths.size(); ++i) {
395 resolvedFiles[resolutionIndices[i]] = resolvedPaths[i].string();
397 batchSucceeded =
true;
402 if (!batchSucceeded) {
403 for (
size_t i = 0; i < filesToResolveWithExtension.size(); ++i) {
404 const auto &unresolvedFileName = filesToResolveWithExtension[i];
405 auto run = FileFinder::Instance().findRun(unresolvedFileName, extsToUse);
407 resolvedFiles[resolutionIndices[i]] = run.result().string();
414 if (std::stoi(unresolvedFileName) != 0)
416 }
catch (std::invalid_argument &) {
425 resolvedFiles[resolutionIndices[i]] = unresolvedFileName;
430 allFullFileNames.emplace_back(std::move(resolvedFiles));