name: New method to get "successor" of a name
Change-Id: I41a53e64994970121766bc92cd9dd4796ba5fcfb
refs #1677
diff --git a/src/name-component.hpp b/src/name-component.hpp
index b7b529f..0e17580 100644
--- a/src/name-component.hpp
+++ b/src/name-component.hpp
@@ -290,6 +290,9 @@
return !hasValue();
}
+ Component
+ getSuccessor() const;
+
/**
* @brief Check if this is the same component as other
*
@@ -566,6 +569,34 @@
return std::memcmp(value(), other.value(), value_size());
}
+inline Component
+Component::getSuccessor() const
+{
+ size_t totalLength = 0;
+ EncodingBuffer encoder(size() + 1, 1); // + 1 in case there is an overflow
+ // in unlikely case TLV length changes more,
+ // EncodingBuffer will take care of that
+
+ bool isOverflow = true;
+ size_t i = value_size();
+ for (; isOverflow && i > 0; i--) {
+ uint8_t newValue = static_cast<uint8_t>((value()[i - 1] + 1) & 0xFF);
+ totalLength += encoder.prependByte(newValue);
+ isOverflow = (newValue == 0);
+ }
+ totalLength += encoder.prependByteArray(value(), i);
+
+ if (isOverflow) {
+ // new name components has to be extended
+ totalLength += encoder.appendByte(0);
+ }
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(Tlv::NameComponent);
+
+ return encoder.block();
+}
+
template<bool T>
inline size_t
diff --git a/src/name.hpp b/src/name.hpp
index 9c33528..7522a19 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -303,6 +303,15 @@
}
/**
+ * @brief get the successor of a name
+ * successor of a name is defined that its last component is
+ * advanced next possible value of last component of original name
+ * @return a new name
+ */
+ Name
+ getSuccessor() const;
+
+ /**
* Check if this name has the same component count and components as the given name.
* @param name The Name to check.
* @return true if the names are equal, otherwise false.
@@ -661,6 +670,19 @@
return result;
}
+inline Name
+Name::getSuccessor() const
+{
+ if (empty()) {
+ static uint8_t firstValue[] = { 0 };
+ Name firstName;
+ firstName.append(firstValue, 1);
+ return firstName;
+ }
+
+ return getPrefix(-1).append(get(-1).getSuccessor());
+}
+
inline bool
Name::equals(const Name& name) const
{
diff --git a/tests/unit-tests/test-name.cpp b/tests/unit-tests/test-name.cpp
index e5f438d..dd9cc78 100644
--- a/tests/unit-tests/test-name.cpp
+++ b/tests/unit-tests/test-name.cpp
@@ -128,6 +128,14 @@
}
}
+BOOST_AUTO_TEST_CASE(GetSuccessor)
+{
+ BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%01%02").getSuccessor(), Name("ndn:/%00%01/%01%03"));
+ BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%01%FF").getSuccessor(), Name("ndn:/%00%01/%02%00"));
+ BOOST_CHECK_EQUAL(Name("ndn:/%00%01/%FF%FF").getSuccessor(), Name("ndn:/%00%01/%00%00%00"));
+ BOOST_CHECK_EQUAL(Name().getSuccessor(), Name("ndn:/%00"));
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace ndn