blob: cf6a4753da05bb6ccb6bba09ca718e67ce1dce18 [file] [log] [blame]
Alexander Afanasyev49a30d02013-01-21 21:38:48 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
19 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 */
21
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080022#include "ccnx-name.h"
23#include <boost/lexical_cast.hpp>
24#include <ctype.h>
25#include <boost/algorithm/string/join.hpp>
26
27namespace Ccnx{
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -080028CcnxCharbufPtr CcnxCharbuf::Null;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080029
Zhenkai Zhub0adefe2013-01-04 21:56:38 -080030void
31CcnxCharbuf::init(ccn_charbuf *buf)
32{
33 if (buf != NULL)
34 {
35 m_buf = ccn_charbuf_create();
36 ccn_charbuf_reserve(m_buf, buf->length);
37 memcpy(m_buf->buf, buf->buf, buf->length);
38 m_buf->length = buf->length;
39 }
40}
41
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080042CcnxCharbuf::CcnxCharbuf()
43 : m_buf(NULL)
44{
45 m_buf = ccn_charbuf_create();
46}
47
48CcnxCharbuf::CcnxCharbuf(ccn_charbuf *buf)
49 : m_buf(NULL)
50{
Zhenkai Zhub0adefe2013-01-04 21:56:38 -080051 init(buf);
52}
53
54CcnxCharbuf::CcnxCharbuf(const CcnxCharbuf &other)
55 : m_buf (NULL)
56{
57 init(other.m_buf);
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080058}
59
Alexander Afanasyev0995f322013-01-22 13:16:46 -080060CcnxCharbuf::CcnxCharbuf(const void *buf, size_t length)
61{
62 m_buf = ccn_charbuf_create ();
63 ccn_charbuf_reserve (m_buf, length);
64 memcpy (m_buf->buf, buf, length);
65 m_buf->length = length;
66}
67
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080068CcnxCharbuf::~CcnxCharbuf()
69{
70 ccn_charbuf_destroy(&m_buf);
71}
72
73Name::Name()
74{
75}
76
77Name::Name(const string &name)
78{
79 stringstream ss(name);
80 string compStr;
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080081 bool first = true;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080082 while(getline(ss, compStr, '/'))
83 {
Zhenkai Zhu3b82d432013-01-03 22:48:40 -080084 // discard the first empty comp before the first '/'
85 if (first)
86 {
87 first = false;
88 continue;
89 }
Zhenkai Zhuf47109b2013-01-02 19:41:34 -080090 Bytes comp(compStr.begin(), compStr.end());
91 m_comps.push_back(comp);
92 }
93}
94
95Name::Name(const vector<Bytes> &comps)
96{
97 m_comps = comps;
98}
99
100Name::Name(const Name &other)
101{
102 m_comps = other.m_comps;
103}
104
105Name::Name(const unsigned char *data, const ccn_indexbuf *comps)
106{
107 for (int i = 0; i < comps->n - 1; i++)
108 {
109 const unsigned char *compPtr;
110 size_t size;
111 ccn_name_comp_get(data, comps, i, &compPtr, &size);
112 Bytes comp;
113 readRaw(comp, compPtr, size);
114 m_comps.push_back(comp);
115 }
116}
117
Alexander Afanasyevd09871f2013-01-04 22:36:37 -0800118Name::Name (const unsigned char *buf, const size_t length)
119{
120 ccn_indexbuf *idx = ccn_indexbuf_create();
121 const ccn_charbuf namebuf = { length, length, const_cast<unsigned char *> (buf) };
122 ccn_name_split (&namebuf, idx);
123
124 const unsigned char *compPtr = NULL;
125 size_t size = 0;
126 int i = 0;
127 while (ccn_name_comp_get(namebuf.buf, idx, i, &compPtr, &size) == 0)
128 {
129 Bytes comp;
130 readRaw (comp, compPtr, size);
131 m_comps.push_back(comp);
132 i++;
133 }
134 ccn_indexbuf_destroy(&idx);
135}
136
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800137Name::Name (const CcnxCharbuf &buf)
138{
139 ccn_indexbuf *idx = ccn_indexbuf_create();
140 ccn_name_split (buf.getBuf (), idx);
141
142 const unsigned char *compPtr = NULL;
143 size_t size = 0;
144 int i = 0;
145 while (ccn_name_comp_get(buf.getBuf ()->buf, idx, i, &compPtr, &size) == 0)
146 {
147 Bytes comp;
148 readRaw (comp, compPtr, size);
149 m_comps.push_back(comp);
150 i++;
151 }
152 ccn_indexbuf_destroy(&idx);
153}
154
155Name::Name (const ccn_charbuf *buf)
156{
157 ccn_indexbuf *idx = ccn_indexbuf_create();
158 ccn_name_split (buf, idx);
159
160 const unsigned char *compPtr = NULL;
161 size_t size = 0;
162 int i = 0;
163 while (ccn_name_comp_get(buf->buf, idx, i, &compPtr, &size) == 0)
164 {
165 Bytes comp;
166 readRaw (comp, compPtr, size);
167 m_comps.push_back(comp);
168 i++;
169 }
170 ccn_indexbuf_destroy(&idx);
171}
Alexander Afanasyevd09871f2013-01-04 22:36:37 -0800172
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800173Name &
174Name::operator=(const Name &other)
175{
176 m_comps = other.m_comps;
177 return *this;
178}
179bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -0800180Name::operator==(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800181{
182 return this->toString() == str;
183}
184
185bool
Zhenkai Zhu3b82d432013-01-03 22:48:40 -0800186Name::operator!=(const string &str) const
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800187{
188 return !(*this == str);
189}
190
191Name
192operator+(const Name &n1, const Name &n2)
193{
194 vector<Bytes> comps = n1.m_comps;
195 copy(n2.m_comps.begin(), n2.m_comps.end(), back_inserter(comps));
196 return Name(comps);
197}
198
199string
200Name::toString() const
201{
202 stringstream ss(stringstream::out);
203 ss << *this;
204 return ss.str();
205}
206
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800207CcnxCharbufPtr
208Name::toCcnxCharbuf() const
209{
210 CcnxCharbufPtr ptr(new CcnxCharbuf());
211 ccn_charbuf *cbuf = ptr->getBuf();
212 ccn_name_init(cbuf);
213 int size = m_comps.size();
214 for (int i = 0; i < size; i++)
215 {
216 ccn_name_append(cbuf, head(m_comps[i]), m_comps[i].size());
217 }
218 return ptr;
219}
220
221Name &
Alexander Afanasyev66f4c492013-01-20 23:32:50 -0800222Name::appendComp(const Name &comp)
223{
224 m_comps.insert (m_comps.end (),
225 comp.m_comps.begin (), comp.m_comps.end ());
226 return *this;
227}
228
229Name &
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800230Name::appendComp(const Bytes &comp)
231{
232 m_comps.push_back(comp);
233 return *this;
234}
235
236Name &
237Name::appendComp(const string &compStr)
238{
239 Bytes comp(compStr.begin(), compStr.end());
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -0800240 return appendComp(comp);
241}
242
243Name &
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -0800244Name::appendComp (const void *buf, size_t size)
245{
246 Bytes comp (reinterpret_cast<const unsigned char*> (buf), reinterpret_cast<const unsigned char*> (buf) + size);
247 return appendComp(comp);
248}
249
250Name &
251Name::appendComp(uint64_t number)
252{
253 Bytes comp;
254 comp.push_back (0);
Alexander Afanasyev66f4c492013-01-20 23:32:50 -0800255
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -0800256 while (number > 0)
257 {
258 comp.push_back (static_cast<unsigned char> (number & 0xFF));
259 number >>= 8;
260 }
261 return appendComp (comp);
262}
263
264uint64_t
265Name::getCompAsInt (int index) const
266{
267 Bytes comp = getComp(index);
268 if (comp.size () < 1 ||
269 comp[0] != 0)
270 {
271 boost::throw_exception(NameException()
272 << error_info_str("Non integer component: " + getCompAsString(index)));
273 }
274 uint64_t ret = 0;
275 for (int i = comp.size () - 1; i >= 1; i--)
276 {
277 ret <<= 8;
278 ret |= comp [i];
279 }
280 return ret;
281}
282
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800283Bytes
284Name::getComp(int index) const
285{
286 if (index >= m_comps.size())
287 {
288 boost::throw_exception(NameException() << error_info_str("Index out of range: " + boost::lexical_cast<string>(index)));
289 }
290 return m_comps[index];
291}
292
293string
294Name::getCompAsString(int index) const
295{
296 Bytes comp = getComp(index);
297 stringstream ss(stringstream::out);
298 int size = comp.size();
299 for (int i = 0; i < size; i++)
300 {
301 unsigned char ch = comp[i];
302 if (isprint(ch))
303 {
304 ss << (char) ch;
305 }
306 else
307 {
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -0800308 ss << "%" << hex << setfill('0') << setw(2) << (unsigned int)ch;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800309 }
310 }
311
312 return ss.str();
313}
314
315Name
316Name::getPartialName(int start, int n) const
317{
318 int size = m_comps.size();
Alexander Afanasyevdcfa9632013-01-07 16:38:19 -0800319 if (start < 0 || start >= size || (n > 0 && start + n > size))
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800320 {
321 stringstream ss(stringstream::out);
322 ss << "getPartialName() parameter out of range! ";
323 ss << "start = " << start;
324 ss << "n = " << n;
325 ss << "size = " << size;
326 boost::throw_exception(NameException() << error_info_str(ss.str()));
327 }
328
329 vector<Bytes> comps;
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800330 int end;
331 if (n > 0)
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800332 {
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800333 end = start + n;
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800334 }
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800335 else
336 {
337 end = size;
338 }
339
340 for (int i = start; i < end; i++)
341 {
342 comps.push_back(m_comps[i]);
343 }
344
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800345 return Name(comps);
346}
347
348ostream &
349operator <<(ostream &os, const Name &name)
350{
351 int size = name.size();
352 vector<string> strComps;
353 for (int i = 0; i < size; i++)
354 {
355 strComps.push_back(name.getCompAsString(i));
356 }
357 string joined = boost::algorithm::join(strComps, "/");
358 os << "/" << joined;
359 return os;
360}
361
Zhenkai Zhucb2d0dd2013-01-03 14:10:48 -0800362bool
363operator ==(const Name &n1, const Name &n2)
364{
365 stringstream ss1(stringstream::out);
366 stringstream ss2(stringstream::out);
367 ss1 << n1;
368 ss2 << n2;
369 return ss1.str() == ss2.str();
370}
371
372bool
373operator !=(const Name &n1, const Name &n2)
374{
375 return !(n1 == n2);
376}
377
378bool
379operator <(const Name &n1, const Name &n2)
380{
381 stringstream ss1(stringstream::out);
382 stringstream ss2(stringstream::out);
383 ss1 << n1;
384 ss2 << n2;
385 return ss1.str() < ss2.str();
386}
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800387
Zhenkai Zhuf47109b2013-01-02 19:41:34 -0800388
389} // Ccnx