name: Optimization of Name implementation
Now, Name directly uses Block as underlying storage for name components
and name::Components (aka Name::Components) class is a helper wrapped on
top of Block class.
Change-Id: I15ca58cc6dba76dd02e973709b7b153c2613de51
refs: #1171
diff --git a/src/name-component.cpp b/src/name-component.cpp
new file mode 100644
index 0000000..3956e80
--- /dev/null
+++ b/src/name-component.cpp
@@ -0,0 +1,167 @@
+/* -*- 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>
+ * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "name-component.hpp"
+
+#include "util/time.hpp"
+#include "util/string-helper.hpp"
+
+namespace ndn {
+namespace name {
+
+Component
+Component::fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset)
+{
+ std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
+ trim(trimmedString);
+ std::string value = unescape(trimmedString);
+
+ if (value.find_first_not_of(".") == std::string::npos) {
+ // Special case for component of only periods.
+ if (value.size() <= 2)
+ // Zero, one or two periods is illegal. Ignore this component.
+ return Component();
+ else
+ // Remove 3 periods.
+ return Component((const uint8_t *)&value[3], value.size() - 3);
+ }
+ else
+ return Component((const uint8_t *)&value[0], value.size());
+}
+
+void
+Component::toEscapedString(std::ostream& result) const
+{
+ const uint8_t *valuePtr = value();
+ size_t valueSize = value_size();
+
+ bool gotNonDot = false;
+ for (unsigned i = 0; i < valueSize; ++i) {
+ if (valuePtr[i] != 0x2e) {
+ gotNonDot = true;
+ break;
+ }
+ }
+ if (!gotNonDot) {
+ // Special case for component of zero or more periods. Add 3 periods.
+ result << "...";
+ for (size_t i = 0; i < valueSize; ++i)
+ result << '.';
+ }
+ else {
+ // In case we need to escape, set to upper case hex and save the previous flags.
+ std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
+
+ for (size_t i = 0; i < valueSize; ++i) {
+ uint8_t x = valuePtr[i];
+ // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
+ if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
+ (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
+ x == 0x2e || x == 0x5f)
+ result << x;
+ else {
+ result << '%';
+ if (x < 16)
+ result << '0';
+ result << (unsigned int)x;
+ }
+ }
+
+ // Restore.
+ result.flags(saveFlags);
+ }
+}
+
+
+uint64_t
+Component::toNumberWithMarker(uint8_t marker) const
+{
+ if (empty() || *value_begin() != marker)
+ throw Error("Name component does not begin with the expected marker");
+
+ uint64_t result = 0;
+ for (Buffer::const_iterator i = value_begin()+1; i != value_end(); ++i) {
+ result <<= 8;
+ result |= *i;
+ }
+
+ return result;
+}
+
+Component
+Component::fromNumber(uint64_t number)
+{
+ ptr_lib::shared_ptr<Buffer> value(new Buffer);
+
+ // First encode in little endian.
+ while (number != 0) {
+ value->push_back(number & 0xff);
+ number >>= 8;
+ }
+
+ // Make it big endian.
+ reverse(value->begin(), value->end());
+ return Component(value);
+}
+
+Component
+Component::fromNumberWithMarker(uint64_t number, uint8_t marker)
+{
+ ptr_lib::shared_ptr<Buffer> value(new Buffer);
+
+ // Add the leading marker.
+ value->push_back(marker);
+
+ // First encode in little endian.
+ while (number != 0) {
+ value->push_back(number & 0xff);
+ number >>= 8;
+ }
+
+ // Make it big endian.
+ reverse(value->begin() + 1, value->end());
+ return Component(value);
+}
+
+uint64_t
+Component::toNumber() const
+{
+ uint64_t result = 0;
+ for (Buffer::const_iterator i = value_begin(); i != value_end(); ++i) {
+ result <<= 8;
+ result |= *i;
+ }
+
+ return result;
+}
+
+int
+Component::compare(const Component& other) const
+{
+ // Imitate ndn_Exclude_compareComponents.
+ if (value_size() < other.value_size())
+ return -1;
+ if (value_size() > other.value_size())
+ return 1;
+
+ if (value_size() == 0)
+ return 0;
+
+ // The components are equal length. Just do a byte compare.
+ return std::memcmp(value(), other.value(), value_size());
+}
+
+// const Block &
+// wireEncode() const
+// {
+
+// }
+
+} // namespace name
+} // namespace ndn