/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2007 INRIA * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage */ #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 #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"); 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 GetTraceResolver (void) const; private: CallbackTraceSource m_test; }; void ObjectTraceTester::Do (uint32_t i) { m_test (i); } Ptr ObjectTraceTester::GetTraceResolver (void) const { Ptr resolver = Create (); 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 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 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 > vec; for (uint32_t i = 0; i < n; i++) { vec.push_back (CreateObject ()); } ArrayTraceResolver resolver; resolver.SetIterators (vec.begin (), vec.end ()); TraceContext context; resolver.Connect (str, MakeCallback (&ArrayTraceResolverTest::OneItem, this), context); uint32_t l = 0; for (std::vector >::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 >::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 */