A comprehensive modern C++ utility library that provides practical functions for common programming tasks.
NekoFunction integrates multiple functional modules including utilities, archive management, file type detection, and pattern matching capabilities.
- Easy to use
 - Modern C++20
 - Header-only library
 - Cross-platform compatibility
 
- 🎯 Utilities - Operators, string processing, memory management, time handling, cryptography
 - 📦 Archive Management - ZIP archive creation and extraction with encryption support
 - 🔍 File Type Detection - Automatic file type detection based on magic numbers and extensions
 - 🎯 Pattern Matching - Advanced pattern matching for file paths with wildcard and regex support
 
- 🎯 Operators - Pipe operator, fallback operator, optional chaining
 - 🔧 String tools - Case conversion, path processing, file extension checking
 - 🧠 Memory utilities - Array creation, value copying, smart pointer helpers
 - 🔄 Lambda utilities - Common lambda functions for functional programming
 - 🧮 Logic and Math - Boolean operations, sum, product calculations
 - ⏰ Time handling - ISO 8601 parsing, UTC/local time conversion
 - 🔢 Base64 encoding/decoding - Standard Base64 encoding and decoding
 - 🎲 Random utilities - Random strings, numbers, hexadecimal values, UUID generation
 - ✅ Validation utilities - URL validation, proxy address validation, resolution matching
 - 🔒 Hash calculation - MD5, SHA1, SHA256, SHA512 support (requires OpenSSL)
 - 🆔 UUID generation - Support for UUID v3 and v4
 
- 📦 ZIP Archive Support - Create and extract ZIP archives
 - 🔐 Encryption Support - AES256 and ZipCrypto encryption
 - ⚙️ Compression Levels - Configurable compression from none to ultra
 - 🎯 Pattern-based Selection - Include/exclude files using patterns, wildcards, and regex
 
- 🔍 Magic Number Detection - Identify file types by examining file headers
 - 📁 Extension Matching - Validate file types based on extensions
 - 🎯 Dual Validation - Combine magic number and extension for accurate detection
 - 📋 Extensive Format Support - Support for common file formats (images, archives, documents, etc.)
 
- 🎯 Wildcard Patterns - Support for 
*wildcard matching - 🔍 Regular Expressions - Full regex pattern support
 - 📁 Path Matching - Absolute, relative, and directory pattern matching
 - 📝 Extension Patterns - Specialized file extension matching
 
- C++20 or higher compatible compiler
 - CMake 3.14 or higher (if using CMake)
 - Git
 
To enable Archive support, set the NEKO_FUNCTION_ENABLE_ARCHIVER variable to ON (default), and install minizip-ng. Then configure CMake to search for your minizip-ng installation path.
Set the CMAKE_PREFIX_PATH or NEKO_FUNCTION_LIBRARY_PATH variable to your minizip-ng installation directory.
cmake -D NEKO_FUNCTION_ENABLE_ARCHIVER=ON -D CMAKE_PREFIX_PATH=/path/to/your/minizip-ng -B ./build -S .
# or
cmake -D NEKO_FUNCTION_ENABLE_ARCHIVER=ON -D NEKO_FUNCTION_LIBRARY_PATH=/path/to/your/minizip-ng -B ./build -S .If minizip-ng is found, you should see output similar to:
-- Dependency summary:
    ...
--   - minizip-ng support: TRUE version: 4.0.1
--   - Archiver support enabled: TRUE via minizip-ng
    ...To enable Hash support, set the NEKO_FUNCTION_ENABLE_HASH variable to ON (default), and install OpenSSL. Then configure CMake to search for your OpenSSL installation path.
cmake -D NEKO_FUNCTION_ENABLE_HASH=ON -D CMAKE_PREFIX_PATH=/path/to/your/openssl -B ./build -S .
# or
cmake -D NEKO_FUNCTION_ENABLE_HASH=ON -D NEKO_FUNCTION_LIBRARY_PATH=/path/to/your/openssl -B ./build -S .if OpenSSL is found, you should see output similar to:
-- Dependency summary:
    ...
--   - OpenSSL support: TRUE version: 3.0.10
--   - Hash support enabled: TRUE via OpenSSL
    ...Configure: CMake | Manual | Static Linking | Test
Usage:
- Using CMake's 
FetchContentto include NekoFunction in your project: 
include(FetchContent)
# Add NekoFunction to your CMake project
FetchContent_Declare(
    NekoFunction
    GIT_REPOSITORY https://github.com/moehoshio/NekoFunction.git
    GIT_TAG        main
)
FetchContent_MakeAvailable(NekoFunction)
target_link_libraries(your_target PRIVATE NekoFunction)- Include the header files in your code
 
