-
Notifications
You must be signed in to change notification settings - Fork 0
/
env.cpp
152 lines (131 loc) · 4.02 KB
/
env.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "stdafx.h"
#include "cfg.h"
using namespace std;
constexpr WCHAR ENV_DELIMITER = L'=';
constexpr WCHAR ENV_DELIMITER_S[] = L"=";
optional<tuple<wstring, wstring>> try_match(const wstring& s) {
constexpr int match_size = 3;
constexpr int name_match_index = 1;
constexpr int value_match_index = 2;
static wregex rgx(L"(\\w+)=(.*)"); wsmatch matches;
if (regex_search(s, matches, rgx)) {
if (matches.size() == match_size) {
return optional<tuple<wstring, wstring>> {
{
matches[name_match_index].str(), matches[value_match_index].str()
}
};
}
}
return nullopt;
}
bool iequals(const std::wstring_view& a, const std::wstring_view& b) {
return std::equal(a.begin(), a.end(),
b.begin(), b.end(),
[](char a, char b) {
return tolower(a) == tolower(b);
});
}
void prefix_env(list<wstring>& env_list, list<wstring>& config_list) {
for (wstring& s : env_list) {
if (auto kvp = try_match(s)) {
wstring name, value;
tie(name, value) = *kvp;
wstring new_val = value;
bool has_prefix = false;
for (const wstring& cs : config_list) {
if (auto ckvp = try_match(cs)) {
wstring cname, cvalue;
tie(cname, cvalue) = *ckvp;
if (iequals(cname, name)) {
new_val = cvalue + new_val;
has_prefix = true;
}
}
}
if (has_prefix) {
s = name + L"=" + new_val;
}
}
}
}
void replace_env(list<wstring>& env_list, const list<wstring>& config_list) {
for (wstring& s : env_list) {
if (auto kvp = try_match(s)) {
wstring name, value;
tie(name, value) = *kvp;
for (const wstring& cs : config_list) {
if (auto ckvp = try_match(cs)) {
wstring cname, cvalue;
tie(cname, cvalue) = *ckvp;
if (iequals(cname, name)) {
s = name + L"=" + cvalue;
}
}
}
}
}
for (const wstring& cs : config_list) {
if (auto ckvp = try_match(cs)) {
bool append = true;
wstring cname;
tie(cname, ignore) = *ckvp;
for (wstring& s : env_list) {
if (auto kvp = try_match(s)) {
wstring name;
tie(name, ignore) = *kvp;
if (iequals(name, cname)) {
append = false;
break;
}
}
}
if (append) {
env_list.push_back(cs);
}
}
}
}
void parse_env(list<wstring>& env_list) {
const LPWCH env = GetEnvironmentStrings();
LPWCH p = env;
while (*p) {
const size_t n = wcslen(p);
wstring s{ p, n };
env_list.emplace_back(s);
p += n + 1;
}
BOOL rt = FreeEnvironmentStrings(env);
assert(rt);
}
unique_ptr<wchar_t[]> env_list_to_block(const list<wstring>& env_list) {
size_t total = 0;
for (const wstring& s : env_list) {
total += s.length() + 1;
}
total += 1;
unique_ptr<wchar_t[]> rv = make_unique<wchar_t[]>(total);
wchar_t* p = rv.get();
for (const wstring& s : env_list) {
const size_t size = s.length();
s.copy(p, size);
p += size;
*p = L'\0';
p++;
}
*p = L'\0';
return rv;
}
unique_ptr<wchar_t[]> build_env_block()
{
list<wstring> env_list{};
parse_env(env_list);
list<wstring> replace_list{};
CIniConfig::GetEnvList(replace_list);
replace_env(env_list, replace_list);
list<wstring> prefix_list{};
CIniConfig::GetEnvPrefixList(prefix_list);
prefix_env(env_list, prefix_list);
unique_ptr<wchar_t[]> rv = env_list_to_block(env_list);
return rv;
}