Skip to content

Commit b527ec5

Browse files
committed
Merge branch 'dev'
2 parents b2bbb55 + a2dbc06 commit b527ec5

4 files changed

Lines changed: 73 additions & 78 deletions

File tree

include/vix/utils/Env.hpp

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,43 @@ namespace vix::utils
8080
}
8181
return true;
8282
}
83+
84+
inline std::string_view trim(std::string_view s) noexcept
85+
{
86+
std::size_t b = 0;
87+
std::size_t e = s.size();
88+
89+
while (b < e && std::isspace(static_cast<unsigned char>(s[b])))
90+
++b;
91+
while (e > b && std::isspace(static_cast<unsigned char>(s[e - 1])))
92+
--e;
93+
94+
return std::string_view{s.data() + b, e - b};
95+
}
8396
} // namespace detail
8497

98+
static inline const char *vix_getenv(const char *name) noexcept
99+
{
100+
#if defined(_WIN32)
101+
// _dupenv_s returns heap memory we must free.
102+
static thread_local std::string value;
103+
value.clear();
104+
105+
char *buf = nullptr;
106+
size_t len = 0;
107+
108+
if (_dupenv_s(&buf, &len, name) != 0 || !buf)
109+
return nullptr;
110+
111+
value.assign(buf);
112+
free(buf);
113+
114+
return value.empty() ? nullptr : value.c_str();
115+
#else
116+
return std::getenv(name);
117+
#endif
118+
}
119+
85120
/**
86121
* @brief Returns the value of an environment variable, or a default if not found.
87122
*
@@ -95,11 +130,11 @@ namespace vix::utils
95130
*/
96131
inline std::string env_or(std::string_view key, std::string_view def = "")
97132
{
98-
if (const char *v = std::getenv(std::string(key).c_str()))
133+
const std::string k(key); // stable null-terminated key
134+
if (const char *v = vix_getenv(k.c_str()))
99135
return std::string(v);
100136
return std::string(def);
101137
}
102-
103138
/**
104139
* @brief Reads an environment variable and interprets it as a boolean.
105140
*
@@ -120,21 +155,13 @@ namespace vix::utils
120155
{
121156
using namespace std::literals;
122157
const auto s = env_or(key, def ? "1"sv : "0"sv);
123-
124-
// Trim leading/trailing spaces
125-
std::size_t b = 0, e = s.size();
126-
while (b < e && std::isspace(static_cast<unsigned char>(s[b])))
127-
++b;
128-
while (e > b && std::isspace(static_cast<unsigned char>(s[e - 1])))
129-
--e;
130-
const std::string_view v{s.data() + b, e - b};
158+
const std::string_view v = detail::trim(s);
131159

132160
return v == "1"sv ||
133161
detail::iequals(v, "true") ||
134162
detail::iequals(v, "yes") ||
135163
detail::iequals(v, "on");
136164
}
137-
138165
/**
139166
* @brief Reads an environment variable as a signed integer (base 10).
140167
*
@@ -153,21 +180,13 @@ namespace vix::utils
153180
inline int env_int(std::string_view key, int def = 0)
154181
{
155182
const auto s = env_or(key);
156-
if (s.empty())
157-
return def;
158-
159-
const char *first = s.data();
160-
const char *last = s.data() + s.size();
161-
while (first < last && std::isspace(static_cast<unsigned char>(*first)))
162-
++first;
163-
while (last > first && std::isspace(static_cast<unsigned char>(*(last - 1))))
164-
--last;
165-
if (first >= last)
183+
const std::string_view v = detail::trim(s);
184+
if (v.empty())
166185
return def;
167186

168187
int value = def;
169-
const auto [ptr, ec] = std::from_chars(first, last, value, 10);
170-
if (ec != std::errc{} || ptr != last)
188+
const auto [ptr, ec] = std::from_chars(v.data(), v.data() + v.size(), value, 10);
189+
if (ec != std::errc{} || ptr != v.data() + v.size())
171190
return def;
172191
return value;
173192
}
@@ -189,21 +208,13 @@ namespace vix::utils
189208
inline unsigned env_uint(std::string_view key, unsigned def = 0u)
190209
{
191210
const auto s = env_or(key);
192-
if (s.empty())
193-
return def;
194-
195-
const char *first = s.data();
196-
const char *last = s.data() + s.size();
197-
while (first < last && std::isspace(static_cast<unsigned char>(*first)))
198-
++first;
199-
while (last > first && std::isspace(static_cast<unsigned char>(*(last - 1))))
200-
--last;
201-
if (first >= last)
211+
const std::string_view v = detail::trim(s);
212+
if (v.empty())
202213
return def;
203214

204215
unsigned value = def;
205-
const auto [ptr, ec] = std::from_chars(first, last, value, 10);
206-
if (ec != std::errc{} || ptr != last)
216+
const auto [ptr, ec] = std::from_chars(v.data(), v.data() + v.size(), value, 10);
217+
if (ec != std::errc{} || ptr != v.data() + v.size())
207218
return def;
208219
return value;
209220
}
@@ -225,14 +236,18 @@ namespace vix::utils
225236
inline double env_double(std::string_view key, double def = 0.0)
226237
{
227238
const auto s = env_or(key);
228-
if (s.empty())
239+
const std::string_view v = detail::trim(s);
240+
if (v.empty())
229241
return def;
230242

243+
const std::string tmp(v); // ensure null-terminated for strtod
231244
char *endp = nullptr;
232-
const double v = std::strtod(s.c_str(), &endp);
245+
const double out = std::strtod(tmp.c_str(), &endp);
246+
233247
if (!endp || *endp != '\0')
234248
return def;
235-
return v;
249+
250+
return out;
236251
}
237252

238253
} // namespace Vix::utils

include/vix/utils/Logger.hpp

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
#include <spdlog/spdlog.h>
106106

107107
#include <vix/utils/ConsoleMutex.hpp>
108+
#include <vix/utils/Env.hpp>
108109

109110
#if defined(SPDLOG_FMT_EXTERNAL)
110111
#include <fmt/format.h>
@@ -1079,28 +1080,6 @@ namespace vix::utils
10791080
static std::string c_bool(std::string_view s, bool on) { return ansi_wrap("\033[35m", s, on); }
10801081
static std::string c_punc(std::string_view s, bool on) { return ansi_wrap("\033[90m", s, on); }
10811082

1082-
static inline const char *vix_getenv(const char *name) noexcept
1083-
{
1084-
#if defined(_WIN32)
1085-
// _dupenv_s returns heap memory we must free.
1086-
static thread_local std::string value;
1087-
value.clear();
1088-
1089-
char *buf = nullptr;
1090-
size_t len = 0;
1091-
1092-
if (_dupenv_s(&buf, &len, name) != 0 || !buf)
1093-
return nullptr;
1094-
1095-
value.assign(buf);
1096-
free(buf);
1097-
1098-
return value.empty() ? nullptr : value.c_str();
1099-
#else
1100-
return std::getenv(name);
1101-
#endif
1102-
}
1103-
11041083
/**
11051084
* @brief Whether console synchronization is enabled.
11061085
*
@@ -1110,7 +1089,7 @@ namespace vix::utils
11101089
*/
11111090
static bool console_sync_enabled()
11121091
{
1113-
if (const char *v = vix_getenv("VIX_CONSOLE_SYNC"); v && *v)
1092+
if (const char *v = vix::utils::vix_getenv("VIX_CONSOLE_SYNC"); v && *v)
11141093
return std::string_view(v) != "0" && std::string_view(v) != "false";
11151094
return false;
11161095
}

