Skip to content

Commit 1c7af86

Browse files
Errata: fix is_ok
1 parent 172f8f9 commit 1c7af86

File tree

7 files changed

+136
-95
lines changed

7 files changed

+136
-95
lines changed

code/include/swoc/Errata.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,7 @@ class Errata {
504504
bool is_ok() const;
505505

506506
/// @return If there is top level severity.
507-
bool
508-
has_severity() const {
509-
return _data && _data->_severity.has_value();
510-
}
507+
bool has_severity() const;
511508

512509
/// @return Top level severity.
513510
Severity severity() const;
@@ -1124,9 +1121,12 @@ Errata::assign(code_type code) -> self_type & {
11241121
return *this;
11251122
}
11261123

1124+
inline bool Errata::has_severity() const {
1125+
return _data && _data->_severity.has_value();
1126+
}
11271127
inline auto
11281128
Errata::severity() const -> Severity {
1129-
return _data ? _data->_severity.value() : DEFAULT_SEVERITY;
1129+
return this->has_severity() ? _data->_severity.value() : DEFAULT_SEVERITY;
11301130
}
11311131

11321132
inline auto
@@ -1142,7 +1142,7 @@ Errata::length() const {
11421142

11431143
inline bool
11441144
Errata::is_ok() const {
1145-
return this->empty() || _data->_severity < FAILURE_SEVERITY;
1145+
return nullptr == _data || this->severity() < FAILURE_SEVERITY;
11461146
}
11471147

11481148
inline const Errata::Annotation &

code/include/swoc/swoc_meta.h

+58
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,62 @@ template <typename... Types> struct type_list {
237237
template <typename T> static constexpr bool contains = is_any_of<T, Types...>::value;
238238
};
239239

240+
/** Scoped value change.
241+
*
242+
* The purpose of this class is to change the value of a variable in a scope and then change it
243+
* back when the scope is exited. The old value will be moved to a cache variable and then moved
244+
* back when the instance is destructed. This is very useful to temporarily tweak global variables
245+
* which having to know what the current value is.
246+
*
247+
* @code
248+
* {
249+
* let save(var, value);
250+
* // var now has value.
251+
* }
252+
* // var now has original value.
253+
* @endcode
254+
*
255+
* @tparam T Type of variable to scope.
256+
*/
257+
template <typename T> struct let {
258+
using self_type = let;
259+
260+
let(self_type const& that) = delete;
261+
self_type & operator = (self_type const&) = delete;
262+
263+
T &_var; ///< Reference to scoped variable.
264+
T _value; ///< Original value.
265+
266+
/** Construct a scope.
267+
*
268+
* @param var Variable to scope.
269+
* @param value temporary value to assign.
270+
*/
271+
let(T &var, T const &value);
272+
273+
/** Construct a scope.
274+
*
275+
* @param var Variable to scope.
276+
* @param value temporary value to assign.
277+
*/
278+
let(T &var, T &&value);
279+
280+
~let();
281+
};
282+
283+
template <typename T> let<T>::let(T &var, T const &value) : _var(var), _value(std::move(var))
284+
{
285+
_var = value;
286+
}
287+
template <typename T> let<T>::let(T &var, T &&value) : _var(var), _value(std::move(var))
288+
{
289+
_var = std::move(value);
290+
}
291+
292+
template <typename T> let<T>::~let()
293+
{
294+
_var = std::move(_value);
295+
}
296+
297+
240298
}}} // namespace swoc::SWOC_VERSION_NS::meta

doc/code/TextView.en.rst

+27-4
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ E.g. the code to write a simple hash function [#]_ could be
8686
return hash;
8787
}
8888
89+
Although alternatively, this can be done in a non-modifying way.
90+
91+
.. code-block:: cpp
92+
93+
void hasher(TextView v) {
94+
size_t hash = 0;
95+
for ( auto c : v) {
96+
hash = hash * 13 + c;
97+
}
98+
return hash;
99+
}
100+
89101
Because |TV| inherits from :code:`std::string_view` it can also be used as a container for range
90102
:code:`for` loops.
91103

