#include "cgiparam.h" #include #include #include TCgiParameters::TCgiParameters(std::initializer_list> il) { for (const auto& item : il) { insert(item); } } const TString& TCgiParameters::Get(const TStringBuf name, size_t numOfValue) const noexcept { const auto it = Find(name, numOfValue); return end() == it ? Default() : it->second; } bool TCgiParameters::Erase(const TStringBuf name, size_t pos) { const auto pair = equal_range(name); for (auto it = pair.first; it != pair.second; ++it, --pos) { if (0 == pos) { erase(it); return true; } } return false; } bool TCgiParameters::Erase(const TStringBuf name, const TStringBuf val) { const auto pair = equal_range(name); bool found = false; for (auto it = pair.first; it != pair.second;) { if (val == it->second) { it = erase(it); found = true; } else { ++it; } } return found; } bool TCgiParameters::ErasePattern(const TStringBuf name, const TStringBuf pat) { const auto pair = equal_range(name); bool found = false; for (auto it = pair.first; it != pair.second;) { bool startsWith = it->second.StartsWith(pat); if (startsWith) { it = erase(it); found = true; } else { ++it; } } return found; } size_t TCgiParameters::EraseAll(const TStringBuf name) { size_t num = 0; const auto pair = equal_range(name); for (auto it = pair.first; it != pair.second; erase(it++), ++num) ; return num; } void TCgiParameters::JoinUnescaped(const TStringBuf key, char sep, TStringBuf val) { const auto pair = equal_range(key); auto it = pair.first; if (it == pair.second) { // not found if (val.IsInited()) { emplace_hint(it, TString(key), TString(val)); } } else { TString& dst = it->second; for (++it; it != pair.second; erase(it++)) { dst += sep; dst.AppendNoAlias(it->second.data(), it->second.size()); } if (val.IsInited()) { dst += sep; dst += val; } } } static inline TString DoUnescape(const TStringBuf s) { TString res; res.ReserveAndResize(CgiUnescapeBufLen(s.size())); res.resize(CgiUnescape(res.begin(), s).size()); return res; } void TCgiParameters::InsertEscaped(const TStringBuf name, const TStringBuf value) { InsertUnescaped(DoUnescape(name), DoUnescape(value)); } template static inline void DoScan(const TStringBuf s, F& f) { ScanKeyValuesecond); if (++i == end()) { break; } *res++ = '&'; } return res; } size_t TCgiParameters::PrintSize() const noexcept { size_t res = size(); // for '&' for (const auto& i : *this) { res += CgiEscapeBufLen(i.first.size() + i.second.size()); // extra zero will be used for '=' } return res; } TString TCgiParameters::QuotedPrint(const char* safe) const { if (empty()) { return TString(); } TString res; res.ReserveAndResize(PrintSize()); char* ptr = res.begin(); for (auto i = begin();;) { ptr = Quote(ptr, i->first, safe); *ptr++ = '='; ptr = Quote(ptr, i->second, safe); if (++i == end()) { break; } *ptr++ = '&'; } res.ReserveAndResize(ptr - res.data()); return res; } TCgiParameters::const_iterator TCgiParameters::Find(const TStringBuf name, size_t pos) const noexcept { const auto pair = equal_range(name); for (auto it = pair.first; it != pair.second; ++it, --pos) { if (0 == pos) { return it; } } return end(); } bool TCgiParameters::Has(const TStringBuf name, const TStringBuf value) const noexcept { const auto pair = equal_range(name); for (auto it = pair.first; it != pair.second; ++it) { if (value == it->second) { return true; } } return false; } TQuickCgiParam::TQuickCgiParam(const TStringBuf cgiParamStr) { UnescapeBuf.reserve(CgiUnescapeBufLen(cgiParamStr.size())); char* buf = UnescapeBuf.begin(); auto f = [this, &buf](const TStringBuf key, const TStringBuf val) { TStringBuf name = CgiUnescapeBuf(buf, key); buf += name.size() + 1; TStringBuf value = CgiUnescapeBuf(buf, val); buf += value.size() + 1; Y_ASSERT(buf <= UnescapeBuf.begin() + UnescapeBuf.capacity() + 1 /*trailing zero*/); emplace(name, value); }; DoScan(cgiParamStr, f); if (buf != UnescapeBuf.begin()) { UnescapeBuf.ReserveAndResize(buf - UnescapeBuf.begin() - 1 /*trailing zero*/); } } const TStringBuf& TQuickCgiParam::Get(const TStringBuf name, size_t pos) const noexcept { const auto pair = equal_range(name); for (auto it = pair.first; it != pair.second; ++it, --pos) { if (0 == pos) { return it->second; } } return Default(); } bool TQuickCgiParam::Has(const TStringBuf name, const TStringBuf value) const noexcept { const auto pair = equal_range(name); for (auto it = pair.first; it != pair.second; ++it) { if (value == it->second) { return true; } } return false; }