// Core utilities
#include <neko/function/utilities.hpp>
// Archive management
#include <neko/function/archiver.hpp>
// File type detection
#include <neko/function/detectFileType.hpp>
// Pattern matching
#include <neko/function/pattern.hpp>When installing manually, you need to manually fetch the dependency NekoSchema.
After installing the dependency, please continue:
- Clone or download the repository to your host
 
git clone https://github.com/moehoshio/NekoFunction.gitor
curl -L -o NekoFunction.zip https://github.com/moehoshio/NekoFunction/archive/refs/heads/main.zip
unzip NekoFunction.zip- Copy the entire include directory to your include path
 
cp -r NekoFunction/include/ /path/to/your/include/- Include the header files in your code
 
// Core utilities
#include <neko/function/utilities.hpp>
// Archive management
#include <neko/function/archiver.hpp>
// File type detection
#include <neko/function/detectFileType.hpp>
// Pattern matching
#include <neko/function/pattern.hpp>If you want to use static linking, make sure all libraries (OpenSSL, libcurl..) are built as static libraries. (NekoFunction itself is always a static library) Enable the static linking option in your CMake configuration:
cmake -B ./build . -DNEKO_FUNCTION_STATIC_LINK=ON -DNEKO_FUNCTION_LIBRARY_PATH="/path/to/x64-windows-static" -S .The utilities module provides the foundation of NekoFunction, including functional programming operators, string manipulation, memory management, and various utility functions.
Pipe operation that passes the result of the previous expression as input to the next expression.
using namespace neko::ops::pipe;
// Basic usage
auto result = 5 | [](int x) { return x * 2; }; // result = 10
// Chaining operations
auto toUpper = [](std::string s) { return neko::util::string::toUpper<std::string>(s); };
auto result = "hello" 
    | neko::util::plusDoubleQuote 
    | toUpper; // result = "HELLO"Fallback operator that uses the result of the next expression when the previous expression's result is empty. Note: Requires function return result to be convertible to bool and dereferenceable with *.
