Last active
October 24, 2023 15:45
-
-
Save battleguard/3197197d891c18c7ad251d6a745a1046 to your computer and use it in GitHub Desktop.
compile time conversion of global strings to snake case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <string_view> | |
#include "WsfPythonNaming.hpp" | |
void Foo() | |
{ | |
} | |
template <typename Func> | |
void def(const char* name_, Func&& f) | |
{ | |
std::cout << "def name= \"" << name_ << "\"\n"; | |
} | |
constexpr bool strings_equal(char const* a, char const* b) | |
{ | |
return std::string_view(a) == b; | |
} | |
constexpr bool strings_equal(std::string_view a, char const* b) | |
{ | |
return std::string_view(a) == b; | |
} | |
int main() | |
{ | |
using namespace wsf::python; | |
def("FooBarFooBar_FOO_BAR_FooFooFoo"_pyfunc, &Foo); | |
def("GetID"_pyfunc, &Foo); | |
def("GetId"_pyfunc, &Foo); | |
def("GetId_WSF"_pyfunc, &Foo); | |
def(PyFuncName("FooBarFooBar_FOO_BAR_FooFooFoo"), &Foo); | |
def(PyFuncName("GetID"), &Foo); | |
def(PyFuncName("GetId"), &Foo); | |
def(PyFuncName("GetId_WSF"), &Foo); | |
std::string comp = "Sensor"; | |
def(PyFuncName("Get" + comp), &Foo); | |
def("WsfStringId"_pyclass, &Foo); | |
def("UtStringId"_pyclass, &Foo); | |
def("StringId"_pyclass, &Foo); | |
def(PyClassName("WsfStringId"), &Foo); | |
def(PyClassName("UtStringId"), &Foo); | |
def(PyClassName("StringId"), &Foo); | |
def(PyClassName(("Wsf" + comp).c_str()), &Foo); | |
static_assert(strings_equal("UtStringId"_pyclass, "StringId"), "class"); | |
def("cENUM_NAME"_pyenum, &Foo); | |
def("cDEFAULT"_pyenum, &Foo); | |
def("FOO_ENUM"_pyenum, &Foo); | |
static_assert(strings_equal("cENUM_NAME"_pyenum, "ENUM_NAME"), "enum"); | |
def(PyEnumName("cENUM_NAME"), &Foo); | |
def(PyEnumName("cDEFAULT"), &Foo); | |
def(PyEnumName("FOO_ENUM"), &Foo); | |
def(PyEnumName(("cENUM_" + comp).c_str()), &Foo); | |
static_assert(strings_equal("GetID_Foo"_pyfunc, "get_id_foo"), "strings are equal"); | |
// static_assert(strings_equal("abc"_x2, "abcabc"), "strings are equal"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <string> | |
#include <string_view> | |
namespace wsf::python | |
{ | |
namespace details | |
{ | |
constexpr char charToLower(const char c) | |
{ | |
return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; | |
} | |
// see DoubleString example from https://en.cppreference.com/w/cpp/language/user_literal | |
template <std::size_t N> | |
struct SnakeCaseConstCharArr | |
{ | |
char result[N + N - 1]{}; | |
constexpr SnakeCaseConstCharArr(char const (&aInputCharArray)[N]) | |
{ | |
size_t idx = 0; | |
bool prevCharUpper = true; | |
for (std::size_t i = 0; i < N; i++) | |
{ | |
char curChar = aInputCharArray[i]; | |
const bool isCurCharUpper = curChar >= 'A' && curChar <= 'Z'; | |
if (isCurCharUpper) | |
{ | |
// handle GetID_Foo -> get_id_foo instead of get_i_d__foo | |
if (!prevCharUpper && result[idx - 1] != '_') | |
{ | |
result[idx++] = '_'; | |
} | |
curChar = charToLower(curChar); | |
} | |
prevCharUpper = isCurCharUpper; | |
result[idx++] = curChar; | |
} | |
result[idx] = '\0'; | |
} | |
}; | |
} | |
inline const char* PyFuncName(std::string_view aData) | |
{ | |
static std::string result; | |
result.clear(); | |
bool prevCharUpper = true; | |
for (char curChar : aData) | |
{ | |
const bool isCurCharUpper = curChar >= 'A' && curChar <= 'Z'; | |
if (isCurCharUpper) | |
{ | |
// handle GetID_Foo -> get_id_foo instead of get_i_d__foo | |
if (!prevCharUpper && result.back() != '_') | |
{ | |
result += '_'; | |
} | |
curChar = details::charToLower(curChar); | |
} | |
prevCharUpper = isCurCharUpper; | |
result += curChar; | |
} | |
return result.c_str(); | |
} | |
constexpr const char* PyClassName(const char* input) | |
{ | |
const auto sv = std::string_view(input); | |
for (const std::string_view prefix : { "Wsf", "Ut" }) | |
{ | |
if (sv.starts_with(prefix)) | |
{ | |
return input + prefix.length(); | |
} | |
} | |
return input; | |
} | |
constexpr const char* PyEnumName(const char* aName) | |
{ | |
if (aName[0] == 'c') | |
{ | |
return aName + 1; | |
} | |
return aName; | |
} | |
constexpr const char* PyConstantName(const char* aName) | |
{ | |
return PyEnumName(aName); | |
} | |
template <details::SnakeCaseConstCharArr A> | |
constexpr const char* operator""_pyfunc() | |
{ | |
return A.result; | |
} | |
constexpr const char* operator""_pyclass(const char* input, std::size_t N) | |
{ | |
return PyClassName(input); | |
} | |
constexpr const char* operator""_pyenum(const char* input, std::size_t N) | |
{ | |
return PyEnumName(input); | |
} | |
constexpr const char* operator""_pyconst(const char* input, std::size_t N) | |
{ | |
return PyConstantName(input); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment