blob: 748410f2c7173492f64ba9b449b4604fceb16b5f [file] [log] [blame]
Zhenkai Zhuf47109b2013-01-02 19:41:34 -08001#include "ccnx-name.h"
2#include <boost/lexical_cast.hpp>
3#include <ctype.h>
4#include <boost/algorithm/string/join.hpp>
5
6namespace Ccnx{
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -08007CcnxCharbufPtr CcnxCharbuf::Null;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -08008
9CcnxCharbuf::CcnxCharbuf()
10 : m_buf(NULL)
11{
12 m_buf = ccn_charbuf_create();
13}
14
15CcnxCharbuf::CcnxCharbuf(ccn_charbuf *buf)
16 : m_buf(NULL)
17{
18 if (buf != NULL)
19 {
20 m_buf = ccn_charbuf_create();
21 ccn_charbuf_reserve(m_buf, buf->length);
22 memcpy(m_buf->buf, buf->buf, buf->length);
23 m_buf->length = buf->length;
24 }
25}
26
27CcnxCharbuf::~CcnxCharbuf()
28{
29 ccn_charbuf_destroy(&m_buf);
30}
31
32Name::Name()
33{
34}
35
36Name::Name(const string &name)
37{
38 stringstream ss(name);
39 string compStr;
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080040 bool first = true;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080041 while(getline(ss, compStr, '/'))
42 {
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080043 // discard the first empty comp before the first '/'
44 if (first)
45 {
46 first = false;
47 continue;
48 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080049 Bytes comp(compStr.begin(), compStr.end());
50 m_comps.push_back(comp);
51 }
52}
53
54Name::Name(const vector<Bytes> &comps)
55{
56 m_comps = comps;
57}
58
59Name::Name(const Name &other)
60{
61 m_comps = other.m_comps;
62}
63
64Name::Name(const unsigned char *data, const ccn_indexbuf *comps)
65{
66 for (int i = 0; i < comps->n - 1; i++)
67 {
68 const unsigned char *compPtr;
69 size_t size;
70 ccn_name_comp_get(data, comps, i, &compPtr, &size);
71 Bytes comp;
72 readRaw(comp, compPtr, size);
73 m_comps.push_back(comp);
74 }
75}
76
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080077Name &
78Name::operator=(const Name &other)
79{
80 m_comps = other.m_comps;
81 return *this;
82}
83bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080084Name::operator==(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080085{
86 return this->toString() == str;
87}
88
89bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080090Name::operator!=(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080091{
92 return !(*this == str);
93}
94
95Name
96operator+(const Name &n1, const Name &n2)
97{
98 vector<Bytes> comps = n1.m_comps;
99 copy(n2.m_comps.begin(), n2.m_comps.end(), back_inserter(comps));
100 return Name(comps);
101}
102
103string
104Name::toString() const
105{
106 stringstream ss(stringstream::out);
107 ss << *this;
108 return ss.str();
109}
110
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800111CcnxCharbufPtr
112Name::toCcnxCharbuf() const
113{
114 CcnxCharbufPtr ptr(new CcnxCharbuf());
115 ccn_charbuf *cbuf = ptr->getBuf();
116 ccn_name_init(cbuf);
117 int size = m_comps.size();
118 for (int i = 0; i < size; i++)
119 {
120 ccn_name_append(cbuf, head(m_comps[i]), m_comps[i].size());
121 }
122 return ptr;
123}
124
125Name &
126Name::appendComp(const Bytes &comp)
127{
128 m_comps.push_back(comp);
129 return *this;
130}
131
132Name &
133Name::appendComp(const string &compStr)
134{
135 Bytes comp(compStr.begin(), compStr.end());
136 appendComp(comp);
137 return *this;
138}
139
140Bytes
141Name::getComp(int index) const
142{
143 if (index >= m_comps.size())
144 {
145 boost::throw_exception(NameException() << error_info_str("Index out of range: " + boost::lexical_cast<string>(index)));
146 }
147 return m_comps[index];
148}
149
150string
151Name::getCompAsString(int index) const
152{
153 Bytes comp = getComp(index);
154 stringstream ss(stringstream::out);
155 int size = comp.size();
156 for (int i = 0; i < size; i++)
157 {
158 unsigned char ch = comp[i];
159 if (isprint(ch))
160 {
161 ss << (char) ch;
162 }
163 else
164 {
165 ss << "%" << hex << setfill('0') << setw(2) << ch;
166 }
167 }
168
169 return ss.str();
170}
171
172Name
173Name::getPartialName(int start, int n) const
174{
175 int size = m_comps.size();
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800176 if (start < 0 || start >= size || n > 0 && start + n > size)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800177 {
178 stringstream ss(stringstream::out);
179 ss << "getPartialName() parameter out of range! ";
180 ss << "start = " << start;
181 ss << "n = " << n;
182 ss << "size = " << size;
183 boost::throw_exception(NameException() << error_info_str(ss.str()));
184 }
185
186 vector<Bytes> comps;
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800187 int end;
188 if (n > 0)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800189 {
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800190 end = start + n;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800191 }
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800192 else
193 {
194 end = size;
195 }
196
197 for (int i = start; i < end; i++)
198 {
199 comps.push_back(m_comps[i]);
200 }
201
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800202 return Name(comps);
203}
204
205ostream &
206operator <<(ostream &os, const Name &name)
207{
208 int size = name.size();
209 vector<string> strComps;
210 for (int i = 0; i < size; i++)
211 {
212 strComps.push_back(name.getCompAsString(i));
213 }
214 string joined = boost::algorithm::join(strComps, "/");
215 os << "/" << joined;
216 return os;
217}
218
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800219bool
220operator ==(const Name &n1, const Name &n2)
221{
222 stringstream ss1(stringstream::out);
223 stringstream ss2(stringstream::out);
224 ss1 << n1;
225 ss2 << n2;
226 return ss1.str() == ss2.str();
227}
228
229bool
230operator !=(const Name &n1, const Name &n2)
231{
232 return !(n1 == n2);
233}
234
235bool
236operator <(const Name &n1, const Name &n2)
237{
238 stringstream ss1(stringstream::out);
239 stringstream ss2(stringstream::out);
240 ss1 << n1;
241 ss2 << n2;
242 return ss1.str() < ss2.str();
243}
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800244
245Selectors::Selectors()
246 : m_maxSuffixComps(-1)
247 , m_minSuffixComps(-1)
248 , m_answerOriginKind(AOK_DEFAULT)
249 , m_interestLifetime(-1.0)
250 , m_scope(-1)
251 , m_childSelector(DEFAULT)
252{
253}
254
255Selectors::Selectors(const Selectors &other)
256{
257 m_maxSuffixComps = other.m_maxSuffixComps;
258 m_minSuffixComps = other.m_minSuffixComps;
259 m_answerOriginKind = other.m_answerOriginKind;
260 m_interestLifetime = other.m_interestLifetime;
261 m_scope = other.m_scope;
262 m_childSelector = other.m_childSelector;
263 m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
264}
265
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800266bool
267Selectors::operator == (const Selectors &other)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800268{
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800269 return m_maxSuffixComps == other.m_maxSuffixComps
270 && m_minSuffixComps == other.m_minSuffixComps
271 && m_answerOriginKind == other.m_answerOriginKind
272 && (m_interestLifetime - other.m_interestLifetime) < 10e-4
273 && m_scope == other.m_scope
274 && m_childSelector == other.m_childSelector;
275}
276
277bool
278Selectors::isEmpty() const
279{
280 return m_maxSuffixComps == -1
281 && m_minSuffixComps == -1
282 && m_answerOriginKind == AOK_DEFAULT
283 && (m_interestLifetime - (-1.0)) < 10e-4
284 && m_scope == -1
285 && m_childSelector == DEFAULT;
286}
287
288
289CcnxCharbufPtr
290Selectors::toCcnxCharbuf() const
291{
292 if (isEmpty())
293 {
294 return CcnxCharbuf::Null;
295 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800296 CcnxCharbufPtr ptr(new CcnxCharbuf());
297 ccn_charbuf *cbuf = ptr->getBuf();
298 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
299 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Name, CCN_DTAG);
300 ccn_charbuf_append_closer(cbuf); // </Name>
301
302 if (m_maxSuffixComps < m_minSuffixComps)
303 {
304 boost::throw_exception(InterestSelectorException() << error_info_str("MaxSuffixComps = " + boost::lexical_cast<string>(m_maxSuffixComps) + " is smaller than MinSuffixComps = " + boost::lexical_cast<string>(m_minSuffixComps)));
305 }
306
307 if (m_maxSuffixComps > 0)
308 {
309 ccnb_tagged_putf(cbuf, CCN_DTAG_MaxSuffixComponents, "%d", m_maxSuffixComps);
310 }
311
312 if (m_minSuffixComps > 0)
313 {
314 ccnb_tagged_putf(cbuf, CCN_DTAG_MinSuffixComponents, "%d", m_minSuffixComps);
315 }
316
317 if (m_answerOriginKind != AOK_DEFAULT)
318 {
319 // it was not using "ccnb_tagged_putf" in ccnx c code, no idea why
320 ccn_charbuf_append_tt(cbuf, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
321 ccnb_append_number(cbuf, m_answerOriginKind);
322 ccn_charbuf_append_closer(cbuf); // <AnswerOriginKind>
323 }
324
325 if (m_scope != -1)
326 {
327 ccnb_tagged_putf(cbuf, CCN_DTAG_Scope, "%d", m_scope);
328 }
329
330 if (m_interestLifetime > 0.0)
331 {
332 // Ccnx timestamp unit is weird 1/4096 second
333 // this is from their code
334 unsigned lifetime = 4096 * (m_interestLifetime + 1.0/8192.0);
335 if (lifetime == 0 || lifetime > (30 << 12))
336 {
337 boost::throw_exception(InterestSelectorException() << error_info_str("Ccnx requires 0 < lifetime < 30.0. lifetime= " + boost::lexical_cast<string>(m_interestLifetime)));
338 }
339 unsigned char buf[3] = {0};
340 for (int i = sizeof(buf) - 1; i >= 0; i--, lifetime >>= 8)
341 {
342 buf[i] = lifetime & 0xff;
343 }
344 ccnb_append_tagged_blob(cbuf, CCN_DTAG_InterestLifetime, buf, sizeof(buf));
345 }
346
347 if (m_childSelector != DEFAULT)
348 {
349 ccnb_tagged_putf(cbuf, CCN_DTAG_ChildSelector, "%d", m_childSelector);
350 }
351
352
353 ccn_charbuf_append_closer(cbuf); // </Interest>
354
355 return ptr;
356}
357
358} // Ccnx