azure-core
Loading...
Searching...
No Matches
etag.hpp
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
9#pragma once
10
13
14#include <string>
15
16namespace Azure {
17
21class ETag final {
22 // ETag is a validator based on https://tools.ietf.org/html/rfc7232#section-2.3.2
23private:
25
26public:
31 enum class ETagComparison
32 {
33 Strong,
34 Weak
35 };
36
37 /*
38 2.3.2. Comparison
39
40 There are two entity-tag comparison functions, depending on whether
41 or not the comparison context allows the use of weak validators:
42
43 o Strong comparison: two entity-tags are equivalent if both are not
44 weak and their opaque-tags match character-by-character.
45
46 o Weak comparison: two entity-tags are equivalent if their
47 opaque-tags match character-by-character, regardless of either or
48 both being tagged as "weak".
49
50 +--------+--------+-------------------+-----------------+
51 | ETag 1 | ETag 2 | Strong Comparison | Weak Comparison |
52 +--------+--------+-------------------+-----------------+
53 | W/"1" | W/"1" | no match | match |
54 | W/"1" | W/"2" | no match | no match |
55 | W/"1" | "1" | no match | match |
56 | "1" | "1" | match | match |
57 +--------+--------+-------------------+-----------------+
58
59 // etag: //This is possible and means no etag is present
60 // etag:""
61 // etag:"*" //This means the etag is value '*'
62 // etag:"some value" //This means the etag is value 'some value'
63 // etag:/W"" //Weak eTag
64 // etag:* //This is special, means any etag
65 // If-Match header can do this
66 // If-Match:"value1","value2","value3" // Do this if any of these match
67
68 */
69
79 static bool Equals(
80 const ETag& left,
81 const ETag& right,
82 const ETagComparison comparisonKind = ETagComparison::Strong)
83 {
84 // ETags are != if one of the values is null
85 if (!left.m_value || !right.m_value)
86 {
87 // Caveat, If both values are null then we consider the ETag equal
88 return !left.m_value && !right.m_value;
89 }
90
91 switch (comparisonKind)
92 {
93 case ETagComparison::Strong:
94 // Strong comparison
95 // If either is weak then there is no match
96 // else tags must match character for character
97 return !left.IsWeak() && !right.IsWeak() && left.m_value.Value() == right.m_value.Value();
98 break;
99
100 case ETagComparison::Weak:
101
102 auto leftStart = left.IsWeak() ? 2 : 0;
103 auto rightStart = right.IsWeak() ? 2 : 0;
104
105 auto leftVal = left.m_value.Value();
106 auto rightVal = right.m_value.Value();
107
108 // Compare if lengths are equal
109 // Compare the strings character by character
110 return ((leftVal.length() - leftStart) == (rightVal.length() - rightStart))
111 && (leftVal.compare(leftStart, leftVal.length() - leftStart, &rightVal[rightStart])
112 == 0);
113 break;
114 }
115 // Unknown comparison
117 }
118
123 ETag() = default;
124
129 explicit ETag(std::string etag) : m_value(std::move(etag)) {}
130
135 bool HasValue() const { return m_value.HasValue(); }
136
141 const std::string& ToString() const
142 {
143 AZURE_ASSERT_MSG(m_value.HasValue(), "Empty ETag, check HasValue() before calling ToString().");
144 return m_value.Value();
145 }
146
153 bool operator==(const ETag& other) const { return Equals(*this, other, ETagComparison::Strong); }
154
161 bool operator!=(const ETag& other) const { return !(*this == other); }
162
167 bool IsWeak() const
168 {
169 // Null ETag is considered Strong
170 // Shortest valid weak etag has length of 4
171 // W/""
172 // Valid weak format must start with W/"
173 // Must end with a /"
174 const bool weak = m_value && (m_value.Value().length() >= 4)
175 && ((m_value.Value()[0] == 'W') && (m_value.Value()[1] == '/')
176 && (m_value.Value()[2] == '"') && (m_value.Value()[m_value.Value().size() - 1] == '"'));
177
178 return weak;
179 }
180
185 static const ETag& Any();
186};
187} // namespace Azure
Provide assert macros to use with pre-conditions.
#define AZURE_UNREACHABLE_CODE()
Indicate that the code cannot be reached.
Definition azure_assert.hpp:64
#define AZURE_ASSERT_MSG(exp, msg)
Azure specific assert macro with message.
Definition azure_assert.hpp:53
Represents an HTTP validator.
Definition etag.hpp:21
bool HasValue() const
Whether ETag is present.
Definition etag.hpp:135
ETag()=default
Constructs an empty (null) ETag.
bool IsWeak() const
Specifies whether the Azure::ETag is strong or weak.
Definition etag.hpp:167
bool operator!=(const ETag &other) const
Compare with other ETag for inequality.
Definition etag.hpp:161
static bool Equals(const ETag &left, const ETag &right, const ETagComparison comparisonKind=ETagComparison::Strong)
Indicates whether two Azure::ETag values are equal.
Definition etag.hpp:79
static const ETag & Any()
Azure::ETag representing everything.
const std::string & ToString() const
Returns the resource metadata represented as a string.
Definition etag.hpp:141
bool operator==(const ETag &other) const
Compare with other ETag for equality.
Definition etag.hpp:153
ETagComparison
The comparison type.
Definition etag.hpp:32
ETag(std::string etag)
Constructs an ETag with string representation.
Definition etag.hpp:129
Manages an optional contained value, i.e. a value that may or may not be present.
Definition nullable.hpp:30
const T & Value() const &noexcept
Get the contained value.
Definition nullable.hpp:236
bool HasValue() const noexcept
Check whether a value is contained.
Definition nullable.hpp:230
Compute the hash value for the input binary data, using SHA256, SHA384 and SHA512.
Definition azure_assert.hpp:57
Manages an optional contained value, i.e. a value that may or may not be present.