Compare commits
2 Commits
215220f98b
...
e2d932ea78
Author | SHA1 | Date |
---|---|---|
Brett | e2d932ea78 | |
Brett | 9e4bfad087 |
|
@ -88,38 +88,38 @@ endif()
|
||||||
|
|
||||||
message("BLT ${CMAKE_PROJECT_VERSION} Successfully included!")
|
message("BLT ${CMAKE_PROJECT_VERSION} Successfully included!")
|
||||||
|
|
||||||
if(${BUILD_TESTS})
|
#if(${BUILD_TESTS})
|
||||||
project(BLT_TESTS)
|
# project(BLT_TESTS)
|
||||||
|
#
|
||||||
file(GLOB_RECURSE TESTS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/*.cpp")
|
# file(GLOB_RECURSE TESTS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/tests/*.cpp")
|
||||||
|
#
|
||||||
add_executable(BLT_TESTS ${TESTS_FILES})
|
# add_executable(BLT_TESTS ${TESTS_FILES})
|
||||||
|
#
|
||||||
target_link_libraries(BLT_TESTS PUBLIC BLT)
|
# target_link_libraries(BLT_TESTS PUBLIC BLT)
|
||||||
|
#
|
||||||
if(MSVC)
|
# if(MSVC)
|
||||||
#target_compile_options(BLT_TESTS PRIVATE /W4)
|
# #target_compile_options(BLT_TESTS PRIVATE /W4)
|
||||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
|
# if(${CMAKE_BUILD_TYPE} MATCHES Debug)
|
||||||
target_link_options(BLT_TESTS PRIVATE /DEBUG)
|
# target_link_options(BLT_TESTS PRIVATE /DEBUG)
|
||||||
endif()
|
# endif()
|
||||||
else()
|
# else()
|
||||||
target_compile_options(BLT_TESTS PRIVATE -Wall -Wextra -Wpedantic)
|
# target_compile_options(BLT_TESTS PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
endif()
|
# endif()
|
||||||
|
#
|
||||||
if (${ENABLE_ADDRSAN} MATCHES ON)
|
# if (${ENABLE_ADDRSAN} MATCHES ON)
|
||||||
target_compile_options(BLT_TESTS PRIVATE -fsanitize=address)
|
# target_compile_options(BLT_TESTS PRIVATE -fsanitize=address)
|
||||||
target_link_options(BLT_TESTS PRIVATE -fsanitize=address)
|
# target_link_options(BLT_TESTS PRIVATE -fsanitize=address)
|
||||||
endif ()
|
# endif ()
|
||||||
|
#
|
||||||
if (${ENABLE_UBSAN} MATCHES ON)
|
# if (${ENABLE_UBSAN} MATCHES ON)
|
||||||
target_compile_options(BLT_TESTS PRIVATE -fsanitize=undefined)
|
# target_compile_options(BLT_TESTS PRIVATE -fsanitize=undefined)
|
||||||
target_link_options(BLT_TESTS PRIVATE -fsanitize=undefined)
|
# target_link_options(BLT_TESTS PRIVATE -fsanitize=undefined)
|
||||||
endif ()
|
# endif ()
|
||||||
|
#
|
||||||
if (${ENABLE_TSAN} MATCHES ON)
|
# if (${ENABLE_TSAN} MATCHES ON)
|
||||||
target_compile_options(BLT_TESTS PRIVATE -fsanitize=thread)
|
# target_compile_options(BLT_TESTS PRIVATE -fsanitize=thread)
|
||||||
target_link_options(BLT_TESTS PRIVATE -fsanitize=thread)
|
# target_link_options(BLT_TESTS PRIVATE -fsanitize=thread)
|
||||||
endif ()
|
# endif ()
|
||||||
|
#
|
||||||
message("BLT tests included!")
|
# message("BLT tests included!")
|
||||||
endif()
|
#endif()
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace blt
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the first flag that starts with '--' otherwise return the first '-' flag
|
// returns the first flag that starts with '--' otherwise return the first '-' flag
|
||||||
[[nodiscard]] std::string getFirstFullFlag();
|
[[nodiscard]] std::string getFirstFullFlag() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class arg_nargs_t
|
class arg_nargs_t
|
||||||
|
@ -127,13 +127,22 @@ namespace blt
|
||||||
std::string a_version{};
|
std::string a_version{};
|
||||||
std::string a_metavar{};
|
std::string a_metavar{};
|
||||||
bool a_required = true;
|
bool a_required = true;
|
||||||
|
bool a_disable_help = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class arg_builder
|
class arg_builder
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
arg_properties_t properties;
|
arg_properties_t properties;
|
||||||
public:
|
public:
|
||||||
arg_builder(const arg_vector_t& flags): properties(flags)
|
explicit arg_builder(const arg_vector_t& flags): properties(flags)
|
||||||
|
{}
|
||||||
|
|
||||||
|
arg_builder(const std::initializer_list<std::string>& flags): properties(flags)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename... string_args>
|
||||||
|
explicit arg_builder(string_args... flags): properties({flags...})
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline arg_properties_t build()
|
inline arg_properties_t build()
|
||||||
|
@ -171,6 +180,12 @@ namespace blt
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline arg_builder& disableHelp()
|
||||||
|
{
|
||||||
|
properties.a_disable_help = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline arg_builder& setHelp(const std::string& help)
|
inline arg_builder& setHelp(const std::string& help)
|
||||||
{
|
{
|
||||||
properties.a_help = help;
|
properties.a_help = help;
|
||||||
|
@ -203,7 +218,7 @@ namespace blt
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
size_t currentIndex = 0;
|
size_t currentIndex = 0;
|
||||||
public:
|
public:
|
||||||
arg_tokenizer(std::vector<std::string> args): args(std::move(args))
|
explicit arg_tokenizer(std::vector<std::string> args): args(std::move(args))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// returns the current arg
|
// returns the current arg
|
||||||
|
@ -265,11 +280,11 @@ namespace blt
|
||||||
friend arg_parse;
|
friend arg_parse;
|
||||||
private:
|
private:
|
||||||
// stores dest value not the flag/name!
|
// stores dest value not the flag/name!
|
||||||
HASHSET<std::string> found_args;
|
HASHSET <std::string> found_args;
|
||||||
std::vector<std::string> unrecognized_args;
|
std::vector<std::string> unrecognized_args;
|
||||||
public:
|
public:
|
||||||
std::string program_name;
|
std::string program_name;
|
||||||
HASHMAP<std::string, arg_data_t> data;
|
HASHMAP <std::string, arg_data_t> data;
|
||||||
|
|
||||||
inline arg_data_t& operator[](const std::string& key)
|
inline arg_data_t& operator[](const std::string& key)
|
||||||
{
|
{
|
||||||
|
@ -296,8 +311,11 @@ namespace blt
|
||||||
}
|
}
|
||||||
} loaded_args;
|
} loaded_args;
|
||||||
|
|
||||||
|
bool help_disabled = false;
|
||||||
|
std::string help_inclusion;
|
||||||
private:
|
private:
|
||||||
static std::string getMetavar(const arg_properties_t* const& arg);
|
static std::string getMetavar(const arg_properties_t* const& arg);
|
||||||
|
|
||||||
static std::string getFlagHelp(const arg_properties_t* const& arg);
|
static std::string getFlagHelp(const arg_properties_t* const& arg);
|
||||||
|
|
||||||
static bool takesArgs(const arg_properties_t* const& arg);
|
static bool takesArgs(const arg_properties_t* const& arg);
|
||||||
|
@ -311,7 +329,7 @@ namespace blt
|
||||||
// expects that the current flag has already been consumed (advanced past), leaves tokenizer in a state where the next element is 'current'
|
// expects that the current flag has already been consumed (advanced past), leaves tokenizer in a state where the next element is 'current'
|
||||||
bool consumeArguments(
|
bool consumeArguments(
|
||||||
arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t& properties, std::vector<arg_data_internal_t>& v_out
|
arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t& properties, std::vector<arg_data_internal_t>& v_out
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
void handlePositionalArgument(arg_tokenizer& tokenizer, size_t& last_pos);
|
void handlePositionalArgument(arg_tokenizer& tokenizer, size_t& last_pos);
|
||||||
|
|
||||||
|
@ -319,6 +337,8 @@ namespace blt
|
||||||
|
|
||||||
void processFlag(arg_tokenizer& tokenizer, const std::string& flag);
|
void processFlag(arg_tokenizer& tokenizer, const std::string& flag);
|
||||||
|
|
||||||
|
void handleFlag(arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t* properties);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -398,6 +418,11 @@ namespace blt
|
||||||
user_args.max_line_length = size;
|
user_args.max_line_length = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void setHelpExtras(std::string str)
|
||||||
|
{
|
||||||
|
help_inclusion = std::move(str);
|
||||||
|
}
|
||||||
|
|
||||||
static std::string filename(const std::string& path);
|
static std::string filename(const std::string& path);
|
||||||
|
|
||||||
~arg_parse()
|
~arg_parse()
|
||||||
|
|
|
@ -13,6 +13,13 @@
|
||||||
|
|
||||||
namespace blt::fs
|
namespace blt::fs
|
||||||
{
|
{
|
||||||
|
class path
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::vector<std::string> paths;
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple interface which provides a way of reading the next block of data from a resource.
|
* A simple interface which provides a way of reading the next block of data from a resource.
|
||||||
|
@ -102,7 +109,8 @@ namespace blt::fs
|
||||||
|
|
||||||
int read(char* buffer, size_t bytes) override;
|
int read(char* buffer, size_t bytes) override;
|
||||||
|
|
||||||
size_t gcount() final {
|
size_t gcount() final
|
||||||
|
{
|
||||||
return m_stream.gcount();
|
return m_stream.gcount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,20 @@
|
||||||
#ifndef BLT_HASH_MAP_H
|
#ifndef BLT_HASH_MAP_H
|
||||||
#define BLT_HASH_MAP_H
|
#define BLT_HASH_MAP_H
|
||||||
|
|
||||||
|
namespace blt
|
||||||
|
{
|
||||||
|
|
||||||
|
// template<typename K, typename V, typename Hash = std::hash<K>, typename Eq = std::equal_to<K>>
|
||||||
|
// class hashmap
|
||||||
|
// {
|
||||||
|
// private:
|
||||||
|
//
|
||||||
|
// public:
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef HASHMAP
|
#ifndef HASHMAP
|
||||||
#if defined __has_include && __has_include(<parallel_hashmap/phmap.h>)
|
#if defined __has_include && __has_include(<parallel_hashmap/phmap.h>)
|
||||||
|
|
||||||
|
|
|
@ -11,39 +11,79 @@
|
||||||
#ifndef BLT_TIME_H
|
#ifndef BLT_TIME_H
|
||||||
#define BLT_TIME_H
|
#define BLT_TIME_H
|
||||||
|
|
||||||
namespace blt::system {
|
namespace blt::system
|
||||||
static inline std::string ensureHasDigits(int current, int digits) {
|
{
|
||||||
|
static inline std::string ensureHasDigits(int current, int digits)
|
||||||
|
{
|
||||||
std::string asString = std::to_string(current);
|
std::string asString = std::to_string(current);
|
||||||
auto length = digits - asString.length();
|
auto length = digits - asString.length();
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
return asString;
|
return asString;
|
||||||
std::string zeros;
|
std::string zeros;
|
||||||
zeros.reserve(length);
|
zeros.reserve(length);
|
||||||
for (unsigned int i = 0; i < length; i++){
|
for (unsigned int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
zeros += '0';
|
zeros += '0';
|
||||||
}
|
}
|
||||||
return zeros + asString;
|
return zeros + asString;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline auto getCurrentTimeNanoseconds() {
|
static inline auto getCurrentTimeNanoseconds()
|
||||||
|
{
|
||||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline auto nanoTime() {
|
static inline auto nanoTime()
|
||||||
|
{
|
||||||
return getCurrentTimeNanoseconds();
|
return getCurrentTimeNanoseconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline auto getCurrentTimeMilliseconds(){
|
static inline auto getCurrentTimeMilliseconds()
|
||||||
|
{
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline auto getCPUThreadTime()
|
||||||
|
{
|
||||||
|
#ifdef unix
|
||||||
|
timespec time{};
|
||||||
|
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time);
|
||||||
|
return time.tv_nsec;
|
||||||
|
#else
|
||||||
|
return std::clock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline auto getCPUTime()
|
||||||
|
{
|
||||||
|
#ifdef unix
|
||||||
|
timespec time{};
|
||||||
|
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
|
||||||
|
return time.tv_nsec;
|
||||||
|
#else
|
||||||
|
return std::clock();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline auto getCPUTimerResolution()
|
||||||
|
{
|
||||||
|
#ifdef unix
|
||||||
|
timespec res{};
|
||||||
|
clock_getres(CLOCK_PROCESS_CPUTIME_ID, &res);
|
||||||
|
return res.tv_nsec;
|
||||||
|
#else
|
||||||
|
return CLOCKS_PER_SECOND;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard time string is formatted as follows:
|
* Standard time string is formatted as follows:
|
||||||
* Year-Month-Date Hour:Min:Second
|
* Year-Month-Date Hour:Min:Second
|
||||||
* If you do not want a space in the string use getTimeStringFS(); (Time String for easy filesystem)
|
* If you do not want a space in the string use getTimeStringFS(); (Time String for easy filesystem)
|
||||||
* @return the BLT standard string of time.now
|
* @return the BLT standard string of time.now
|
||||||
*/
|
*/
|
||||||
static inline std::string getTimeString() {
|
static inline std::string getTimeString()
|
||||||
|
{
|
||||||
auto t = std::time(nullptr);
|
auto t = std::time(nullptr);
|
||||||
auto now = std::localtime(&t);
|
auto now = std::localtime(&t);
|
||||||
std::stringstream timeString;
|
std::stringstream timeString;
|
||||||
|
@ -66,7 +106,8 @@ namespace blt::system {
|
||||||
* Hour:Min:Second
|
* Hour:Min:Second
|
||||||
* @return the BLT standard logging string of time.now
|
* @return the BLT standard logging string of time.now
|
||||||
*/
|
*/
|
||||||
static inline std::string getTimeStringLog() {
|
static inline std::string getTimeStringLog()
|
||||||
|
{
|
||||||
auto t = std::time(nullptr);
|
auto t = std::time(nullptr);
|
||||||
auto now = std::localtime(&t);
|
auto now = std::localtime(&t);
|
||||||
std::string timeString = "[";
|
std::string timeString = "[";
|
||||||
|
@ -82,7 +123,8 @@ namespace blt::system {
|
||||||
/**
|
/**
|
||||||
* @return the BLT standard string of time.now (See getTimeString()) that is filesystem friendly (FAT compatible).
|
* @return the BLT standard string of time.now (See getTimeString()) that is filesystem friendly (FAT compatible).
|
||||||
*/
|
*/
|
||||||
static inline std::string getTimeStringFS() {
|
static inline std::string getTimeStringFS()
|
||||||
|
{
|
||||||
auto t = std::time(nullptr);
|
auto t = std::time(nullptr);
|
||||||
auto now = std::localtime(&t);
|
auto now = std::localtime(&t);
|
||||||
std::stringstream timeString;
|
std::stringstream timeString;
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace blt
|
||||||
name = str;
|
name = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string arg_vector_t::getFirstFullFlag()
|
std::string arg_vector_t::getFirstFullFlag() const
|
||||||
{
|
{
|
||||||
// assign flag so it always exists, will be first '-' flag if we fail to find a '--' flag
|
// assign flag so it always exists, will be first '-' flag if we fail to find a '--' flag
|
||||||
std::string flag = flags[0];
|
std::string flag = flags[0];
|
||||||
|
@ -156,7 +156,7 @@ namespace blt
|
||||||
|
|
||||||
bool arg_parse::consumeArguments(
|
bool arg_parse::consumeArguments(
|
||||||
arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t& properties, std::vector<arg_data_internal_t>& v_out
|
arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t& properties, std::vector<arg_data_internal_t>& v_out
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
switch (properties.a_nargs.flags)
|
switch (properties.a_nargs.flags)
|
||||||
{
|
{
|
||||||
|
@ -231,8 +231,26 @@ namespace blt
|
||||||
loaded_args.unrecognized_args.push_back(tokenizer.get());
|
loaded_args.unrecognized_args.push_back(tokenizer.get());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
loaded_args.data[user_args.name_associations[index]->a_dest] = tokenizer.get();
|
bool found = false;
|
||||||
loaded_args.found_args.insert(user_args.name_associations[index]->a_dest);
|
for (const auto& pos_properties : user_args.name_associations)
|
||||||
|
{
|
||||||
|
const auto& flag = tokenizer.get();
|
||||||
|
if (pos_properties->a_flags.contains(flag))
|
||||||
|
{
|
||||||
|
tokenizer.advance();
|
||||||
|
handleFlag(tokenizer, flag, pos_properties);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
const auto& arg_property = user_args.name_associations[index];
|
||||||
|
if (arg_property->a_disable_help)
|
||||||
|
help_disabled = true;
|
||||||
|
loaded_args.data[arg_property->a_dest] = tokenizer.get();
|
||||||
|
loaded_args.found_args.insert(arg_property->a_dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tokenizer.advance();
|
tokenizer.advance();
|
||||||
}
|
}
|
||||||
|
@ -282,6 +300,11 @@ namespace blt
|
||||||
|
|
||||||
const auto* const properties = user_args.flag_associations.at(flag);
|
const auto* const properties = user_args.flag_associations.at(flag);
|
||||||
|
|
||||||
|
handleFlag(tokenizer, flag, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arg_parse::handleFlag(arg_tokenizer& tokenizer, const std::string& flag, const arg_properties_t* properties)
|
||||||
|
{
|
||||||
if (properties->a_dest.empty())
|
if (properties->a_dest.empty())
|
||||||
{
|
{
|
||||||
loaded_args.unrecognized_args.push_back(flag);
|
loaded_args.unrecognized_args.push_back(flag);
|
||||||
|
@ -291,6 +314,9 @@ namespace blt
|
||||||
|
|
||||||
loaded_args.found_args.insert(dest);
|
loaded_args.found_args.insert(dest);
|
||||||
|
|
||||||
|
if (properties->a_disable_help)
|
||||||
|
help_disabled = true;
|
||||||
|
|
||||||
switch (properties->a_action)
|
switch (properties->a_action)
|
||||||
{
|
{
|
||||||
case arg_action_t::HELP:
|
case arg_action_t::HELP:
|
||||||
|
@ -438,6 +464,8 @@ namespace blt
|
||||||
|
|
||||||
void arg_parse::printHelp() const
|
void arg_parse::printHelp() const
|
||||||
{
|
{
|
||||||
|
if (help_disabled)
|
||||||
|
return;
|
||||||
if (!user_args.prefix.empty())
|
if (!user_args.prefix.empty())
|
||||||
{
|
{
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
|
@ -452,7 +480,8 @@ namespace blt
|
||||||
{
|
{
|
||||||
if (!arg->a_flags.isFlag())
|
if (!arg->a_flags.isFlag())
|
||||||
max_length = std::max(arg->a_flags.name.size(), max_length);
|
max_length = std::max(arg->a_flags.name.size(), max_length);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
auto tmp = getFlagHelp(arg);
|
auto tmp = getFlagHelp(arg);
|
||||||
max_length = std::max(tmp.size(), max_length);
|
max_length = std::max(tmp.size(), max_length);
|
||||||
}
|
}
|
||||||
|
@ -495,7 +524,9 @@ namespace blt
|
||||||
|
|
||||||
void arg_parse::printUsage() const
|
void arg_parse::printUsage() const
|
||||||
{
|
{
|
||||||
std::string usage = "Usage: " + filename(loaded_args.program_name) + " ";
|
if (help_disabled)
|
||||||
|
return;
|
||||||
|
std::string usage = "Usage: " + filename(loaded_args.program_name) + " " + help_inclusion + " ";
|
||||||
std::cout << usage;
|
std::cout << usage;
|
||||||
size_t current_line_length = 0;
|
size_t current_line_length = 0;
|
||||||
|
|
||||||
|
@ -566,7 +597,7 @@ namespace blt
|
||||||
}
|
}
|
||||||
tmp += ", ";
|
tmp += ", ";
|
||||||
}
|
}
|
||||||
tmp = tmp.substr(0, tmp.size()-2);
|
tmp = tmp.substr(0, tmp.size() - 2);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue