Added support for ContentObject
diff --git a/ndn-cpp/ContentObject.cpp b/ndn-cpp/ContentObject.cpp
new file mode 100644
index 0000000..e675e5a
--- /dev/null
+++ b/ndn-cpp/ContentObject.cpp
@@ -0,0 +1,88 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "common.hpp"
+#include "ContentObject.hpp"
+
+using namespace std;
+
+namespace ndn {
+
+void Signature::get(struct ndn_Signature &signatureStruct) const 
+{
+  signatureStruct.digestAlgorithmLength = digestAlgorithm_.size();
+  if (digestAlgorithm_.size() > 0)
+    signatureStruct.digestAlgorithm = (unsigned char *)&digestAlgorithm_[0];
+  else
+    signatureStruct.digestAlgorithm = 0;
+
+  signatureStruct.witnessLength = witness_.size();
+  if (witness_.size() > 0)
+    signatureStruct.witness = (unsigned char *)&witness_[0];
+  else
+    signatureStruct.witness = 0;
+
+  signatureStruct.signatureLength = signature_.size();
+  if (signature_.size() > 0)
+    signatureStruct.signature = (unsigned char *)&signature_[0];
+  else
+    signatureStruct.signature = 0;
+}
+
+void Signature::set(const struct ndn_Signature &signatureStruct)
+{
+  setVector(digestAlgorithm_, signatureStruct.digestAlgorithm, signatureStruct.digestAlgorithmLength);
+  setVector(witness_, signatureStruct.witness, signatureStruct.witnessLength);
+  setVector(signature_, signatureStruct.signature, signatureStruct.signatureLength);
+}
+
+void SignedInfo::get(struct ndn_SignedInfo &signedInfoStruct) const 
+{
+  publisherPublicKeyDigest_.get(signedInfoStruct.publisherPublicKeyDigest);
+  // TODO: Implement timestamp
+  signedInfoStruct.type = type_;
+  signedInfoStruct.freshnessSeconds = freshnessSeconds_;
+  
+  signedInfoStruct.finalBlockIDLength = finalBlockID_.size();
+  if (finalBlockID_.size() > 0)
+    signedInfoStruct.finalBlockID = (unsigned char *)&finalBlockID_[0];
+  else
+    signedInfoStruct.finalBlockID = 0;
+
+  keyLocator_.get(signedInfoStruct.keyLocator);
+}
+
+void SignedInfo::set(const struct ndn_SignedInfo &signedInfoStruct)
+{
+  publisherPublicKeyDigest_.set(signedInfoStruct.publisherPublicKeyDigest);
+  // TODO: Implement timestamp
+  type_ = signedInfoStruct.type;
+  freshnessSeconds_ = signedInfoStruct.freshnessSeconds;
+  setVector(finalBlockID_, signedInfoStruct.finalBlockID, signedInfoStruct.finalBlockIDLength);
+  keyLocator_.set(signedInfoStruct.keyLocator);
+}
+
+void ContentObject::get(struct ndn_ContentObject &contentObjectStruct) const 
+{
+  signature_.get(contentObjectStruct.signature);
+  name_.get(contentObjectStruct.name);
+  signedInfo_.get(contentObjectStruct.signedInfo);
+  
+  contentObjectStruct.contentLength = content_.size();
+  if (content_.size() > 0)
+    contentObjectStruct.content = (unsigned char *)&content_[0];
+  else
+    contentObjectStruct.content = 0;
+}
+
+void ContentObject::set(const struct ndn_ContentObject &contentObjectStruct)
+{
+  signature_.set(contentObjectStruct.signature);
+  name_.set(contentObjectStruct.name);
+  signedInfo_.set(contentObjectStruct.signedInfo);
+  setVector(content_, contentObjectStruct.content, contentObjectStruct.contentLength);
+}
+
+}
diff --git a/ndn-cpp/ContentObject.hpp b/ndn-cpp/ContentObject.hpp
new file mode 100644
index 0000000..9cf1c3d
--- /dev/null
+++ b/ndn-cpp/ContentObject.hpp
@@ -0,0 +1,142 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_CONTENTOBJECT_HPP
+#define	NDN_CONTENTOBJECT_HPP
+
+#include "Name.hpp"
+#include "PublisherPublicKeyDigest.hpp"
+#include "Key.hpp"
+#include "c/ContentObject.h"
+
+namespace ndn {
+
+class Signature {
+public:
+  /**
+   * Set the signatureStruct to point to the values in this signature object, without copying any memory.
+   * WARNING: The resulting pointers in signatureStruct are invalid after a further use of this object which could reallocate memory.
+   * @param signatureStruct a C ndn_Signature struct where the name components array is already allocated.
+   */
+  void get(struct ndn_Signature &signatureStruct) const;
+
+  /**
+   * Clear this signature, and set the values by copying from the ndn_Signature struct.
+   * @param signatureStruct a C ndn_Signature struct
+   */
+  void set(const struct ndn_Signature &signatureStruct);
+
+  const std::vector<unsigned char> getDigestAlgorithm() const { return digestAlgorithm_; }
+
+  const std::vector<unsigned char> getWitness() const { return witness_; }
+
+  const std::vector<unsigned char> getSignature() const { return signature_; }
+  
+private:
+  std::vector<unsigned char> digestAlgorithm_; /**< if empty, the default is 2.16.840.1.101.3.4.2.1 (sha-256) */
+  std::vector<unsigned char> witness_;
+  std::vector<unsigned char> signature_;
+};
+
+class SignedInfo {
+public:
+  SignedInfo() 
+  {   
+    type_ = ndn_ContentType_DATA;
+    freshnessSeconds_ = -1;
+  }
+
+  /**
+   * Set the signedInfoStruct to point to the values in this signed info object, without copying any memory.
+   * WARNING: The resulting pointers in signedInfoStruct are invalid after a further use of this object which could reallocate memory.
+   * @param signedInfoStruct a C ndn_SignedInfo struct where the name components array is already allocated.
+   */
+  void get(struct ndn_SignedInfo &signedInfoStruct) const;
+
+  /**
+   * Clear this signed info, and set the values by copying from the ndn_SignedInfo struct.
+   * @param signedInfoStruct a C ndn_SignedInfo struct
+   */
+  void set(const struct ndn_SignedInfo &signedInfoStruct);
+
+  const PublisherPublicKeyDigest &getPublisherPublicKeyDigest() const { return publisherPublicKeyDigest_; }
+  
+  // TODO: Implement timestamp
+  
+  int getType() const { return type_; }
+  
+  int getFreshnessSeconds() const { return freshnessSeconds_; }
+  
+  const std::vector<unsigned char> getFinalBlockID() const { return finalBlockID_; }
+  
+  const KeyLocator &getKeyLocator() const { return keyLocator_; }
+  
+private:
+  PublisherPublicKeyDigest publisherPublicKeyDigest_;
+  // TODO: Implement timestamp
+  int type_;
+  int freshnessSeconds_;
+  std::vector<unsigned char> finalBlockID_;
+  KeyLocator keyLocator_;
+};
+  
+class ContentObject {
+public:
+  void encode(std::vector<unsigned char> &output, WireFormat &wireFormat) const 
+  {
+    wireFormat.encodeContentObject(*this, output);
+  }
+  void encode(std::vector<unsigned char> &output) const 
+  {
+    encode(output, BinaryXMLWireFormat::instance());
+  }
+  void decode(const unsigned char *input, unsigned int inputLength, WireFormat &wireFormat) 
+  {
+    wireFormat.decodeContentObject(*this, input, inputLength);
+  }
+  void decode(const unsigned char *input, unsigned int inputLength) 
+  {
+    decode(input, inputLength, BinaryXMLWireFormat::instance());
+  }
+  void decode(const std::vector<unsigned char> &input, WireFormat &wireFormat) 
+  {
+    decode(&input[0], input.size(), wireFormat);
+  }
+  void decode(const std::vector<unsigned char> &input) 
+  {
+    decode(&input[0], input.size());
+  }
+  
+  /**
+   * Set the contentObjectStruct to point to the values in this interest, without copying any memory.
+   * WARNING: The resulting pointers in contentObjectStruct are invalid after a further use of this object which could reallocate memory.
+   * @param contentObjectStruct a C ndn_ContentObject struct where the name components array is already allocated.
+   */
+  void get(struct ndn_ContentObject &contentObjectStruct) const;
+
+  /**
+   * Clear this content object, and set the values by copying from the ndn_ContentObject struct.
+   * @param contentObjectStruct a C ndn_ContentObject struct
+   */
+  void set(const struct ndn_ContentObject &contentObjectStruct);
+
+  const Signature &getSignature() const { return signature_; }
+  
+  const Name &getName() const { return name_; }
+  
+  const SignedInfo &getSignedInfo() const { return signedInfo_; }
+  
+  const std::vector<unsigned char> getContent() const { return content_; }
+  
+private:
+  Signature signature_;
+  Name name_;
+  SignedInfo signedInfo_;
+  std::vector<unsigned char> content_;
+};
+  
+}
+
+#endif
diff --git a/ndn-cpp/Key.cpp b/ndn-cpp/Key.cpp
new file mode 100644
index 0000000..45425f2
--- /dev/null
+++ b/ndn-cpp/Key.cpp
@@ -0,0 +1,34 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "common.hpp"
+#include "Key.hpp"
+
+using namespace std;
+
+namespace ndn {
+
+void KeyLocator::get(struct ndn_KeyLocator &keyLocatorStruct) const 
+{
+  keyLocatorStruct.type = type_;
+  
+  keyLocatorStruct.keyOrCertificateLength = keyOrCertificate_.size();
+  if (keyOrCertificate_.size() > 0)
+    keyLocatorStruct.keyOrCertificate = (unsigned char *)&keyOrCertificate_[0];
+  else
+    keyLocatorStruct.keyOrCertificate = 0;
+
+  // TODO: Implement keyName.
+}
+
+void KeyLocator::set(const struct ndn_KeyLocator &keyLocatorStruct)
+{
+  type_ = keyLocatorStruct.type;
+  setVector(keyOrCertificate_, keyLocatorStruct.keyOrCertificate, keyLocatorStruct.keyOrCertificateLength);
+  // TODO: Implement keyName.
+}
+
+}
+
diff --git a/ndn-cpp/Key.hpp b/ndn-cpp/Key.hpp
new file mode 100644
index 0000000..aa2f01b
--- /dev/null
+++ b/ndn-cpp/Key.hpp
@@ -0,0 +1,48 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_KEY_HPP
+#define	NDN_KEY_HPP
+
+#include <vector>
+#include "c/Key.h"
+
+namespace ndn {
+  
+class KeyLocator {
+public:
+  KeyLocator()
+  {
+    type_ = (ndn_KeyLocatorType)-1;
+  }
+  
+  /**
+   * Set the keyLocatorStruct to point to the values in this key locator, without copying any memory.
+   * WARNING: The resulting pointers in keyLocatorStruct are invalid after a further use of this object which could reallocate memory.
+   * @param keyLocatorStruct a C ndn_KeyLocator struct where the name components array is already allocated.
+   */
+  void get(struct ndn_KeyLocator &keyLocatorStruct) const;
+  
+  /**
+   * Clear this key locator, and set the values by copying from the ndn_KeyLocator struct.
+   * @param keyLocatorStruct a C ndn_KeyLocator struct
+   */
+  void set(const struct ndn_KeyLocator &keyLocatorStruct);
+
+  ndn_KeyLocatorType getType() const { return type_; }
+  
+  const std::vector<unsigned char> getKeyOrCertificate() const { return keyOrCertificate_; }
+
+  // TODO: Implement keyName.
+
+private:
+  ndn_KeyLocatorType type_;
+  std::vector<unsigned char> keyOrCertificate_; /**< used if type_ is ndn_KeyLocatorType_KEY or ndn_KeyLocatorType_CERTIFICATE */
+  // TODO: Implement keyName.
+};
+  
+}
+
+#endif
diff --git a/ndn-cpp/c/ContentObject.h b/ndn-cpp/c/ContentObject.h
new file mode 100644
index 0000000..4d46e53
--- /dev/null
+++ b/ndn-cpp/c/ContentObject.h
@@ -0,0 +1,96 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_CONTENTOBJECT_H
+#define	NDN_CONTENTOBJECT_H
+
+#include "Name.h"
+#include "PublisherPublicKeyDigest.h"
+#include "Key.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+struct ndn_Signature {
+  unsigned char *digestAlgorithm;      /**< pointer to pre-allocated buffer.  0 for none.
+                                        *   If none, default is 2.16.840.1.101.3.4.2.1 (sha-256). */
+  unsigned int digestAlgorithmLength; /**< length of digestAlgorithm.  0 for none */
+  unsigned char *witness;              /**< pointer to pre-allocated buffer.  0 for none. */
+  unsigned int witnessLength;          /**< length of witness.  0 for none */
+  unsigned char *signature;
+  unsigned int signatureLength;
+};
+
+static inline void ndn_Signature_init(struct ndn_Signature *self) {
+  self->digestAlgorithm = 0;
+  self->digestAlgorithmLength = 0;
+  self->witness = 0;
+  self->witnessLength = 0;
+  self->signature = 0;
+  self->signatureLength = 0;
+}
+
+enum {
+  ndn_ContentType_DATA = 0,
+  ndn_ContentType_ENCR = 1,
+  ndn_ContentType_GONE = 2,
+  ndn_ContentType_KEY =  3,
+  ndn_ContentType_LINK = 4,
+  ndn_ContentType_NACK = 5
+};
+
+struct ndn_SignedInfo {
+  struct ndn_PublisherPublicKeyDigest publisherPublicKeyDigest;
+  // TODO: Implement timestamp
+  int type;              /**< default is ndn_ContentType_DATA. -1 for none */
+  int freshnessSeconds;  /**< -1 for none */
+	unsigned char *finalBlockID;	    /**< pointer to pre-allocated buffer.  0 for none */
+  unsigned int finalBlockIDLength;  /**< length of finalBlockID.  0 for none */
+  struct ndn_KeyLocator keyLocator;
+};
+
+/**
+ * Initialize the ndn_SignedInfo struct with values for none and the type to the default ndn_ContentType_DATA.
+ * @param self pointer to the ndn_SignedInfo struct.
+ */
+static inline void ndn_SignedInfo_init(struct ndn_SignedInfo *self) {
+  ndn_PublisherPublicKeyDigest_init(&self->publisherPublicKeyDigest);
+  self->type = ndn_ContentType_DATA;
+  self->freshnessSeconds = -1;
+  self->finalBlockID = 0;
+  self->finalBlockIDLength = 0;
+  ndn_KeyLocator_init(&self->keyLocator);
+}
+
+struct ndn_ContentObject {
+  struct ndn_Signature signature;
+  struct ndn_Name name;
+  struct ndn_SignedInfo signedInfo;
+  unsigned char *content;     /**< pointer to the content */
+  unsigned int contentLength; /**< length of content */
+};
+
+/**
+ * Initialize an ndn_ContentObject struct with the pre-allocated nameComponents,
+ * and defaults for all the values.
+ * @param self pointer to the ndn_ContentObject struct
+ * @param nameComponents the pre-allocated array of ndn_NameComponent
+ * @param maxNameComponents the number of elements in the allocated nameComponents array
+ */
+static inline void ndn_ContentObject_init(struct ndn_ContentObject *self, struct ndn_NameComponent *nameComponents, unsigned int maxNameComponents) 
+{
+  ndn_Signature_init(&self->signature);
+  ndn_Name_init(&self->name, nameComponents, maxNameComponents);
+  ndn_SignedInfo_init(&self->signedInfo);
+  self->content = 0;
+  self->contentLength = 0;
+}
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif
diff --git a/ndn-cpp/c/Key.h b/ndn-cpp/c/Key.h
new file mode 100644
index 0000000..1545a74
--- /dev/null
+++ b/ndn-cpp/c/Key.h
@@ -0,0 +1,38 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_KEY_H
+#define	NDN_KEY_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+  ndn_KeyLocatorType_KEY = 1,
+  ndn_KeyLocatorType_CERTIFICATE = 2,
+  ndn_KeyLocatorType_KEYNAME = 3
+} ndn_KeyLocatorType;
+  
+struct ndn_KeyLocator {
+  ndn_KeyLocatorType type;
+  unsigned char *keyOrCertificate; /**< if type is ndn_KeyLocatorType_KEY, pointer to the pre-allocated buffer for the key value.
+                                        if type is ndn_KeyLocatorType_CERTIFICATE, pointer to the pre-allocated buffer for the cetrificate value. */
+  unsigned int keyOrCertificateLength;
+  // TODO: Implement keyName.
+};
+
+static inline void ndn_KeyLocator_init(struct ndn_KeyLocator *self) {
+  self->type = (ndn_KeyLocatorType)-1;
+  self->keyOrCertificate = 0;
+  self->keyOrCertificateLength = 0;
+  // TODO: Implement keyName.
+}
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif
diff --git a/ndn-cpp/c/encoding/BinaryXMLContentObject.h b/ndn-cpp/c/encoding/BinaryXMLContentObject.h
new file mode 100644
index 0000000..b6444bb
--- /dev/null
+++ b/ndn-cpp/c/encoding/BinaryXMLContentObject.h
@@ -0,0 +1,26 @@
+/**
+ * @author: Jeff Thompson
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_BINARYXMLCONTENTOBJECT_H
+#define	NDN_BINARYXMLCONTENTOBJECT_H
+
+#include "../errors.h"
+#include "../ContentObject.h"
+#include "BinaryXMLEncoder.h"
+#include "BinaryXMLDecoder.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+ndn_Error ndn_encodeBinaryXMLContentObject(struct ndn_ContentObject *contentObject, struct ndn_BinaryXMLEncoder *encoder);
+
+ndn_Error ndn_decodeBinaryXMLContentObject(struct ndn_ContentObject *contentObject, struct ndn_BinaryXMLDecoder *decoder);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif
diff --git a/ndn-cpp/encoding/BinaryXMLWireFormat.cpp b/ndn-cpp/encoding/BinaryXMLWireFormat.cpp
index f3af9c8..83261de 100644
--- a/ndn-cpp/encoding/BinaryXMLWireFormat.cpp
+++ b/ndn-cpp/encoding/BinaryXMLWireFormat.cpp
@@ -6,7 +6,9 @@
 #include <stdexcept>
 #include "../c/encoding/BinaryXMLName.h"
 #include "../c/encoding/BinaryXMLInterest.h"
+#include "../c/encoding/BinaryXMLContentObject.h"
 #include "../Interest.hpp"
+#include "../ContentObject.hpp"
 #include "BinaryXMLEncoder.hpp"
 #include "../c/encoding/BinaryXMLDecoder.h"
 #include "BinaryXMLWireFormat.hpp"
@@ -81,4 +83,35 @@
   interest.set(interestStruct);
 }
 
+void BinaryXMLWireFormat::encodeContentObject(const ContentObject &contentObject, vector<unsigned char> &output) 
+{
+  struct ndn_NameComponent nameComponents[100];
+  struct ndn_ContentObject contentObjectStruct;
+  ndn_ContentObject_init
+    (&contentObjectStruct, nameComponents, sizeof(nameComponents) / sizeof(nameComponents[0]));
+  contentObject.get(contentObjectStruct);
+
+  BinaryXMLEncoder encoder;
+  ndn_encodeBinaryXMLContentObject(&contentObjectStruct, encoder.getEncoder());
+     
+  encoder.appendTo(output);
+}
+
+void BinaryXMLWireFormat::decodeContentObject(ContentObject &contentObject, const unsigned char *input, unsigned int inputLength)
+{
+  struct ndn_NameComponent nameComponents[100];
+  struct ndn_ContentObject contentObjectStruct;
+  ndn_ContentObject_init
+    (&contentObjectStruct, nameComponents, sizeof(nameComponents) / sizeof(nameComponents[0]));
+    
+  struct ndn_BinaryXMLDecoder decoder;
+  ndn_BinaryXMLDecoder_init(&decoder, (unsigned char *)input, inputLength);
+  
+  ndn_Error error;
+  if (error = ndn_decodeBinaryXMLContentObject(&contentObjectStruct, &decoder))
+    throw std::runtime_error(ndn_getErrorString(error));
+
+  contentObject.set(contentObjectStruct);
+}
+
 }
diff --git a/ndn-cpp/encoding/BinaryXMLWireFormat.hpp b/ndn-cpp/encoding/BinaryXMLWireFormat.hpp
index ad3a88c..a1a5e6a 100644
--- a/ndn-cpp/encoding/BinaryXMLWireFormat.hpp
+++ b/ndn-cpp/encoding/BinaryXMLWireFormat.hpp
@@ -17,6 +17,9 @@
 
   virtual void encodeInterest(const Interest &interest, std::vector<unsigned char> &output);
   virtual void decodeInterest(Interest &interest, const unsigned char *input, unsigned int inputLength);
+
+  virtual void encodeContentObject(const ContentObject &contentObject, std::vector<unsigned char> &output);
+  virtual void decodeContentObject(ContentObject &contentObject, const unsigned char *input, unsigned int inputLength);
   
   static BinaryXMLWireFormat &instance() { return instance_; }
   
diff --git a/ndn-cpp/encoding/WireFormat.cpp b/ndn-cpp/encoding/WireFormat.cpp
index 3217fe1..7e784a3 100644
--- a/ndn-cpp/encoding/WireFormat.cpp
+++ b/ndn-cpp/encoding/WireFormat.cpp
@@ -28,4 +28,13 @@
   throw logic_error("unimplemented");
 }
 
+void WireFormat::encodeContentObject(const ContentObject &contentObject, vector<unsigned char> &output) 
+{
+  throw logic_error("unimplemented");
+}
+void WireFormat::decodeContentObject(ContentObject &contentObject, const unsigned char *input, unsigned int inputLength) 
+{
+  throw logic_error("unimplemented");
+}
+
 }
diff --git a/ndn-cpp/encoding/WireFormat.hpp b/ndn-cpp/encoding/WireFormat.hpp
index f09ae22..8458f94 100644
--- a/ndn-cpp/encoding/WireFormat.hpp
+++ b/ndn-cpp/encoding/WireFormat.hpp
@@ -12,6 +12,7 @@
   
 class Name;
 class Interest;
+class ContentObject;
   
 class WireFormat {
 public:
@@ -21,7 +22,8 @@
   virtual void encodeInterest(const Interest &interest, std::vector<unsigned char> &output);
   virtual void decodeInterest(Interest &interest, const unsigned char *input, unsigned int inputLength);
 
-  // etc. for each type of object.
+  virtual void encodeContentObject(const ContentObject &contentObject, std::vector<unsigned char> &output);
+  virtual void decodeContentObject(ContentObject &contentObject, const unsigned char *input, unsigned int inputLength);
 };
 
 }