Skip to content

Commit

Permalink
Ready for 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Madman10K committed May 19, 2024
1 parent 118c427 commit 61bf5de
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 213 deletions.
2 changes: 1 addition & 1 deletion C/cucli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
extern "C"
{
#endif
#define to_class(data) ((UCLI::Parser*)data)
#define to_class(data) ((UCLI::Parser*)(data))

void UCLI_Parser_init(UCLI_Parser_Data* data)
{
Expand Down
297 changes: 107 additions & 190 deletions CLIParser.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
#include <cstring>
#include "CLIParser.hpp"
#ifdef UCLI_COMPILE_WITH_UTF_SUPPORT
#include "utf8cpp/utf8.h"
#endif
#include <span>

void UCLI::Parser::parse(int argc, char** argv,
UCLI_Parser_ArrayFlag* arrayFlags, size_t arrayFlagsSize,
UCLI_Parser_BooleanFlag* booleanFlags, size_t booleanFlagsSize,
UCLI_Parser_BooleanFlagWithFunc* booleanFlagsWithFunc, size_t booleanFlagsWithFuncSize,
UCLI_Parser_Pair* pairs, size_t pairsSize,
UCLI_Parser_PairWithFunc* pairsWithFunc, size_t pairsWithFuncSize) noexcept
ArrayFlag* arrayFlags, size_t arrayFlagsSize,
BooleanFlag* booleanFlags, size_t booleanFlagsSize,
BooleanFlagWithFunc* booleanFlagsWithFunc, size_t booleanFlagsWithFuncSize,
Pair* pairs, size_t pairsSize,
PairWithFunc* pairsWithFunc, size_t pairsWithFuncSize) noexcept
{
std::string tmp;

std::u32string singleCharU32;
singleCharU32.resize(1);

std::string singleChar;
singleChar.resize(1);

Expand Down Expand Up @@ -44,7 +39,10 @@ void UCLI::Parser::parse(int argc, char** argv,
pairs, pairsSize,
pairsWithFunc, pairsWithFuncSize, true);
else
parseShortArgument(currentArray, singleChar, singleCharU32, tmp, arrayFlags, arrayFlagsSize, booleanFlags, booleanFlagsSize, booleanFlagsWithFunc, booleanFlagsWithFuncSize);
parseShortArgument(currentArray, singleChar, tmp,
arrayFlags, arrayFlagsSize,
booleanFlags, booleanFlagsSize,
booleanFlagsWithFunc, booleanFlagsWithFuncSize);
}
}
else
Expand All @@ -54,7 +52,7 @@ void UCLI::Parser::parse(int argc, char** argv,
data.currentArrayFlag->func(data.currentArrayFlag, currentArray.data(), currentArray.size());
}

void UCLI::Parser::setDefaultArray(void* additionalData, UCLI_Parser_ArrayFlagFunc func) noexcept
void UCLI::Parser::setDefaultArray(void* additionalData, ArrayFlagFunc func) noexcept
{
data.defaultArrayFlag.additionalData = additionalData;
data.defaultArrayFlag.func = func;
Expand All @@ -70,7 +68,7 @@ void UCLI::Parser::setArgumentStyleWindows(bool bWindows) noexcept
data.bWindowsStyle = bWindows;
}

void UCLI::Parser::setUnknownArgumentCallback(UCLI_Parser_UnknownArgumentsCallback func, void* callbackData) noexcept
void UCLI::Parser::setUnknownArgumentCallback(UnknownArgumentsCallback func, void* callbackData) noexcept
{
data.unknownArgumentsCallback = func;
data.unknownArgumentsCallbackAdditionalData = callbackData;
Expand All @@ -87,7 +85,7 @@ void UCLI::Parser::init() noexcept
.longType = "",
.shortType = "",
.additionalData = nullptr,
.func = [](UCLI_Parser_ArrayFlag*, char**, size_t) -> void {},
.func = [](ArrayFlag*, char**, size_t) -> void {},
};
}

