blob: 3956e80d1a20be5870045a2aff05dbceaf540473 [file] [log] [blame]
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
5 * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
6 * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
7 * See COPYING for copyright and distribution information.
8 */
9
10#include "name-component.hpp"
11
12#include "util/time.hpp"
13#include "util/string-helper.hpp"
14
15namespace ndn {
16namespace name {
17
18Component
19Component::fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset)
20{
21 std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
22 trim(trimmedString);
23 std::string value = unescape(trimmedString);
24
25 if (value.find_first_not_of(".") == std::string::npos) {
26 // Special case for component of only periods.
27 if (value.size() <= 2)
28 // Zero, one or two periods is illegal. Ignore this component.
29 return Component();
30 else
31 // Remove 3 periods.
32 return Component((const uint8_t *)&value[3], value.size() - 3);
33 }
34 else
35 return Component((const uint8_t *)&value[0], value.size());
36}
37
38void
39Component::toEscapedString(std::ostream& result) const
40{
41 const uint8_t *valuePtr = value();
42 size_t valueSize = value_size();
43
44 bool gotNonDot = false;
45 for (unsigned i = 0; i < valueSize; ++i) {
46 if (valuePtr[i] != 0x2e) {
47 gotNonDot = true;
48 break;
49 }
50 }
51 if (!gotNonDot) {
52 // Special case for component of zero or more periods. Add 3 periods.
53 result << "...";
54 for (size_t i = 0; i < valueSize; ++i)
55 result << '.';
56 }
57 else {
58 // In case we need to escape, set to upper case hex and save the previous flags.
59 std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
60
61 for (size_t i = 0; i < valueSize; ++i) {
62 uint8_t x = valuePtr[i];
63 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
64 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
65 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
66 x == 0x2e || x == 0x5f)
67 result << x;
68 else {
69 result << '%';
70 if (x < 16)
71 result << '0';
72 result << (unsigned int)x;
73 }
74 }
75
76 // Restore.
77 result.flags(saveFlags);
78 }
79}
80
81
82uint64_t
83Component::toNumberWithMarker(uint8_t marker) const
84{
85 if (empty() || *value_begin() != marker)
86 throw Error("Name component does not begin with the expected marker");
87
88 uint64_t result = 0;
89 for (Buffer::const_iterator i = value_begin()+1; i != value_end(); ++i) {
90 result <<= 8;
91 result |= *i;
92 }
93
94 return result;
95}
96
97Component
98Component::fromNumber(uint64_t number)
99{
100 ptr_lib::shared_ptr<Buffer> value(new Buffer);
101
102 // First encode in little endian.
103 while (number != 0) {
104 value->push_back(number & 0xff);
105 number >>= 8;
106 }
107
108 // Make it big endian.
109 reverse(value->begin(), value->end());
110 return Component(value);
111}
112
113Component
114Component::fromNumberWithMarker(uint64_t number, uint8_t marker)
115{
116 ptr_lib::shared_ptr<Buffer> value(new Buffer);
117
118 // Add the leading marker.
119 value->push_back(marker);
120
121 // First encode in little endian.
122 while (number != 0) {
123 value->push_back(number & 0xff);
124 number >>= 8;
125 }
126
127 // Make it big endian.
128 reverse(value->begin() + 1, value->end());
129 return Component(value);
130}
131
132uint64_t
133Component::toNumber() const
134{
135 uint64_t result = 0;
136 for (Buffer::const_iterator i = value_begin(); i != value_end(); ++i) {
137 result <<= 8;
138 result |= *i;
139 }
140
141 return result;
142}
143
144int
145Component::compare(const Component& other) const
146{
147 // Imitate ndn_Exclude_compareComponents.
148 if (value_size() < other.value_size())
149 return -1;
150 if (value_size() > other.value_size())
151 return 1;
152
153 if (value_size() == 0)
154 return 0;
155
156 // The components are equal length. Just do a byte compare.
157 return std::memcmp(value(), other.value(), value_size());
158}
159
160// const Block &
161// wireEncode() const
162// {
163
164// }
165
166} // namespace name
167} // namespace ndn