Thanks to visit codestin.com
Credit goes to github.com

Skip to content
 
 

Latest commit

 

History

248 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MATCHABLE

Matchable provides string-convertable and flaggable enumerated types
These types can have properties, and these properties can have observers
Examples can be found under test/programs

Files Needed For Getting Started

Matchable is primarily a header-only library. To get started quickly you could just copy the following two files into your project:

  • include/matchable/matchable.h
  • include/matchable/matchable_fwd.h

If using cmake then you could instead install matchable, set matchable_DIR and use find_package() within your project.

Hello Matchable

The following program can be found at: test/programs/matchable_usage.cpp

#include <iostream>
#include "matchable/matchable.h"


MATCHABLE(
    // type
    DayOfWeek,

    // variants
    Monday,
    Tuesday,
    Wednessday,
    Thursday,
    Friday,
    Saturday,
    Sunday
)


MATCHABLE(
    Status,

    // escape codes can be used for characters that are invalid for identifiers
    success_bng_,              // Status::success_bng_::grab().as_string() == "success!"
    invalid_spc_input,         // Status::invalid_spc_input::grab().as_string() == "invalid input"
    timed_spc_out,             // Status::from_string("timed out") == Status::timed_spc_out::grab()
    nothing_spc_to_spc_do,
    insufficient_spc_memory,
    index_spc_out_spc_of_spc_bounds,

    // optionally, variants can be prefixed with esc_ as needed
    esc_17                     // Status::esc_17::grab().as_string() == "17"

    // see bottom of matchable/matchable.h for all the escape codes
    // also reference test/programs/escapable.cpp for more on this
);


Status::Type foo(std::string day_string)
{
    // create an instance of the DayOfWeek matchable
    DayOfWeek::Type day_of_week;

    // all matchable types have a hidden "nil" variant
    // at this point day_of_week == DayOfWeek::nil
    assert(day_of_week == DayOfWeek::nil);

    // nil is a valid and usable variant but its syntax is a bit different
    // notice how we don't "grab()" nil like we do for the other variants
    // also, to test for nil we could alternatively do:
    assert(day_of_week.is_nil());

    // lets try to assign the variant from the day_string parameter
    // note the complexity for from_string() is O(log N)
    // if day_string is equal to the output of "as_string()" for any defined variant,
    // then day_of_week will be set to that variant
    // if no variant is found then nil will be assigned instead
    day_of_week = DayOfWeek::from_string(day_string);
    if (day_of_week.is_nil())
        return Status::invalid_spc_input::grab();

    // to show how flags work, we'll create a flags instance and flag our favorite days
    DayOfWeek::Flags favorite_days;
    for (int i = 0; i < 3; ++i)
        favorite_days.set(DayOfWeek::from_index(i)); // note the complexity for from_index is O(1)

    // oops, actually we don't like Wednessday after all
    favorite_days.unset(DayOfWeek::Wednessday::grab());

    // to get all flagged variants we can use currently_set()
    for (auto day : favorite_days.currently_set())
        if (day == day_of_week)
            std::cout << day << " is one of my favorite days! ";

    // we can also use is_set() to check for flagged variants
    if (favorite_days.is_set(DayOfWeek::Friday::grab()))
        return Status::esc_17::grab();

    // we could also use MATCHABLE_INSTANCE_IN()
    if (!MATCHABLE_INSTANCE_IN(DayOfWeek, day_of_week, Monday, Tuesday))
        return Status::nothing_spc_to_spc_do::grab();

    return Status::success_bng_::grab();
}


int main()
{
    std::cout << "variant iteration by index:" << std::endl;
    for (auto day_of_week : DayOfWeek::variants_by_index())
        std::cout << "    " << day_of_week << std::endl;

    std::cout << "\nvariant iteration by string (alphabetic):" << std::endl;
    for (auto day_of_week : DayOfWeek::variants_by_string())
        std::cout << "    " << day_of_week << std::endl;

    std::cout << "\noutput of foo(\"bad input\") --> " << foo("bad input") << std::endl;
    std::cout << "output of foo(\"Saturday\") --> " << foo("Saturday") << std::endl;
    std::cout << "output of foo(\"Tuesday\") --> " << foo("Tuesday") << std::endl;

    return 0;
}

Output for the program above:

$  ./matchable_usage
variant iteration by index:
    Monday
    Tuesday
    Wednessday
    Thursday
    Friday
    Saturday
    Sunday

variant iteration by string (alphabetic):
    Friday
    Monday
    Saturday
    Sunday
    Thursday
    Tuesday
    Wednessday

output of foo("bad input") --> invalid input
output of foo("Saturday") --> nothing to do
output of foo("Tuesday") --> Tuesday is one of my favorite days! success!

Macro-API

Macros for creating new types

MATCHABLE(type, variant...)

Params:

  • type The new "matchable" to be created
  • variant... 0..108 comma separated variants of the new matchable type

PROPERTYx1_MATCHABLE(property_type, property_name, type, variant...)

Same as MATCHABLE(), but injects a property called property_name of type property_type
Params:

  • property_type type of injected property
  • property_name name of injected property
  • type name of the new "matchable" to be created
  • variant... 0..108 comma separated variants of the new matchable

The property is available both as a single value and as a vector with:

