Skip to content
Snippets Groups Projects
Commit 0f47b665 authored by rk's avatar rk
Browse files

Merge branch 'master' of nlp.pwr.wroc.pl:wccl

Conflicts:
	libwccl/CMakeLists.txt
parents fcfb65f9 ddb5ae3b
No related merge requests found
......@@ -18,7 +18,7 @@ SET(libwccl_STAT_SRC
ops/and.cpp
ops/or.cpp
ops/logicalpredicate.cpp
ops/nor.cpp
ops/nor.cpp
ops/predicate.cpp
parser/Parser.cpp
parser/ParserException.cpp
......
......@@ -63,6 +63,71 @@ public:
std::string varname;
};
/**
* Exception class for invalid variable name errors in situations where
* it is not possible to return a NULL-equivalent
*/
class InvalidVariableName : public WcclError
{
public:
InvalidVariableName(const std::string& varname)
: WcclError("Invalid variable name"), varname(varname)
{}
~InvalidVariableName() throw() {}
std::string varname;
};
/**
* Base class for the "fast" variable accesors.
*/
class BaseAccesor
{
public:
/// Variable name getter
const std::string get_name() const {
return varname_;
}
protected:
/// Protected ctor, only constructed by derived classes
BaseAccesor(const std::string& varname)
: varname_(varname)
{
}
std::string varname_;
};
/**
* A "fast" accesor class for getting a variable off a Variables object.
*
* It should be faster to create an accesor object from the variables name and
* then use it multiple times than to use the name itself often.
*
* @todo the above is not the case yet.
*
* Objects of the accesor class can only be created by the Variables object,
* are valid only for that Variables object and its copies, and might stop
* working if the Variables object is touched in the wrong way in between the
* creation and use of a VariableAccesor. UB is meant by "stop working".
* Bad touch is not yet fully defined, removing a variable certainly is one.
*/
template<typename T>
class VariableAccesor : public BaseAccesor
{
public:
protected:
/// Protected ctor, only created by Variables::create_accesor
VariableAccesor(const std::string& varname)
: BaseAccesor(varname)
{
}
friend class Variables;
};
/**
* A class for holding variables.
*
......@@ -124,6 +189,44 @@ public:
return detail::Vmap<T>::get(s);
}
/** Create a "fast" accesor for a variable by name.
*
* Returns a special object which is valid for use in get_fast, which when
* used should be faster than calling get<T>(s) repeatedly.
*
* If the variable name is invalid or teh type doesn't match, an exception
* will be thrown, either VariableTypeMismatch or InvalidVariableName.
*/
template<typename T>
VariableAccesor<T> create_accesor(const std::string& s) {
BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
if (!get<T>(s)) {
if (get<Value>(s)) {
throw VariableTypeMismatch(s);
} else {
throw InvalidVariableName(s);
}
}
return VariableAccesor<T>(s);
}
/** Get a variable using a "fast" accesor.
*
* The accesor is required to have been created by this particular object,
* or a copy (either way), and the Variables object must have not had
* variables removed (adding new variables should not invalidate accesors).
*
* If the VariableAccesor comes form a different Variables object or there
* have been invalidating changes to this Variables object, behavior is not
* well defined. You might get a NULL, a different variable than you
* expected, or a segfault.
*/
template<typename T>
boost::shared_ptr<T> get_fast(const VariableAccesor<T>& a) const {
BOOST_MPL_ASSERT(( boost::mpl::count<types, T> ));
return get<T>(a.get_name());
}
/** Get a variable, possibly default-creatng it.
*
* Returns the variable with the given name, or, if it does not exist,
......
......@@ -11,6 +11,7 @@ add_executable(tests
main.cpp
position.cpp
values.cpp
varaccess.cpp
variables.cpp
)
......
#include <boost/test/unit_test.hpp>
#include <boost/bind.hpp>
#include <libwccl/variables.h>
#include <libpwrutils/foreach.h>
#include <iostream>
using namespace Wccl;
BOOST_AUTO_TEST_SUITE(varaccess);
struct VAfx
{
Variables v;
VAfx() {
Variables v2;
v2.put("a", new Bool(true));
v2.put("b", new Bool(true));
v2.put("c", new Bool(true));
v2.put("bb", new Bool(true));
v2.put("aa", new Position(1));
v2.put("aaa", new Position(2));
v = v2;
}
};
BOOST_FIXTURE_TEST_CASE(access, VAfx)
{
std::vector<std::string> vnames;
vnames.push_back("a");
vnames.push_back("b");
vnames.push_back("c");
vnames.push_back("bb");
foreach (const std::string vn, vnames) {
VariableAccesor<Bool> a1 = v.create_accesor<Bool>(vn);
BOOST_CHECK(v.get_fast(a1) == v.get<Bool>(vn));
v.set("a", Bool(false));
BOOST_CHECK(v.get_fast(a1) == v.get<Bool>(vn));
v.put("a", Bool(true));
BOOST_CHECK(v.get_fast(a1) == v.get<Bool>(vn));
}
}
BOOST_FIXTURE_TEST_CASE(badaccess, VAfx)
{
BOOST_CHECK_THROW(v.create_accesor<Bool>("asd"), InvalidVariableName);
BOOST_CHECK_THROW(v.create_accesor<Bool>("aaa"), VariableTypeMismatch);
}
BOOST_AUTO_TEST_SUITE_END()
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment