blob: 9e9f9e086b285fc4627f40dcf810554e61b6ca2e [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
Alexander Afanasyevd09871f2013-01-04 22:36:37 -080077Name::Name (const unsigned char *buf, const size_t length)
78{
79 ccn_indexbuf *idx = ccn_indexbuf_create();
80 const ccn_charbuf namebuf = { length, length, const_cast<unsigned char *> (buf) };
81 ccn_name_split (&namebuf, idx);
82
83 const unsigned char *compPtr = NULL;
84 size_t size = 0;
85 int i = 0;
86 while (ccn_name_comp_get(namebuf.buf, idx, i, &compPtr, &size) == 0)
87 {
88 Bytes comp;
89 readRaw (comp, compPtr, size);
90 m_comps.push_back(comp);
91 i++;
92 }
93 ccn_indexbuf_destroy(&idx);
94}
95
96
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080097Name &
98Name::operator=(const Name &other)
99{
100 m_comps = other.m_comps;
101 return *this;
102}
103bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -0800104Name::operator==(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800105{
106 return this->toString() == str;
107}
108
109bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -0800110Name::operator!=(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800111{
112 return !(*this == str);
113}
114
115Name
116operator+(const Name &n1, const Name &n2)
117{
118 vector<Bytes> comps = n1.m_comps;
119 copy(n2.m_comps.begin(), n2.m_comps.end(), back_inserter(comps));
120 return Name(comps);
121}
122
123string
124Name::toString() const
125{
126 stringstream ss(stringstream::out);
127 ss << *this;
128 return ss.str();
129}
130
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800131CcnxCharbufPtr
132Name::toCcnxCharbuf() const
133{
134 CcnxCharbufPtr ptr(new CcnxCharbuf());
135 ccn_charbuf *cbuf = ptr->getBuf();
136 ccn_name_init(cbuf);
137 int size = m_comps.size();
138 for (int i = 0; i < size; i++)
139 {
140 ccn_name_append(cbuf, head(m_comps[i]), m_comps[i].size());
141 }
142 return ptr;
143}
144
145Name &
146Name::appendComp(const Bytes &comp)
147{
148 m_comps.push_back(comp);
149 return *this;
150}
151
152Name &
153Name::appendComp(const string &compStr)
154{
155 Bytes comp(compStr.begin(), compStr.end());
156 appendComp(comp);
157 return *this;
158}
159
160Bytes
161Name::getComp(int index) const
162{
163 if (index >= m_comps.size())
164 {
165 boost::throw_exception(NameException() << error_info_str("Index out of range: " + boost::lexical_cast<string>(index)));
166 }
167 return m_comps[index];
168}
169
170string
171Name::getCompAsString(int index) const
172{
173 Bytes comp = getComp(index);
174 stringstream ss(stringstream::out);
175 int size = comp.size();
176 for (int i = 0; i < size; i++)
177 {
178 unsigned char ch = comp[i];
179 if (isprint(ch))
180 {
181 ss << (char) ch;
182 }
183 else
184 {
185 ss << "%" << hex << setfill('0') << setw(2) << ch;
186 }
187 }
188
189 return ss.str();
190}
191
192Name
193Name::getPartialName(int start, int n) const
194{
195 int size = m_comps.size();
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800196 if (start < 0 || start >= size || n > 0 && start + n > size)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800197 {
198 stringstream ss(stringstream::out);
199 ss << "getPartialName() parameter out of range! ";
200 ss << "start = " << start;
201 ss << "n = " << n;
202 ss << "size = " << size;
203 boost::throw_exception(NameException() << error_info_str(ss.str()));
204 }
205
206 vector<Bytes> comps;
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800207 int end;
208 if (n > 0)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800209 {
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800210 end = start + n;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800211 }
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800212 else
213 {
214 end = size;
215 }
216
217 for (int i = start; i < end; i++)
218 {
219 comps.push_back(m_comps[i]);
220 }
221
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800222 return Name(comps);
223}
224
225ostream &
226operator <<(ostream &os, const Name &name)
227{
228 int size = name.size();
229 vector<string> strComps;
230 for (int i = 0; i < size; i++)
231 {
232 strComps.push_back(name.getCompAsString(i));
233 }
234 string joined = boost::algorithm::join(strComps, "/");
235 os << "/" << joined;
236 return os;
237}
238
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800239bool
240operator ==(const Name &n1, const Name &n2)
241{
242 stringstream ss1(stringstream::out);
243 stringstream ss2(stringstream::out);
244 ss1 << n1;
245 ss2 << n2;
246 return ss1.str() == ss2.str();
247}
248
249bool
250operator !=(const Name &n1, const Name &n2)
251{
252 return !(n1 == n2);
253}
254
255bool
256operator <(const Name &n1, const Name &n2)
257{
258 stringstream ss1(stringstream::out);
259 stringstream ss2(stringstream::out);
260 ss1 << n1;
261 ss2 << n2;
262 return ss1.str() < ss2.str();
263}
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800264
265Selectors::Selectors()
266 : m_maxSuffixComps(-1)
267 , m_minSuffixComps(-1)
268 , m_answerOriginKind(AOK_DEFAULT)
269 , m_interestLifetime(-1.0)
270 , m_scope(-1)
271 , m_childSelector(DEFAULT)
272{
273}
274
275Selectors::Selectors(const Selectors &other)
276{
277 m_maxSuffixComps = other.m_maxSuffixComps;
278 m_minSuffixComps = other.m_minSuffixComps;
279 m_answerOriginKind = other.m_answerOriginKind;
280 m_interestLifetime = other.m_interestLifetime;
281 m_scope = other.m_scope;
282 m_childSelector = other.m_childSelector;
283 m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
284}
285
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800286bool
287Selectors::operator == (const Selectors &other)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800288{
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800289 return m_maxSuffixComps == other.m_maxSuffixComps
290 && m_minSuffixComps == other.m_minSuffixComps
291 && m_answerOriginKind == other.m_answerOriginKind
292 && (m_interestLifetime - other.m_interestLifetime) < 10e-4
293 && m_scope == other.m_scope
294 && m_childSelector == other.m_childSelector;
295}
296
297bool
298Selectors::isEmpty() const
299{
300 return m_maxSuffixComps == -1
301 && m_minSuffixComps == -1
302 && m_answerOriginKind == AOK_DEFAULT
303 && (m_interestLifetime - (-1.0)) < 10e-4
304 && m_scope == -1
305 && m_childSelector == DEFAULT;
306}
307
308
309CcnxCharbufPtr
310Selectors::toCcnxCharbuf() const
311{
312 if (isEmpty())
313 {
314 return CcnxCharbuf::Null;
315 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800316 CcnxCharbufPtr ptr(new CcnxCharbuf());
317 ccn_charbuf *cbuf = ptr->getBuf();
318 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
319 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Name, CCN_DTAG);
320 ccn_charbuf_append_closer(cbuf); // </Name>
321
322 if (m_maxSuffixComps < m_minSuffixComps)
323 {
324 boost::throw_exception(InterestSelectorException() << error_info_str("MaxSuffixComps = " + boost::lexical_cast<string>(m_maxSuffixComps) + " is smaller than MinSuffixComps = " + boost::lexical_cast<string>(m_minSuffixComps)));
325 }
326
327 if (m_maxSuffixComps > 0)
328 {
329 ccnb_tagged_putf(cbuf, CCN_DTAG_MaxSuffixComponents, "%d", m_maxSuffixComps);
330 }
331
332 if (m_minSuffixComps > 0)
333 {
334 ccnb_tagged_putf(cbuf, CCN_DTAG_MinSuffixComponents, "%d", m_minSuffixComps);
335 }
336
337 if (m_answerOriginKind != AOK_DEFAULT)
338 {
339 // it was not using "ccnb_tagged_putf" in ccnx c code, no idea why
340 ccn_charbuf_append_tt(cbuf, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
341 ccnb_append_number(cbuf, m_answerOriginKind);
342 ccn_charbuf_append_closer(cbuf); // <AnswerOriginKind>
343 }
344
345 if (m_scope != -1)
346 {
347 ccnb_tagged_putf(cbuf, CCN_DTAG_Scope, "%d", m_scope);
348 }
349
350 if (m_interestLifetime > 0.0)
351 {
352 // Ccnx timestamp unit is weird 1/4096 second
353 // this is from their code
354 unsigned lifetime = 4096 * (m_interestLifetime + 1.0/8192.0);
355 if (lifetime == 0 || lifetime > (30 << 12))
356 {
357 boost::throw_exception(InterestSelectorException() << error_info_str("Ccnx requires 0 < lifetime < 30.0. lifetime= " + boost::lexical_cast<string>(m_interestLifetime)));
358 }
359 unsigned char buf[3] = {0};
360 for (int i = sizeof(buf) - 1; i >= 0; i--, lifetime >>= 8)
361 {
362 buf[i] = lifetime & 0xff;
363 }
364 ccnb_append_tagged_blob(cbuf, CCN_DTAG_InterestLifetime, buf, sizeof(buf));
365 }
366
367 if (m_childSelector != DEFAULT)
368 {
369 ccnb_tagged_putf(cbuf, CCN_DTAG_ChildSelector, "%d", m_childSelector);
370 }
371
372
373 ccn_charbuf_append_closer(cbuf); // </Interest>
374
375 return ptr;
376}
377
378} // Ccnx