Skip to content
Draft
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ artifacts
dist
cbxp-*
*egg-info/
cbxp/mappings/*.hpp
cbxp/schemas/*.hpp

# CMake
CMakeLists.txt.user
Expand Down
59 changes: 57 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,73 @@ file(
# ============================================================================
# Build '/lib/libcbxp.a'
# ============================================================================
# ============================================================================
# Generate schema header from cbxp/schemas/control_block_v1.json
# ============================================================================
set(CBXP_SCHEMAS_GENERATED_DIR "${CMAKE_BINARY_DIR}/cbxp/schemas")
file(MAKE_DIRECTORY "${CBXP_SCHEMAS_GENERATED_DIR}")

file(READ "${CMAKE_CURRENT_SOURCE_DIR}/cbxp/schemas/control_block_v1.json" CBXP_SCHEMA_JSON)

file(WRITE "${CBXP_SCHEMAS_GENERATED_DIR}/control_block_v1.hpp"
"#ifndef CBXP_SCHEMA_CONTROL_BLOCK_V1_JSON_HPP\n\
#define CBXP_SCHEMA_CONTROL_BLOCK_V1_JSON_HPP\n\
\n\
#define CBXP_SCHEMA_JSON R\"JSON(${CBXP_SCHEMA_JSON})JSON\"\n\
\n\
#endif // CBXP_SCHEMA_CONTROL_BLOCK_V1_JSON_HPP\n"
)

# ============================================================================
# Generate mapping headers from JSON files in cbxp/mappings/
# ============================================================================
set(CBXP_MAPPINGS_GENERATED_DIR "${CMAKE_BINARY_DIR}/cbxp/mappings")
file(MAKE_DIRECTORY "${CBXP_MAPPINGS_GENERATED_DIR}")

file(GLOB CBXP_MAPPING_JSON_FILES "${CMAKE_CURRENT_SOURCE_DIR}/cbxp/mappings/*.json")

set(CBXP_MAPPING_FORCED_INCLUDES "")

foreach(MAPPING_JSON_FILE ${CBXP_MAPPING_JSON_FILES})
get_filename_component(MAPPING_NAME "${MAPPING_JSON_FILE}" NAME_WE)
string(TOUPPER "${MAPPING_NAME}" MAPPING_NAME_UPPER)

file(READ "${MAPPING_JSON_FILE}" MAPPING_JSON)

set(MAPPING_GUARD "${MAPPING_NAME_UPPER}_JSON_HPP")
set(MAPPING_MACRO "${MAPPING_NAME_UPPER}_JSON")
set(MAPPING_HEADER_PATH "${CBXP_MAPPINGS_GENERATED_DIR}/${MAPPING_NAME}.hpp")

file(WRITE "${MAPPING_HEADER_PATH}"
"#ifndef ${MAPPING_GUARD}\n\
#define ${MAPPING_GUARD}\n\
\n\
#define ${MAPPING_MACRO} R\"JSON(${MAPPING_JSON})JSON\"\n\
\n\
#endif // ${MAPPING_GUARD}\n"
)

list(APPEND CBXP_MAPPING_FORCED_INCLUDES "--include=${MAPPING_HEADER_PATH}")
endforeach()

add_library(libcbxp STATIC ${CBXP_SRC_LIB})
set_target_properties(libcbxp PROPERTIES OUTPUT_NAME "cbxp")

target_include_directories(
libcbxp PUBLIC
cbxp
cbxp/control_blocks
externals
externals/json
externals/json-schema-validator
/usr/include/zos
)

target_compile_options(libcbxp PUBLIC ${COMPILE_OPTIONS})
target_compile_options(
libcbxp PUBLIC
${COMPILE_OPTIONS}
"--include=${CBXP_SCHEMAS_GENERATED_DIR}/control_block_v1.hpp"
${CBXP_MAPPING_FORCED_INCLUDES}
)
target_link_options(libcbxp PUBLIC ${LINK_OPTIONS})

# ============================================================================
Expand Down
20 changes: 19 additions & 1 deletion cbxp/control_block_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ enum Error {
BadInclude = 2,
BadFilter = 3,
DataTooSmall = 4,
NullDataPtr = 5
NullDataPtr = 5,
BadCbxpPath = 6,
BadJsonFile = 7,
CantReachBlock = 8,
};

class CBXPError : public std::exception {
Expand Down Expand Up @@ -39,6 +42,21 @@ class DataLengthError : public CBXPError {
DataLengthError() : CBXPError(Error::DataTooSmall) {}
};

class CbxpPathError : public CBXPError {
public:
CbxpPathError() : CBXPError(Error::BadCbxpPath) {}
};

class CbxpJsonError : public CBXPError {
public:
CbxpJsonError() : CBXPError(Error::BadJsonFile) {}
};

class CbxpReachBlockError : public CBXPError {
public:
CbxpReachBlockError() : CBXPError(Error::CantReachBlock) {}
};

} // namespace CBXP

#endif
126 changes: 93 additions & 33 deletions cbxp/control_block_explorer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,104 @@

#include <algorithm>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>

#include "cbxp.h"
#include "control_block_error.hpp"
#include "control_blocks/ascb.hpp"
#include "control_blocks/assb.hpp"
#include "control_blocks/asvt.hpp"
#include "control_blocks/control_block.hpp"
#include "control_blocks/cvt.hpp"
#include "control_blocks/ecvt.hpp"
#include "control_blocks/ldax.hpp"
#include "control_blocks/oucb.hpp"
#include "control_blocks/psa.hpp"
#include "logger.hpp"

namespace CBXP {

std::unordered_map<std::string, ControlBlock>
ControlBlockExplorer::loadCustomControlBlocks(std::filesystem::path path) {
std::unordered_map<std::string, ControlBlock> new_maps = {};
try {
if (!std::filesystem::exists(path) ||
!std::filesystem::is_directory(path)) {
throw CbxpPathError();
}
for (const auto& file : std::filesystem::directory_iterator(path)) {
if (file.extension() != ".json") {
continue;
}
std::string file_name = file.stem().string();
std::ifstream ifs(file.path());
nlohmann::json json_data = nlohmann::json::parse(ifs);
Logger::getInstance().debug("Adding '" + file_name +
"' control block from '" +
file.path().string() + "'.");
ControlBlock new_map = ControlBlock(json_data);
new_maps[file_name] = new_map;
}
} catch (const std::filesystem::filesystem_error& e) {
throw CbxpPathError();
} catch (const std::exception& e) {
throw CbxpJsonError();
}
return new_maps;
}

std::string ControlBlockExplorer::mapToString(
const std::unordered_map<std::string, ControlBlock>& map) {
std::string map_as_string = "";
if (map.empty()) {
return map_as_string;
}
map_as_string = "[";

bool first_entry = true;
for (const auto& [key, value] : map) {
if (!first_entry) {
map_as_string += ", ";
} else {
first_entry = false;
}
map_as_string += key;
}

map_as_string += "]";
return map_as_string;
}

std::unordered_map<std::string, ControlBlock>
ControlBlockExplorer::buildControlBlock() {
// Load known control blocks
std::unordered_map<std::string, ControlBlock> control_blocks = {
{ "psa", ControlBlock(PSA_JSON)},
{ "cvt", ControlBlock(CVT_JSON)},
{"ecvt", ControlBlock(ECVT_JSON)},
{"asvt", ControlBlock(ASVT_JSON)},
{"ascb", ControlBlock(ASCB_JSON)},
{"assb", ControlBlock(ASSB_JSON)},
{"oucb", ControlBlock(OUCB_JSON)},
{"ldax", ControlBlock(LDAX_JSON)},
};

// Load custom control blocks
std::string env_p(std::getenv("CBXPPATH"));
if (env_p.empty()) {
return control_blocks;
}
// Logic for loading custom control block mappings, overwriting any that were
// already loaded with custom mappings as well.
std::filesystem::path cbxp_path(env_p);
for (const auto& path : cbxp_path) {
std::unordered_map<std::string, ControlBlock> custom_control_blocks =
ControlBlockExplorer::loadCustomControlBlocks(path);
if (!custom_control_blocks.empty()) {
Logger::getInstance().debug(
"Added the following custom control blocks from path '" + path +
"': " + ControlBlockExplorer::mapToString(custom_control_blocks));
custom_control_blocks.insert(control_blocks.begin(),
control_blocks.end());
}
}
}

std::vector<std::string> ControlBlockExplorer::createOptionsList(
const std::string& comma_separated_string) {
if (comma_separated_string == "") {
Expand Down Expand Up @@ -92,31 +172,11 @@ void ControlBlockExplorer::processControlBlock(
nlohmann::json control_block_json = {};

try {
if (control_block_name == "psa") {
control_block_json =
PSA(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "cvt") {
control_block_json =
CVT(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "ecvt") {
control_block_json =
ECVT(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "ascb") {
control_block_json =
ASCB(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "asvt") {
control_block_json =
ASVT(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "assb") {
control_block_json =
ASSB(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "oucb") {
control_block_json =
OUCB(cbxp_options_).get(p_control_block_, control_block_data_length_);
} else if (control_block_name == "ldax") {
control_block_json =
LDAX(cbxp_options_).get(p_control_block_, control_block_data_length_);

if (control_blocks_.contains(control_block_name)) {
explorer_options_ =
ExplorerOptionsMap(cbxp_options_, control_block_name, control_blocks_,
p_control_block_, control_block_data_length_);
control_block_json = explorer_options_.getControlBlockData();
} else {
throw ControlBlockError();
}
Expand Down
17 changes: 16 additions & 1 deletion cbxp/control_block_explorer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@

namespace CBXP {

typedef struct {
std::vector<std::string> include_patterns;
std::vector<std::string> filters;
bool skip_buffer_length_check;
} cbxp_options_t;

class ControlBlockExplorer {
private:
cbxp_options_t cbxp_options_ = {{}, {}, false};
cbxp_result_t* p_result_;
cbxp_options_t cbxp_options_ = {{}, {}, false};
const void* p_control_block_ = nullptr;
size_t control_block_data_length_ = 0;
std::string control_block_operation_ = "";

static std::unordered_map<std::string, ControlBlock> control_blocks_() {
return buildControlBlockMap();
};
static std::string mapToString(
const std::unordered_map<std::string, ControlBlock>& map);
static std::unordered_map<std::string, ControlBlock> loadCustomControlBlocks(
std::filesystem::path path);
static std::unordered_map<std::string, ControlBlock> buildControlBlockMap();
static std::vector<std::string> createOptionsList(
const std::string& comma_separated_string);

Expand Down
Loading
Loading