Skip to content

Commit

Permalink
Merge pull request #29 from m-peko/use-member-ptrs-instead-of-map
Browse files Browse the repository at this point in the history
Use class member pointers instead of key-value map
  • Loading branch information
m-peko authored Apr 11, 2020
2 parents db320ec + 912a784 commit cc884ba
Show file tree
Hide file tree
Showing 20 changed files with 998 additions and 491 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ script:
# Generate build files
- cmake .. -DBOOLEVAL_ENABLE_COVERAGE:BOOL=${ENABLE_COVERAGE-False}

# Compile and execute tests
# Compile examples and tests
- cmake --build .
- cmake --build . --target examples
- cmake --build . --target tests

# Execute tests
- ctest
11 changes: 7 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cmake_minimum_required (VERSION 3.2)

project (booleval)

option (BOOLEVAL_BUILD_EXAMPLES "Build examples" ON)
option (BOOLEVAL_BUILD_TESTS "Build tests" ON)

# Compile in release mode by default
Expand All @@ -23,10 +24,7 @@ if (MSVC)
else ()
option (BOOLEVAL_ENABLE_COVERAGE "Enable code coverage reporting" OFF)
if (BOOLEVAL_ENABLE_COVERAGE)
message (
STATUS
"Code coverage reporting is enabled."
)
message (STATUS "Code coverage reporting is enabled.")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -O0 --coverage")
else ()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -O3")
Expand Down Expand Up @@ -70,6 +68,11 @@ endif ()

add_subdirectory (src)

if (BOOLEVAL_BUILD_EXAMPLES)
message (STATUS "Examples have been enabled")
add_subdirectory (examples)
endif ()

if (BOOLEVAL_BUILD_TESTS)
# Only include googletest if the git submodule has been fetched
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/googletest/CMakeLists.txt")
Expand Down
45 changes: 23 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,26 @@ issue tracker indicating the following information:

## Example

Let's say we have a large number of objects coming through our interface. Objects can be of the following `struct Object` type:
Let's say we have a large number of objects coming through our interface. Objects can be of the following `class obj` type:

```c++
struct Object {
Object(std::string const& a,
uint32_t const b)
: field_a(a),
field_b(b)
struct obj {
std::string field_a_;
uint32_t field_b_;

public:
obj(std::string const& field_a, uint32_t const field_b)
: field_a_(field_a),
field_b_(field_b)
{}

std::string field_a;
uint32_t field_b;
std::string const& field_a() {
return field_a_;
}

uint32_t field_b() {
return field_b_;
}
};
```

Expand All @@ -163,8 +171,8 @@ In our application, we want to let end-users to specify some sort of a rule whic
#include <booleval/evaluator.h>

int main() {
Object pass_obj("foo", 123);
Object fail_obj("bar", 456);
obj pass("foo", 123);
obj fail("bar", 456);

booleval::evaluator evaluator;

Expand All @@ -174,24 +182,17 @@ int main() {
}

if (evaluator.is_activated()) {
auto passes = evaluator.evaluate({
{ "field_a", pass_obj.field_a },
{ "field_b", pass_obj.field_b }
evaluator.map({
{ "field_a", &obj::field_a },
{ "field_b", &obj::field_b }
});

std::cout << std::boolalpha << passes << std::endl; // output: true
auto fails = evaluator.evaluate({
{ "field_a", fail_obj.field_a },
{ "field_b", fail_obj.field_b }
});
std::cout << std::boolalpha << fails << std::endl; // output: false
std::cout << std::boolalpha << evaluator.evaluate(pass) << std::endl; // output: true
std::cout << std::boolalpha << evaluator.evaluate(fail) << std::endl; // output: false
} else {
std::cerr << "Evaluator is not activated!" << std::endl;
}

return 0;
}
```
18 changes: 18 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required (VERSION 3.2)

set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src)
include_directories (
${CMAKE_CURRENT_SOURCE_DIR}/../include
)

link_libraries (booleval)

add_custom_target (
examples DEPENDS
evaluator
)

# Make sure we first build libbooleval
add_dependencies (examples booleval)

add_executable (evaluator EXCLUDE_FROM_ALL evaluator.cpp)
78 changes: 78 additions & 0 deletions examples/evaluator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2020, Marin Peko
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include <string>
#include <iostream>
#include <booleval/evaluator.h>

struct obj {
public:
obj(std::string const& field_a, uint32_t const field_b)
: field_a_(field_a),
field_b_(field_b)
{}

std::string const& field_a() const noexcept {
return field_a_;
}

uint32_t field_b() const noexcept {
return field_b_;
}

private:
std::string field_a_;
uint32_t field_b_;
};

int main() {
obj pass("foo", 123);
obj fail("bar", 456);

booleval::evaluator evaluator;

auto valid = evaluator.expression("field_a foo and field_b 123");
if (!valid) {
std::cerr << "Expression not valid!" << std::endl;
}

if (evaluator.is_activated()) {
evaluator.map({
{ "field_a", &obj::field_a },
{ "field_b", &obj::field_b }
});

std::cout << std::boolalpha << evaluator.evaluate(pass) << std::endl; // output: true
std::cout << std::boolalpha << evaluator.evaluate(fail) << std::endl; // output: false
} else {
std::cerr << "Evaluator is not activated!" << std::endl;
}

return 0;
}
26 changes: 20 additions & 6 deletions include/booleval/evaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

#include <map>
#include <string_view>
#include <booleval/utils/any_value.h>
#include <booleval/utils/any_mem_fn.h>
#include <booleval/tree/result_visitor.h>
#include <booleval/tree/expression_tree.h>

Expand All @@ -45,7 +45,7 @@ namespace booleval {
* It builds an expression tree and traverses that tree in order to evaluate fields.
*/
class evaluator {
using field_map = std::map<std::string_view, utils::any_value>;
using field_map = std::map<std::string_view, utils::any_mem_fn>;

public:
evaluator();
Expand Down Expand Up @@ -75,13 +75,27 @@ class evaluator {
[[nodiscard]] bool expression(std::string_view expression);

/**
* Evaluates expression tree based on the key value map passed in.
* Sets the key - member function map used for evaluation of expression tree.
*
* @param fields Key value map to be evaluated
* @param fields Key - member function map
*/
void map(field_map const& fields);

/**
* Evaluates expression tree for the object passed in.
*
* @param obj Object to be evaluated
*
* @return True if the key value map satisfies expression, otherwise false
* @return True if the object's members satisfy the expression, otherwise false
*/
[[nodiscard]] bool evaluate(field_map const& fields);
template <typename T>
[[nodiscard]] bool evaluate(T const& obj) {
if (is_activated_) {
return result_visitor_.visit(*expression_tree_.root(), obj);
} else {
return true;
}
}

private:
bool is_activated_;
Expand Down
Loading

0 comments on commit cc884ba

Please sign in to comment.