blob: 7963f9c9685a971bcff7497f032d6a76fb678f19 [file] [log] [blame]
//===- POSIXEnvironment.h ---------------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H
#define LLBUILD_BUILDSYSTEM_PROCESSENVIRONMENT_H
#include "llbuild/Basic/LLVM.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Hashing.h"
#include <unordered_set>
#include <utility>
#include <vector>
namespace std {
template<> struct hash<llvm::StringRef> {
size_t operator()(const llvm::StringRef& value) const {
return size_t(hash_value(value));
}
};
}
namespace llbuild {
namespace buildsystem {
/// A helper class for constructing a POSIX-style environment.
class POSIXEnvironment {
/// The actual environment, this is only populated once frozen.
std::vector<const char*> env;
/// The underlying string storage.
//
// FIXME: This is not efficient, we could store into a single allocation.
std::vector<std::string> envStorage;
/// The list of known keys in the environment.
std::unordered_set<StringRef> keys{};
/// Whether the environment pointer has been vended, and assignments can no
/// longer be mutated.
bool isFrozen = false;
public:
POSIXEnvironment() {}
/// Add a key to the environment, if missing.
///
/// If the key has already been defined, it will **NOT** be inserted.
void setIfMissing(StringRef key, StringRef value) {
assert(!isFrozen);
if (keys.insert(key).second) {
llvm::SmallString<256> assignment;
assignment += key;
assignment += '=';
assignment += value;
assignment += '\0';
envStorage.emplace_back(assignment.str());
}
}
/// Get the envirnonment pointer.
///
/// This pointer is only valid for the lifetime of the environment itself.
const char* const* getEnvp() {
isFrozen = true;
// Form the final environment.
env.clear();
for (const auto& entry: envStorage) {
env.emplace_back(entry.c_str());
}
env.emplace_back(nullptr);
return env.data();
}
};
}
}
#endif