Expand All @@ -96,223 +94,142 @@ UCLI::Parser::Parser() noexcept
init();
}

void UCLI::Parser::parseShortArgument(std::vector<char*>& args, std::string& singleChar, std::u32string& singleCharU32, const std::string& tmp,
UCLI_Parser_ArrayFlag* arrayFlags, size_t arrayFlagsSize,
UCLI_Parser_BooleanFlag* booleanFlags, size_t booleanFlagsSize,
UCLI_Parser_BooleanFlagWithFunc* booleanFlagsWithFunc, size_t booleanFlagsWithFuncSize) noexcept
{
#ifdef UCLI_COMPILE_WITH_UTF_SUPPORT
utf8::iterator begin(tmp.begin() + 1, tmp.begin() + 1, tmp.end());
utf8::iterator end(tmp.end(), tmp.begin() + 1, tmp.end());

for (auto f = begin; f != end; ++f)
{
singleCharU32[0] = *f;

if (booleanFlags != nullptr)
{
for (size_t t = 0; t < booleanFlagsSize; t++)
{
auto& a = booleanFlags[t];
if (a.shortType == utf8::utf32to8(singleCharU32))
{
if (data.bFlipBool)
*a.flag = !*a.flag;
else
*a.flag = true;
goto continue_from_single_flag_inner_loops;
}
}
}
if (booleanFlagsWithFunc != nullptr)
{
for (size_t t = 0; t < booleanFlagsWithFuncSize; t++)
{
auto& a = booleanFlagsWithFunc[t];
if (a.shortType == utf8::utf32to8(singleCharU32))
{
a.func(&a);
goto continue_from_single_flag_inner_loops;
}
}
}
if (arrayFlags != nullptr)
{
for (size_t i = 0; i < arrayFlagsSize; i++)
{
if (arrayFlags[i].shortType == utf8::utf32to8(singleCharU32))
{
data.currentArrayFlag->func(data.currentArrayFlag, args.data(), args.size());
args.clear();
#define FOR_EACH_WITH_CHECK(x, y, z, w) if ((x) != nullptr) for (auto& (z) : std::span(x, y)) w

data.currentArrayFlag = &arrayFlags[i];
goto continue_from_single_flag_inner_loops;
}
}
}
data.unknownArgumentsCallback(utf8::utf32to8(singleCharU32).c_str(), data.unknownArgumentsCallbackAdditionalData);
continue_from_single_flag_inner_loops:;
}
#else
void UCLI::Parser::parseShortArgument(std::vector<char*>& args, std::string& singleChar, const std::string& tmp,
ArrayFlag* arrayFlags, size_t arrayFlagsSize,
BooleanFlag* booleanFlags, size_t booleanFlagsSize,
BooleanFlagWithFunc* booleanFlagsWithFunc, size_t booleanFlagsWithFuncSize) noexcept
{
for (size_t f = 1; f < tmp.size(); f++)
{
singleChar[0] = tmp[f];

if (booleanFlags != nullptr)
{
for (size_t t = 0; t < booleanFlagsSize; t++)
FOR_EACH_WITH_CHECK(booleanFlags, booleanFlagsSize, a, {
if (a.shortType == singleChar)
{
auto& a = booleanFlags[t];
if (a.shortType == singleChar)
{
if (data.bFlipBool)
*a.flag = !*a.flag;
else
*a.flag = true;
goto continue_from_single_flag_inner_loops;
}
if (data.bFlipBool)
*a.flag = !*a.flag;
else
*a.flag = true;
goto continue_from_single_flag_inner_loops;
}
}
if (booleanFlagsWithFunc != nullptr)
{
for (size_t t = 0; t < booleanFlagsWithFuncSize; t++)
});
FOR_EACH_WITH_CHECK(booleanFlagsWithFunc, booleanFlagsWithFuncSize, a, {
if (a.shortType == singleChar)
{
auto& a = booleanFlagsWithFunc[t];
if (a.shortType == singleChar)
{
a.func(&a);
goto continue_from_single_flag_inner_loops;
}
a.func(&a);
goto continue_from_single_flag_inner_loops;
}
}
if (arrayFlags != nullptr)
{
for (size_t i = 0; i < arrayFlagsSize; i++)
});
FOR_EACH_WITH_CHECK(arrayFlags, arrayFlagsSize, a, {
if (singleChar == a.shortType)
{
if (singleChar == arrayFlags[i].shortType)
{
data.currentArrayFlag->func(data.currentArrayFlag, args.data(), args.size());
args.clear();
data.currentArrayFlag->func(data.currentArrayFlag, args.data(), args.size());
args.clear();

data.currentArrayFlag = &arrayFlags[i];
goto continue_from_single_flag_inner_loops;
}
data.currentArrayFlag = &a;
goto continue_from_single_flag_inner_loops;
}
}
});
data.unknownArgumentsCallback(singleChar.c_str(), data.unknownArgumentsCallbackAdditionalData);
continue_from_single_flag_inner_loops:;
}
#endif
}

void UCLI::Parser::parseLongArgument(std::vector<char*>& args, uint8_t frontTruncate, std::string& tmp,
UCLI_Parser_ArrayFlag* arrayFlags, size_t arrayFlagsSize,
UCLI_Parser_BooleanFlag* booleanFlags, size_t booleanFlagsSize,
UCLI_Parser_BooleanFlagWithFunc* booleanFlagsWithFunc, size_t booleanFlagsWithFuncSize,
UCLI_Parser_Pair* pairs, size_t pairsSize,
UCLI_Parser_PairWithFunc* pairsWithFunc, size_t pairsWithFuncSize, bool bCheckShort) noexcept
ArrayFlag* arrayFlags, size_t arrayFlagsSize,
BooleanFlag* booleanFlags, size_t booleanFlagsSize,
BooleanFlagWithFunc* booleanFlagsWithFunc, size_t booleanFlagsWithFuncSize,
Pair* pairs, size_t pairsSize,
PairWithFunc* pairsWithFunc, size_t pairsWithFuncSize, bool bCheckShort) noexcept
{
std::string currentTmp = tmp;
currentTmp.erase(0, frontTruncate);
std::string currentTmp = tmp.substr(0, frontTruncate);

if (booleanFlags != nullptr)
{
for (size_t t = 0; t < booleanFlagsSize; t++)
FOR_EACH_WITH_CHECK(booleanFlags, booleanFlagsSize, a, {
if (a.longType == currentTmp)
{
auto& a = booleanFlags[t];
if (a.longType == currentTmp)
{
if (data.bFlipBool)
*a.flag = !*a.flag;
else
*a.flag = true;
return;
}
if (data.bFlipBool)
*a.flag = !*a.flag;
else
*a.flag = true;
return;
}
}
if (booleanFlagsWithFunc != nullptr)
{
for (size_t t = 0; t < booleanFlagsWithFuncSize; t++)
});
FOR_EACH_WITH_CHECK(booleanFlagsWithFunc, booleanFlagsWithFuncSize, a, {
if (a.longType == currentTmp)
{
auto& a = booleanFlagsWithFunc[t];
if (a.longType == currentTmp)
{
a.func(&a);
return;
}
a.func(&a);
return;
}
}

if (pairs != nullptr)
{
for (size_t i = 0; i < pairsSize; i++)
});
FOR_EACH_WITH_CHECK(pairs, pairsSize, a, {
std::string it = a.longType;
a.InternalbFound = false;
// This is a valid pair
if (currentTmp.starts_with(it + "="))
{
std::string it = pairs[i].longType;
pairs[i].InternalbFound = false;
// This is a valid pair
if (currentTmp.starts_with(it + "="))
{
currentTmp.erase(0, it.length() + 1);
currentTmp.erase(0, it.length() + 1);

// Allocate memory for this
pairs[i].data = static_cast<const char*>(malloc(currentTmp.size()));
pairs[i].InternalbFound = true;
memcpy((void*)pairs[i].data, currentTmp.data(), currentTmp.size());
return;
}
// Allocate memory for this
a.data = static_cast<const char*>(malloc(currentTmp.size()));
a.InternalbFound = true;
memcpy((void*)a.data, currentTmp.data(), currentTmp.size());
return;
}
}


if (pairsWithFunc != nullptr)
{
for (size_t i = 0; i < pairsWithFuncSize; i++)
});
FOR_EACH_WITH_CHECK(pairsWithFunc, pairsWithFuncSize, a, {
std::string it = a.longType;
// This is a valid pair
if (currentTmp.starts_with(it + "="))
{
std::string it = pairsWithFunc[i].longType;
// This is a valid pair
if (currentTmp.starts_with(it + "="))
{
currentTmp.erase(0, it.length() + 1);
pairsWithFunc[i].func(&pairsWithFunc[i], currentTmp.c_str());
return;
}
currentTmp.erase(0, it.length() + 1);
a.func(&a, currentTmp.c_str());
return;
}
}

if (arrayFlags != nullptr)
{
for (size_t i = 0; i < arrayFlagsSize; i++)
});
FOR_EACH_WITH_CHECK(arrayFlags, arrayFlagsSize, a, {
if (currentTmp == a.longType || (bCheckShort && currentTmp == a.shortType))
{
if (currentTmp == arrayFlags[i].longType || (bCheckShort && currentTmp == arrayFlags[i].shortType))
{
data.currentArrayFlag->func(data.currentArrayFlag, args.data(), args.size());
args.clear();
data.currentArrayFlag->func(data.currentArrayFlag, args.data(), args.size());
args.clear();

data.currentArrayFlag = &arrayFlags[i];
return;
}
data.currentArrayFlag = &a;
return;
}
}
});

data.unknownArgumentsCallback(tmp.c_str(), data.unknownArgumentsCallbackAdditionalData);
}

