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