data: Corrections and separations for Data abstraction

MetaInfo and Signature are now defined in separate files

Change-Id: I8e370c7b3e057bf5f752e3271bf8375f44d603d0
diff --git a/include/ndn-cpp/data.hpp b/include/ndn-cpp/data.hpp
index 1fb098f..4bda816 100644
--- a/include/ndn-cpp/data.hpp
+++ b/include/ndn-cpp/data.hpp
@@ -12,278 +12,125 @@
 #include "name.hpp"
 #include "encoding/block.hpp"
 
+#include "signature.hpp"
+#include "meta-info.hpp"
+#include "key-locator.hpp"
 
 namespace ndn {
-
-/**
- * A Signature is storage for the signature-related information (info and value) in a Data packet.
- */
-class Signature {
-public:
-  enum {
-    DigestSha256 = 0,
-    SignatureSha256WithRsa = 1
-  };
-  
-  Signature()
-    : type_(-1)
-  {
-  }
-  
-  Signature(const Block &info, const Block &value)
-    : info_(info)
-    , value_(value)
-  {
-    Buffer::const_iterator i = info_.value_begin();
-    type_ = Tlv::readVarNumber(i, info_.value_end());
-  }
-
-  operator bool() const
-  {
-    return type_ != -1;
-  }
-
-  uint32_t
-  getType() const
-  {
-    return type_;
-  }
-  
-  const Block&
-  getInfo() const
-  {
-    return info_;
-  }
-
-  void
-  setInfo(const Block &info)
-  {
-    info_ = info;
-    if (info_.hasWire() || info_.hasValue())
-      {
-        info_.parse();
-        const Block &signatureType = info_.get(Tlv::SignatureType);
-        
-        Buffer::const_iterator i = signatureType.value_begin();
-        type_ = Tlv::readVarNumber(i, signatureType.value_end());
-      }
-    else
-      {
-        type_ = -1;
-      }
-  }  
-
-  const Block&
-  getValue() const
-  {
-    return value_;
-  }
-
-  void
-  setValue(const Block &value)
-  {
-    value_ = value;
-  }
-
-  void
-  reset()
-  {
-    type_ = -1;
-    info_.reset();
-    value_.reset();
-  }
-
-private:
-  int32_t type_;
-  
-  Block info_;
-  Block value_;
-};
-
-/**
- * An MetaInfo holds the meta info which is signed inside the data packet.
- */
-class MetaInfo {
-public:
-  enum {
-    TYPE_DEFAULT = 0,
-    TYPE_LINK = 1,
-    TYPE_KEY = 2
-  };
-  
-  MetaInfo()
-    : type_(TYPE_DEFAULT)
-    , freshnessPeriod_(-1)
-  {   
-  }
-  
-  uint32_t 
-  getType() const
-  { return type_; }
-  
-  void 
-  setType(uint32_t type)
-  { type_ = type; }
-  
-  Milliseconds 
-  getFreshnessPeriod() const
-  { return freshnessPeriod_; }
-  
-  void 
-  setFreshnessPeriod(Milliseconds freshnessPeriod)
-  { freshnessPeriod_ = freshnessPeriod; }
-
-private:
-  uint32_t type_;
-  Milliseconds freshnessPeriod_;
-
-  Block wire_;
-};
   
 class Data {
 public:
+  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+  
   /**
-   * Create a new Data object with default values and where the signature is a blank Sha256WithRsaSignature.
+   * @brief Create an empty Data object
    */
-  Data()
-  {
-  }
-
+  inline
+  Data();
+  
   /**
-   * Create a new Data object with the given name and default values and where the signature is a blank Sha256WithRsaSignature.
+   * @brief Create a new Data object with the given name
    * @param name A reference to the name which is copied.
    */
-  Data(const Name& name)
-    : name_(name)
-  {
-  }
+  inline
+  Data(const Name& name);
   
   /**
-   * The virtual destructor.
+   * @brief The virtual destructor.
    */
-  virtual ~Data()
-  {
-  }
+  inline virtual
+  ~Data();
   
   /**
-   * Encode this Data for a particular wire format. If wireFormat is the default wire format, also set the defaultWireEncoding 
-   * field to the encoded result.
-   * Even though this is const, if wireFormat is the default wire format we update the defaultWireEncoding.
-   * @param wireFormat A WireFormat object used to encode the input. If omitted, use WireFormat getDefaultWireFormat().
+   * @brief Encode this Data for a wire format.
    * @return The encoded byte array.
    */
   const Block& 
   wireEncode() const;
   
+  /**
+   * @brief Decode the input using a particular wire format and update this Data. 
+   * @param input The input byte array to be decoded.
+   */
   void
   wireDecode(const Block &wire);
-  
-  /**
-   * Decode the input using a particular wire format and update this Data. If wireFormat is the default wire format, also 
-   * set the defaultWireEncoding field to the input.
-   * @param input The input byte array to be decoded.
-   * @param inputLength The length of input.
-   * @param wireFormat A WireFormat object used to decode the input. If omitted, use WireFormat getDefaultWireFormat().
-   */
-  void
-  wireDecode(const uint8_t* input, size_t inputLength);
 
-  const Signature&
-  getSignature() const
-  {
-    return signature_;
-  }
+  inline const Name& 
+  getName() const;
   
   /**
-   * Set the signature to a copy of the given signature.
-   * @param signature The signature object which is cloned.
-   * @return This Data so that you can chain calls to update values.
-   */
-  Data& 
-  setSignature(const Signature& signature) 
-  {
-    signature_ = signature;
-    onChanged();
-    return *this;
-  }
-  
-  const Name& 
-  getName() const
-  {
-    return name_;
-  }
-  
-  /**
-   * Set name to a copy of the given Name.  This is virtual so that a subclass can override to validate the name.
+   * @brief Set name to a copy of the given Name.
+   *
+   * This is virtual so that a subclass can override to validate the name.
+   *
    * @param name The Name which is copied.
    * @return This Data so that you can chain calls to update values.
    */
-  void
-  setName(const Name& name)
-  { 
-    name_ = name; 
-    onChanged();
-  }
-  
-  const MetaInfo& 
-  getMetaInfo() const { return metaInfo_; }
+  inline virtual void
+  setName(const Name& name);
+
+  inline const MetaInfo& 
+  getMetaInfo() const;
   
   /**
-   * Set metaInfo to a copy of the given MetaInfo.
+   * @brief Set metaInfo to a copy of the given MetaInfo.
    * @param metaInfo The MetaInfo which is copied.
    * @return This Data so that you can chain calls to update values.
    */
-  void
-  setMetaInfo(const MetaInfo& metaInfo) 
-  { 
-    metaInfo_ = metaInfo; 
-    onChanged();
-  }
+  inline void
+  setMetaInfo(const MetaInfo& metaInfo);
 
-  const Block& 
-  getContent() const { return content_; }
+  ///////////////////////////////////////////////////////////////
+  // MetaInfo proxy methods
+  inline uint32_t 
+  getContentType() const;
+  
+  inline void 
+  setContentType(uint32_t type);
+  
+  inline Milliseconds 
+  getFreshnessPeriod() const;
+  
+  inline void 
+  setFreshnessPeriod(Milliseconds freshnessPeriod);
+  
+  /**
+   * @brief Get content Block
+   *
+   * To access content value, one can use value()/value_size() or
+   * value_begin()/value_end() methods of the Block class
+   */
+  inline const Block& 
+  getContent() const;
 
   /**
-   * Set the content to a copy of the data in the vector.
+   * @brief Set the content to a copy of the data in the vector.
    * @param content A vector whose contents are copied.
    * @return This Data so that you can chain calls to update values.
    */
-  void
-  setContent(const std::vector<uint8_t>& content) 
-  {
-    setContent(&content[0], content.size());
-    onChanged();
-  }
-  
-  void
-  setContent(const uint8_t* content, size_t contentLength) 
-  {
-    OBufferStream os;
-    Tlv::writeVarNumber(os, Tlv::Content);
-    Tlv::writeVarNumber(os, contentLength);
-    os.write(reinterpret_cast<const char *>(content), contentLength);
-    
-    content_ = Block(os.buf());
-    onChanged();
-  }
+  inline void
+  setContent(const uint8_t* content, size_t contentLength);
 
-  void
-  setContent(const ConstBufferPtr &contentValue)
-  {
-    content_ = Block(Tlv::Content, contentValue); // not real a wire encoding yet
-    onChanged();
-  }
+  inline void
+  setContent(const Block& content);
+
+  inline void
+  setContent(const ConstBufferPtr &contentValue);
   
-  void
-  setContent(const Block& content) 
-  { 
-    content_ = content;
-    onChanged();
-  }
+  inline const Signature&
+  getSignature() const;
+  
+  /**
+   * @brief Set the signature to a copy of the given signature.
+   * @param signature The signature object which is cloned.
+   * @return This Data so that you can chain calls to update values.
+   */
+  inline Data& 
+  setSignature(const Signature& signature);
 
 private:
   /**
-   * Clear the wire encoding.
+   * @brief Clear the wire encoding.
    */
   inline void 
   onChanged();
@@ -291,19 +138,141 @@
 private:
   Name name_;
   MetaInfo metaInfo_;
-  Block content_;
+  mutable Block content_;
   Signature signature_;
 
-  Block wire_;
+  mutable Block wire_;
 };
 
+inline
+Data::Data()
+{
+}
+
+inline
+Data::Data(const Name& name)
+  : name_(name)
+{
+}
+
+inline
+Data::~Data()
+{
+}
+
+inline const Name& 
+Data::getName() const
+{
+  return name_;
+}
+  
+inline void
+Data::setName(const Name& name)
+{ 
+  onChanged();
+  name_ = name; 
+}
+  
+inline const MetaInfo& 
+Data::getMetaInfo() const
+{
+  return metaInfo_;
+}
+  
+inline void
+Data::setMetaInfo(const MetaInfo& metaInfo) 
+{ 
+  onChanged();
+  metaInfo_ = metaInfo; 
+}
+
+inline uint32_t 
+Data::getContentType() const
+{
+  return metaInfo_.getType();
+}
+  
+inline void 
+Data::setContentType(uint32_t type)
+{
+  onChanged();
+  metaInfo_.setType(type);
+}
+  
+inline Milliseconds 
+Data::getFreshnessPeriod() const
+{
+  return metaInfo_.getFreshnessPeriod();
+}
+  
+inline void 
+Data::setFreshnessPeriod(Milliseconds freshnessPeriod)
+{
+  onChanged();
+  metaInfo_.setFreshnessPeriod(freshnessPeriod);
+}
+
+inline const Block& 
+Data::getContent() const
+{
+  if (!content_.hasWire())
+      content_.encode();
+  return content_;
+}
+
+inline void
+Data::setContent(const uint8_t* content, size_t contentLength) 
+{
+  onChanged();
+
+  OBufferStream os;
+  Tlv::writeVarNumber(os, Tlv::Content);
+  Tlv::writeVarNumber(os, contentLength);
+  os.write(reinterpret_cast<const char *>(content), contentLength);
+    
+  content_ = Block(os.buf());
+}
+
+inline void
+Data::setContent(const ConstBufferPtr &contentValue)
+{
+  onChanged();
+
+  content_ = Block(Tlv::Content, contentValue); // not real a wire encoding yet
+}
+  
+inline void
+Data::setContent(const Block& content) 
+{ 
+  onChanged();
+
+  content_ = content;
+}
+
+inline const Signature&
+Data::getSignature() const
+{
+  return signature_;
+}
+  
+inline Data& 
+Data::setSignature(const Signature& signature) 
+{
+  onChanged();
+  signature_ = signature;
+
+  return *this;
+}
 
 inline void 
 Data::onChanged()
 {
-  // The values have changed, so the signature and wire format is invalidated
-  signature_.reset();
-  wire_.reset();
+  // The values have changed, so the wire format is invalidated
+
+  // !!!Note!!! Signature is not invalidated and it is responsibility of
+  // the application to do proper re-signing if necessary
+  
+  wire_ = Block();
 }
 
 } // namespace ndn
diff --git a/include/ndn-cpp/key-locator.hpp b/include/ndn-cpp/key-locator.hpp
index f6c6f9d..3f53ef4 100644
--- a/include/ndn-cpp/key-locator.hpp
+++ b/include/ndn-cpp/key-locator.hpp
@@ -8,20 +8,20 @@
 #ifndef NDN_KEY_LOCATOR_HPP
 #define NDN_KEY_LOCATOR_HPP
 
-#include "encoding/tlv-element.hpp"
+#include "encoding/block.hpp"
 #include "name.hpp"
 
 namespace ndn {
 
-namespace error {
-struct KeyLocator : public std::runtime_error { KeyLocator(const std::string &what) : std::runtime_error(what) {} };
-} // error
-
 class KeyLocator {
 public:
+  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+  
   enum {
     KeyLocator_None = -1,
-    KeyLocator_Name = 0
+    KeyLocator_Name = 0,
+    
+    KeyLocator_Unknown = 255
   };
   
   KeyLocator()
@@ -29,6 +29,12 @@
   {
   }
 
+  inline const Block& 
+  wireEncode() const;
+
+  inline void 
+  wireDecode(const Block &value);
+  
   inline bool
   empty() const
   {
@@ -37,42 +43,79 @@
   
   uint32_t 
   getType() const { return type_; }
-  
-  void 
-  setType(uint32_t type) { type_ = type; }
-    
-  const Block& 
-  getValue() const { return value_; }
-
-  void 
-  setValue(const Block &value) { value_ = value; }
-
+      
   ////////////////////////////////////////////////////////
   // Helper methods for different types of key locators
   //
   // For now only Name type is actually supported
   
-  Name
-  getName() const
-  {
-    if (type_ != KeyLocator_Name)
-      throw error::KeyLocator("Requested Name, but KeyLocator is not of the Name type");
+  inline const Name&
+  getName() const;
 
-    return Name(getValue());
-  }
-
-  void
-  setName(const Name &name)
-  {
-    type_ = KeyLocator_Name;
-    value_ = name.wireEncode();
-  }
+  inline void
+  setName(const Name &name);
   
 private:
   uint32_t type_;
-  Block value_;
+  Name name_;
+  
+  mutable Block wire_;
 };
 
+inline const Block& 
+KeyLocator::wireEncode() const
+{
+  if (empty())
+    throw Error("Wire encoding requested, but KeyLocator is empty");
+
+  if (wire_.hasWire())
+    return wire_;
+  
+  if (type_ != KeyLocator_Name)
+    throw Error("Unsupported KeyLocator type");
+  
+  // KeyLocator
+  wire_ = Block(Tlv::KeyLocator);
+  wire_.push_back(name_.wireEncode());
+  wire_.encode();
+  
+  return wire_;
 }
 
+inline void 
+KeyLocator::wireDecode(const Block &value)
+{
+  wire_ = value;
+  wire_.parse();
+  
+  if (!wire_.getAll().empty() && wire_.getAll().front().type() == Tlv::Name)
+    {
+      type_ = KeyLocator_Name;
+      name_.wireDecode(wire_.getAll().front());
+    }
+  else
+    {
+      type_ = KeyLocator_Unknown;
+    }
+}
+
+inline const Name&
+KeyLocator::getName() const
+{
+  if (type_ != KeyLocator_Name)
+    throw Error("Requested Name, but KeyLocator is not of the Name type");
+
+  return name_;
+}
+
+inline void
+KeyLocator::setName(const Name &name)
+{
+  type_ = KeyLocator_Name;
+  name_ = name;
+}
+
+
+} // namespace ndn
+
 #endif
diff --git a/include/ndn-cpp/meta-info.hpp b/include/ndn-cpp/meta-info.hpp
new file mode 100644
index 0000000..27e97e8
--- /dev/null
+++ b/include/ndn-cpp/meta-info.hpp
@@ -0,0 +1,116 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_META_INFO_HPP
+#define NDN_META_INFO_HPP
+
+namespace ndn {
+
+/**
+ * An MetaInfo holds the meta info which is signed inside the data packet.
+ */
+class MetaInfo {
+public:
+  enum {
+    TYPE_DEFAULT = 0,
+    TYPE_LINK = 1,
+    TYPE_KEY = 2
+  };
+  
+  MetaInfo()
+    : type_(TYPE_DEFAULT)
+    , freshnessPeriod_(-1)
+  {   
+  }
+  
+  uint32_t 
+  getType() const
+  { return type_; }
+  
+  void 
+  setType(uint32_t type)
+  { type_ = type; }
+  
+  Milliseconds 
+  getFreshnessPeriod() const
+  { return freshnessPeriod_; }
+  
+  void 
+  setFreshnessPeriod(Milliseconds freshnessPeriod)
+  { freshnessPeriod_ = freshnessPeriod; }
+
+  inline const Block& 
+  wireEncode() const;
+  
+  inline void
+  wireDecode(const Block &wire);  
+  
+private:
+  uint32_t type_;
+  Milliseconds freshnessPeriod_;
+
+  mutable Block wire_;
+};
+
+inline const Block& 
+MetaInfo::wireEncode() const
+{
+  if (wire_.hasWire())
+    return wire_;
+
+  wire_ = Block(Tlv::MetaInfo);
+
+  // ContentType
+  if (type_ != TYPE_DEFAULT) {
+    OBufferStream os;
+    Tlv::writeVarNumber(os, Tlv::ContentType);
+    Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(type_));
+    Tlv::writeNonNegativeInteger(os, type_);
+
+    wire_.push_back(Block(os.buf()));
+  }
+
+  // FreshnessPeriod
+  if (freshnessPeriod_ >= 0) {
+    OBufferStream os;
+    Tlv::writeVarNumber(os, Tlv::FreshnessPeriod);
+    Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(freshnessPeriod_));
+    Tlv::writeNonNegativeInteger(os, freshnessPeriod_);
+
+    wire_.push_back(Block(os.buf()));
+  }
+  
+  wire_.encode();
+  return wire_;  
+}
+  
+inline void
+MetaInfo::wireDecode(const Block &wire)
+{
+  wire_ = wire;
+  wire_.parse();
+
+  // ContentType
+  Block::element_iterator val = wire_.find(Tlv::ContentType);
+  if (val != wire_.getAll().end())
+    {
+      Buffer::const_iterator begin = val->value_begin();
+      type_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+    }
+
+  // FreshnessPeriod
+  val = wire_.find(Tlv::FreshnessPeriod);
+  if (val != wire_.getAll().end())
+    {
+      Buffer::const_iterator begin = val->value_begin();
+      freshnessPeriod_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+    }
+}
+
+} // namespace ndn
+
+#endif // NDN_META_INFO_HPP
diff --git a/include/ndn-cpp/signature.hpp b/include/ndn-cpp/signature.hpp
new file mode 100644
index 0000000..c6d914c
--- /dev/null
+++ b/include/ndn-cpp/signature.hpp
@@ -0,0 +1,102 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_SIGNATURE_HPP
+#define NDN_SIGNATURE_HPP
+
+namespace ndn {
+
+/**
+ * A Signature is storage for the signature-related information (info and value) in a Data packet.
+ */
+class Signature {
+public:
+  enum {
+    DigestSha256 = 0,
+    SignatureSha256WithRsa = 1
+  };
+  
+  Signature()
+    : type_(-1)
+  {
+  }
+  
+  Signature(const Block &info, const Block &value)
+    : info_(info)
+    , value_(value)
+  {
+    Buffer::const_iterator i = info_.value_begin();
+    Tlv::readVarNumber(i, info_.value_end());
+    size_t length = Tlv::readVarNumber(i, info_.value_end());
+    type_ = Tlv::readNonNegativeInteger(length, i, info_.value_end());
+  }
+
+  operator bool() const
+  {
+    return type_ != -1;
+  }
+
+  uint32_t
+  getType() const
+  {
+    return type_;
+  }
+  
+  const Block&
+  getInfo() const
+  {
+    return info_;
+  }
+
+  void
+  setInfo(const Block &info)
+  {
+    info_ = info;
+    if (info_.hasWire() || info_.hasValue())
+      {
+        info_.parse();
+        const Block &signatureType = info_.get(Tlv::SignatureType);
+        
+        Buffer::const_iterator i = signatureType.value_begin();
+        type_ = Tlv::readVarNumber(i, signatureType.value_end());
+      }
+    else
+      {
+        type_ = -1;
+      }
+  }  
+
+  const Block&
+  getValue() const
+  {
+    return value_;
+  }
+
+  void
+  setValue(const Block &value)
+  {
+    value_ = value;
+  }
+
+  void
+  reset()
+  {
+    type_ = -1;
+    info_ = Block();
+    value_ = Block();
+  }
+
+private:
+  int32_t type_;
+  
+  Block info_;
+  Block value_;
+};
+
+} // namespace ndn
+
+#endif // NDN_SIGNATURE_HPP