void UCLI::Parser::cleanupPairs(UCLI_Parser_Pair* pairs, size_t pairsSize)
void UCLI::Parser::cleanupPairs(Pair* pairs, size_t pairsSize)
{
if (pairs != nullptr)
{
for (size_t i = 0; i < pairsSize; i++)
FOR_EACH_WITH_CHECK(pairs, pairsSize, a, {
if (a.InternalbFound)
{
if (pairs[i].InternalbFound)
{
free((void*)pairs[i].data);
pairs[i].InternalbFound = false;
}
free((void*)a.data);
a.InternalbFound = false;
}
}
})
}

void UCLI::Parser::setBooleanFlipping(bool bFlip) noexcept
{
data.bFlipBool = bFlip;
}

#define PASS_VECTOR(x, y) const_cast<x*>((y).data()), (y).size()

void UCLI::Parser::parse(int argc, char** argv, const std::vector<ArrayFlag>& arrayFlags,
const std::vector<BooleanFlag>& booleanFlags,
const std::vector<BooleanFlagWithFunc>& booleanFlagsWithFunc,
const std::vector<Pair>& pairs,
const std::vector<PairWithFunc>& pairsWithFunc) noexcept
{
parse(argc, argv,
PASS_VECTOR(ArrayFlag, arrayFlags),
PASS_VECTOR(BooleanFlag, booleanFlags),
PASS_VECTOR(BooleanFlagWithFunc, booleanFlagsWithFunc),
PASS_VECTOR(Pair, pairs),
PASS_VECTOR(PairWithFunc, pairsWithFunc));
}
Loading

0 comments on commit 61bf5de

Please sign in to comment.