name: Converting Name to TLV
Change-Id: Idc44608d3f0610f7f6b07204a00a3510e8041393
diff --git a/Makefile.am b/Makefile.am
index 17f3eb6..9821775 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -136,7 +136,8 @@
src/util/dynamic-uint8-vector.cpp \
src/util/dynamic-uint8-vector.hpp \
src/util/logging.cpp \
- src/util/logging.hpp
+ src/util/logging.hpp \
+ src/util/string-helper.hpp
libndn_cpp_la_LIBADD = @OPENSSL_LIBS@ @OSX_SECURITY_LIBS@
libndn_cpp_la_LDFLAGS = @OPENSSL_LDFLAGS@ @SQLITE3_LDFLAGS@ @BOOST_LDFLAGS@
diff --git a/include/ndn-cpp/name.hpp b/include/ndn-cpp/name.hpp
index 633593c..00f6d21 100644
--- a/include/ndn-cpp/name.hpp
+++ b/include/ndn-cpp/name.hpp
@@ -12,12 +12,9 @@
#include <vector>
#include <string>
-#include <string.h>
#include <sstream>
-#include "util/blob.hpp"
-
-struct ndn_NameComponent;
-struct ndn_Name;
+#include <string.h>
+#include "encoding/block.hpp"
namespace ndn {
@@ -29,7 +26,8 @@
/**
* A Name::Component holds a read-only name component value.
*/
- class Component {
+ class Component : private ConstBufferPtr
+ {
public:
/**
* Create a new Name::Component with a null value.
@@ -37,13 +35,24 @@
Component()
{
}
+
+ // copy constructor OK
+
+ /**
+ * Create a new Name::Component, taking another pointer to the Blob value.
+ * @param value A blob with a pointer to an immutable array. The pointer is copied.
+ */
+ Component(const ConstBufferPtr &buffer)
+ : ConstBufferPtr (buffer)
+ {
+ }
/**
* Create a new Name::Component, copying the given value.
* @param value The value byte array.
*/
- Component(const std::vector<uint8_t>& value)
- : value_(value)
+ Component(const Buffer& value)
+ : ConstBufferPtr (new Buffer(value))
{
}
@@ -53,29 +62,18 @@
* @param valueLen Length of value.
*/
Component(const uint8_t *value, size_t valueLen)
- : value_(value, valueLen)
+ : ConstBufferPtr (new Buffer(value, valueLen))
+ {
+ }
+
+ template<class InputIterator>
+ Component(InputIterator begin, InputIterator end)
+ : ConstBufferPtr (new Buffer(begin, end))
{
}
- /**
- * Create a new Name::Component, taking another pointer to the Blob value.
- * @param value A blob with a pointer to an immutable array. The pointer is copied.
- */
- Component(const Blob &value)
- : value_(value)
- {
- }
-
- /**
- * Set the componentStruct to point to this component, without copying any memory.
- * WARNING: The resulting pointer in componentStruct is invalid after a further use of this object which could reallocate memory.
- * @param componentStruct The C ndn_NameComponent struct to receive the pointer.
- */
- void
- get(struct ndn_NameComponent& componentStruct) const;
-
- const Blob&
- getValue() const { return value_; }
+ const Buffer&
+ getValue() const { return **this; }
/**
* Write this component value to result, escaping characters according to the NDN URI Scheme.
@@ -83,9 +81,9 @@
* @param result the string stream to write to.
*/
void
- toEscapedString(std::ostringstream& result) const
+ toEscapedString(std::ostream& result) const
{
- Name::toEscapedString(*value_, result);
+ Name::toEscapedString(**this, result);
}
/**
@@ -96,7 +94,7 @@
std::string
toEscapedString() const
{
- return Name::toEscapedString(*value_);
+ return Name::toEscapedString(**this);
}
/**
@@ -176,7 +174,13 @@
bool
equals(const Component& other) const
{
- return *value_ == *other.value_;
+ return **this == *other;
+ }
+
+ bool
+ empty() const
+ {
+ return !*this || (*this)->empty();
}
/**
@@ -241,11 +245,8 @@
*/
bool
operator > (const Component& other) const { return compare(other) > 0; }
+ };
- private:
- Blob value_;
- };
-
/**
* Create a new Name with no components.
*/
@@ -260,6 +261,16 @@
: components_(components)
{
}
+
+ Name(const Block &name)
+ {
+ for (Block::element_const_iterator i = name.getAll().begin();
+ i != name.getAll().end();
+ ++i)
+ {
+ append(Component(i->value_begin(), i->value_end()));
+ }
+ }
/**
* Parse the uri according to the NDN URI Scheme and create the name with the components.
@@ -279,20 +290,8 @@
set(uri.c_str());
}
- /**
- * Set the nameStruct to point to the components in this name, without copying any memory.
- * WARNING: The resulting pointers in nameStruct are invalid after a further use of this object which could reallocate memory.
- * @param nameStruct A C ndn_Name struct where the components array is already allocated.
- */
- void
- get(struct ndn_Name& nameStruct) const;
-
- /**
- * Clear this name, and set the components by copying from the name struct.
- * @param nameStruct A C ndn_Name struct
- */
- void
- set(const struct ndn_Name& nameStruct);
+ const Block &
+ wireEncode() const;
/**
* Parse the uri according to the NDN URI Scheme and set the name with the components.
@@ -324,14 +323,14 @@
* @return This name so that you can chain calls to append.
*/
Name&
- append(const std::vector<uint8_t>& value)
+ append(const Buffer& value)
{
components_.push_back(value);
return *this;
}
Name&
- append(const Blob &value)
+ append(const ConstBufferPtr &value)
{
components_.push_back(value);
return *this;
@@ -343,6 +342,13 @@
components_.push_back(value);
return *this;
}
+
+ Name&
+ append(const Block &value)
+ {
+ components_.push_back(Component(value.begin(), value.end()));
+ return *this;
+ }
/**
* Append the components of the given name to this name.
@@ -365,7 +371,7 @@
* @deprecated Use append.
*/
Name&
- appendComponent(const std::vector<uint8_t>& value)
+ appendComponent(const Buffer& value)
{
return append(value);
}
@@ -374,7 +380,7 @@
* @deprecated Use append.
*/
Name&
- appendComponent(const Blob &value)
+ appendComponent(const ConstBufferPtr &value)
{
return append(value);
}
@@ -392,7 +398,7 @@
* @deprecated Use append.
*/
Name&
- addComponent(const std::vector<uint8_t>& value)
+ addComponent(const Buffer& value)
{
return append(value);
}
@@ -401,7 +407,7 @@
* @deprecated Use append.
*/
Name&
- addComponent(const Blob &value)
+ addComponent(const ConstBufferPtr &value)
{
return append(value);
}
@@ -466,15 +472,6 @@
toUri() const;
/**
- * @deprecated Use toUri().
- */
- std::string
- to_uri() const
- {
- return toUri();
- }
-
- /**
* Append a component with the encoded segment number.
* @param segment The segment number.
* @return This name so that you can chain calls to append.
@@ -513,7 +510,13 @@
* @return true if this matches the given name, otherwise false. This always returns true if this name is empty.
*/
bool
- match(const Name& name) const;
+ isPrefixOf(const Name& name) const;
+
+ bool
+ match(const Name& name) const
+ {
+ return isPrefixOf(name);
+ }
/**
* Make a Blob value by decoding the escapedString between beginOffset and endOffset according to the NDN URI Scheme.
@@ -524,7 +527,7 @@
* @param endOffset The offset in escapedString of the end of the portion to decode.
* @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
*/
- static Blob
+ static Component
fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset);
/**
@@ -534,7 +537,7 @@
* @param escapedString The null-terminated escaped string.
* @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
*/
- static Blob
+ static Component
fromEscapedString(const char *escapedString);
/**
@@ -544,7 +547,7 @@
* @param escapedString The escaped string.
* @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
*/
- static Blob
+ static Component
fromEscapedString(const std::string& escapedString) { return fromEscapedString(escapedString.c_str()); }
/**
@@ -554,7 +557,7 @@
* @param result the string stream to write to.
*/
static void
- toEscapedString(const std::vector<uint8_t>& value, std::ostringstream& result);
+ toEscapedString(const std::vector<uint8_t>& value, std::ostream& result);
/**
* Convert the value by escaping characters according to the NDN URI Scheme.
@@ -568,6 +571,12 @@
//
// vector equivalent interface.
//
+
+ /**
+ * @brief Check if name is emtpy
+ */
+ bool
+ empty() const { return components_.empty(); }
/**
* Get the number of components.
@@ -657,7 +666,7 @@
typedef std::vector<Component>::reference reference;
typedef std::vector<Component>::const_reference const_reference;
- typedef Component partial_type;
+ typedef Component value_type;
/**
* Begin iterator (const).
@@ -709,13 +718,19 @@
private:
std::vector<Component> components_;
-};
-inline std::ostream&
-operator << (std::ostream& os, const Name& name)
+ mutable Block wire_;
+};
+
+std::ostream &
+operator << (std::ostream &os, const Name &name);
+
+inline std::string
+Name::toUri() const
{
- os << name.toUri();
- return os;
+ std::ostringstream os;
+ os << *this;
+ return os.str();
}
}
diff --git a/src/name.cpp b/src/name.cpp
index b17a163..3d9b395 100644
--- a/src/name.cpp
+++ b/src/name.cpp
@@ -10,126 +10,33 @@
#include <algorithm>
#include <string.h>
#include <ndn-cpp/name.hpp>
-#include "c/name.h"
#include "c/util/ndn_memory.h"
+#include "util/string-helper.hpp"
+
using namespace std;
namespace ndn {
-static const char *WHITESPACE_CHARS = " \n\r\t";
-
-/**
- * Modify str in place to erase whitespace on the left.
- * @param str
- */
-static inline void
-trimLeft(string& str)
+uint64_t
+Name::Component::toNumberWithMarker(uint8_t marker) const
{
- size_t found = str.find_first_not_of(WHITESPACE_CHARS);
- if (found != string::npos) {
- if (found > 0)
- str.erase(0, found);
- }
- else
- // All whitespace
- str.clear();
-}
-
-/**
- * Modify str in place to erase whitespace on the right.
- * @param str
- */
-static inline void
-trimRight(string& str)
-{
- size_t found = str.find_last_not_of(WHITESPACE_CHARS);
- if (found != string::npos) {
- if (found + 1 < str.size())
- str.erase(found + 1);
- }
- else
- // All whitespace
- str.clear();
-}
-
-/**
- * Modify str in place to erase whitespace on the left and right.
- * @param str
- */
-static void
-trim(string& str)
-{
- trimLeft(str);
- trimRight(str);
-}
-
-/**
- * Convert the hex character to an integer from 0 to 15, or -1 if not a hex character.
- * @param c
- * @return
- */
-static int
-fromHexChar(uint8_t c)
-{
- if (c >= '0' && c <= '9')
- return (int)c - (int)'0';
- else if (c >= 'A' && c <= 'F')
- return (int)c - (int)'A' + 10;
- else if (c >= 'a' && c <= 'f')
- return (int)c - (int)'a' + 10;
- else
- return -1;
-}
-
-/**
- * Return a copy of str, converting each escaped "%XX" to the char value.
- * @param str
- */
-static string
-unescape(const string& str)
-{
- ostringstream result;
+ if (empty() || *getValue().begin() != marker)
+ throw runtime_error("Name component does not begin with the expected marker");
- for (size_t i = 0; i < str.size(); ++i) {
- if (str[i] == '%' && i + 2 < str.size()) {
- int hi = fromHexChar(str[i + 1]);
- int lo = fromHexChar(str[i + 2]);
-
- if (hi < 0 || lo < 0)
- // Invalid hex characters, so just keep the escaped string.
- result << str[i] << str[i + 1] << str[i + 2];
- else
- result << (uint8_t)(16 * hi + lo);
-
- // Skip ahead past the escaped value.
- i += 2;
- }
- else
- // Just copy through.
- result << str[i];
+ uint64_t result = 0;
+ for (Buffer::const_iterator i = getValue().begin()+1; i != getValue().end(); ++i) {
+ result <<= 8;
+ result |= *i;
}
- return result.str();
-}
-
-uint64_t Name::Component::toNumberWithMarker(uint8_t marker) const
-{
- struct ndn_NameComponent componentStruct;
- get(componentStruct);
- uint64_t result;
-
- ndn_Error error;
- if ((error = ndn_NameComponent_toNumberWithMarker(&componentStruct, marker, &result)))
- throw runtime_error(ndn_getErrorString(error));
-
return result;
}
Name::Component
Name::Component::fromNumber(uint64_t number)
{
- ptr_lib::shared_ptr<vector<uint8_t> > value(new vector<uint8_t>());
+ ptr_lib::shared_ptr<Buffer> value(new Buffer);
// First encode in little endian.
while (number != 0) {
@@ -139,13 +46,13 @@
// Make it big endian.
reverse(value->begin(), value->end());
- return Blob(value);
+ return Component(value);
}
Name::Component
Name::Component::fromNumberWithMarker(uint64_t number, uint8_t marker)
{
- ptr_lib::shared_ptr<vector<uint8_t> > value(new vector<uint8_t>());
+ ptr_lib::shared_ptr<Buffer> value(new Buffer);
// Add the leading marker.
value->push_back(marker);
@@ -158,36 +65,40 @@
// Make it big endian.
reverse(value->begin() + 1, value->end());
- return Blob(value);
-}
-
-void
-Name::Component::get(struct ndn_NameComponent& componentStruct) const
-{
- value_.get(componentStruct.value);
+ return Component(value);
}
uint64_t
Name::Component::toNumber() const
{
- struct ndn_NameComponent componentStruct;
- get(componentStruct);
- return ndn_NameComponent_toNumber(&componentStruct);
+ uint64_t result = 0;
+ for (Buffer::const_iterator i = getValue().begin(); i != getValue().end(); ++i) {
+ result <<= 8;
+ result |= *i;
+ }
+
+ return result;
}
int
Name::Component::compare(const Name::Component& other) const
{
// Imitate ndn_Exclude_compareComponents.
- if (value_.size() < other.value_.size())
+ if (getValue().size() < other.getValue().size())
return -1;
- if (value_.size() > other.value_.size())
+ if (getValue().size() > other.getValue().size())
return 1;
// The components are equal length. Just do a byte compare.
- return ndn_memcmp((uint8_t*)value_.buf(), (uint8_t*)other.value_.buf(), value_.size());
+ return ndn_memcmp(getValue().buf(), other.getValue().buf(), getValue().size());
}
+// const Block &
+// Name::wireEncode() const
+// {
+
+// }
+
void
Name::set(const char *uri_cstr)
{
@@ -238,32 +149,13 @@
Component component(fromEscapedString(&uri[0], iComponentStart, iComponentEnd));
// Ignore illegal components. This also gets rid of a trailing '/'.
- if (component.getValue())
+ if (!component.empty())
components_.push_back(Component(component));
iComponentStart = iComponentEnd + 1;
}
}
-void
-Name::get(struct ndn_Name& nameStruct) const
-{
- if (nameStruct.maxComponents < components_.size())
- throw runtime_error("nameStruct.maxComponents must be >= this name getNComponents()");
-
- nameStruct.nComponents = components_.size();
- for (size_t i = 0; i < nameStruct.nComponents; ++i)
- components_[i].get(nameStruct.components[i]);
-}
-
-void
-Name::set(const struct ndn_Name& nameStruct)
-{
- clear();
- for (size_t i = 0; i < nameStruct.nComponents; ++i)
- append(nameStruct.components[i].value.value, nameStruct.components[i].value.length);
-}
-
Name&
Name::append(const Name& name)
{
@@ -277,21 +169,6 @@
return *this;
}
-string
-Name::toUri() const
-{
- if (components_.size() == 0)
- return "/";
-
- ostringstream result;
- for (size_t i = 0; i < components_.size(); ++i) {
- result << "/";
- toEscapedString(*components_[i].getValue(), result);
- }
-
- return result.str();
-}
-
Name
Name::getSubName(size_t iStartComponent, size_t nComponents) const
{
@@ -322,7 +199,7 @@
return false;
for (size_t i = 0; i < components_.size(); ++i) {
- if (*components_[i].getValue() != *name.components_[i].getValue())
+ if (components_[i].getValue() != name.components_[i].getValue())
return false;
}
@@ -330,7 +207,7 @@
}
bool
-Name::match(const Name& name) const
+Name::isPrefixOf(const Name& name) const
{
// Imitate ndn_Name_match.
@@ -340,14 +217,14 @@
// Check if at least one of given components doesn't match.
for (size_t i = 0; i < components_.size(); ++i) {
- if (*components_[i].getValue() != *name.components_[i].getValue())
+ if (components_[i].getValue() != name.components_[i].getValue())
return false;
}
return true;
}
-Blob
+Name::Component
Name::fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset)
{
string trimmedString(escapedString + beginOffset, escapedString + endOffset);
@@ -358,23 +235,23 @@
// Special case for component of only periods.
if (value.size() <= 2)
// Zero, one or two periods is illegal. Ignore this component.
- return Blob();
+ return Component();
else
// Remove 3 periods.
- return Blob((const uint8_t *)&value[3], value.size() - 3);
+ return Component((const uint8_t *)&value[3], value.size() - 3);
}
else
- return Blob((const uint8_t *)&value[0], value.size());
+ return Component((const uint8_t *)&value[0], value.size());
}
-Blob
+Name::Component
Name::fromEscapedString(const char *escapedString)
{
return fromEscapedString(escapedString, 0, ::strlen(escapedString));
}
-void
-Name::toEscapedString(const vector<uint8_t>& value, ostringstream& result)
+void
+Name::toEscapedString(const vector<uint8_t>& value, std::ostream& result)
{
bool gotNonDot = false;
for (unsigned i = 0; i < value.size(); ++i) {
@@ -437,5 +314,22 @@
return name1.size() < name2.size();
}
+std::ostream&
+operator << (std::ostream& os, const Name& name)
+{
+ if (name.empty())
+ {
+ os << "/";
+ }
+ else
+ {
+ for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
+ os << "/";
+ i->toEscapedString(os);
+ }
+ }
+
+ return os;
+}
}
diff --git a/src/util/string-helper.hpp b/src/util/string-helper.hpp
new file mode 100644
index 0000000..ee3f5bd
--- /dev/null
+++ b/src/util/string-helper.hpp
@@ -0,0 +1,114 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_STRING_HELPER_HPP
+#define NDN_STRING_HELPER_HPP
+
+#include <string>
+#include <sstream>
+
+namespace ndn {
+
+const char *WHITESPACE_CHARS = " \n\r\t";
+
+/**
+ * Modify str in place to erase whitespace on the left.
+ * @param str
+ */
+inline void
+trimLeft(std::string& str)
+{
+ size_t found = str.find_first_not_of(WHITESPACE_CHARS);
+ if (found != std::string::npos) {
+ if (found > 0)
+ str.erase(0, found);
+ }
+ else
+ // All whitespace
+ str.clear();
+}
+
+/**
+ * Modify str in place to erase whitespace on the right.
+ * @param str
+ */
+inline void
+trimRight(std::string& str)
+{
+ size_t found = str.find_last_not_of(WHITESPACE_CHARS);
+ if (found != std::string::npos) {
+ if (found + 1 < str.size())
+ str.erase(found + 1);
+ }
+ else
+ // All whitespace
+ str.clear();
+}
+
+/**
+ * Modify str in place to erase whitespace on the left and right.
+ * @param str
+ */
+inline void
+trim(std::string& str)
+{
+ trimLeft(str);
+ trimRight(str);
+}
+
+/**
+ * Convert the hex character to an integer from 0 to 15, or -1 if not a hex character.
+ * @param c
+ * @return
+ */
+inline int
+fromHexChar(uint8_t c)
+{
+ if (c >= '0' && c <= '9')
+ return (int)c - (int)'0';
+ else if (c >= 'A' && c <= 'F')
+ return (int)c - (int)'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return (int)c - (int)'a' + 10;
+ else
+ return -1;
+}
+
+/**
+ * Return a copy of str, converting each escaped "%XX" to the char value.
+ * @param str
+ */
+inline std::string
+unescape(const std::string& str)
+{
+ std::ostringstream result;
+
+ for (size_t i = 0; i < str.size(); ++i) {
+ if (str[i] == '%' && i + 2 < str.size()) {
+ int hi = fromHexChar(str[i + 1]);
+ int lo = fromHexChar(str[i + 2]);
+
+ if (hi < 0 || lo < 0)
+ // Invalid hex characters, so just keep the escaped string.
+ result << str[i] << str[i + 1] << str[i + 2];
+ else
+ result << (uint8_t)(16 * hi + lo);
+
+ // Skip ahead past the escaped value.
+ i += 2;
+ }
+ else
+ // Just copy through.
+ result << str[i];
+ }
+
+ return result.str();
+}
+
+} // namespace ndn
+
+#endif // NDN_STRING_HELPER_HPP