blob: 9ecad2e27770d282054fff24735e5e348d9adcb2 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include <filesystem>
#include <set>
#include <functional>
struct FilePatternTestAccessor;
namespace org::apache::nifi::minifi::utils::file {
class FilePatternError : public std::invalid_argument {
public:
explicit FilePatternError(const std::string& msg) : invalid_argument(msg) {}
};
class FilePattern {
friend struct ::FilePatternTestAccessor;
friend std::set<std::filesystem::path> match(const FilePattern& pattern);
class FilePatternSegmentError : public std::invalid_argument {
public:
explicit FilePatternSegmentError(const std::string& msg) : invalid_argument(msg) {}
};
class FilePatternSegment {
public:
explicit FilePatternSegment(std::string pattern);
enum class MatchResult {
INCLUDE, // dir/file should be processed according to the pattern
EXCLUDE, // dir/file is explicitly rejected by the pattern
NOT_MATCHING // dir/file does not match pattern, do what you may
};
[[nodiscard]] bool isExcluding() const {
return excluding_;
}
[[nodiscard]] MatchResult matchDir(const std::filesystem::path& directory) const;
[[nodiscard]] MatchResult matchFile(const std::filesystem::path& directory, const std::filesystem::path& filename) const;
[[nodiscard]] MatchResult match(const std::filesystem::path& path) const;
/**
* @return The lowermost parent directory without wildcards.
*/
[[nodiscard]]
std::filesystem::path getBaseDirectory() const;
private:
enum class DirMatchResult {
NONE, // pattern does not match the directory (e.g. p = "/home/inner/*test", v = "/home/banana")
PARENT, // directory is a parent of the pattern (e.g. p = "/home/inner/*test", v = "/home/inner")
EXACT, // pattern exactly matches the directory (e.g. p = "/home/inner/*test", v = "/home/inner/cool_test")
TREE // pattern matches the whole subtree of the directory (e.g. p = "/home/**", v = "/home/banana")
};
using DirIt = std::filesystem::path::const_iterator;
static DirMatchResult matchDirectory(DirIt pattern_it, const DirIt& pattern_end, DirIt value_it, const DirIt& value_end);
std::filesystem::path directory_pattern_;
std::string file_pattern_;
bool excluding_;
};
using ErrorHandler = std::function<void(std::string_view /*subpattern*/, std::string_view /*error_message*/)>;
static void defaultErrorHandler(std::string_view subpattern, std::string_view error_message) {
std::string message = "Error in subpattern '";
message += subpattern;
message += "': ";
message += error_message;
throw FilePatternError(message);
}
public:
explicit FilePattern(const std::string& pattern, const ErrorHandler& error_handler = defaultErrorHandler);
private:
std::vector<FilePatternSegment> segments_;
};
std::set<std::filesystem::path> match(const FilePattern& pattern);
} // namespace org::apache::nifi::minifi::utils::file