using namespace neko::ops::fallback;
auto try_parse = [](std::string s) -> std::optional<int> {
    try { return std::stoi(s); }
    catch(...) { return std::nullopt; }
};
auto default_value = [](std::string s) -> int { return -1; };
auto parser = try_parse || default_value;
auto result = parser("invalid"); // result = -1Optional chaining that continuously passes expression results to the next expression when the result is non-empty. If the result is empty, it short-circuits. Note: Requires function return result to be convertible to bool and dereferenceable with * (dereferences value to next expression).
using namespace neko::ops::logic;
std::optional<int> parse(std::string s) { /* ... */ }
std::optional<double> to_double(int x) { return x * 1.5; }
std::optional<std::string> to_string(double x) { return std::to_string(x); };
auto result = parse("42") >>= to_double >>= to_string; // std::optional<std::string> "63.00"using namespace neko::ops::ranges;
// Apply function to range
auto sum = {1, 2, 3, 4} | [](const auto& vec) {
    return std::accumulate(vec.begin(), vec.end(), 0);
}; // sum = 10
using namespace neko::ops::foreach;
// Execute operation on each element
{1, 2, 3} | [](int x) { std::cout << x << " "; }; // Output: 1 2 3note : This conflicts with the syntax of std::ranges::views.
using namespace neko::util::string;
// Add quotes
auto quoted = wrapWith("hello", "\"", "\""); // "hello"
auto quoted2 = wrapWith("world", "'"); // 'world'
// Case conversion
auto lower = toLower<std::string>("HELLO"); // "hello"
auto upper = toUpper<std::string>("world"); // "WORLD"// Get extension
auto ext = getExtensionName("document.txT"); // "txt"
auto ext2 = getExtensionName("archive.TAR.GZ", true); // "GZ" (case sensitive)
// Check extension
bool isText = matchExtensionName("file.txt", "txT"); // true
bool isDoc = matchExtensionNames("doc.pdF", {"txt", "md", "pdf"}); // true
// Path normalization
auto unixPath = convertToUnixPath("C:\\Users\\Name\\file.txt"); // "C:/Users/Name/file.txt"using namespace neko::util::memory;
// Create array
auto arr = makeArray(1, 2, 3, 4); // std::array<int, 4>
// Copy value
auto copied = copy(42); // 42
int* ptr = new int(100);
auto deep_copied_ptr = copy(ptr); // Deep copy pointerLambda wrappers for common utilities, so they can be used with Ops
using namespace neko::util::lambda;
// Common lambdas
auto quoted = "hello" | plusDoubleQuote; // "hello"
auto path = "C:\\test" | unifiedPath; // "C:/test"
auto shared = 42 | makeShared; // std::shared_ptr<int>
auto copied = some_value | copy;using namespace neko::util::logic;
// Boolean conversion
auto str = boolTo<std::string>(true, "yes", "no"); // "yes"
// Logic operations
bool all = allTrue(true, true, false); // false
bool any = anyTrue(false, false, true); // true
using namespace neko::util::math;
// Math operations
auto total = sum(1, 2, 3, 4, 5); // 15
auto product_val = product(2, 3, 4); // 24using namespace neko::util::time;
// Get current time
std::time_t now = getUtcNow(); // Current UTC integer timestamp
std::string nowStr = timeToString( getUtcNow() ); // String timestamp "1680000"
// Format time
auto local_time = getLocalTimeString(); // "2024-01-15-14-30-45"
auto utc_time = getUtcZTimeString(); // "2024-01-15T14:30:45Z"// Parse ISO 8601 format
auto utc_time = parseToUTCTime("2024-01-15T14:30:45Z"); // 1680000
auto utc_str = parseToUTCTimeString("2024-01-15T14:30:45+08:00"); // 168000
auto local_str = parseToLocalTimeString("2024-01-15T14:30:45Z"); // "2024-01-15-20-30-45" Local timeusing namespace neko::util::base64;
// Encoding
auto encoded = base64Encode("Hello, World!"); // "SGVsbG8sIFdvcmxkIQ=="
// Decoding
auto decoded = base64Decode("SGVsbG8sIFdvcmxkIQ=="); // "Hello, World!"using namespace neko::util::random;
// Random hexadecimal string
auto hex = randomHex(8); // "a1b2c3d4"
// Random number, 3-5 digit random number
auto num = randomNDigitNumber(3, 5); // 999
// Random string
auto str = generateRandomString(10); // 10 character random string
auto custom = generateRandomString(8, "ABCDEF0123456789-/.*"); // Custom character setusing namespace neko::util::check;
// URL validation
bool valid_url = isUrl("https://www.example.com"); // true
// Proxy address validation
bool valid_proxy = isProxyAddress("socks5://127.0.0.1:1080"); // true
// Resolution matching
auto res = matchResolution("Set to 1920x1080 resolution");
if (res) {
    std::cout << "Width: " << res.width << ", Height: " << res.height; // Width: 1920, Height: 1080
}using namespace neko::util::hash;
// String hash
auto md5_hash = hash("hello", Algorithm::md5);
auto sha256_hash = hash("hello", Algorithm::sha256);
// File hash
auto file_hash = hashFile("document.txt", Algorithm::sha1);
// Algorithm mapping
auto algo = mapAlgorithm("sha256"); // Algorithm::sha256
auto name = mapAlgorithm(Algorithm::md5); // "md5"using namespace neko::util::uuid;
// UUID v4 (fully random)
auto uuid4 = uuidV4(); // "550e8400-e29b-41d4-a716-446655440000"
#if defined(NEKO_ENABLE_HASH_SUPPORT)
// UUID v3 (requires hash support, name-based)
auto uuid3 = uuidV3("example.com"); // Based on default namespace
auto uuid3_custom = uuidV3("example.com", "custom-namespace-uuid");
#endifThe archive management module provides comprehensive support for creating and extracting ZIP archives with advanced features like encryption and pattern-based file selection.
#include <neko/function/archiver.hpp>
using namespace neko::archive;
// Create archive configuration
CreateConfig createConfig;
createConfig.outputArchivePath = "backup.zip";
createConfig.password = "secret123";
createConfig.compressionLevel = CompressionLevel::maximum;
createConfig.encryption = ZipEncryption::AES256;
// Include specific files and patterns
createConfig.inputPaths = {
    "/path/to/documents/",     // Include entire directory
    "*.txt",                   // Include all text files
    "logs/*.log",              // Include log files in logs directory
    "^config/.*\\.json$"       // Regex: all JSON files in config directory
};
// Exclude patterns
createConfig.excludePaths = {
    "temp/",                   // Exclude temp directory
    "*.tmp"                    // Exclude temporary files
};
// Create the archive
zip::create(createConfig);
// Extract archive configuration
ExtractConfig extractConfig;
extractConfig.inputArchivePath = "backup.zip";
extractConfig.destDir = "/path/to/extract/";
extractConfig.password = "secret123";
extractConfig.overwriteExisting = true;
// Selectively extract files
extractConfig.includePaths = {
    "documents/",              // Extract only documents folder
    "*.pdf"                    // Extract only PDF files
};
// Extract the archive
zip::extract(extractConfig);
// Check if file is a ZIP archive
bool isZip = zip::isZipFile("backup.zip");- Compression Levels: 
none,fast,normal,maximum,ultra - Encryption: 
ZipCrypto,AES256 - Pattern Support: File names, relative paths, absolute paths, wildcards, regex
 - Directory Handling: Include/exclude entire directories
 - Selective Operations: Choose specific files to include or exclude
 
