nrd: basic implementation of rib

Change-Id: I0d6acf8188d39068081babd8c23f6ea6eb3c9406
diff --git a/src/common.hpp b/src/common.hpp
new file mode 100644
index 0000000..e19ead0
--- /dev/null
+++ b/src/common.hpp
@@ -0,0 +1,15 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NRD_COMMON_HPP
+#define NRD_COMMON_HPP
+
+#include <iostream>
+#include <list>
+
+#include <ndn-cpp-dev/management/nrd-prefix-reg-options.hpp>
+
+#endif // NRD_COMMON_HPP
diff --git a/nrd.cpp b/src/main.cpp
similarity index 100%
rename from nrd.cpp
rename to src/main.cpp
diff --git a/src/rib.cpp b/src/rib.cpp
new file mode 100644
index 0000000..0e0cbfe
--- /dev/null
+++ b/src/rib.cpp
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "rib.hpp"
+
+namespace ndn {
+namespace nrd {
+
+Rib::Rib()
+{
+}
+
+//
+Rib::~Rib()
+{
+}
+
+static inline bool
+ribEntryNameCompare(const PrefixRegOptions& opt1, const PrefixRegOptions& opt2)
+{
+  return opt1.getName() == opt2.getName();
+}
+
+//
+Rib::const_iterator
+Rib::find(const PrefixRegOptions& options) const
+{
+  RibTable::const_iterator it = std::find_if(m_rib.begin(), m_rib.end(),
+                                             bind(&ribEntryNameCompare, _1, options));
+  if (it == m_rib.end())
+    {
+      return end();
+    }
+  else
+    return it;
+}
+
+//
+void
+Rib::insert(const PrefixRegOptions& options)
+{
+  RibTable::const_iterator it = std::find_if(m_rib.begin(), m_rib.end(),
+                                             bind(&ribEntryNameCompare, _1, options));
+  if (it == m_rib.end())
+    {
+      m_rib.push_front(options);
+    }
+}
+
+//
+void
+Rib::erase(const PrefixRegOptions& options)
+{
+  RibTable::iterator it = std::find_if(m_rib.begin(), m_rib.end(),
+                                       bind(&ribEntryNameCompare, _1, options));
+  if (it != m_rib.end())
+    {
+      m_rib.erase(it);
+    }
+}
+
+} // namespace nrd
+} // namespace ndn
diff --git a/src/rib.hpp b/src/rib.hpp
new file mode 100644
index 0000000..f3a713a
--- /dev/null
+++ b/src/rib.hpp
@@ -0,0 +1,81 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NRD_RIB_HPP
+#define NRD_RIB_HPP
+
+#include "common.hpp"
+
+namespace ndn {
+namespace nrd {
+
+/** \brief represents the RIB
+ */
+class Rib
+{
+public:
+  typedef std::list<PrefixRegOptions> RibTable;
+  typedef RibTable::const_iterator const_iterator;
+
+  Rib();
+
+  ~Rib();
+
+  const_iterator
+  find(const PrefixRegOptions& options) const;
+
+  void
+  insert(const PrefixRegOptions& options);
+
+  void
+  erase(const PrefixRegOptions& options);
+
+  const_iterator
+  begin() const;
+
+  const_iterator
+  end() const;
+
+  size_t
+  size() const;
+
+  size_t
+  empty() const;
+
+private:
+  // Note: Taking a list right now. A Trie will be used later to store
+  // prefixes
+  RibTable m_rib;
+};
+
+inline Rib::const_iterator
+Rib::begin() const
+{
+  return m_rib.begin();
+}
+
+inline Rib::const_iterator
+Rib::end() const
+{
+  return m_rib.end();
+}
+
+inline size_t
+Rib::size() const
+{
+  return m_rib.size();
+}
+
+inline size_t
+Rib::empty() const
+{
+  return m_rib.empty();
+}
+
+} // namespace nrd
+} // namespace ndn
+
+#endif // NRD_RIB_HPP
diff --git a/tests/main.cpp b/tests/main.cpp
new file mode 100644
index 0000000..a7e827d
--- /dev/null
+++ b/tests/main.cpp
@@ -0,0 +1,10 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#define BOOST_TEST_MAIN 1
+#define BOOST_TEST_DYN_LINK 1
+
+#include <boost/test/unit_test.hpp>
diff --git a/tests/test-rib.cpp b/tests/test-rib.cpp
new file mode 100644
index 0000000..c9a5dff
--- /dev/null
+++ b/tests/test-rib.cpp
@@ -0,0 +1,56 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "rib.hpp"
+
+#include <boost/test/unit_test.hpp>
+
+namespace ndn {
+namespace nrd {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(TestRib)
+
+BOOST_AUTO_TEST_CASE(Basic)
+{
+  Rib rib;
+
+  PrefixRegOptions options1;
+  options1.setName("/hello/world");
+  options1.setFlags(tlv::nrd::NDN_FORW_CHILD_INHERIT | tlv::nrd::NDN_FORW_CAPTURE);
+  options1.setCost(10);
+  options1.setExpirationPeriod(1500);
+
+  PrefixRegOptions options2;
+  options2.setName("/hello/world");
+  options2.setFlags(tlv::nrd::NDN_FORW_CHILD_INHERIT);
+  options2.setExpirationPeriod(0);
+
+  rib.insert(options1);
+  BOOST_CHECK_EQUAL(rib.size(), 1);
+  
+  rib.insert(options2);
+  BOOST_CHECK_EQUAL(rib.size(), 1);
+
+  options2.setName("/foo/bar");
+  rib.insert(options2);
+  BOOST_CHECK_EQUAL(rib.size(), 2);
+
+  rib.erase(options2);
+  BOOST_CHECK_EQUAL(rib.size(), 1);
+
+  BOOST_CHECK(rib.find(options2) == rib.end());
+  BOOST_CHECK(rib.find(options1) != rib.end());
+
+  rib.erase(options1);
+  BOOST_CHECK(rib.empty());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nrd
+} // namespace ndn
diff --git a/wscript b/wscript
index 3d4799e..a1f7a76 100644
--- a/wscript
+++ b/wscript
@@ -6,7 +6,7 @@
 def options(opt):
     opt.load('compiler_cxx gnu_dirs')
     opt.load('flags boost doxygen coverage', tooldir=['.waf-tools'])
-    
+
     nrdopt = opt.add_option_group('NRD Options')
     nrdopt.add_option('--debug',action='store_true',default=False,dest='debug',help='''Compile library debugging mode without all optimizations (-O0)''')
     nrdopt.add_option('--with-tests', action='store_true',default=False,dest='with_tests',help='''Build unit tests''')
@@ -36,13 +36,29 @@
     # except:
     #     pass
 
-    conf.write_config_header('config.hpp')
+    conf.write_config_header('src/config.hpp')
 
 def build (bld):
-    bld (
-        features=['cxx', 'cxxprogram'],
-        target="nrd",
-        source = bld.path.ant_glob('*.cpp'),
+    bld(
+        features=['cxx'],
+        name="nrd-objects",
+        source = bld.path.ant_glob('src/*.cpp', excl='src/main.cpp'),
         use = 'NDN_CPP BOOST',
         )
 
+    bld.program(
+        target = 'nrd',
+        source = 'src/main.cpp',
+        use = 'nrd-objects'
+        )
+
+    # Unit tests
+    if bld.env['WITH_TESTS']:
+        unit_tests = unittests = bld.program(
+            target='unit-tests',
+            features = 'cxx cxxprogram',
+            source = bld.path.ant_glob(['tests/**/*.cpp']),
+            use = 'nrd-objects',
+            includes = ['.', 'src'],
+            install_prefix = None,
+          )