blob: ccb7c6a4c0507f3d09360ce4a1c9c3232a2a27f1 [file] [log] [blame]
Alexander Afanasyev5ba90362013-07-15 19:58:38 -07001## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
2#
3# Copyright (c) 2011-2013, Regents of the University of California
4# Alexander Afanasyev
5#
6# GNU 3.0 license, See the LICENSE file for more information
7#
8# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
9#
10
11#
12# Based on PyCCN code, copyrighted and licensed as follows
13#
14# Copyright (c) 2011-2013, Regents of the University of California
15# BSD license, See the COPYING file for more information
16# Written by: Derek Kulinski <takeda@takeda.tk>
17# Jeff Burke <jburke@ucla.edu>
18#
19
20import ndn
21from . import _ndn
22
23from copy import copy
24import time, struct, random
25
26NAME_NORMAL = 0
27NAME_ANY = 1
28
29class Name(object):
30 def __init__(self, components=[], name_type=NAME_NORMAL, ccn_data=None, ccnb_buffer=None):
31 self._setattr('type', name_type)
32
33 # py-ndn
34 #self._setattr('ccn_data_dirty', True)
35 self._setattr('ccn_data', ccn_data)
36
37 # Name from simple buffer containing name in ccnb encoding
38 if ccnb_buffer:
39 self._setattr('components', _ndn.name_comps_from_ccn_buffer (bytes (ccnb_buffer)))
40
41 # Name from CCN
42 elif ccn_data:
43 self._setattr('components', _ndn.name_comps_from_ccn(ccn_data))
44 self._setattr('ccn_data_dirty', False)
45
46 # Copy Name from another Name object
47 elif isinstance(components, self.__class__):
48 self._setattr('components', copy(components.components))
49 if not components.ccn_data_dirty:
50 self._setattr('ccn_data', components.ccn_data)
51 self._setattr('ccn_data_dirty', False)
52
53 # Name as string (URI)
54 elif type(components) is str:
55 ccn_data = _ndn.name_from_uri(components)
56 self._setattr('components', _ndn.name_comps_from_ccn(ccn_data))
57 self._setattr('ccn_data', ccn_data)
58 self._setattr('ccn_data_dirty', False)
59
60 # Otherwise assume name is a list
61 else:
62 self._setattr('components', copy(components))
63
64 def _setattr(self, name, value):
65 if name == 'components' or name == 'ccn_data':
66 self._setattr('ccn_data_dirty', True)
67 super(Name, self).__setattr__(name, value)
68
69 def _append(self, component):
70 components = copy(self.components)
71 components.append(component)
72
73 return Name(components)
74
75 def append(self, value):
76 components = copy(self.components)
77 if isinstance (value, Name):
78 components.extend (value.components)
79 else:
80 components.append (bytes (value))
81 return Name(components)
82
83 def appendKeyID(self, digest):
84 if isinstance(digest, ndn.Key):
85 digest = digest.publicKeyID
86
87 component = b'\xc1.M.K\x00'
88 component += digest
89
90 return self._append(component)
91
92 def appendVersion(self, version = None):
93 if not version:
94 inttime = int(time.time() * 4096 + 0.5)
95 bintime = struct.pack("!Q", inttime)
96 version = bintime.lstrip(b'\x00')
97 component = b'\xfd' + version
98
99 return self._append(component)
100
101 def appendSegment(self, segment):
102 return self._append(self.num2seg(segment))
103
104 def appendNonce(self):
105 val = random.getrandbits(64)
106 component = b'\xc1.N\x00' + struct.pack("@Q", val)
107
108 return self._append(component)
109
110 def get_ccnb(self):
111 return _ndn.dump_charbuf(self.ccn_data)
112
113 def __repr__(self):
114 global NAME_NORMAL, NAME_ANY
115
116 if self.type == NAME_NORMAL:
117 return "ndn.Name('ccnx:" + _ndn.name_to_uri(self.ccn_data) + "')"
118 elif self.type == NAME_ANY:
119 return "ndn.Name(name_type=ndn.NAME_ANY)"
120 else:
121 raise ValueError("Name is of wrong type %d" % self.type)
122
123 def __str__(self):
124 global NAME_NORMAL, NAME_ANY
125
126 if self.type == NAME_NORMAL:
127 return _ndn.name_to_uri(self.ccn_data)
128 elif self.type == NAME_ANY:
129 return "<any>"
130 else:
131 raise ValueError("Name is of wrong type %d" % self.type)
132
133 def __len__(self):
134 return len(self.components)
135
136 def __add__(self, other):
137 return self.append(other)
138
139 def __setattr__(self, name, value):
140 raise TypeError("can't modify immutable instance")
141
142 __delattr__ = __setattr__
143
144 def __getattribute__(self, name):
145 if name == "ccn_data":
146 if object.__getattribute__(self, 'ccn_data_dirty'):
147 self._setattr('ccn_data', _ndn.name_comps_to_ccn(self.components))
148 self._setattr('ccn_data_dirty', False)
149 return object.__getattribute__(self, name)
150
151 def __getitem__(self, key):
152 if type(key) is int:
153 return self.components[key]
154 elif type(key) is slice:
155 return Name(self.components[key])
156 else:
157 raise ValueError("Unknown __getitem__ type: %s" % type(key))
158
159 def __setitem__(self, key, value):
160 self.components[key] = value
161
162 def __delitem__(self, key):
163 del self.components[key]
164
165 def __len__(self):
166 return len(self.components)
167
168 def __lt__(self, other):
169 return _ndn.compare_names(self.ccn_data, other.ccn_data) < 0
170
171 def __gt__(self, other):
172 return _ndn.compare_names(self.ccn_data, other.ccn_data) > 0
173
174 def __eq__(self, other):
175 return _ndn.compare_names(self.ccn_data, other.ccn_data) == 0
176
177 def __le__(self, other):
178 return _ndn.compare_names(self.ccn_data, other.ccn_data) <= 0
179
180 def __ge__(self, other):
181 return _ndn.compare_names(self.ccn_data, other.ccn_data) >= 0
182
183 def __ne__(self, other):
184 return _ndn.compare_names(self.ccn_data, other.ccn_data) != 0
185
186 @staticmethod
187 def num2seg(num):
188 return b'\x00' + struct.pack('!Q', num).lstrip(b'\x00')
189
190 @staticmethod
191 def seg2num(segment):
192 return long(struct.unpack("!Q", (8 - len(segment)) * "\x00" + segment)[0])
193
194 def isPrefixOf (self, other):
195 return self[:] == other[:len(self)]