The file type detection module provides accurate file type identification using both magic numbers (file signatures) and file extensions.
#include <neko/function/detectFileType.hpp>
using namespace neko::util::detect;
// Detect file type from file path
auto fileType = detectFileType("/path/to/document.pdf");
if (fileType) {
    std::cout << "Detected type: " << *fileType << std::endl;  // "PDF"
}
// Check if file is of specific type
bool isPdf = isFileType("/path/to/document.pdf", "PDF");
bool isImage = isFileType("/path/to/photo.jpg", "JPEG");
// Detect from file content (when extension is misleading)
auto actualType = detectFileType("/path/to/renamed_file.txt");  // Might detect "PNG" if it's actually an imageThe detection system uses a dual approach:
- Magic Number Scanning: Reads file headers to identify true file type
 - Extension Validation: Verifies that the detected type matches expected extensions
 - Combined Validation: Ensures both magic number and extension are consistent
 
Supported formats include:
- Images: PNG, JPEG, GIF, BMP, TIFF, WebP
 - Archives: ZIP, RAR, 7Z, TAR, GZIP
 - Documents: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX
 - Executables: EXE, DLL, SO, DMG
 - Media: MP3, MP4, AVI, MOV, WAV
 - And many more...
 
The pattern matching module provides sophisticated pattern matching capabilities for file paths and names, supporting wildcards, regular expressions, and various path matching strategies.
#include <neko/function/pattern.hpp>
using namespace neko::util::pattern;
// Basic wildcard matching
bool matches = matchPattern("document.txt", "*.txt");        // true
bool matches2 = matchPattern("logs/app.log", "logs/*.log");  // true
bool matches3 = matchPattern("src/main.cpp", "src/*");       // true
// Check pattern types
bool isWild = containsWildcard("*.txt");      // true
bool isExt = isExtensionPattern(".pdf");      // true
bool isDir = isPatternDir("logs/");           // true// Advanced regex patterns
std::vector<std::string> patterns = {
    "^logs/.*\\.log$",          // Log files in logs directory
    "^config/.*\\.json$",       // JSON files in config directory  
    "^src/.*\\.(cpp|hpp)$"      // C++ source files in src directory
};
std::vector<std::string> testPaths = {
    "logs/application.log",
    "config/settings.json", 
    "src/main.cpp",
    "docs/readme.txt"
};
// Test multiple patterns
for (const auto& path : testPaths) {
    bool matched = matchPatterns(path, patterns);
    if (matched) {
        std::cout << path << " matches one of the patterns" << std::endl;
    }
}// Different path matching strategies
// 1. Absolute path matching
bool exactMatch = matchAbsolutePath("/home/user/docs/file.txt", "/home/user/docs/file.txt");
// 2. Directory containment
bool inDirectory = matchAbsoluteDirectory("/home/user/docs/file.txt", "/home/user/docs/");
// 3. Relative path ending
bool endsWithPath = matchRelativePath("/home/user/docs/project/src/main.cpp", "src/main.cpp");
// 4. Directory name matching
bool hasDirectory = matchDirectoryName("/project/logs/app.log", "logs");
// 5. Extension matching  
bool isTextFile = matchExtension("document.txt", ".txt");
// Combined pattern matching with multiple rules
std::vector<std::string> includePatterns = {
    "/home/user/docs/",         // Absolute directory
    "*.cpp",                    // All C++ files
    "logs/",                    // Any logs directory
    "^config/.*\\.json$"        // JSON files in config (regex)
};
bool shouldInclude = matchPatterns("/home/user/project/src/main.cpp", includePatterns);#include <neko/function/utilities.hpp>
#include <neko/function/archiver.hpp>
#include <neko/function/detectFileType.hpp>
#include <neko/function/pattern.hpp>
#include <iostream>
using namespace neko::ops::pipe;
using namespace neko::util;
using namespace neko::archive;
int main() {
    // Functional style data processing
    auto toUpper = [](std::string s) { return string::toUpper<std::string>(s); };
    auto result = "Hello World" 
        | toUpper
        | lambda::plusDoubleQuote
        | [](const std::string& s) {
            std::cout << "Processing result: " << s << std::endl;
            return s;
        };
    
    // Time handling
    std::time_t now = time::getUtcNow(); 
    auto local_time = time::getLocalTimeString();
    auto utc_time = time::getUtcZTimeString();
    if (logic::allTrue(local_time, utc_time)) {
        std::cout << "Current timestamp: " << now << std::endl;
        std::cout << "Current local time: " << *local_time << std::endl;
        std::cout << "Current UTC time: " << *utc_time << std::endl;
    }
    
    // Random numbers and UUID
    auto random_id = uuid::uuidV4();
    auto random_token = random::generateRandomString(16);
    
    std::cout << "UUID: " << random_id << std::endl;
    std::cout << "Token: " << random_token << std::endl;
    
    // Hash calculation (if OpenSSL is available)
    #ifdef NEKO_ENABLE_HASH_SUPPORT
    auto hash_value = hash::hash("sensitive_data", hash::Algorithm::sha256);
    std::cout << "SHA256: " << hash_value << std::endl;
    #endif
    
    // File type detection
    auto fileType = detect::detectFileType("document.pdf");
    if (fileType) {
        std::cout << "File type detected: " << *fileType << std::endl;
    }
    
    // Pattern matching
    std::vector<std::string> patterns = {"*.cpp", "*.hpp", "logs/*.log"};
    bool matches = pattern::matchPatterns("src/main.cpp", patterns);
    std::cout << "Pattern match result: " << (matches ? "true" : "false") << std::endl;
    
    // Archive creation
    CreateConfig archiveConfig;
    archiveConfig.outputArchivePath = "backup.zip";
    archiveConfig.compressionLevel = CompressionLevel::maximum;
    archiveConfig.inputPaths = {"src/", "*.txt", "docs/"};
    archiveConfig.excludePaths = {"*.tmp", "temp/"};
    
    try {
        zip::create(archiveConfig);
        std::cout << "Archive created successfully!" << std::endl;
    } catch (const std::exception& e) {
        std::cout << "Archive creation failed: " << e.what() << std::endl;
    }
    
    return 0;
}You can run the tests to verify that everything is working correctly.
If you haven't configured the build yet, please run:
# Global options
cmake -D NEKO_BUILD_TESTS=ON -D NEKO_AUTO_FETCH_DEPS=ON -D CMAKE_PREFIX_PATH=<path_to_openssl_and_minizip_ng> -B ./build -S .
# or specify to Neko Function only
cmake -D NEKO_FUNCTION_BUILD_TESTS=ON -D NEKO_FUNCTION_AUTO_FETCH_DEPS=ON -D NEKO_FUNCTION_LIBRARY_PATH=<path_to_openssl_and_minizip_ng> -B ./build -S .Now, you can build the test files (you must build them manually at least once before running the tests!).
cmake --build ./build --config DebugThen, you can run the tests with the following commands:
cd ./build && ctest --output-on-failureIf everything is set up correctly, you should see output similar to the following:
  Test project /path/to/NekoFunction/build
      Start 1: NekoFunction_tests
  1/1 Test #1: NekoFunction_tests ...............   Passed    0.21 sec
  100% tests passed, 0 tests failed out of 1
  Total Test time (real) =   0.21 secIf you want to disable building and running tests, you can set the following CMake option when configuring your project:
cmake -B ./build -DNEKO_FUNCTION_BUILD_TESTS=OFF -S .or
cmake -B ./build -DNEKO_BUILD_TESTS=OFF -S .(Note: This will disable tests for all Neko modules!)
This will skip test targets during the build process.
License MIT OR Apache-2.0
- NekoNet: A modern , easy-to-use C++20 networking library via libcurl.
 - NekoLog: An easy-to-use, modern, lightweight, and efficient C++20 logging library.
 - NekoEvent: A modern easy to use type-safe and high-performance event handling system for C++.
 - NekoSchema: A lightweight, header-only C++20 schema library.
 - NekoSystem: A modern C++20 cross-platform system utility library.
 - NekoFunction: A comprehensive modern C++ utility library that provides practical functions for common programming tasks.
 - NekoThreadPool: An easy to use and efficient C++ 20 thread pool that supports priorities and submission to specific threads.