Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
IfNoneMatch.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
6
7 /*
8 ********************************************************************************
9 ***************************** HTTP::IfNoneMatch ********************************
10 ********************************************************************************
11 */
12 inline IfNoneMatch::IfNoneMatch (const Containers::Sequence<ETag>& etags)
13 : fETags{etags}
14 {
15 }
16 inline bool IfNoneMatch::IsAsterisk () const
17 {
18 return fETags.empty ();
19 }
20 inline optional<IfNoneMatch> IfNoneMatch::Parse (const String& wireFormat)
21 {
22 // @see https://tools.ietf.org/html/rfc7232#section-3.2
23 // If-None-Match = "*" / 1#entity-tag
24 // @see https://tools.ietf.org/html/rfc7232#appendix-C
25 // If-Match = "*" / ( *( "," OWS ) entity-tag *( OWS "," [ OWS entity-tag ] ) )
26 // entity-tag = [ weak ] opaque-tag
27 // opaque-tag = DQUOTE *etagc DQUOTE
28 // etagc = "!" / %x23-7E ; '#'-'~' / obs - text
29 // weak = %x57.2F ; W/
30 // @see https://tools.ietf.org/html/rfc7230#section-3.2.6
31 // obs-text = %x80-FF
32 //
33 // So space/comma separated. But etags always start with W or ", and always end with next "
35 wstring t = wireFormat.As<wstring> ();
36 wstring curETagToken;
37 bool readingETag = false;
38 for (auto i = t.begin (); i != t.end (); ++i) {
39 if (readingETag) {
40 curETagToken += *i;
41 if (*i == '\"') {
42 if (auto oe = ETag::Parse (curETagToken)) {
43 result += *oe;
44 readingETag = false;
45 curETagToken.clear ();
46 }
47 else {
48 // Treat a bad etag as a bad if-none-else line, and just silently fail to parse
49 return nullopt;
50 }
51 }
52 }
53 else {
54 if (*i == 'W' or *i == '\"') {
55 curETagToken += *i;
56 readingETag = true;
57 }
58 }
59 }
60 if (readingETag) {
61 // then parse didn't parse correctly, so treat as failure
62 return nullopt;
63 }
64 else {
65 return IfNoneMatch{result};
66 }
67 }
68 template <>
69 inline Characters::String IfNoneMatch::As () const
70 {
71 if (IsAsterisk ()) {
72 return "*"sv;
73 }
74 return String::Join (fETags.Map<Traversal::Iterable<String>> ([] (const ETag& e) { return e.As<String> (); }));
75 }
76 inline Characters::String IfNoneMatch::ToString () const
77 {
78 return As<String> ();
79 }
80
81}
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Definition Sequence.h:187
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237