@@ -97,10 +109,21 @@ Because |TV| inherits from :code:`std::string_view` it can also be used as a con
97109
return hash;
98110
}
99111
112+
The first approach enables dropping out of the loop on some condition with the view updated to
113+
no longer contain processed characters, making restart or other processing simple.
114+
100115
The standard functions :code:`strcmp`, :code:`memcmp`, code:`memcpy`, and :code:`strcasecmp` are
101116
overloaded for |TV| so that a |TV| can be used as if it were a C-style string. The size is is taken
102117
from the |TV| and doesn't need to be passed in explicitly.
103118

119+
.. class:: CharSet
120+
121+
:libswoc:`Reference documentation <swoc::CharSet>`.
122+
123+
This is a simple class that contains a set of characters. This is intended primarily to make
124+
parsing faster and simpler. Rather than checking a list of delimiters the character can be checked
125+
with a single `std::bitset` lookup.
126+
104127
Basic Operations
105128
================
106129

@@ -130,7 +153,7 @@ Searching
130153
---------
131154

132155
Because |TV| is a subclass of :code:`std::string_view` all of its search method work on a |TV|. The
133-
only search methods provided beyond those are :libswoc:`TextView::find_if` and
156+
only search methods provided beyond those in :code:`std::string` are :libswoc:`TextView::find_if` and
134157
:libswoc:`TextView::rfind_if` which search the view by a predicate. The predicate takes a single
135158
:code:`char` argument and returns a :code:`bool`. The search terminates on the first character for
136159
which the predicate returns :code:`true`.
@@ -281,12 +304,12 @@ developing |TV| parsing.
281304

282305
The first was to minimize the need to allocate memory to hold intermediate results. For this reason, the normal
283306
style of use is a streaming / incremental one, where tokens are extracted from a source one by one
284-
and placed in |TV| instances, with the orignal source |TV| being reduced by each extraction until
307+
and placed in |TV| instances, with the original source |TV| being reduced by each extraction until
285308
it is empty.
286309

287310
The second was to minimize cut and paste coding. Typical C or C++ parsing logic consists mostly of
288311
very generic code to handle pointer and size updates. The point of |TV| is to automate all of that
289-
so the resulting code is focused entirely on the parsing logic, not boiler plate string or view manipulation.
312+
yielding code focused entirely on the parsing logic, not boiler plate string or view manipulation.
290313
It is a common occurrence to not get such code exactly correct leading to hard to track bugs. Use
291314
of |TV| eliminates those problems.
292315

@@ -313,7 +336,7 @@ are very cheap to copy. This is essentially the same as having a current pointer
313336
and checking for :code:`current >= end` except :code:`TextView` does all the work, leading to
314337
simpler and less buggy code.
315338

316-
White space is dropped because of the calls to :code:`ltrim_if` and `rtrim_if`. By calling in the
339+
White space is dropped because of the calls to :code:`ltrim_if` and :code:`rtrim_if`. By calling in the
317340
loop condition, the loop exits if the remaining text is only whitespace and no token is processed.
318341
Alternatively :code:`trim_if` could be used after extraction. The performance will be *slightly*
319342
better because although :code:`trim_if` calls :code:`ltrim_if` and :code:`rtrim_if`, a final

doc/index.rst

+10-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@ Solid Wall of C++
1818
*****************
1919

