This library uses c++20 consteval functions and python (partly generated using codex and github copilot) in order to generate Enums on the fly.
The main anticipated usage for this library is to allow faster logging for performance oriented client-server applications.
- Automatically generate Enum types and members on usage
- Provide a to_string function for each generated Enum type
- Each Enum member is calculated a hashed value based on its name - ensures better backwards compatibility(member order is irrelevant)
- Easy version control and backwards compatibility using git. (members deleted in source placed under
deprecated
tag until manual deletion)
Example usage:
main.cpp:
import enums; // auto generated on build
import enums_to_string; // auto generated on build
#include "LogE/StringToEnum.hpp"
using namespace loge;
LogEnum do_work()
{
// do some work
if(/*failure conditon*/){
return to_enum<LogEnum>("some_failure_status");
}
if(/*other failure conditon*/){
return to_enum<LogEnum>("other_failure_status");
}
return to_enum<LogEnum>("success_status");
}
int main()
{
LogEnum result = do_work();
if(result != LogEnum::success_status){
std::cout << LogEnum_to_string(result).c_str() << std::endl;
}
}
given this cmd-line as a pre-build event:
python $(SolutionDir)LogE\scripts\enum_generator.py -o $(ProjectDir)enums.ixx -m enums $(SolutionDir) .hpp,.cpp
these will be generated:
enums.ixx:
module;
#include <cstdint>
export module enums;
export enum class LogEnum : uint64_t {
// commit: c4279bc9
some_failure_status = 0xc668c49b3be6432e,
other_failure_status = 0x68c81e2f081370b9,
success_status = 0xfad661541767d1da,
};
to_string_enums.ixx:
module;
#include <string>
export module enums_to_string;
import enums;
export constexpr std::string_view LogEnum_to_string(LogEnum value) {
switch(value) {
case LogEnum::some_failure_status: return "some_failure_status";
case LogEnum::other_failure_status: return "other_failure_status";
case LogEnum::success_status: return "success_status";
default: return "";
}
}
};
enum_generator.py usage:
\LogE\scripts>python enum_generator.py -h
usage: enum_generator.py [-h] [-o OUTPUT_PATH] [-m MODULE_NAME] root_dir extensions
positional arguments:
root_dir Root directory to start the search from
extensions Comma separated list of file extensions to search for
optional arguments:
-h, --help show this help message and exit
-o OUTPUT_PATH, --output_path OUTPUT_PATH
Output file path
-m MODULE_NAME, --module-name MODULE_NAME
Module name
- note that the output file name you give will have
to_string_
appended to it for the second file(to_string_enums.ixx in the example) same is true for the module name.
The script will recursively iterate over all files and directories starting from the given root dir, it will only parse files ending with the given extensions. it will then uses this regex to find new enum types and members:
# regex to find to_enum<EnumType>(enum_member)
enum_regex = re.compile(r"to_enum<(\w+)>\(\"(\w+)\"\)")
- Using this for logging, you can send enum values (8 byte integers) over the network instead of costly strings.
- In addition the client application only needs the enums themselves and doesn't have to link with the to_string module, saving on size(if you have lots of logs) and hiding your log strings in case they are sensitive.
- For applications already using enums for logs this:
- reduces manual maintenance of large enum headers - auto generated based on usage in source code
- handles backwards compatibility and version control
- ensuring mis-matched clients and servers can still communicate using still-valid and deprecated values
As you can see in the example above, the enum generator script is git aware.
if you use git in your project any new enum value will be placed under the current commit.
should you delete an enum value (actually delete, commenting it won't be enough) it will not be immediately wiped from the generated module but will be placed under the depcricated
tag for backwards compatibility.
for instance:
module;
#include <cstdint>
export module enums;
export enum class LogEnum : uint64_t {
// commit: 21b89507
test_log = 0x817a1d5a33978dbb,
// commit: c4279bc9
success_status = 0xfad661541767d1da,
other_failure_status = 0x68c81e2f081370b9,
// commit: deprecated
some_failure_status = 0xc668c49b3be6432e,
};
- Support generating header versions
- Consider making StringToEnum.hpp a module too
- Flesh out LogE to better demonstrate the logger
Credits:
- sha256 compile time hash - https://github.com/aguinet/sha256_literal