PyNDN: Initial import of PyNDN code

Refs #1010 (http://redmine.named-data.net/issues/1010)
diff --git a/PyNDN/impl/__init__.py b/PyNDN/impl/__init__.py
new file mode 100644
index 0000000..e048223
--- /dev/null
+++ b/PyNDN/impl/__init__.py
@@ -0,0 +1,18 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+# 
+# Copyright (c) 2011-2013, Regents of the University of California
+#                          Alexander Afanasyev
+# 
+# GNU 3.0 license, See the LICENSE file for more information
+# 
+# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+# 
+
+#
+# Based on PyCCN code, copyrighted and licensed as follows
+#
+# Copyright (c) 2011-2013, Regents of the University of California
+# BSD license, See the COPYING file for more information
+# Written by: Derek Kulinski <takeda@takeda.tk>
+#             Jeff Burke <jburke@ucla.edu>
+#
diff --git a/PyNDN/impl/ccnb.py b/PyNDN/impl/ccnb.py
new file mode 100644
index 0000000..b95b3fa
--- /dev/null
+++ b/PyNDN/impl/ccnb.py
@@ -0,0 +1,129 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+# 
+# Copyright (c) 2011-2013, Regents of the University of California
+#                          Alexander Afanasyev
+# 
+# GNU 3.0 license, See the LICENSE file for more information
+# 
+# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+# 
+
+#
+# Based on PyCCN code, copyrighted and licensed as follows
+#
+# Copyright (c) 2011-2013, Regents of the University of California
+# BSD license, See the COPYING file for more information
+# Written by: Derek Kulinski <takeda@takeda.tk>
+#             Jeff Burke <jburke@ucla.edu>
+#
+
+__TT_BITS__ = 3
+__TT_MASK__ = (1 << __TT_BITS__) - 1
+__TT_HBIT__ = (1 << 7)
+__TT_LBIT__ = __TT_HBIT__ - 1
+
+DTAG_NAME       = 14
+DTAG_COLLECTION = 17
+DTAG_LINK       = 31
+
+def blob(value):
+    return _encode(len(value), 5) + value
+
+def dtag(tag, value):
+    return _encode(tag, 2) + value + '\x00'
+
+def _encode(value, tt):
+    global __TT_BITS__, __TT_HBIT__, __TT_LBIT__
+
+    header = (value << __TT_BITS__) | tt
+
+    blocks = []
+    blocks.append((header & __TT_LBIT__) | __TT_HBIT__)
+    header >>= 7
+
+    while header != 0:
+        blocks.append(header & __TT_LBIT__)
+        header >>= 7
+
+    blocks.reverse()
+
+    return bytearray(blocks)
+
+class CCNBDecoder(object):
+    def __init__(self, ccnb_data):
+        self.ccnb_data = ccnb_data
+        self.reset()
+
+    def reset(self):
+        self.position = 0
+        self.decoded = 0
+        self.stack = []
+
+    def _process_next_byte(self):
+        global __TT_HBIT__, __TT_LBIT__
+
+        assert self.position < len(self.ccnb_data)
+
+        char = ord(self.ccnb_data[self.position])
+        self.position += 1
+
+        if self.decoded == 0 and char == 0:
+            return None, True
+
+        decoded = (self.decoded << 7) | (char & __TT_LBIT__)
+        complete = (char & __TT_HBIT__) == __TT_HBIT__
+
+        self.decoded = decoded if not complete else 0
+
+        return decoded, complete
+
+    def print_element(self, tt, value, data = None):
+        if tt == 2:
+            print "DTAG",
+
+            if value == 14:
+                print "Name"
+            elif value == 15:
+                print "Component"
+            elif value == 17:
+                print "Collection"
+            elif value == 31:
+                print "Link"
+            else:
+                print value
+
+        elif tt == 5:
+            print "BLOB",
+            print value,
+            print repr(data)
+        else:
+            print tt,
+            print value,
+            print repr(data)
+
+    def get_tags(self):
+        global __TT_MASK__, __TT_BITS__
+
+        while self.position < len(self.ccnb_data):
+            while True:
+                decoded, complete = self._process_next_byte()
+                if complete:
+                    break
+
+            if decoded is None:
+                tt, value = self.stack.pop()
+                print "Close",
+            else:
+                tt = decoded & __TT_MASK__
+                value = decoded >> __TT_BITS__
+
+            data = None
+            if decoded is not None:
+                if tt == 2:
+                    self.stack.append((tt, value))
+                elif tt == 5:
+                    data = self.ccnb_data[self.position:self.position + value]
+                    self.position += value
+
+            self.print_element(tt, value, data)
+
diff --git a/PyNDN/impl/enumeration.py b/PyNDN/impl/enumeration.py
new file mode 100644
index 0000000..851e43c
--- /dev/null
+++ b/PyNDN/impl/enumeration.py
@@ -0,0 +1,29 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+# 
+# Copyright (c) 2011-2013, Regents of the University of California
+#                          Alexander Afanasyev
+# 
+# GNU 3.0 license, See the LICENSE file for more information
+# 
+# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+# 
+
+#
+# Based on PyCCN code, copyrighted and licensed as follows
+#
+# Copyright (c) 2011-2013, Regents of the University of California
+# BSD license, See the COPYING file for more information
+# Written by: Derek Kulinski <takeda@takeda.tk>
+#             Jeff Burke <jburke@ucla.edu>
+#
+
+import ndn
+from ndn.impl import ccnb
+
+def ccnb_enumerate(names):
+    out = bytearray()
+
+    for name in names:
+        out += ccnb.dtag(ccnb.DTAG_LINK, name.get_ccnb())
+
+    return ccnb.dtag(ccnb.DTAG_COLLECTION, out)
diff --git a/PyNDN/impl/segmenting.py b/PyNDN/impl/segmenting.py
new file mode 100644
index 0000000..fb2d253
--- /dev/null
+++ b/PyNDN/impl/segmenting.py
@@ -0,0 +1,55 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+# 
+# Copyright (c) 2011-2013, Regents of the University of California
+#                          Alexander Afanasyev
+# 
+# GNU 3.0 license, See the LICENSE file for more information
+# 
+# Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+# 
+
+#
+# Based on PyCCN code, copyrighted and licensed as follows
+#
+# Copyright (c) 2011-2013, Regents of the University of California
+# BSD license, See the COPYING file for more information
+# Written by: Derek Kulinski <takeda@takeda.tk>
+#             Jeff Burke <jburke@ucla.edu>
+#
+
+import math
+import ndn
+
+class Wrapper(object):
+    def __init__(self, name, key):
+        self.name = name
+        self.key = key
+
+        kl = ndn.KeyLocator(key)
+        self.signed_info = ndn.SignedInfo(key_locator = kl, key_digest = key.publicKeyID)
+
+    def __call__(self, chunk, segment, segments):
+        name = self.name + ndn.Name.num2seg(segment)
+        self.signed_info.finalBlockID = ndn.Name.num2seg(segments - 1)
+
+        co = ndn.ContentObject(name = name, content = chunk, signed_info = self.signed_info)
+        co.sign(self.key)
+
+        return co
+
+def segmenter(data, wrapper = None, chunk_size = 4096):
+    segment = 0
+    segments = math.ceil(len(data) / float(chunk_size))
+
+    while segment < segments:
+        start = segment * chunk_size
+        end = min(start + chunk_size, len(data))
+        chunk = data[start : end]
+
+        if wrapper is not None:
+            chunk = wrapper(chunk, segment, segments)
+
+        yield chunk
+
+        segment += 1
+