property_type const & as_property_name()
std::vector<property_type> const & as_property_name_vect()

void set_property_name(property_type const &)
void set_property_name_vect(std::vector<property_type> const &)

Examples:
test/programs/cards.cpp
test/programs/matchbox.cpp
test/programs/sorting.cpp

PROPERTYx*_MATCHABLE()

Similar to PROPERTYx1_MATCHABLE(), the following macros exist for injecting multiple properties when creating matchables.

PROPERTYx2_MATCHABLE()
PROPERTYx3_MATCHABLE()
PROPERTYx4_MATCHABLE()
PROPERTYx5_MATCHABLE()
PROPERTYx6_MATCHABLE()
PROPERTYx7_MATCHABLE()
PROPERTYx8_MATCHABLE()
PROPERTYx9_MATCHABLE()
PROPERTYx10_MATCHABLE()
PROPERTYx11_MATCHABLE()
PROPERTYx12_MATCHABLE()
PROPERTYx13_MATCHABLE()
PROPERTYx14_MATCHABLE()
PROPERTYx15_MATCHABLE()
PROPERTYx16_MATCHABLE()
PROPERTYx17_MATCHABLE()
PROPERTYx18_MATCHABLE()
PROPERTYx19_MATCHABLE()
PROPERTYx20_MATCHABLE()
PROPERTYx21_MATCHABLE()

Example: test/programs/relationships.cpp

Going beyond 108 variants

Although a matchable is initially defined with up to 108 variants, it may grow to achieve variant counts higher than 108.

GROW_MATCHABLE(type, variant...)

Add up to 108 new variants to type.
This may be repeated as needed...
Example: test/programs/max_variants.cpp

Macros for setting properties at link-time

MATCHABLE_VARIANT_PROPERTY_VALUE(type, variant, property_name, property_value)

Params:

  • type A matchable type
  • variant A variant of type
  • property_name A property available to type.
  • property_value The new value to be set

Calls type::variant::grab().set_property_name(property_value) at link-time.
Examples:
test/programs/cards.cpp
test/programs/relationships.cpp

MATCHABLE_VARIANT_PROPERTY_VALUES(type, variant, property_name, property_values...)

Params:

  • type A matchable type
  • variant A variant of type
  • property_name A property available to type
  • property_values... The new values to be set

Calls type::variant::grab().set_property_name_vect() with a vector formed by the given property_values...
Example: test/programs/relationships.cpp

Run-time macros

UNMATCHABLE(type, variant...)

Removes variants for the current scope. When the scope exits the removed variants are restored.
For matchables defined within namespaces the following macros are available:

  • NAMESPACEx1_UNMATCHABLE()
  • NAMESPACEx2_UNMATCHABLE()
  • NAMESPACEx3_UNMATCHABLE()
  • NAMESPACEx4_UNMATCHABLE()
  • NAMESPACEx5_UNMATCHABLE()

Further namespace nesting beyond 5 is supported by using the Unmatchable template directly (see example)
Example: test/programs/unmatchable.cpp

MATCHABLE_INSTANCE_IN(type, instance, variant...) -> bool

returns true if instance is one of the given variants or false otherwise
Example:

bool is_weekday(DayOfWeek::Type day)
{
    return MATCHABLE_INSTANCE_IN(DayOfWeek, day, Monday, Tuesday, Wednesday, Thursday, Friday);
}

Example: test/programs/relationships.cpp

Forward Declaring Matchables

To benchmark compile time performace with and without forward declarations run:

scripts/test_buildtimes.py

MATCHABLE_FWD(type)

Forward declare a matchable
Example:

#include "matchable/matchable_fwd.h"
MATCHABLE_FWD(DayOfWeek)

Building, Installing and Running Tests

scripts/build_and_install.py

build_and_install.py without arguments will from the project root do:

mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=../install ..
make install
cd ..

refer to help for custom build/install directories and other options:

scripts/build_and_install.py -h
  • use of build_and_install.py is of course optional and serves as a reference or example workflow

Running Tests / Examples

Assuming workflow above with install directory under the project root (modify paths accordingly for your workflow).

List all tests:

install/share/matchable/test/bin/list.sh

Run Single Test (for example "max_variants"):

install/share/matchable/test/bin/run_test.sh max_variants

Run Quietly:

install/share/matchable/test/bin/run_test.sh max_variants quietly

Run All Tests:

install/share/matchable/test/bin/run_all.sh

Run All Tests Quietly

install/share/matchable/test/bin/run_all.sh quietly

Supported Systems

Artix Linux, amd64
Gentoo Linux, sparc64

Matchable should work on any unix-like system but only Artix and Gentoo are supported. OpenBSD, sparc64 is also known to work but you may need to use the "-c" option when building.

Authors

  • shtroizel

See also the list of contributors who participated in this project.

License

This project is licensed under the "BSD 3-Clause License" - see the LICENSE file for details

Donating To This Project

donations are greatly appreciated, thank you!

  • monero: 4BETuKtvLjkT7VBW85HLJ1XPqhr1TqQj11UmEMnphgG4DzNtSgJmK8b3ZmTudnbbjf7oHfNpCPxDG3BWnmVSCrtrNXMnhyv

About

MATCHABLE (forked from shtroizel/matchable)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages