Skip to content
This repository was archived by the owner on Dec 19, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ jobs:


- name: Install Boost
uses: MarkusJx/install-boost@v2.4.5
uses: MarkusJx/install-boost@v2
id: install-boost
with:
# REQUIRED: Specify the required boost version
# A list of supported versions can be found here:
# https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json
boost_version: 1.83.0
boost_version: 1.87.0
# OPTIONAL: Specify a platform version
# platform_version: 18.04
# OPTIONAL: Specify a custom install location
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
/.cache
/**/build
/.idea/
Expand Down
29 changes: 24 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ cmake_minimum_required(VERSION 3.14)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(ALLOW_DUPLICATE_CUSTOM_TARGETS TRUE)

# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()

project(CLIPPy
VERSION 0.2
DESCRIPTION "Command Line Interface Plus Python"
Expand Down Expand Up @@ -87,11 +92,25 @@ FetchContent_MakeAvailable(Boost)

#
# JSONLogic
FetchContent_Declare(jsonlogic
GIT_REPOSITORY https://github.com/LLNL/jsonlogic.git
GIT_TAG master
)
FetchContent_MakeAvailable(jsonlogic)
# find_package(jsonlogic QUIET)
# if (NOT jsonlogic_FOUND)
# message(STATUS "jsonlogic not found, doing stuff")
set(Boost_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/boost-install) # needed for jsonlogic

FetchContent_Declare(jsonlogic
GIT_REPOSITORY https://github.com/LLNL/jsonlogic.git
GIT_TAG master
SOURCE_SUBDIR cpp
)
# set(jsonlogic_INCLUDE_DIR ${jsonlogic_SOURCE_DIR}/cpp/include/jsonlogic)
FetchContent_MakeAvailable(jsonlogic)
message(STATUS "jsonlogic source dir: ${jsonlogic_SOURCE_DIR}")


# else()
# message(STATUS "jsonlogic found, weird")

# endif()

### Require out-of-source builds
file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH)
Expand Down
136 changes: 52 additions & 84 deletions examples/logic/testeval.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@


#include <iostream>
#include <fstream>

#include <boost/lexical_cast.hpp>

#include "clippy/clippy-eval.hpp"

#include <boost/json/src.hpp>
#include <boost/lexical_cast.hpp>
#include <fstream>
#include <iostream>
#include <jsonlogic/src.hpp>

namespace bjsn = boost::json;

