nfd-control: Adding class of ControlResponse

Change-Id: I596bb3f5470e3d3c6671e74bef991e9b047637c9
refs: #1162
diff --git a/src/management/control-response.hpp b/src/management/control-response.hpp
new file mode 100644
index 0000000..b14409c
--- /dev/null
+++ b/src/management/control-response.hpp
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
+#define NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
+
+#include "encoding/block.hpp"
+#include "encoding/tlv-nfd-control.hpp"
+
+namespace ndn {
+
+/**
+ * @brief Class defining abstraction of ControlResponse for NFD Control Protocol
+ *
+ * @see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ */
+class ControlResponse {
+public:
+  struct Error : public Tlv::Error { Error(const std::string &what) : Tlv::Error(what) {} };
+
+  ControlResponse()
+    : m_code(200)
+  {
+  }
+
+  ControlResponse(uint32_t code, const std::string &text)
+    : m_code(code)
+    , m_text(text)
+  {
+  }
+  
+  inline uint32_t
+  getCode() const;
+
+  inline void
+  setCode(uint32_t code);
+
+  inline const std::string &
+  getText() const;
+
+  inline void
+  setText(const std::string &text);
+
+  inline const Block&
+  getBody() const;
+
+  inline void
+  setBody(const Block& body);
+  
+  inline const Block&
+  wireEncode() const;
+
+  inline void
+  wireDecode(const Block &block);
+  
+protected:
+  uint32_t m_code;
+  std::string m_text;
+  Block m_body;
+
+  mutable Block m_wire;
+};
+
+inline uint32_t
+ControlResponse::getCode() const
+{
+  return m_code;
+}
+
+inline void
+ControlResponse::setCode(uint32_t code)
+{
+  m_code = code;
+  m_wire.reset();
+}
+
+inline const std::string &
+ControlResponse::getText() const
+{
+  return m_text;
+}
+
+inline void
+ControlResponse::setText(const std::string &text)
+{
+  m_text = text;
+  m_wire.reset();
+}
+
+inline const Block&
+ControlResponse::getBody() const
+{
+  return m_body;
+}
+
+inline void
+ControlResponse::setBody(const Block& body)
+{
+  m_body = body;
+  m_body.encode(); // will do nothing if already encoded
+  m_wire.reset();
+}
+
+
+inline const Block&
+ControlResponse::wireEncode() const
+{
+  if (m_wire.hasWire())
+    return m_wire;
+
+  m_wire = Block(tlv::nfd_control::ControlResponse);
+  m_wire.push_back
+    (nonNegativeIntegerBlock(tlv::nfd_control::StatusCode, m_code));
+
+  m_wire.push_back
+    (dataBlock(tlv::nfd_control::StatusText, m_text.c_str(), m_text.size()));
+
+  if (m_body.hasWire())
+    {
+      m_wire.push_back(m_body);
+    }
+  
+  m_wire.encode();  
+  return m_wire;
+}
+
+inline void
+ControlResponse::wireDecode(const Block &wire)
+{
+  m_wire = wire;
+  m_wire.parse();
+
+  Block::element_iterator val = m_wire.getAll().begin();
+  if (val == m_wire.getAll().end() ||
+      val->type() != tlv::nfd_control::StatusCode)
+    {
+      throw Error("Incorrect ControlResponse format (StatusCode missing or not the first item)");
+    }
+  
+  m_code = readNonNegativeInteger(*val);
+  ++val;
+
+  if (val == m_wire.getAll().end() ||
+      val->type() != tlv::nfd_control::StatusText)
+    {
+      throw Error("Incorrect ControlResponse format (StatusText missing or not the second item)");
+    }
+  m_text.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+  ++val;
+
+  if (val != m_wire.getAll().end())
+    m_body = *val;
+  else
+    m_body = Block();
+}
+
+inline std::ostream&
+operator << (std::ostream &os, const ControlResponse &status)
+{
+  os << status.getCode() << " " << status.getText();
+  return os;
+}
+
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_CONTROL_RESPONSE_HPP