/* -*- 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 <mathieu.lacage@sophia.inria.fr>
*/
#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 (CreateObject<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 */