Skip to content

Header-only C++17 library for evaluating logical expressions.

License

Notifications You must be signed in to change notification settings

m-peko/booleval

Repository files navigation

license Build Status codecov Standard

Header-only C++17 library for evaluating logical expressions.


The library is under development and subject to change. Contributions are welcome. You can also log an issue if you have a wish for enhancement or if you spot a bug.

Quick start

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

class foo
{
public:
    foo( std::string value ) noexcept : value_{ std::move( value ) } {}

    std::string const & value() const noexcept { return value_; }

private:
    std::string value_{};
};

int main()
{
    foo x{ "foo" };
    foo y{ "bar" };

    booleval::evaluator evaluator
    {
        booleval::make_field( "field", &foo::value )
    };

    if ( !evaluator.expression( "field eq foo" ) )
    {
        std::cerr << "Expression not valid!" << std::endl;
    }

    if ( evaluator.is_activated() )
    {
        std::cout << std::boolalpha << evaluator.evaluate( x ) << std::endl; // true
        std::cout << std::boolalpha << evaluator.evaluate( y ) << std::endl; // false
    }

    return 0;
}

Table of Contents

Motivation

booleval is a header-only C++17 library for evaluating logical expressions. It implements recursive descent parser mechanism for building an expression tree for a user-defined logical expression. After the expression tree is being built, map of fields and values representing a certain object can be passed to the evaluator component of this library which will evaluate those values to true or false according to the user-defined logical expression.




In programming languages like Java and C# accessing arbitrary fields inside a class represents an omnipresent problem. However, it got solved by introducing a reflections feature. This feature provides us information about the class to which a certain object belongs to and, also, the methods of that class which we can invoke at runtime.

Since the reflection feature is missing in C++, booleval library is implemented. It checks whether the members of a class to which an object belongs to have certain values. Members of a class are specified in a string format and can be used to form a logical expression.

Providing an end-user a functionality of specifying a logical expression is a common way of filtering out a large amounts of objects. E.g. tcpdump and BPF (Berkeley Packet Filter), network tools available on most UNIX-like operating systems, have pretty much the same syntax for their filter expression.

Getting Started

booleval is a header-only C++17 library for evaluating logical expressions.

Zero Copy

In order to improve performance, booleval library does not copy objects that are being evaluated.

EQUAL TO operator

EQUAL TO operator is an optional operator. Therefore, logical expression that checks whether a field with the name field_a has a value of foo can be constructed in a two different ways:

  • EQUAL TO operator is specified in the expression: field_a eq foo
  • EQUAL TO operator is not specified in the expression: field_a foo

To conclude, equality operator is a default operator between two fields. Thus, it does not need to be specified in the logical expression.

Valid expressions

  • (field_a foo and field_b bar) or field_a bar
  • (field_a eq foo and field_b eq bar) or field_a eq bar

Invalid expressions

  • (field_a foo and field_b bar Note: Missing closing parentheses
  • field_a foo bar Note: Two field values in a row

Evaluation Result

Result of evaluation process contains two information:

  • success: true if evaluation process is successful; otherwise, false
  • message: meaningful message if evaluation process is unsuccessful; otherwise, empty message

This kind of enriched lightweight result is being used instead of exceptions for performance reasons.

Examples of messages:

  • "Missing operand"
  • "Unknown field"
  • "Unknown token type"

Supported tokens

Name Keyword Symbol
AND operator AND / and &&
OR operator OR / or | |
EQUAL TO operator EQ / eq ==
NOT EQUAL TO operator NEQ / neq !=
GREATER THAN operator GT / gt >
LESS THAN operator LT / lt <
GREATER THAN OR EQUAL TO operator GEQ / geq >=
LESS THAN OR EQUAL TO operator LEQ / leq <=
LEFT parentheses (
RIGHT parentheses )

Benchmark

Following table shows benchmark results:

Benchmark Time Iterations
Building expression tree 3817 ns 180904
Evaluation 1285 ns 532522

In other words, it is possible to evaluate 2,413,045.84 objects per second.

Compilation

In order to compile the library, run the following commands:

$ # create the build directory
$ mkdir build
$ cd build

$ # configure the project
$ cmake ../

$ # compile
$ make

Tests

In order to run unit tests, run the following commands:

$ # fetch the googletest submodule, needed for tests
$ git submodule init
$ git submodule update

$ mkdir build
$ cd build

$ # configure the project
$ cmake ..

$ # compile tests
$ make tests

$ # run tests
$ make test

Compiler Compatibility

  • Clang/LLVM >= 7
  • MSVC++ >= 19.16
  • GCC >= 8.4

There are no 3rd party dependencies.

Contributing

Feel free to contribute.

If you find that any of the tests fail, please create a ticket in the issue tracker indicating the following information:

  • platform
  • architecture
  • library version
  • minimal reproducible example

License

The project is available under the MIT license.

Support

If you like the work booleval library is doing, please consider supporting it:

Buy Me A Coffee