2020
The Solid Wall of C++ library is a collection of C++ classes and utilities. This code evolved out of
21-
infrastructure used in `Apache Traffic Server <https://trafficserver.apache.org>`__. The utilities
22-
had become useful enough there were requests to be able to use them in ATS plugins and other,
23-
unrelated projects. Hence this library. I hope you find it as useful as I have.
21+
infrastructure used in `Apache Traffic Server <https://trafficserver.apache.org>`__ as I strove to combine
22+
functionality, ease of use, and performance.
23+
The utilities had become useful enough there were requests to be able to use them in ATS plugins and other,
24+
unrelated projects. Hence this library. After much production use, this library has been imported back
25+
in to Traffic Server and can be used there in the core or any plugin.
26+
I hope you find it as useful as I have.
27+
28+
Most of the library is dedicated to convenience, such as :class:`TextView` which provides Python like
29+
string manipulation on top of :code:`std::string_view`, and performance, such as :class:`IPSpace` which
30+
enables very fast IP address range storage.
2431

2532
.. toctree::
2633
:maxdepth: 1

tools/ats-drop.sh

-82
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ else
2323
mkdir -p ${TARGET_SRC_DIR}
2424
fi
2525

26-
cp code/CMakeLists.txt ${TARGET_BASE_DIR}/swoc
27-
(cd ${ATS}/${BASE_PATH}/swoc ; sed -i -e '/^if (LIBSWOC_INSTALL)/,/^endif/d' CMakeLists.txt ; git add CMakeLists.txt)
28-
2926
cp code/src/*.cc ${TARGET_SRC_DIR}
3027
(cd ${ATS}; git add ${BASE_PATH}/swoc/CMakeLists.txt ; git add ${SRC_PATH}/*.cc)
3128

@@ -48,82 +45,3 @@ cp code/include/swoc/*.h ${TARGET_INC_DIR}
4845
cp code/include/swoc/ext/*.h ${TARGET_INC_DIR}/ext
4946
cp code/include/swoc/ext/HashFNV.h ${TARGET_INC_DIR}
5047
(cd ${ATS}; git add ${INC_PATH}/*.h ; git add ${INC_PATH}/ext/*.h)
51-
52-
# Build the source
53-
cat <<'TEXT' > ${ATS}/${BASE_PATH}/swoc/Makefile.am
54-
# swoc Makefile.am
55-
#
56-
# Licensed to the Apache Software Foundation (ASF) under one
57-
# or more contributor license agreements. See the NOTICE file
58-
# distributed with this work for additional information
59-
# regarding copyright ownership. The ASF licenses this file
60-
# to you under the Apache License, Version 2.0 (the
61-
# "License"); you may not use this file except in compliance
62-
# with the License. You may obtain a copy of the License at
63-
#
64-
# http://www.apache.org/licenses/LICENSE-2.0
65-
#
66-
# Unless required by applicable law or agreed to in writing, software
67-
# distributed under the License is distributed on an "AS IS" BASIS,
68-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69-
# See the License for the specific language governing permissions and
70-
# limitations under the License.
71-
72-
lib_LTLIBRARIES = libtsswoc.la
73-
74-
library_includedir=$(includedir)/swoc
75-
76-
AM_CPPFLAGS += @SWOC_INCLUDES@
77-
78-
libtsswoc_la_LDFLAGS = @AM_LDFLAGS@ -no-undefined -release 1.5.8
79-
libtsswoc_la_SOURCES = \
80-
src/ArenaWriter.cc src/bw_format.cc src/bw_ip_format.cc src/Errata.cc src/MemArena.cc src/RBTree.cc src/swoc_file.cc src/swoc_ip.cc src/TextView.cc src/string_view_util.cc
81-
82-
if EXPORT_SWOC_HEADERS
83-
library_include_HEADERS = \
84-
include/swoc/ArenaWriter.h \
85-
include/swoc/BufferWriter.h \
86-
include/swoc/bwf_base.h \
87-
include/swoc/bwf_ex.h \
88-
include/swoc/bwf_fwd.h \
89-
include/swoc/bwf_ip.h \
90-
include/swoc/bwf_std.h \
91-
include/swoc/DiscreteRange.h \
92-
include/swoc/Errata.h \
93-
include/swoc/IntrusiveDList.h \
94-
include/swoc/IntrusiveHashMap.h \
95-
include/swoc/IPAddr.h \
96-
include/swoc/IPEndpoint.h \
97-
include/swoc/IPRange.h \
98-
include/swoc/IPSrv.h \
99-
include/swoc/Lexicon.h \
100-
include/swoc/MemArena.h \
101-
include/swoc/MemSpan.h \
102-
include/swoc/RBTree.h \
103-
include/swoc/Scalar.h \
104-
include/swoc/swoc_file.h \
105-
include/swoc/swoc_ip.h \
106-
include/swoc/swoc_meta.h \
107-
include/swoc/swoc_version.h\
108-
include/swoc/string_view_util.h \
109-
include/swoc/TextView.h \
110-
include/swoc/Vectray.h \
111-
include/swoc/HashFNV.h
112-
endif
113-
114-
clean-local:
115-
116-
clang-tidy-local: $(DIST_SOURCES)
117-
$(CXX_Clang_Tidy)
118-
TEXT
119-
(cd ${ATS} ; git add ${BASE_PATH}/swoc/Makefile.am)
120-
121-
if ! grep -q swoc ${ATS}/configure.ac ; then
122-
sed -i -e 's!lib/yamlcpp/Makefile!lib/swoc/Makefile\n &!' ${ATS}/configure.ac
123-
(cd ${ATS} ; git add configure.ac)
124-
fi
125-
126-
if ! grep -q swoc ${ATS}/${BASE_PATH}/Makefile.am ; then
127-
sed -i -e '/SUBDIRS =/s!$! swoc!' ${ATS}/${BASE_PATH}/Makefile.am
128-
(cd ${ATS} ; git add ${BASE_PATH}/Makefile.am)
129-
fi

unit_tests/test_Errata.cc

+11
Original file line numberDiff line numberDiff line change
@@ -414,4 +414,15 @@ TEST_CASE("Errata Autotext", "[libswoc][errata]") {
414414
REQUIRE(b.front().text() == "Bravo [2]");
415415
Errata c{ecode(ECode::ALPHA), ERRATA_ERROR, Errata::AUTO};
416416
REQUIRE(c.front().text() == "Error: Alpha [1]");
417+
418+
Errata d{ERRATA_ERROR};
419+
REQUIRE_FALSE(d.is_ok());
420+
Errata e{ERRATA_INFO};
421+
REQUIRE(e.is_ok());
422+
Errata f{ecode(ECode::BRAVO)};
423+
REQUIRE_FALSE(f.is_ok());
424+
// Change properties but need to restore them for other tests.
425+
swoc::meta::let g1(Errata::DEFAULT_SEVERITY, ERRATA_WARN);
426+
swoc::meta::let g2(Errata::FAILURE_SEVERITY, ERRATA_ERROR);
427+
REQUIRE(f.is_ok());
417428
}

unit_tests/test_meta.cc

+24
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,27 @@ TEST_CASE("Meta vary", "[meta][vary]") {
9393
v = "956"_tv;
9494
REQUIRE(std::visit(visitor, v) == 956);
9595
}
96+
97+
TEST_CASE("Meta let", "[meta][let]") {
98+
using swoc::meta::let;
99+
100+
unsigned x = 56;
101+
{
102+
REQUIRE(x == 56);
103+
let guard(x, unsigned(3136));
104+
REQUIRE(x == 3136);
105+
// auto bogus = guard; // should not compile.
106+
}
107+
REQUIRE(x == 56);
108+
109+
// Checking move semantics - avoid reallocating the original string.
110+
std::string s{"Evil Dave Rulz With An Iron Keyboard"}; // force allocation.
111+
auto sptr = s.data();
112+
{
113+
char const * text = "Twas brillig and the slithy toves";
114+
let guard(s, std::string(text));
115+
REQUIRE(s == text);
116+
REQUIRE(s.data() != sptr);
117+
}
118+
REQUIRE(s.data() == sptr);
119+
}

0 commit comments

Comments
 (0)