1 //===-- Environment.h -------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_UTILITY_ENVIRONMENT_H
10 #define LLDB_UTILITY_ENVIRONMENT_H
11 
12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/Support/Allocator.h"
14 #include "llvm/Support/FormatProviders.h"
15 
16 namespace lldb_private {
17 
18 class Environment : private llvm::StringMap<std::string> {
19   using Base = llvm::StringMap<std::string>;
20 
21 public:
22   class Envp {
23   public:
24     Envp(Envp &&RHS) = default;
25     Envp &operator=(Envp &&RHS) = default;
26 
27     char *const *get() const { return Data; }
28     operator char *const *() const { return get(); }
29 
30   private:
31     explicit Envp(const Environment &Env);
32     char *make_entry(llvm::StringRef Key, llvm::StringRef Value);
33     Envp(const Envp &) = delete;
34     Envp &operator=(const Envp &) = delete;
35     friend class Environment;
36 
37     llvm::BumpPtrAllocator Allocator;
38     char **Data;
39   };
40 
41   using Base::const_iterator;
42   using Base::iterator;
43   using Base::value_type;
44 
45   using Base::begin;
46   using Base::clear;
47   using Base::count;
48   using Base::empty;
49   using Base::end;
50   using Base::erase;
51   using Base::find;
52   using Base::insert;
53   using Base::insert_or_assign;
54   using Base::lookup;
55   using Base::size;
56   using Base::try_emplace;
57   using Base::operator[];
58 
59   Environment() {}
60   Environment(const Environment &RHS) : Base(static_cast<const Base&>(RHS)) {}
61   Environment(Environment &&RHS) : Base(std::move(RHS)) {}
62   Environment(char *const *Env)
63       : Environment(const_cast<const char *const *>(Env)) {}
64   Environment(const char *const *Env);
65 
66   Environment &operator=(Environment RHS) {
67     Base::operator=(std::move(RHS));
68     return *this;
69   }
70 
71   std::pair<iterator, bool> insert(llvm::StringRef KeyEqValue) {
72     auto Split = KeyEqValue.split('=');
73     return insert(std::make_pair(Split.first, std::string(Split.second)));
74   }
75 
76   void insert(iterator first, iterator last);
77 
78   Envp getEnvp() const { return Envp(*this); }
79 
80   static std::string compose(const value_type &KeyValue) {
81     return (KeyValue.first() + "=" + KeyValue.second).str();
82   }
83 };
84 
85 } // namespace lldb_private
86 
87 namespace llvm {
88 template <> struct format_provider<lldb_private::Environment> {
89   static void format(const lldb_private::Environment &Env, raw_ostream &Stream,
90                      StringRef Style) {
91     for (const auto &KV : Env)
92       Stream << "env[" << KV.first() << "] = " << KV.second << "\n";
93   }
94 };
95 } // namespace llvm
96 
97 #endif // LLDB_UTILITY_ENVIRONMENT_H
98