Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
InternetMediaType.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
9#include "Stroika/Foundation/Containers/SortedMapping.h"
10#include "Stroika/Foundation/DataExchange/BadFormatException.h"
11
12#include "InternetMediaType.h"
13
14using namespace Stroika::Foundation;
17using namespace Stroika::Foundation::Execution;
18
19/*
20 ********************************************************************************
21 **************************** InternetMediaType *********************************
22 ********************************************************************************
23 */
25{
26 // @todo RECALL / DOCUMENT where I got this regexp from - roughly corresponds to https://tools.ietf.org/html/rfc2045#section-5.1
27
28 // ROUGHLY based on
29 // grammar from RFC 2045 Section 5.1 and RFC 7231 Section 3.1.1.1
30 // and
31 // https://tools.ietf.org/html/rfc2045#section-5.1
32 // https://tools.ietf.org/html/rfc7230#section-3.2.6
33 //
34 // but I'm not sure its really correct (but probably OK)
35 // based on https://www.regextester.com/110183 and fiddling with that regexp to add suffix/params
36 static const RegularExpression kTopLevelMatcher_ = "(^[-\\w.]+)/([-\\w.]+)(\\+[a-z]*)?(.*)"_RegEx;
38 if (ct.Matches (kTopLevelMatcher_, &matches) and matches.length () >= 2) {
39 fType_ = matches[0];
40 fSubType_ = matches[1];
41 if (matches.length () >= 3 and matches[2].length () > 1) {
42 fSuffix_ = matches[2].SubString (1);
43 }
44 if (matches.length () == 4) {
45 String moreParameters = matches[3];
46 while (not moreParameters.empty ()) {
47 static const RegularExpression kParameterMatcher_ = "\\s*;\\s*([_\\-[:alnum:]]+)\\s*=\\s*(\\S+)(.*)"_RegEx;
48 matches.clear ();
49 if (moreParameters.Matches (kParameterMatcher_, &matches)) {
50 String pName = matches[0];
51 String pValue = matches[1];
52 if (pValue.StartsWith ("\""_k) and pValue.EndsWith ("\""_k)) {
53 pValue = pValue.SubString (1, -1);
54 }
55 fParameters_.Add (pName, pValue);
56 if (matches.length () == 3) {
57 moreParameters = matches[2];
58 }
59 else {
60 break;
61 }
62 }
63 else {
64 break; // rest allowed - treated as comments
65 }
66 }
67 }
68 }
69 else {
70 static const auto kException_ = BadFormatException{"Badly formatted InternetMediaType"sv};
71 Execution::Throw (kException_);
72 }
73}
74
76{
77 return Characters::ToString (As<String> ()); // format this string as any other normal string
78}
79
80template <>
82{
83 if (empty ()) {
84 return String{};
85 }
87 sb << fType_.GetPrintName () << "/"sv << fSubType_.GetPrintName ();
88 if (fSuffix_) {
89 sb << "+"sv << fSuffix_->GetPrintName ();
90 }
91 for (const auto& p : fParameters_) {
92 sb << "; "sv << p.fKey << ": "sv << p.fValue;
93 }
94 return sb;
95}
96
97strong_ordering InternetMediaType::THREEWAYCOMPARE_ (const InternetMediaType& rhs) const
98{
99 strong_ordering cmp = fType_ <=> rhs.fType_;
100 if (cmp != strong_ordering::equal) {
101 return cmp;
102 }
103 cmp = fSubType_ <=> rhs.fSubType_;
104 if (cmp != strong_ordering::equal) {
105 return cmp;
106 }
107 cmp = Common::StdCompat::compare_three_way{}(fSuffix_, rhs.fSuffix_);
108 if (cmp != strong_ordering::equal) {
109 return cmp;
110 }
111 if (fParameters_.empty () and rhs.fParameters_.empty ()) {
112 return strong_ordering::equal; // very common case, shortcut
113 }
114 else {
115 // expensive for rare case, but if we must compare parameters, need some standardized way to iterate over them (key)
116 using namespace Containers;
117 using namespace Characters;
118 auto sortedMapping = [] (auto m) { return SortedMapping<String, String>{String::LessComparer{eCaseInsensitive}, m}; };
119#if qCompilerAndStdLib_template_DefaultArgIgnoredWhenFailedDeduction_Buggy
120 return Mapping<String, String>::SequentialThreeWayComparer{compare_three_way{}}(sortedMapping (fParameters_), sortedMapping (rhs.fParameters_));
121#else
122 return Mapping<String, String>::SequentialThreeWayComparer{}(sortedMapping (fParameters_), sortedMapping (rhs.fParameters_));
123#endif
124 }
125}
126
127/*
128 ********************************************************************************
129 ******** hash<Stroika::Foundation::DataExchange::InternetMediaType> ************
130 ********************************************************************************
131 */
132size_t std::hash<Stroika::Foundation::DataExchange::InternetMediaType>::operator() (const Stroika::Foundation::DataExchange::InternetMediaType& arg) const
133{
134 return hash<wstring>{}(arg.As<wstring> ());
135}
136
137/*
138 ********************************************************************************
139 ****** DataExchange::DefaultSerializer<DataExchange::InternetMediaType> ********
140 ********************************************************************************
141 */
143{
145}
RegularExpression is a compiled regular expression which can be used to match on a String class.
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual bool Matches(const RegularExpression &regEx) const
Definition String.cpp:1133
nonvirtual bool EndsWith(const Character &c, CompareOptions co=eWithCase) const
Definition String.cpp:1088
nonvirtual String SubString(SZ from) const
nonvirtual bool StartsWith(const Character &c, CompareOptions co=eWithCase) const
Definition String.cpp:1059
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Definition Sequence.h:187
nonvirtual T As() const
convert to type T supported types: o String o wstring
nonvirtual size_t length() const
STL-ish alias for size() - really in STL only used in string, I think, but still makes sense as an al...
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
Definition ToString.inl:465
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43
very similar to ThreeWayComparer but returns true if less
Definition String.h:1856
function object which serializes type T to a BLOB (or BLOB like) object