123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #pragma once
- #include <library/cpp/iterator/iterate_values.h>
- #include <util/generic/iterator_range.h>
- #include <util/generic/map.h>
- #include <util/generic/strbuf.h>
- #include <util/generic/string.h>
- #include <initializer_list>
- class TCgiParameters: public TMultiMap<TString, TString> {
- public:
- TCgiParameters() = default;
- explicit TCgiParameters(const TStringBuf cgiParamStr) {
- Scan(cgiParamStr);
- }
- TCgiParameters(std::initializer_list<std::pair<TString, TString>> il);
- void Flush() {
- erase(begin(), end());
- }
- size_t EraseAll(const TStringBuf name);
- size_t NumOfValues(const TStringBuf name) const noexcept {
- return count(name);
- }
- TString operator()() const {
- return Print();
- }
- void Scan(const TStringBuf cgiParStr, bool form = true);
- void ScanAdd(const TStringBuf cgiParStr);
- void ScanAddUnescaped(const TStringBuf cgiParStr);
- void ScanAddAllUnescaped(const TStringBuf cgiParStr);
- void ScanAddAll(const TStringBuf cgiParStr);
- /// Returns the string representation of all the stored parameters
- /**
- * @note The returned string has format <name1>=<value1>&<name2>=<value2>&...
- * @note Names and values in the returned string are CGI-escaped.
- */
- TString Print() const;
- char* Print(char* res) const;
- Y_PURE_FUNCTION
- size_t PrintSize() const noexcept;
- /** The same as Print* except that RFC-3986 reserved characters are escaped.
- * @param safe - set of characters to be skipped in escaping
- */
- TString QuotedPrint(const char* safe = "/") const;
- Y_PURE_FUNCTION
- auto Range(const TStringBuf name) const noexcept {
- return IterateValues(MakeIteratorRange(equal_range(name)));
- }
- Y_PURE_FUNCTION
- const_iterator Find(const TStringBuf name, size_t numOfValue = 0) const noexcept;
- Y_PURE_FUNCTION
- bool Has(const TStringBuf name, const TStringBuf value) const noexcept;
- Y_PURE_FUNCTION
- bool Has(const TStringBuf name) const noexcept {
- const auto pair = equal_range(name);
- return pair.first != pair.second;
- }
- /// Returns value by name
- /**
- * @note The returned value is CGI-unescaped.
- */
- Y_PURE_FUNCTION
- const TString& Get(const TStringBuf name, size_t numOfValue = 0) const noexcept;
- void InsertEscaped(const TStringBuf name, const TStringBuf value);
- #if !defined(__GLIBCXX__)
- template <typename TName, typename TValue>
- inline void InsertUnescaped(TName&& name, TValue&& value) {
- // TStringBuf use as TName or TValue is C++17 actually.
- // There is no pair constructor available in C++14 when required type
- // is not implicitly constructible from given type.
- // But libc++ pair allows this with C++14.
- emplace(std::forward<TName>(name), std::forward<TValue>(value));
- }
- #else
- template <typename TName, typename TValue>
- inline void InsertUnescaped(TName&& name, TValue&& value) {
- emplace(TString(name), TString(value));
- }
- #endif
- // replace all values for a given key with new values
- template <typename TIter>
- void ReplaceUnescaped(const TStringBuf key, TIter valuesBegin, const TIter valuesEnd);
- void ReplaceUnescaped(const TStringBuf key, std::initializer_list<TStringBuf> values) {
- ReplaceUnescaped(key, values.begin(), values.end());
- }
- void ReplaceUnescaped(const TStringBuf key, const TStringBuf value) {
- ReplaceUnescaped(key, {value});
- }
- // join multiple values into a single one using a separator
- // if val is a [possibly empty] non-NULL string, append it as well
- void JoinUnescaped(const TStringBuf key, char sep, TStringBuf val = TStringBuf());
- bool Erase(const TStringBuf name, size_t numOfValue = 0);
- bool Erase(const TStringBuf name, const TStringBuf val);
- bool ErasePattern(const TStringBuf name, const TStringBuf pat);
- inline const char* FormField(const TStringBuf name, size_t numOfValue = 0) const {
- const_iterator it = Find(name, numOfValue);
- if (it == end()) {
- return nullptr;
- }
- return it->second.data();
- }
- inline TStringBuf FormFieldBuf(const TStringBuf name, size_t numOfValue = 0) const {
- const_iterator it = Find(name, numOfValue);
- if (it == end()) {
- return nullptr;
- }
- return it->second.data();
- }
- };
- template <typename TIter>
- void TCgiParameters::ReplaceUnescaped(const TStringBuf key, TIter valuesBegin, const TIter valuesEnd) {
- const auto oldRange = equal_range(key);
- auto current = oldRange.first;
- // reuse as many existing nodes as possible (probably none)
- for (; valuesBegin != valuesEnd && current != oldRange.second; ++valuesBegin, ++current) {
- current->second = *valuesBegin;
- }
- // if there were more nodes than we need to insert then erase remaining ones
- for (; current != oldRange.second; erase(current++)) {
- }
- // if there were less nodes than we need to insert then emplace the rest of the range
- if (valuesBegin != valuesEnd) {
- const TString keyStr = TString(key);
- for (; valuesBegin != valuesEnd; ++valuesBegin) {
- emplace_hint(oldRange.second, keyStr, TString(*valuesBegin));
- }
- }
- }
- /** TQuickCgiParam is a faster non-editable version of TCgiParameters.
- * Care should be taken when replacing:
- * - note that the result of Get() is invalidated when TQuickCgiParam object is destroyed.
- */
- class TQuickCgiParam: public TMultiMap<TStringBuf, TStringBuf> {
- public:
- TQuickCgiParam() = default;
- explicit TQuickCgiParam(const TStringBuf cgiParamStr);
- Y_PURE_FUNCTION
- bool Has(const TStringBuf name, const TStringBuf value) const noexcept;
- Y_PURE_FUNCTION
- bool Has(const TStringBuf name) const noexcept {
- const auto pair = equal_range(name);
- return pair.first != pair.second;
- }
- Y_PURE_FUNCTION
- const TStringBuf& Get(const TStringBuf name, size_t numOfValue = 0) const noexcept;
- private:
- TString UnescapeBuf;
- };
|