blob: ce5f270414eb304fa5ba07b25697e5333dcd23c6 [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;
40 while(getline(ss, compStr, '/'))
41 {
42 Bytes comp(compStr.begin(), compStr.end());
43 m_comps.push_back(comp);
44 }
45}
46
47Name::Name(const vector<Bytes> &comps)
48{
49 m_comps = comps;
50}
51
52Name::Name(const Name &other)
53{
54 m_comps = other.m_comps;
55}
56
57Name::Name(const unsigned char *data, const ccn_indexbuf *comps)
58{
59 for (int i = 0; i < comps->n - 1; i++)
60 {
61 const unsigned char *compPtr;
62 size_t size;
63 ccn_name_comp_get(data, comps, i, &compPtr, &size);
64 Bytes comp;
65 readRaw(comp, compPtr, size);
66 m_comps.push_back(comp);
67 }
68}
69
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080070Name &
71Name::operator=(const Name &other)
72{
73 m_comps = other.m_comps;
74 return *this;
75}
76bool
77Name::operator==(const string &str)
78{
79 return this->toString() == str;
80}
81
82bool
83Name::operator!=(const string &str)
84{
85 return !(*this == str);
86}
87
88Name
89operator+(const Name &n1, const Name &n2)
90{
91 vector<Bytes> comps = n1.m_comps;
92 copy(n2.m_comps.begin(), n2.m_comps.end(), back_inserter(comps));
93 return Name(comps);
94}
95
96string
97Name::toString() const
98{
99 stringstream ss(stringstream::out);
100 ss << *this;
101 return ss.str();
102}
103
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800104CcnxCharbufPtr
105Name::toCcnxCharbuf() const
106{
107 CcnxCharbufPtr ptr(new CcnxCharbuf());
108 ccn_charbuf *cbuf = ptr->getBuf();
109 ccn_name_init(cbuf);
110 int size = m_comps.size();
111 for (int i = 0; i < size; i++)
112 {
113 ccn_name_append(cbuf, head(m_comps[i]), m_comps[i].size());
114 }
115 return ptr;
116}
117
118Name &
119Name::appendComp(const Bytes &comp)
120{
121 m_comps.push_back(comp);
122 return *this;
123}
124
125Name &
126Name::appendComp(const string &compStr)
127{
128 Bytes comp(compStr.begin(), compStr.end());
129 appendComp(comp);
130 return *this;
131}
132
133Bytes
134Name::getComp(int index) const
135{
136 if (index >= m_comps.size())
137 {
138 boost::throw_exception(NameException() << error_info_str("Index out of range: " + boost::lexical_cast<string>(index)));
139 }
140 return m_comps[index];
141}
142
143string
144Name::getCompAsString(int index) const
145{
146 Bytes comp = getComp(index);
147 stringstream ss(stringstream::out);
148 int size = comp.size();
149 for (int i = 0; i < size; i++)
150 {
151 unsigned char ch = comp[i];
152 if (isprint(ch))
153 {
154 ss << (char) ch;
155 }
156 else
157 {
158 ss << "%" << hex << setfill('0') << setw(2) << ch;
159 }
160 }
161
162 return ss.str();
163}
164
165Name
166Name::getPartialName(int start, int n) const
167{
168 int size = m_comps.size();
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800169 if (start < 0 || start >= size || n > 0 && start + n > size)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800170 {
171 stringstream ss(stringstream::out);
172 ss << "getPartialName() parameter out of range! ";
173 ss << "start = " << start;
174 ss << "n = " << n;
175 ss << "size = " << size;
176 boost::throw_exception(NameException() << error_info_str(ss.str()));
177 }
178
179 vector<Bytes> comps;
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800180 int end;
181 if (n > 0)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800182 {
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800183 end = start + n;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800184 }
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800185 else
186 {
187 end = size;
188 }
189
190 for (int i = start; i < end; i++)
191 {
192 comps.push_back(m_comps[i]);
193 }
194
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800195 return Name(comps);
196}
197
198ostream &
199operator <<(ostream &os, const Name &name)
200{
201 int size = name.size();
202 vector<string> strComps;
203 for (int i = 0; i < size; i++)
204 {
205 strComps.push_back(name.getCompAsString(i));
206 }
207 string joined = boost::algorithm::join(strComps, "/");
208 os << "/" << joined;
209 return os;
210}
211
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800212bool
213operator ==(const Name &n1, const Name &n2)
214{
215 stringstream ss1(stringstream::out);
216 stringstream ss2(stringstream::out);
217 ss1 << n1;
218 ss2 << n2;
219 return ss1.str() == ss2.str();
220}
221
222bool
223operator !=(const Name &n1, const Name &n2)
224{
225 return !(n1 == n2);
226}
227
228bool
229operator <(const Name &n1, const Name &n2)
230{
231 stringstream ss1(stringstream::out);
232 stringstream ss2(stringstream::out);
233 ss1 << n1;
234 ss2 << n2;
235 return ss1.str() < ss2.str();
236}
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800237
238Selectors::Selectors()
239 : m_maxSuffixComps(-1)
240 , m_minSuffixComps(-1)
241 , m_answerOriginKind(AOK_DEFAULT)
242 , m_interestLifetime(-1.0)
243 , m_scope(-1)
244 , m_childSelector(DEFAULT)
245{
246}
247
248Selectors::Selectors(const Selectors &other)
249{
250 m_maxSuffixComps = other.m_maxSuffixComps;
251 m_minSuffixComps = other.m_minSuffixComps;
252 m_answerOriginKind = other.m_answerOriginKind;
253 m_interestLifetime = other.m_interestLifetime;
254 m_scope = other.m_scope;
255 m_childSelector = other.m_childSelector;
256 m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
257}
258
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800259bool
260Selectors::operator == (const Selectors &other)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800261{
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800262 return m_maxSuffixComps == other.m_maxSuffixComps
263 && m_minSuffixComps == other.m_minSuffixComps
264 && m_answerOriginKind == other.m_answerOriginKind
265 && (m_interestLifetime - other.m_interestLifetime) < 10e-4
266 && m_scope == other.m_scope
267 && m_childSelector == other.m_childSelector;
268}
269
270bool
271Selectors::isEmpty() const
272{
273 return m_maxSuffixComps == -1
274 && m_minSuffixComps == -1
275 && m_answerOriginKind == AOK_DEFAULT
276 && (m_interestLifetime - (-1.0)) < 10e-4
277 && m_scope == -1
278 && m_childSelector == DEFAULT;
279}
280
281
282CcnxCharbufPtr
283Selectors::toCcnxCharbuf() const
284{
285 if (isEmpty())
286 {
287 return CcnxCharbuf::Null;
288 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800289 CcnxCharbufPtr ptr(new CcnxCharbuf());
290 ccn_charbuf *cbuf = ptr->getBuf();
291 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
292 ccn_charbuf_append_tt(cbuf, CCN_DTAG_Name, CCN_DTAG);
293 ccn_charbuf_append_closer(cbuf); // </Name>
294
295 if (m_maxSuffixComps < m_minSuffixComps)
296 {
297 boost::throw_exception(InterestSelectorException() << error_info_str("MaxSuffixComps = " + boost::lexical_cast<string>(m_maxSuffixComps) + " is smaller than MinSuffixComps = " + boost::lexical_cast<string>(m_minSuffixComps)));
298 }
299
300 if (m_maxSuffixComps > 0)
301 {
302 ccnb_tagged_putf(cbuf, CCN_DTAG_MaxSuffixComponents, "%d", m_maxSuffixComps);
303 }
304
305 if (m_minSuffixComps > 0)
306 {
307 ccnb_tagged_putf(cbuf, CCN_DTAG_MinSuffixComponents, "%d", m_minSuffixComps);
308 }
309
310 if (m_answerOriginKind != AOK_DEFAULT)
311 {
312 // it was not using "ccnb_tagged_putf" in ccnx c code, no idea why
313 ccn_charbuf_append_tt(cbuf, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
314 ccnb_append_number(cbuf, m_answerOriginKind);
315 ccn_charbuf_append_closer(cbuf); // <AnswerOriginKind>
316 }
317
318 if (m_scope != -1)
319 {
320 ccnb_tagged_putf(cbuf, CCN_DTAG_Scope, "%d", m_scope);
321 }
322
323 if (m_interestLifetime > 0.0)
324 {
325 // Ccnx timestamp unit is weird 1/4096 second
326 // this is from their code
327 unsigned lifetime = 4096 * (m_interestLifetime + 1.0/8192.0);
328 if (lifetime == 0 || lifetime > (30 << 12))
329 {
330 boost::throw_exception(InterestSelectorException() << error_info_str("Ccnx requires 0 < lifetime < 30.0. lifetime= " + boost::lexical_cast<string>(m_interestLifetime)));
331 }
332 unsigned char buf[3] = {0};
333 for (int i = sizeof(buf) - 1; i >= 0; i--, lifetime >>= 8)
334 {
335 buf[i] = lifetime & 0xff;
336 }
337 ccnb_append_tagged_blob(cbuf, CCN_DTAG_InterestLifetime, buf, sizeof(buf));
338 }
339
340 if (m_childSelector != DEFAULT)
341 {
342 ccnb_tagged_putf(cbuf, CCN_DTAG_ChildSelector, "%d", m_childSelector);
343 }
344
345
346 ccn_charbuf_append_closer(cbuf); // </Interest>
347
348 return ptr;
349}
350
351} // Ccnx