123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- #include "cgiparam.h"
- #include <library/cpp/string_utils/scan/scan.h>
- #include <library/cpp/string_utils/quote/quote.h>
- #include <util/generic/singleton.h>
- TCgiParameters::TCgiParameters(std::initializer_list<std::pair<TString, TString>> 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<TString>() : 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 <bool addAll, class F>
- static inline void DoScan(const TStringBuf s, F& f) {
- ScanKeyValue<addAll, '&', '='>(s, f);
- }
- struct TAddEscaped {
- TCgiParameters* C;
- inline void operator()(const TStringBuf key, const TStringBuf val) {
- C->InsertEscaped(key, val);
- }
- };
- void TCgiParameters::Scan(const TStringBuf query, bool form) {
- Flush();
- form ? ScanAdd(query) : ScanAddAll(query);
- }
- void TCgiParameters::ScanAdd(const TStringBuf query) {
- TAddEscaped f = {this};
- DoScan<false>(query, f);
- }
- void TCgiParameters::ScanAddUnescaped(const TStringBuf query) {
- auto f = [this](const TStringBuf key, const TStringBuf val) {
- this->InsertUnescaped(key, val);
- };
- DoScan<false>(query, f);
- }
- void TCgiParameters::ScanAddAllUnescaped(const TStringBuf query) {
- auto f = [this](const TStringBuf key, const TStringBuf val) {
- this->InsertUnescaped(key, val);
- };
- DoScan<true>(query, f);
- }
- void TCgiParameters::ScanAddAll(const TStringBuf query) {
- TAddEscaped f = {this};
- DoScan<true>(query, f);
- }
- TString TCgiParameters::Print() const {
- TString res;
- res.ReserveAndResize(PrintSize());
- const char* end = Print(res.begin());
- res.ReserveAndResize(end - res.data());
- return res;
- }
- char* TCgiParameters::Print(char* res) const {
- if (empty()) {
- return res;
- }
- for (auto i = begin();;) {
- res = CGIEscape(res, i->first);
- *res++ = '=';
- res = CGIEscape(res, i->second);
- 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.ReserveAndResize(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<false>(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<TStringBuf>();
- }
- 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;
- }
|