include/vix/utils/ServerPrettyLogs.hpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <string>
2727

2828
#include <vix/utils/ConsoleMutex.hpp>
29+
#include <vix/utils/Env.hpp>
2930

3031
#if !defined(_WIN32)
3132
#include <unistd.h>
@@ -179,10 +180,10 @@ namespace vix::utils
179180
*/
180181
static bool colors_enabled()
181182
{
182-
if (const char *no = std::getenv("NO_COLOR"); no && *no)
183+
if (const char *no = vix_getenv("NO_COLOR"); no && *no)
183184
return false;
184185

185-
if (const char *v = std::getenv("VIX_COLOR"); v && *v)
186+
if (const char *v = vix_getenv("VIX_COLOR"); v && *v)
186187
{
187188
std::string s(v);
188189
for (auto &c : s)
@@ -208,7 +209,7 @@ namespace vix::utils
208209
*/
209210
static std::string mode_from_env()
210211
{
211-
const char *v = std::getenv("VIX_MODE");
212+
const char *v = vix_getenv("VIX_MODE");
212213
if (!v || !*v)
213214
return "run";
214215

@@ -234,33 +235,33 @@ namespace vix::utils
234235
*/
235236
static bool hyperlinks_enabled()
236237
{
237-
if (const char *no = std::getenv("VIX_NO_HYPERLINK"); no && *no)
238+
if (const char *no = vix_getenv("VIX_NO_HYPERLINK"); no && *no)
238239
return false;
239240

240241
if (!stderr_is_tty())
241242
return false;
242243

243-
if (std::getenv("VSCODE_PID"))
244+
if (vix_getenv("VSCODE_PID"))
244245
return true;
245-
if (std::getenv("WT_SESSION"))
246+
if (vix_getenv("WT_SESSION"))
246247
return true;
247-
if (std::getenv("WEZTERM_EXECUTABLE"))
248+
if (vix_getenv("WEZTERM_EXECUTABLE"))
248249
return true;
249250

250-
if (const char *tp = std::getenv("TERM_PROGRAM"))
251+
if (const char *tp = vix_getenv("TERM_PROGRAM"))
251252
{
252253
std::string s(tp);
253254
if (s == "iTerm.app" || s == "Apple_Terminal" || s == "WezTerm" || s == "vscode")
254255
return true;
255256
}
256257

257-
if (std::getenv("KITTY_WINDOW_ID"))
258+
if (vix_getenv("KITTY_WINDOW_ID"))
258259
return true;
259260

260-
if (std::getenv("VTE_VERSION"))
261+
if (vix_getenv("VTE_VERSION"))
261262
return true;
262263

263-
if (const char *term = std::getenv("TERM"))
264+
if (const char *term = vix_getenv("TERM"))
264265
{
265266
std::string t(term);
266267
if (t.find("screen") != std::string::npos)
@@ -426,13 +427,13 @@ namespace vix::utils
426427
*/
427428
static bool animations_enabled()
428429
{
429-
if (const char *no = std::getenv("VIX_NO_ANIM"); no && *no)
430+
if (const char *no = vix_getenv("VIX_NO_ANIM"); no && *no)
430431
return false;
431432

432433
if (!stderr_is_tty())
433434
return false;
434435

435-
if (const char *nc = std::getenv("NO_COLOR"); nc && *nc)
436+
if (const char *nc = vix_getenv("NO_COLOR"); nc && *nc)
436437
return false;
437438

438439
return true;

src/Logger.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ namespace vix::utils
6969
Logger::Level Logger::parseLevelFromEnv(std::string_view envName, Level fallback)
7070
{
7171
const std::string key(envName);
72-
const char *raw = vix_getenv(key.c_str());
72+
const char *raw = vix::utils::vix_getenv(key.c_str());
7373
if (!raw || !*raw)
7474
return fallback;
7575
return parseLevel(raw);
@@ -222,18 +222,18 @@ namespace vix::utils
222222
void Logger::setFormatFromEnv(std::string_view envName)
223223
{
224224
const std::string key(envName);
225-
const char *raw = vix_getenv(key.c_str());
225+
const char *raw = vix::utils::vix_getenv(key.c_str());
226226
if (!raw || !*raw)
227227
return;
228228
setFormat(parseFormat(raw));
229229
}
230230

231231
bool Logger::jsonColorsEnabled()
232232
{
233-
if (const char *nc = vix_getenv("NO_COLOR"); nc && *nc)
233+
if (const char *nc = vix::utils::vix_getenv("NO_COLOR"); nc && *nc)
234234
return false;
235235

236-
if (const char *c = vix_getenv("VIX_COLOR"); c && *c)
236+
if (const char *c = vix::utils::vix_getenv("VIX_COLOR"); c && *c)
237237
{
238238
const std::string v = lower_copy(c);
239239

0 commit comments

Comments
 (0)