blob: 05df5b38ed20d73af7b14a2960fa5139a1870593 [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
Zhenkai Zhub0adefe2013-01-04 21:56:38 -08009void
10CcnxCharbuf::init(ccn_charbuf *buf)
11{
12 if (buf != NULL)
13 {
14 m_buf = ccn_charbuf_create();
15 ccn_charbuf_reserve(m_buf, buf->length);
16 memcpy(m_buf->buf, buf->buf, buf->length);
17 m_buf->length = buf->length;
18 }
19}
20
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080021CcnxCharbuf::CcnxCharbuf()
22 : m_buf(NULL)
23{
24 m_buf = ccn_charbuf_create();
25}
26
27CcnxCharbuf::CcnxCharbuf(ccn_charbuf *buf)
28 : m_buf(NULL)
29{
Zhenkai Zhub0adefe2013-01-04 21:56:38 -080030 init(buf);
31}
32
33CcnxCharbuf::CcnxCharbuf(const CcnxCharbuf &other)
34 : m_buf (NULL)
35{
36 init(other.m_buf);
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080037}
38
39CcnxCharbuf::~CcnxCharbuf()
40{
41 ccn_charbuf_destroy(&m_buf);
42}
43
44Name::Name()
45{
46}
47
48Name::Name(const string &name)
49{
50 stringstream ss(name);
51 string compStr;
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080052 bool first = true;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080053 while(getline(ss, compStr, '/'))
54 {
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080055 // discard the first empty comp before the first '/'
56 if (first)
57 {
58 first = false;
59 continue;
60 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080061 Bytes comp(compStr.begin(), compStr.end());
62 m_comps.push_back(comp);
63 }
64}
65
66Name::Name(const vector<Bytes> &comps)
67{
68 m_comps = comps;
69}
70
71Name::Name(const Name &other)
72{
73 m_comps = other.m_comps;
74}
75
76Name::Name(const unsigned char *data, const ccn_indexbuf *comps)
77{
78 for (int i = 0; i < comps->n - 1; i++)
79 {
80 const unsigned char *compPtr;
81 size_t size;
82 ccn_name_comp_get(data, comps, i, &compPtr, &size);
83 Bytes comp;
84 readRaw(comp, compPtr, size);
85 m_comps.push_back(comp);
86 }
87}
88
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080089Name &
90Name::operator=(const Name &other)
91{
92 m_comps = other.m_comps;
93 return *this;
94}
95bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080096Name::operator==(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080097{
98 return this->toString() == str;
99}
100
101bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -0800102Name::operator!=(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800103{
104 return !(*this == str);
105}
106
107Name
108operator+(const Name &n1, const Name &n2)
109{
110 vector<Bytes> comps = n1.m_comps;
111 copy(n2.m_comps.begin(), n2.m_comps.end(), back_inserter(comps));
112 return Name(comps);
113}
114
115string
116Name::toString() const
117{
118 stringstream ss(stringstream::out);
119 ss << *this;
120 return ss.str();
121}
122
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800123CcnxCharbufPtr
124Name::toCcnxCharbuf() const
125{
126 CcnxCharbufPtr ptr(new CcnxCharbuf());
127 ccn_charbuf *cbuf = ptr->getBuf();
128 ccn_name_init(cbuf);
129 int size = m_comps.size();
130 for (int i = 0; i < size; i++)
131 {
132 ccn_name_append(cbuf, head(m_comps[i]), m_comps[i].size());
133 }
134 return ptr;
135}
136
137Name &
138Name::appendComp(const Bytes &comp)
139{
140 m_comps.push_back(comp);
141 return *this;
142}
143
144Name &
145Name::appendComp(const string &compStr)
146{
147 Bytes comp(compStr.begin(), compStr.end());
148 appendComp(comp);
149 return *this;
150}
151
152Bytes
153Name::getComp(int index) const
154{
155 if (index >= m_comps.size())
156 {
157 boost::throw_exception(NameException() << error_info_str("Index out of range: " + boost::lexical_cast<string>(index)));
158 }
159 return m_comps[index];
160}
161
162string
163Name::getCompAsString(int index) const
164{
165 Bytes comp = getComp(index);
166 stringstream ss(stringstream::out);
167 int size = comp.size();
168 for (int i = 0; i < size; i++)
169 {
170 unsigned char ch = comp[i];
171 if (isprint(ch))
172 {
173 ss << (char) ch;
174 }
175 else
176 {
177 ss << "%" << hex << setfill('0') << setw(2) << ch;
178 }
179 }
180
181 return ss.str();
182}
183
184Name
185Name::getPartialName(int start, int n) const
186{
187 int size = m_comps.size();
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800188 if (start < 0 || start >= size || n > 0 && start + n > size)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800189 {
190 stringstream ss(stringstream::out);
191 ss << "getPartialName() parameter out of range! ";
192 ss << "start = " << start;
193 ss << "n = " << n;
194 ss << "size = " << size;
195 boost::throw_exception(NameException() << error_info_str(ss.str()));
196 }
197
198 vector<Bytes> comps;
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800199 int end;
200 if (n > 0)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800201 {
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800202 end = start + n;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800203 }
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800204 else
205 {
206 end = size;
207 }
208
209 for (int i = start; i < end; i++)
210 {
211 comps.push_back(m_comps[i]);
212 }
213
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800214 return Name(comps);
215}
216
217ostream &
218operator <<(ostream &os, const Name &name)
219{
220 int size = name.size();
221 vector<string> strComps;
222 for (int i = 0; i < size; i++)
223 {
224 strComps.push_back(name.getCompAsString(i));
225 }
226 string joined = boost::algorithm::join(strComps, "/");
227 os << "/" << joined;
228 return os;
229}
230
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800231bool
232operator ==(const Name &n1, const Name &n2)
233{
234 stringstream ss1(stringstream::out);
235 stringstream ss2(stringstream::out);
236 ss1 << n1;
237 ss2 << n2;
238 return ss1.str() == ss2.str();
239}
240
241bool
242operator !=(const Name &n1, const Name &n2)
243{
244 return !(n1 == n2);
245}
246
247bool
248operator <(const Name &n1, const Name &n2)
249{
250 stringstream ss1(stringstream::out);
251 stringstream ss2(stringstream::out);
252 ss1 << n1;
253 ss2 << n2;
254 return ss1.str() < ss2.str();
255}
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800256
257Selectors::Selectors()
258 : m_maxSuffixComps(-1)
259 , m_minSuffixComps(-1)
260 , m_answerOriginKind(AOK_DEFAULT)
261 , m_interestLifetime(-1.0)
262 , m_scope(-1)
263 , m_childSelector(DEFAULT)
264{
265}
266
267Selectors::Selectors(const Selectors &other)
268{
269 m_maxSuffixComps = other.m_maxSuffixComps;
270 m_minSuffixComps = other.m_minSuffixComps;
271 m_answerOriginKind = other.m_answerOriginKind;
272 m_interestLifetime = other.m_interestLifetime;
273 m_scope = other.m_scope;
274 m_childSelector = other.m_childSelector;
275 m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
276}
277
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800278bool
279Selectors::operator == (const Selectors &other)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800280{
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800281 return m_maxSuffixComps == other.m_maxSuffixComps
282 && m_minSuffixComps == other.m_minSuffixComps
283 && m_answerOriginKind == other.m_answerOriginKind
284 && (m_interestLifetime - other.m_interestLifetime) < 10e-4
285 && m_scope == other.m_scope
286 && m_childSelector == other.m_childSelector;
287}
288
289bool
290Selectors::isEmpty() const
291{
292 return m_maxSuffixComps == -1
293 && m_minSuffixComps == -1
294 && m_answerOriginKind == AOK_DEFAULT
295 && (m_interestLifetime - (-1.0)) < 10e-4
296 && m_scope == -1
297 && m_childSelector == DEFAULT;
298}
299
300
301CcnxCharbufPtr
302Selectors::toCcnxCharbuf() const
303{
304 if (isEmpty())
305 {
306 return CcnxCharbuf::Null;
307 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800308 CcnxCharbufPtr ptr(new CcnxCharbuf());
309 ccn_charbuf *cbuf = ptr->getBuf();
310 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
311 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Name, CCN_DTAG);
312 ccn_charbuf_append_closer(cbuf); // </Name>
313
314 if (m_maxSuffixComps < m_minSuffixComps)
315 {
316 boost::throw_exception(InterestSelectorException() << error_info_str("MaxSuffixComps = " + boost::lexical_cast<string>(m_maxSuffixComps) + " is smaller than MinSuffixComps = " + boost::lexical_cast<string>(m_minSuffixComps)));
317 }
318
319 if (m_maxSuffixComps > 0)
320 {
321 ccnb_tagged_putf(cbuf, CCN_DTAG_MaxSuffixComponents, "%d", m_maxSuffixComps);
322 }
323
324 if (m_minSuffixComps > 0)
325 {
326 ccnb_tagged_putf(cbuf, CCN_DTAG_MinSuffixComponents, "%d", m_minSuffixComps);
327 }
328
329 if (m_answerOriginKind != AOK_DEFAULT)
330 {
331 // it was not using "ccnb_tagged_putf" in ccnx c code, no idea why
332 ccn_charbuf_append_tt(cbuf, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
333 ccnb_append_number(cbuf, m_answerOriginKind);
334 ccn_charbuf_append_closer(cbuf); // <AnswerOriginKind>
335 }
336
337 if (m_scope != -1)
338 {
339 ccnb_tagged_putf(cbuf, CCN_DTAG_Scope, "%d", m_scope);
340 }
341
342 if (m_interestLifetime > 0.0)
343 {
344 // Ccnx timestamp unit is weird 1/4096 second
345 // this is from their code
346 unsigned lifetime = 4096 * (m_interestLifetime + 1.0/8192.0);
347 if (lifetime == 0 || lifetime > (30 << 12))
348 {
349 boost::throw_exception(InterestSelectorException() << error_info_str("Ccnx requires 0 < lifetime < 30.0. lifetime= " + boost::lexical_cast<string>(m_interestLifetime)));
350 }
351 unsigned char buf[3] = {0};
352 for (int i = sizeof(buf) - 1; i >= 0; i--, lifetime >>= 8)
353 {
354 buf[i] = lifetime & 0xff;
355 }
356 ccnb_append_tagged_blob(cbuf, CCN_DTAG_InterestLifetime, buf, sizeof(buf));
357 }
358
359 if (m_childSelector != DEFAULT)
360 {
361 ccnb_tagged_putf(cbuf, CCN_DTAG_ChildSelector, "%d", m_childSelector);
362 }
363
364
365 ccn_charbuf_append_closer(cbuf); // </Interest>
366
367 return ptr;
368}
369
370} // Ccnx