#include <dhcp/option_data_types.h>
#include <dns/labelsequence.h>
#include <dns/name.h>
+#include <util/strutil.h>
#include <util/encode/hex.h>
#include <algorithm>
#include <limits>
if (!buf.empty()) {
// Per RFC 2132, section 2 we need to drop trailing NULLs
auto begin = buf.begin();
- auto end = buf.end();
- for ( ; end != begin && *(end - 1) == 0x0; --end);
-
+ auto end = util::str::seekTrimmed(begin, buf.end(), 0x0);
if (std::distance(begin, end) == 0) {
isc_throw(isc::OutOfRange, "string value carried by the option "
<< " contained only NULLs");
-// Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <config.h>
#include <dhcp/option_string.h>
+#include <util/strutil.h>
#include <sstream>
namespace isc {
// Trim off any trailing NULLs.
auto begin = value.begin();
- auto end = value.end();
- for ( ; end != begin && *(end - 1) == 0x0; --end);
+ auto end = util::str::seekTrimmed(begin, value.end(), 0x0);
if (std::distance(begin, end) == 0) {
isc_throw(isc::OutOfRange, "string value carried by the option '"
OptionString::unpack(OptionBufferConstIter begin,
OptionBufferConstIter end) {
// Trim off trailing null(s)
- for ( ; end != begin && *(end - 1) == 0x0; --end);
-
+ end = util::str::seekTrimmed(begin, end, 0x0);
if (std::distance(begin, end) == 0) {
isc_throw(isc::OutOfRange, "failed to parse an option '"
<< getType() << "' holding string value"
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// \return String with leading and trailing spaces removed
std::string trim(const std::string& instring);
+/// \brief Finds the "trimmed" end of a buffer
+///
+/// Works backward from the the end of the buffer, looking for the first
+/// character not equal to the trim value, and returns an iterator
+/// pointing that that position.
+///
+/// \param begin - Forward iterator pointing to the beginning of the
+/// buffer to trim
+/// \param end - Forward iterator pointing to the untrimmed end of
+/// the buffer to trim
+/// \param val - byte value to trim off
+///
+/// \retrun Iterator pointing the first character from the end of the
+/// buffer not equal to the trim value
+template<typename Iterator>
+Iterator
+seekTrimmed(Iterator begin, Iterator end, uint8_t trim_val) {
+ for ( ; end != begin && *(end - 1) == trim_val; --end);
+ return(end);
+}
/// \brief Split String into Tokens
///
"abc.123");
}
+// Verifies templated buffer iterator trim() function
+TEST(StringUtilTest, seekTrimmed) {
+
+ // Empty buffer should be fine.
+ std::vector<uint8_t> buffer;
+ auto begin = buffer.end();
+ auto end = buffer.end();
+ ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
+ EXPECT_EQ(0, std::distance(begin, end));
+
+ // Buffer of only trim values, should be fine.
+ buffer = { 1, 1 };
+ begin = buffer.begin();
+ end = buffer.end();
+ ASSERT_NO_THROW(end = seekTrimmed(begin, end, 1));
+ EXPECT_EQ(0, std::distance(begin, end));
+
+ // One trailing null should trim off.
+ buffer = {'o', 'n', 'e', 0 };
+ begin = buffer.begin();
+ end = buffer.end();
+ ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
+ EXPECT_EQ(3, std::distance(begin, end));
+
+ // More than one trailing null should trim off.
+ buffer = { 't', 'h', 'r', 'e', 'e', 0, 0, 0 };
+ begin = buffer.begin();
+ end = buffer.end();
+ ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
+ EXPECT_EQ(5, std::distance(begin, end));
+
+ // Embedded null should be left in place.
+ buffer = { 'e', 'm', 0, 'b', 'e', 'd' };
+ begin = buffer.begin();
+ end = buffer.end();
+ ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
+ EXPECT_EQ(6, std::distance(begin, end));
+
+ // Leading null should be left in place.
+ buffer = { 0, 'l', 'e', 'a', 'd', 'i', 'n', 'g' };
+ begin = buffer.begin();
+ end = buffer.end();
+ ASSERT_NO_THROW(end = seekTrimmed(begin, end, 0));
+ EXPECT_EQ(8, std::distance(begin, end));
+}
+
} // end of anonymous namespace