// Copyright (c) 2016-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). #pragma once #ifndef ROCKSDB_LITE #include #include #include #include #include #include "rocksdb/env.h" namespace rocksdb { // Creates a new T using the factory function that was registered with a pattern // that matches the provided "target" string according to std::regex_match. // // If no registered functions match, returns nullptr. If multiple functions // match, the factory function used is unspecified. // // Populates res_guard with result pointer if caller is granted ownership. template T* NewCustomObject(const std::string& target, std::unique_ptr* res_guard); // Returns a new T when called with a string. Populates the unique_ptr argument // if granting ownership to caller. template using FactoryFunc = std::function*)>; // To register a factory function for a type T, initialize a Registrar object // with static storage duration. For example: // // static Registrar hdfs_reg("hdfs://.*", &CreateHdfsEnv); // // Then, calling NewCustomObject("hdfs://some_path", ...) will match the // regex provided above, so it returns the result of invoking CreateHdfsEnv. template class Registrar { public: explicit Registrar(std::string pattern, FactoryFunc factory); }; // Implementation details follow. namespace internal { template struct RegistryEntry { std::regex pattern; FactoryFunc factory; }; template struct Registry { static Registry* Get() { static Registry instance; return &instance; } std::vector> entries; private: Registry() = default; }; } // namespace internal template T* NewCustomObject(const std::string& target, std::unique_ptr* res_guard) { res_guard->reset(); for (const auto& entry : internal::Registry::Get()->entries) { if (std::regex_match(target, entry.pattern)) { return entry.factory(target, res_guard); } } return nullptr; } template Registrar::Registrar(std::string pattern, FactoryFunc factory) { internal::Registry::Get()->entries.emplace_back(internal::RegistryEntry{ std::regex(std::move(pattern)), std::move(factory)}); } } // namespace rocksdb #endif // ROCKSDB_LITE