X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fexperimental%2FEnvUtil.h;h=3ab3b16af726bf35aa4add3cdcca6da28318cf15;hp=a44e07bc249a7e744d3fff43f7c72e5dc56b38a4;hb=4fe88e4c921168ffbc53ccfa5210d9b9721d9f29;hpb=ceac4e9ef26fdad9bb3259c2d3702051a331d193 diff --git a/folly/experimental/EnvUtil.h b/folly/experimental/EnvUtil.h index a44e07bc..3ab3b16a 100644 --- a/folly/experimental/EnvUtil.h +++ b/folly/experimental/EnvUtil.h @@ -16,19 +16,106 @@ #pragma once +#include #include #include +#include +#include namespace folly { +namespace experimental { + +// Class to model the process environment in idiomatic C++ +// +// Changes to the modeled environment do not change the process environment +// unless `setAsCurrentEnvironment()` is called. +struct EnvironmentState { + using EnvType = std::unordered_map; + + // Returns an EnvironmentState containing a copy of the current process + // environment. Subsequent changes to the process environment do not + // alter the stored model. If the process environment is altered during the + // execution of this method the results are not defined. + // + // Throws MalformedEnvironment if the process environment cannot be modeled. + static EnvironmentState fromCurrentEnvironment(); + + // Returns an empty EnvironmentState + static EnvironmentState empty() { + return {}; + } + + explicit EnvironmentState(EnvType const& env) : env_(env) {} + explicit EnvironmentState(EnvType&& env) : env_(std::move(env)) {} + + // Get the model environment for querying. + EnvType const& operator*() const { + return env_; + } + EnvType const* operator->() const { + return &env_; + } + + // Get the model environment for mutation or querying. + EnvType& operator*() { + return env_; + } + EnvType* operator->() { + return &env_; + } + + // Update the process environment with the one in the stored model. + // Subsequent changes to the model do not alter the process environment. The + // state of the process environment during execution of this method is not + // defined. If the process environment is altered by another thread during the + // execution of this method the results are not defined. + void setAsCurrentEnvironment(); + + // Get a copy of the model environment in the form used by `folly::Subprocess` + std::vector toVector() const; + + // Get a copy of the model environment in the form commonly used by C routines + // such as execve, execle, etc. Example usage: + // + // EnvironmentState forChild{}; + // ... manipulate `forChild` as needed ... + // execve("/bin/program",pArgs,forChild.toPointerArray().get()); + std::unique_ptr toPointerArray() const; + + private: + EnvironmentState() {} + EnvType env_; +}; + +struct MalformedEnvironment : std::runtime_error { + using std::runtime_error::runtime_error; +}; +} // namespace experimental + namespace test { +// RAII class allowing scoped changes to the process environment. The +// environment state at the time of its construction is restored at the time +// of its destruction. +struct EnvVarSaver { + EnvVarSaver() + : state_(make_unique( + experimental::EnvironmentState::fromCurrentEnvironment())) {} + + EnvVarSaver(EnvVarSaver&& other) noexcept : state_(std::move(other.state_)) {} + + EnvVarSaver& operator=(EnvVarSaver&& other) noexcept { + state_ = std::move(other.state_); + return *this; + } -class EnvVarSaver { - public: - EnvVarSaver(); - ~EnvVarSaver(); + ~EnvVarSaver() { + if (state_) { + state_->setAsCurrentEnvironment(); + } + } private: - std::map saved_; + std::unique_ptr state_; }; -} -} +} // namespace test +} // namespace folly