bjsn::value
parseStream(std::istream& inps)
{
bjsn::value parseStream(std::istream& inps) {
bjsn::stream_parser p;
std::string line;
std::string line;

// \todo skips ws in strings
while (inps >> line)
{
while (inps >> line) {
bjsn::error_code ec;

p.write(line.c_str(), line.size(), ec);
Expand All @@ -34,18 +28,15 @@ parseStream(std::istream& inps)
return p.release();
}

bjsn::value
parseFile(const std::string& filename)
{
bjsn::value parseFile(const std::string& filename) {
std::ifstream is{filename};

return parseStream(is);
}


template <class N, class T>
bool matchOpt1(const std::vector<std::string>& args, N& pos, std::string opt, T& fld)
{
bool matchOpt1(const std::vector<std::string>& args, N& pos, std::string opt,
T& fld) {
std::string arg(args.at(pos));

if (arg.find(opt) != 0) return false;
Expand All @@ -57,8 +48,8 @@ bool matchOpt1(const std::vector<std::string>& args, N& pos, std::string opt, T&
}

template <class N, class Fn>
bool matchOpt1(const std::vector<std::string>& args, N& pos, std::string opt, Fn fn)
{
bool matchOpt1(const std::vector<std::string>& args, N& pos, std::string opt,
Fn fn) {
std::string arg(args.at(pos));

if (arg.find(opt) != 0) return false;
Expand All @@ -70,8 +61,8 @@ bool matchOpt1(const std::vector<std::string>& args, N& pos, std::string opt, Fn
}

template <class N, class Fn>
bool matchOpt0(const std::vector<std::string>& args, N& pos, std::string opt, Fn fn)
{
bool matchOpt0(const std::vector<std::string>& args, N& pos, std::string opt,
Fn fn) {
std::string arg(args.at(pos));

if (arg.find(opt) != 0) return false;
Expand All @@ -82,90 +73,77 @@ bool matchOpt0(const std::vector<std::string>& args, N& pos, std::string opt, Fn
}

template <class N, class Fn>
bool noSwitch0(const std::vector<std::string>& args, N& pos, Fn /*fn*/)
{
bool noSwitch0(const std::vector<std::string>& args, N& pos, Fn /*fn*/) {
//~ if (fn(args[pos]))
//~ return true;
//~ return true;

std::cerr << "unrecognized argument: " << args[pos] << std::endl;
++pos;
return false;
}

bool endsWith(const std::string& str, const std::string& suffix)
{
return ( str.size() >= suffix.size()
&& std::equal(suffix.rbegin(), suffix.rend(), str.rbegin())
);
bool endsWith(const std::string& str, const std::string& suffix) {
return (str.size() >= suffix.size() &&
std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()));
}


int main(int argc, const char** argv)
{
int main(int argc, const char** argv) {
constexpr bool MATCH = false;

bool verbose = false;
bool verbose = false;
bool genExpected = false;

int errorCode = 0;
std::vector<std::string> arguments(argv, argv+argc);
std::string filename;
size_t argn = 1;
int errorCode = 0;
std::vector<std::string> arguments(argv, argv + argc);
std::string filename;
size_t argn = 1;

auto setVerbose = [&verbose]() -> void { verbose = true; };
auto setResult = [&genExpected]() -> void { genExpected = true; };
auto setFile = [&filename](const std::string& name) -> bool
{
auto setVerbose = [&verbose]() -> void { verbose = true; };
auto setResult = [&genExpected]() -> void { genExpected = true; };
auto setFile = [&filename](const std::string& name) -> bool {
const bool jsonFile = endsWith(name, ".json");

if (jsonFile) filename = name;

return jsonFile;
};

while (argn < arguments.size())
{
while (argn < arguments.size()) {
MATCH
|| matchOpt0(arguments, argn, "-v", setVerbose)
|| matchOpt0(arguments, argn, "--verbose", setVerbose)
|| matchOpt0(arguments, argn, "-r", setResult)
|| matchOpt0(arguments, argn, "--result", setResult)
|| noSwitch0(arguments, argn, setFile)
;
|| matchOpt0(arguments, argn, "-v", setVerbose) ||
matchOpt0(arguments, argn, "--verbose", setVerbose) ||
matchOpt0(arguments, argn, "-r", setResult) ||
matchOpt0(arguments, argn, "--result", setResult) ||
noSwitch0(arguments, argn, setFile);
}

bjsn::value all = parseStream(std::cin);
bjsn::object& allobj = all.as_object();
bjsn::value all = parseStream(std::cin);
bjsn::object& allobj = all.as_object();

bjsn::value rule = allobj["rule"];
const bool hasData = allobj.contains("data");
bjsn::value dat;
const bool hasExpected = allobj.contains("expected");
bjsn::value rule = allobj["rule"];
const bool hasData = allobj.contains("data");
bjsn::value dat;
const bool hasExpected = allobj.contains("expected");

if (hasData)
dat = allobj["data"];
else
dat.emplace_object();

try
{
json_logic::ValueExpr res = json_logic::apply(rule, dat);
try {
jsonlogic::any_expr res = jsonlogic::apply(rule, dat);

if (verbose)
std::cerr << res << std::endl;
if (verbose) std::cerr << res << std::endl;

if (genExpected)
{
if (genExpected) {
std::stringstream resStream;

resStream << res;

allobj["expected"] = parseStream(resStream);

if (verbose) std::cerr << allobj["expected"] << std::endl;
}
else if (hasExpected)
{
} else if (hasExpected) {
std::stringstream expStream;
std::stringstream resStream;

Expand All @@ -176,37 +154,27 @@ int main(int argc, const char** argv)
if (verbose && errorCode)
std::cerr << "test failed: "
<< "\n exp: " << expStream.str()
<< "\n got: " << resStream.str()
<< std::endl;
}
else
{
<< "\n got: " << resStream.str() << std::endl;
} else {
errorCode = 1;

if (verbose)
std::cerr << "unexpected completion, result: " << res << std::endl;
}
}
catch (const std::exception& ex)
{
if (verbose)
std::cerr << "caught error: " << ex.what() << std::endl;
} catch (const std::exception& ex) {
if (verbose) std::cerr << "caught error: " << ex.what() << std::endl;

if (genExpected)
allobj.erase("expected");
else if (hasExpected)
errorCode = 1;
}
catch (...)
{
if (verbose)
std::cerr << "caught unknown error" << std::endl;
} catch (...) {
if (verbose) std::cerr << "caught unknown error" << std::endl;

errorCode = 1;
}

if (genExpected && (errorCode == 0))
std::cout << allobj << std::endl;
if (genExpected && (errorCode == 0)) std::cout << allobj << std::endl;

if (verbose && errorCode)
std::cerr << "errorCode: " << errorCode << std::endl;
Expand Down
Loading
Loading