fix bug 98
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 25 Dec 2007 11:09:15 +0100
changeset 2198 ebe61d20a7ae
parent 2197 2a729c1b2e68
child 2199 fd70fd33b046
fix bug 98
src/core/array-trace-resolver.cc
src/core/array-trace-resolver.h
src/core/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/array-trace-resolver.cc	Tue Dec 25 11:09:15 2007 +0100
@@ -0,0 +1,287 @@
+#include "array-trace-resolver.h"
+
+
+namespace ns3 {
+
+ArrayTraceResolverMatcher::ArrayTraceResolverMatcher (std::string element)
+  : m_element (element)
+{}
+bool 
+ArrayTraceResolverMatcher::Matches (uint32_t i) const
+{
+  if (m_element == "*")
+    {
+      return true;
+    }
+  std::string::size_type tmp;
+  tmp = m_element.find ("|");
+  if (tmp != std::string::npos)
+    {
+      std::string left = m_element.substr (0, tmp-0);
+      std::string right = m_element.substr (tmp+1, m_element.size () - (tmp + 1));
+      ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (left);
+      if (matcher.Matches (i))
+	{
+	  return true;
+	}
+      matcher = ArrayTraceResolverMatcher (right);
+      if (matcher.Matches (i))
+	{
+	  return true;
+	}
+      return false;
+    }
+  std::string::size_type leftBracket = m_element.find ("[");
+  std::string::size_type rightBracket = m_element.find ("]");
+  std::string::size_type dash = m_element.find ("-");
+  if (leftBracket == 0 && rightBracket == m_element.size () - 1 &&
+      dash > leftBracket && dash < rightBracket)
+    {
+      std::string lowerBound = m_element.substr (leftBracket + 1, dash - (leftBracket + 1));
+      std::string upperBound = m_element.substr (dash + 1, rightBracket - (dash + 1));
+      uint32_t min;
+      uint32_t max;
+      if (StringToUint32 (lowerBound, &min) && 
+	  StringToUint32 (upperBound, &max) &&
+	  i >= min && i <= max)
+        {
+          return true;
+        }
+      else
+	{
+	  return false;
+	}
+    }
+  uint32_t value;
+  if (StringToUint32 (m_element, &value) &&
+      i == value)
+    {
+      return true;
+    }
+  return false;
+}
+
+bool
+ArrayTraceResolverMatcher::StringToUint32 (std::string str, uint32_t *value) const
+{
+  std::istringstream iss;
+  iss.str (str);
+  iss >> (*value);
+  return !iss.bad () && !iss.fail ();
+}
+
+}//namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+#include <stdarg.h>
+#include "test.h"
+#include "object.h"
+#include "array-trace-resolver.h"
+#include "callback-trace-source.h"
+#include "composite-trace-resolver.h"
+
+namespace ns3 {
+
+class ObjectTraceTesterIndex : public TraceContextElement
+{
+public:
+  ObjectTraceTesterIndex ();
+  ObjectTraceTesterIndex (uint32_t index);
+  void Print (std::ostream &os);
+  static uint16_t GetUid (void);
+  uint32_t Get (void) const;
+  std::string GetTypeName (void) const;
+private:
+  uint32_t m_index;
+};
+
+
+ObjectTraceTesterIndex::ObjectTraceTesterIndex ()
+  : m_index (0)
+{}
+ObjectTraceTesterIndex::ObjectTraceTesterIndex (uint32_t index)
+  : m_index (index)
+{}
+void 
+ObjectTraceTesterIndex::Print (std::ostream &os)
+{
+  os << "nodeid=" << m_index;
+}
+uint16_t 
+ObjectTraceTesterIndex::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<ObjectTraceTesterIndex> ("ObjectTraceTesterIndex");
+  return uid;
+}
+uint32_t 
+ObjectTraceTesterIndex::Get (void) const
+{
+  return m_index;
+}
+std::string 
+ObjectTraceTesterIndex::GetTypeName (void) const
+{
+  return "ns3::ObjectTraceTesterIndex";
+}
+
+
+class ObjectTraceTester : public Object
+{
+public:
+  void Do (uint32_t i);
+protected:
+  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
+private:
+  CallbackTraceSource<uint32_t> m_test;
+};
+
+void 
+ObjectTraceTester::Do (uint32_t i)
+{
+  m_test (i);
+}
+
+Ptr<TraceResolver>
+ObjectTraceTester::GetTraceResolver (void) const
+{
+  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
+  resolver->AddSource ("test", 
+		       TraceDoc ("Test"),
+		       m_test);
+  resolver->SetParentResolver (Object::GetTraceResolver ());
+  return resolver;
+}
+
+class ArrayTraceResolverTest : public Test
+{
+public:
+  ArrayTraceResolverTest ();
+  virtual bool RunTests (void);
+private:
+  bool RunOne (uint32_t n, std::string str, 
+	       uint32_t nExpected, ...);
+  void OneItem (const TraceContext &context,
+		uint32_t i);
+
+  typedef std::vector<uint32_t> Got;
+  Got m_got;
+};
+
+ArrayTraceResolverTest::ArrayTraceResolverTest ()
+  : Test ("ArrayTraceResolver")
+{}
+bool
+ArrayTraceResolverTest::RunOne (uint32_t n, std::string str, 
+				uint32_t nExpected, ...)
+{
+  bool result = true;
+  std::vector<uint32_t> expected;
+  va_list ap;
+  va_start (ap, nExpected);
+  for (uint32_t k = 0; k < nExpected; k++)
+    {
+      uint32_t v = va_arg (ap, uint32_t);
+      expected.push_back (v);
+    }
+  va_end (ap);
+  std::sort (expected.begin (), expected.end ());
+  std::sort (m_got.begin (), m_got.end ());
+
+  std::vector<Ptr<ObjectTraceTester> > vec;
+  for (uint32_t i = 0; i < n; i++)
+    {
+      vec.push_back (Create<ObjectTraceTester> ());
+    }
+  ArrayTraceResolver<ObjectTraceTesterIndex> resolver;
+  resolver.SetIterators (vec.begin (), vec.end ());
+
+  TraceContext context;
+  resolver.Connect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this), context);
+  uint32_t l = 0;
+  for (std::vector<Ptr<ObjectTraceTester> >::const_iterator j = vec.begin (); j != vec.end (); j++)
+    {
+      (*j)->Do (l);
+      l++;
+    }
+  NS_TEST_ASSERT_EQUAL (m_got.size (), expected.size ());
+  for (uint32_t m = 0; m < expected.size (); m++)
+    {
+      NS_TEST_ASSERT_EQUAL (m_got[m], expected[m]);
+    }
+  m_got.clear ();
+  resolver.Disconnect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this));
+  for (std::vector<Ptr<ObjectTraceTester> >::const_iterator j = vec.begin (); j != vec.end (); j++)
+    {
+      (*j)->Do (l);
+      l++;
+    }
+  NS_TEST_ASSERT_EQUAL (m_got.size (), 0);
+  m_got.clear ();
+
+  return result;
+}
+void
+ArrayTraceResolverTest::OneItem (const TraceContext &context,
+				 uint32_t i)
+{
+  ObjectTraceTesterIndex index;
+  bool found = context.GetElement (index);
+  if (!found)
+    {
+      return;
+    }
+  if (index.Get () != i)
+    {
+      return;
+    }
+  m_got.push_back (i);
+}
+
+bool 
+ArrayTraceResolverTest::RunTests (void)
+{
+  bool result = true;
+
+  NS_TEST_ASSERT (RunOne (0, "/*/test", 0));
+  NS_TEST_ASSERT (RunOne (1, "/*/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (1, "/0/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (1, "/[0-0]/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (1, "/0|0/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (2, "/*/test", 2, 0, 1));
+  NS_TEST_ASSERT (RunOne (2, "/0|1/test", 2, 0, 1));
+  NS_TEST_ASSERT (RunOne (2, "/1/test", 1, 1));
+  NS_TEST_ASSERT (RunOne (2, "/|1|/test", 1, 1));
+  NS_TEST_ASSERT (RunOne (2, "/0/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (2, "/0|/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (2, "/|0/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (2, "/[0-1]/test", 2, 0, 1));
+  NS_TEST_ASSERT (RunOne (2, "/[0-0]/test", 1, 0));
+  NS_TEST_ASSERT (RunOne (2, "/[1-1]/test", 1, 1));
+  NS_TEST_ASSERT (RunOne (2, "/0|[1-1]/test", 2, 0, 1));
+  NS_TEST_ASSERT (RunOne (3, "/1|0/test", 2, 0, 1));
+  NS_TEST_ASSERT (RunOne (3, "/2|0/test", 2, 0, 2));
+  NS_TEST_ASSERT (RunOne (3, "/2|1/test", 2, 1, 2));
+  NS_TEST_ASSERT (RunOne (3, "/[0-1]/test", 2, 0, 1));
+  NS_TEST_ASSERT (RunOne (3, "/[1-2]/test", 2, 1, 2));
+  NS_TEST_ASSERT (RunOne (3, "/[0-2]/test", 3, 0, 1, 2));
+  NS_TEST_ASSERT (RunOne (3, "/[1-2]|0/test", 3, 0, 1, 2));
+  NS_TEST_ASSERT (RunOne (3, "/[1-1]|0|[2-2]/test", 3, 0, 1, 2));
+  NS_TEST_ASSERT (RunOne (3, "/[1-2]||/test", 2, 1, 2));
+  NS_TEST_ASSERT (RunOne (3, "/[1-2]||/test", 2, 2, 1));
+  NS_TEST_ASSERT (RunOne (3, "/||||/test", 0));
+  NS_TEST_ASSERT (RunOne (20, "/[5-10]|[2-3]|[15-17]/test", 11, 2, 3, 5, 6, 7, 8, 9, 10, 15, 16, 17));
+  NS_TEST_ASSERT (RunOne (3, "/[1-2]|[0-1]/test", 3, 0, 1, 2));
+
+  return result;
+}
+
+
+
+static ArrayTraceResolverTest g_arrayTraceResolverTest;
+
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/core/array-trace-resolver.h	Sat Dec 22 18:46:43 2007 +0000
+++ b/src/core/array-trace-resolver.h	Tue Dec 25 11:09:15 2007 +0100
@@ -23,6 +23,7 @@
 
 #include <stdint.h>
 #include <string>
+#include <sstream>
 #include "callback.h"
 #include "trace-resolver.h"
 #include "object.h"
@@ -78,6 +79,17 @@
   };
   IteratorBase *m_iter;
 };
+
+class ArrayTraceResolverMatcher
+{
+public:
+  ArrayTraceResolverMatcher (std::string element);
+  bool Matches (uint32_t i) const;
+  bool StringToUint32 (std::string str, uint32_t *value) const;
+private:
+  std::string m_element;
+};
+
 }//namespace ns3
 
 
@@ -133,19 +145,20 @@
     }
   std::string id = GetElement (path);
   std::string subpath = GetSubpath (path);
-  if (id == "*")
-  {
-    uint32_t j = 0;
-    for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
-      {
-        TraceContext tmp = context;
-        INDEX index = j;
-        tmp.AddElement (index);
-        Ptr<Object> obj = m_iter->Get ();
-        obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
-        j++;
-      }
-  }
+  ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (id);
+  uint32_t i = 0;
+  for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
+    {
+      if (matcher.Matches (i))
+        {
+          TraceContext tmp = context;
+          INDEX index = i;
+          tmp.AddElement (index);
+          Ptr<Object> obj = m_iter->Get ();
+          obj->GetTraceResolver ()->Connect (subpath, cb, tmp);
+        }
+        i++;
+    }
 }
 template <typename INDEX>
 void 
@@ -157,14 +170,17 @@
     }
   std::string id = GetElement (path);
   std::string subpath = GetSubpath (path);
-  if (id == "*")
-  {
-    for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
-      {
-        Ptr<Object> obj = m_iter->Get ();
-        obj->TraceDisconnect (subpath, cb);
-      }
-  }
+  ArrayTraceResolverMatcher matcher = ArrayTraceResolverMatcher (id);
+  uint32_t i = 0;
+  for (m_iter->Rewind (); m_iter->HasNext (); m_iter->Next ())
+    {
+      if (matcher.Matches (i))
+        {
+          Ptr<Object> obj = m_iter->Get ();
+          obj->TraceDisconnect (subpath, cb);
+        }
+      i++;
+    }
 }
 template <typename INDEX>
 void 
--- a/src/core/wscript	Sat Dec 22 18:46:43 2007 +0000
+++ b/src/core/wscript	Tue Dec 25 11:09:15 2007 +0100
@@ -51,6 +51,7 @@
         'trace-doc.cc',
         'trace-source.cc',
         'type-traits-test.cc',
+        'array-trace-resolver.cc',
         ]
 
     if sys.platform == 'win32':