From c2e83613f26603b2f9361e104b6e87013346355b Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Fri, 13 Oct 2023 04:23:34 -0700 Subject: [PATCH] initial import --- .gitignore | 18 ++++++ Makefile | 45 ++++++++++++++ rcpp.cc | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 rcpp.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd03c9f --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +.cmake +.trunk +.vc +.vs +.vscode + +*.a +*.o +*.bin +*.pc +build +core +core.* +cmake-build-* +tags + +rcpp + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4c665bb --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +CC := clang +CXX := clang++ +CXXFLAGS := -std=c++17 -g +# CXXFLAGS += -Werror -Wall -Wextra -g -fsanitize=address +LDFLAGS := +SOURCE_DIR ?= "/mnt/Kyle/Documents/Fonts/Equity + Concourse Standard + Triplicate" +TARGET_DIR ?= "$(HOME)/.local/share/fonts" + +SOURCES := rcpp.cc +OBJS := $(patsubst %.cc,%.o,$(filter %.cc,$(SOURCES))) +TARGET := rcpp + +.PHONY: all +all: tags $(TARGET) + +.PHONY: run +run: $(TARGET) + ./$(TARGET) '.+\.ttf$$' $(SOURCE_DIR) $(TARGET_DIR) + +.PHONY: cmake +cmake: build + cd build && cmake --config Debug --build .. + +build: + mkdir -p build + +.PHONY: +clean: + rm -f *.o $(TARGET) + +tags: $(SOURCES) + ctags -o $@ $(SOURCES) + +$(TARGET): $(OBJS) + $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJS) + + +.PHONY: cclean +cclean: + rm -r build cmake-build-* + +print-%: ; @echo '$(subst ','\'',$*=$($*))' + +%.o:%.cc + $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/rcpp.cc b/rcpp.cc new file mode 100644 index 0000000..2c7e204 --- /dev/null +++ b/rcpp.cc @@ -0,0 +1,170 @@ +/// +/// \file rcpp.cc +/// \author kyle +/// \created 2023-10-12 +/// \brief rcpp is a recursive copy by pattern program. +/// +/// \section COPYRIGHT +/// +/// Copyright 2023 K. Isom +/// +/// Permission to use, copy, modify, and/or distribute this software for +/// any purpose with or without fee is hereby granted, provided that +/// the above copyright notice and this permission notice appear in all +/// copies. +/// +/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +/// PERFORMANCE OF THIS SOFTWARE. +/// + + +#include +#include +#include +#include + + +#define ALIAS_FS namespace fs = std::filesystem +typedef std::filesystem::path Path; + + +#ifdef NO_TRACE +static std::ofstream null("/dev/null"); +#define TRACE null +#else +#define TRACE std::cout +#endif + + + +int +preflightDirectory(Path dst) +{ + ALIAS_FS; + if (!fs::exists(dst)) { + fs::create_directory(dst); + } else if (!fs::is_directory(dst)) { + return -1; + } + + return 0; +} + + +int +preflightChecks(Path dst, Path src) +{ + ALIAS_FS; + + if (preflightDirectory(dst) != 0) { + return -1; + } + + if (!fs::exists(src)) { + return -1; + } + + if (!fs::is_regular_file(src)) { + return -1; + } + + return 0; +} + +int +copyToPath(Path dst, Path src) +{ + ALIAS_FS; + + TRACE << "copyToPath " << dst << " " << src << "\n"; + + if (preflightChecks(dst, src)) { + return -1; + } + + Path dstFile = dst / src.filename(); + TRACE << "destination file: " << dstFile << "\n"; + + fs::copy(src, dst, fs::copy_options::update_existing); + return 0; +} + + +int +maybeCopyPattern(Path dst, Path entry, std::regex &pattern) +{ + ALIAS_FS; + + TRACE << "maybeCopyPattern " << entry << "\n"; + if (!fs::is_regular_file(entry)) { + TRACE << "\tnot a file\n"; + return 0; + } + + if (!std::regex_search(entry.string(), pattern)) { + TRACE << "\tpattern doesn't match\n"; + return 0; + } + + return (copyToPath(dst, entry)); +} + + + +int +recursiveCopyPattern(Path &dst, Path &src, std::regex &pattern) +{ + ALIAS_FS; + + if (!fs::exists(src)) { + return -1; + } + + if (!fs::is_directory(src)) { + return -1; + } + + for (auto entry : fs::recursive_directory_iterator(src)) { + TRACE << "found " << entry << "\n"; + if (maybeCopyPattern(dst, entry, pattern)) { + return -1; + } + } + + return 0; +} + + +int +main(int argc, char *argv[]) +{ + ALIAS_FS; + + auto regexOptions = std::regex_constants::optimize; + if (argc < 4) { + std::cerr << "Usage: rcpp pattern files... destination\n"; + } + + auto pattern = std::string(argv[1]); + auto destDir = fs::absolute(fs::path(argv[argc-1])); + bool value; + + TRACE << "argc: " << argc << "\n"; + + auto rePattern = std::regex(pattern); + for (int i = 2; i < argc-1; i++) { + TRACE << "[" << i << "] consider " << argv[i] << "\n"; + auto src = fs::path(argv[i]); + if (recursiveCopyPattern(destDir, src, rePattern) != 0) { + TRACE << "failed\n"; + } + } + + return 0; +}