Skip to content

Commit 271ee72

Browse files
committed
refactor
1 parent fa26d1c commit 271ee72

1 file changed

Lines changed: 161 additions & 0 deletions

File tree

include/vix/utils/String.hpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <algorithm>
2121
#include <cctype>
2222
#include <cstddef>
23+
#include <unordered_map>
2324

2425
/**
2526
* @brief Small string helpers (trim, case transform, prefix/suffix checks, split/join).
@@ -344,6 +345,166 @@ namespace vix::utils
344345
return std::string(b);
345346
}
346347

348+
inline std::string url_decode(std::string_view in)
349+
{
350+
std::string out;
351+
out.reserve(in.size());
352+
353+
for (size_t i = 0; i < in.size(); ++i)
354+
{
355+
const unsigned char c = static_cast<unsigned char>(in[i]);
356+
if (c == '+')
357+
{
358+
out.push_back(' ');
359+
}
360+
else if (c == '%' && i + 2 < in.size())
361+
{
362+
auto hex = [](unsigned char ch) -> int
363+
{
364+
if (ch >= '0' && ch <= '9')
365+
return ch - '0';
366+
if (ch >= 'a' && ch <= 'f')
367+
return 10 + (ch - 'a');
368+
if (ch >= 'A' && ch <= 'F')
369+
return 10 + (ch - 'A');
370+
return -1;
371+
};
372+
373+
int hi = hex(static_cast<unsigned char>(in[i + 1]));
374+
int lo = hex(static_cast<unsigned char>(in[i + 2]));
375+
if (hi >= 0 && lo >= 0)
376+
{
377+
out.push_back(static_cast<char>((hi << 4) | lo));
378+
i += 2;
379+
}
380+
else
381+
{
382+
out.push_back(static_cast<char>(c));
383+
}
384+
}
385+
else
386+
{
387+
out.push_back(static_cast<char>(c));
388+
}
389+
}
390+
391+
return out;
392+
}
393+
394+
inline std::unordered_map<std::string, std::string>
395+
parse_query_string(std::string_view qs)
396+
{
397+
std::unordered_map<std::string, std::string> out;
398+
399+
size_t pos = 0;
400+
while (pos < qs.size())
401+
{
402+
size_t amp = qs.find('&', pos);
403+
if (amp == std::string_view::npos)
404+
amp = qs.size();
405+
406+
std::string_view pair = qs.substr(pos, amp - pos);
407+
if (!pair.empty())
408+
{
409+
size_t eq = pair.find('=');
410+
std::string_view key, val;
411+
if (eq == std::string_view::npos)
412+
{
413+
key = pair;
414+
val = std::string_view{};
415+
}
416+
else
417+
{
418+
key = pair.substr(0, eq);
419+
val = pair.substr(eq + 1);
420+
}
421+
422+
auto key_dec = url_decode(key);
423+
auto val_dec = url_decode(val);
424+
if (!key_dec.empty())
425+
{
426+
out[std::move(key_dec)] = std::move(val_dec);
427+
}
428+
}
429+
430+
if (amp == qs.size())
431+
break;
432+
pos = amp + 1;
433+
}
434+
435+
return out;
436+
}
437+
438+
inline std::unordered_map<std::string, std::string>
439+
extract_params_from_path(const std::string &pattern, std::string_view path)
440+
{
441+
std::unordered_map<std::string, std::string> params;
442+
443+
std::size_t rpos = 0;
444+
std::size_t ppos = 0;
445+
446+
while (rpos < pattern.size() && ppos <= path.size())
447+
{
448+
if (pattern[rpos] == '{')
449+
{
450+
const std::size_t end_brace = pattern.find('}', rpos);
451+
if (end_brace == std::string::npos)
452+
{
453+
break;
454+
}
455+
456+
const std::string name = pattern.substr(rpos + 1, end_brace - rpos - 1);
457+
458+
const std::size_t next_slash = path.find('/', ppos);
459+
const std::string_view value =
460+
(next_slash == std::string_view::npos)
461+
? path.substr(ppos)
462+
: path.substr(ppos, next_slash - ppos);
463+
464+
if (!name.empty())
465+
{
466+
params.emplace(name, std::string(value));
467+
}
468+
469+
rpos = end_brace + 1;
470+
if (next_slash == std::string_view::npos)
471+
{
472+
ppos = path.size();
473+
}
474+
else
475+
{
476+
ppos = next_slash + 1;
477+
}
478+
479+
continue;
480+
}
481+
482+
if (ppos >= path.size() || pattern[rpos] != path[ppos])
483+
{
484+
return {};
485+
}
486+
487+
++rpos;
488+
++ppos;
489+
}
490+
491+
while (rpos < pattern.size())
492+
{
493+
if (pattern[rpos] != '/')
494+
return {};
495+
++rpos;
496+
}
497+
498+
while (ppos < path.size())
499+
{
500+
if (path[ppos] != '/')
501+
return {};
502+
++ppos;
503+
}
504+
505+
return params;
506+
}
507+
347508
} // namespace vix::utils
348509

349510
#endif // VIX_STRING_HPP

0 commit comments

Comments
 (0)