Skip to content

Commit

Permalink
Merge branch 'feature/dynamic_runtree_and_argparse' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
marciovmf committed Oct 26, 2024
2 parents 0645730 + d6859c6 commit 788b1c4
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 18 deletions.
9 changes: 0 additions & 9 deletions demo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,3 @@ target_compile_definitions(demo PRIVATE
$<$<BOOL:${OPTION_BUILD_EDITOR}>:LDK_EDITOR>
$<$<BOOL:${OPTION_LDKSHAREDLIB}>:LDK_SHAREDLIB>
)

add_custom_command(
TARGET demo POST_BUILD
COMMAND ${CMAKE_COMMAND} -E remove "${OUTPUT_DIR}/assets/"
COMMAND ${CMAKE_COMMAND} -E remove "${OUTPUT_DIR}/ldk.cfg"
COMMAND ${CMAKE_COMMAND} -E create_symlink "${RUNTREE_DIR}/assets/" "${OUTPUT_DIR}/assets/"
COMMAND ${CMAKE_COMMAND} -E create_symlink "${RUNTREE_DIR}/ldk.cfg" "${OUTPUT_DIR}/ldk.cfg"
)

2 changes: 1 addition & 1 deletion demo/demo_mixed_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Mixed approach
int mixedModeApplication()
{
ldkEngineInitialize();
ldkEngineInitialize("../../runtree");
ldkGraphicsViewportTitleSet("LDK");
ldkGraphicsViewportIconSet("assets/ldk.ico");

Expand Down
21 changes: 19 additions & 2 deletions demo/main.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "argparse.h"
#include "asset/config.h"
#include "asset/material.h"
#include "asset/mesh.h"
Expand Down Expand Up @@ -352,11 +353,27 @@ bool onUpdate(const LDKEvent* event, void* data)
return true;
}

int main(void)
int main(int32 argc, char** argv)
{
// Parse command line arguments
LDKArgParser parser = {0};
ldkArgAddArgument(&parser, "--help", LDK_ARG_TYPE_FLAG, "Display this help message");
ldkArgAddArgument(&parser, "--runtree", LDK_ARG_TYPE_STRING, "Path to game runtree directory");
ldkArgParseArguments(&parser, argc, argv);
if (ldkArgGetFlagValue(&parser, "--help"))
{
ldkArgPrintUsage(&parser);
return 0;
}

const char* cmdLineRunTree = ldkArgGetStringValue(&parser, "--runtree");
if (cmdLineRunTree == NULL)
cmdLineRunTree = "../../runtree/";

// Initialize stuff
GameState state = {0};
ldkEngineInitialize();

ldkEngineInitialize(cmdLineRunTree);

// Bind events
ldkEventHandlerAdd(onKeyboardEvent, LDK_EVENT_TYPE_KEYBOARD, (void*) &state);
Expand Down
88 changes: 88 additions & 0 deletions include/ldk/argparse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* argparse.h
*
* A very simple Command-Line argument parser
*
* Features:
* - Define expected command-line arguments with types and descriptions.
* - Parse command-line input and automatically recognize flags and their associated values.
* - Generate usage information based on argument descriptions for user guidance.
* - Provides safe mechanisms to access argument values while preventing buffer overflows.
*
* Usage:
* 1. Initialize the argument parser using ldkArgInitParser.
* 2. Add expected arguments with ldkArgAddArgument.
* 3. Parse command-line arguments using ldkArgParseArguments.
* 4. Access argument values with the corresponding retrieval functions.
* 5. Print usage information with ldkArgPrintUsage when needed.
* 6. Iterate over found arguments using ldkArgForEachArgument.
*
*
* Limitations:
* - The number of arguments is intentionally fixed and determined at compile time.
* - Currently, no dynamic memory management is implemented as arguments are stored in
* a statically allocated array.
* - The size of the array is defined by the macro LDK_ARGPARSE_MAX_ARGS. The
* default value is 8. In case a larger value is needed, please define the
* macro with the required value before including this header.
*/

#ifndef LDK_ARGPARSE_H
#define LDK_ARGPARSE_H

#include <stdbool.h>
#include "common.h"

#define LDK_ARGPARSE_MAX_ARGS_DEFAULT 8

#ifndef LDK_ARGPARSE_MAX_ARGS
#define LDK_ARGPARSE_MAX_ARGS LDK_ARGPARSE_MAX_ARGS_DEFAULT
#endif

#ifdef __cplusplus
extern "C"
{
#endif

typedef enum
{
LDK_ARG_TYPE_FLAG,
LDK_ARG_TYPE_INT,
LDK_ARG_TYPE_STRING
} LDKArgType;

typedef struct
{
const char *name;
LDKArgType type;
const char *description;
char *stringValue;
bool isFound;
union
{
bool flagValue;
int32 intValue;
};
} LDKArgument;

typedef struct
{
LDKArgument args[LDK_ARGPARSE_MAX_ARGS];
uint32 argCount;
} LDKArgParser;

LDK_API void ldkArgInitParser(LDKArgParser* parser);
LDK_API void ldkArgAddArgument(LDKArgParser* parser, const char* name, LDKArgType type, const char* description);
LDK_API void ldkArgParseArguments(LDKArgParser* parser, uint32 argc, char* argv[]);
LDK_API void ldkArgPrintUsage(const LDKArgParser* parser);
LDK_API bool ldkArgGetFlagValue(const LDKArgParser* parser, const char* name);
LDK_API int32 ldkArgGetIntValue(const LDKArgParser* parser, const char* name);
LDK_API const char* ldkArgGetStringValue(const LDKArgParser* parser, const char* name);
LDK_API void ldkArgForEachArgument(const LDKArgParser* parser, void (*callback)(const LDKArgument* arg));

#ifdef __cplusplus
}
#endif

#endif //LDK_ARGPARSE_H

37 changes: 34 additions & 3 deletions include/ldk/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,44 @@
extern "C" {
#endif
LDK_API void ldkEngineSetTimeScale(float scale);
LDK_API float ldkEngineGetTimeScale();
/**
* ldkEngineInitialize
*
* The engie will change it's current working directory (CWD) to the runtreeDir then
* loads the ldk.cfg file and Initializes the engine and all subsystems.
*
* @param runtreeDir Path to the runtree directory. If NULL, the CWD is not changed.
* @return Returns true in case of sucessfull initialization of all engine subsystems or false if any initialization fails.
*/
LDK_API bool ldkEngineInitialize(const char* runtreeDir);

LDK_API bool ldkEngineInitialize(void);

/**
* ldkEngineTerminate
* Terminates all subsystems and clean resources.
*/
LDK_API void ldkEngineTerminate(void);


/**
* ldkEngineRun
*
* Runs the engine main loop. It serves as the a core function to manage the
* main loop of a game or application by handling events, rendering and
* updating application state.
* This function blocks execution of the main thread.
*
* @return Returns the the exit status of the application.
*/
LDK_API int32 ldkEngineRun(void);

/**
* ldkEngineStop
*
* ldkEngineStop is used to force ldkEngineRun to stop and return.
*/
LDK_API void ldkEngineStop(int32);

#ifdef LDK_EDITOR
LDK_API bool ldkEngineIsEditorRunning(void);
#endif
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ list(APPEND SOURCE
# Core
${INCLUDE_DIR}/ldk.h
${INCLUDE_DIR}/os.h
${INCLUDE_DIR}/argparse.h argparse.c
${INCLUDE_DIR}/gl.h gl.c
${INCLUDE_DIR}/maths.h maths.c
${INCLUDE_DIR}/arena.h arena.c
Expand Down
175 changes: 175 additions & 0 deletions src/argparse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#include "ldk/argparse.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


void ldkArgInitParser(LDKArgParser *parser)
{
parser->argCount = 0;
memset(parser->args, 0, LDK_ARGPARSE_MAX_ARGS * sizeof(LDKArgument));
}


void ldkArgAddArgument(LDKArgParser *parser, const char *name, LDKArgType type, const char *description)
{
if (parser->argCount < LDK_ARGPARSE_MAX_ARGS)
{
LDKArgument *arg = &parser->args[parser->argCount++];
arg->name = name;
arg->type = type;
arg->description = description;
arg->isFound = false; // Newly added argument is not found yet
} else
{
fprintf(stderr, "Error: Maximum number of arguments reached (%d)\n", LDK_ARGPARSE_MAX_ARGS);
exit(EXIT_FAILURE); // Exit if trying to add too many arguments
}
}


void ldkArgPrintUsage(const LDKArgParser *parser)
{
printf("Usage:\n");
for (uint32 i = 0; i < parser->argCount; i++)
{
const LDKArgument *arg = &parser->args[i];

printf(" %s", arg->name);

int spacesToAlign = 24 - (int)strlen(arg->name);
if (spacesToAlign > 0)
{
printf("%*s", spacesToAlign, " ");
}

printf("%s\n", arg->description);
}
}


void ldkArgParseArguments(LDKArgParser *parser, uint32 argc, char *argv[])
{
for (uint32 i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
{
// Display usage message and exit if -h or --help is encountered
ldkArgPrintUsage(parser);
exit(0);
}

// Parse other arguments
for (uint32 j = 0; j < parser->argCount; j++)
{
LDKArgument *arg = &parser->args[j];
if (strcmp(argv[i], arg->name) == 0)
{
arg->isFound = true; // Mark the argument as found
switch (arg->type)
{
case LDK_ARG_TYPE_FLAG:
arg->flagValue = true;
break;
case LDK_ARG_TYPE_INT:
if (i + 1 < argc)
{
arg->intValue = atoi(argv[++i]);
}
break;
case LDK_ARG_TYPE_STRING:
if (i + 1 < argc)
{
arg->stringValue = argv[++i];
}
break;
}
}
}
}
}


bool ldkArgGetFlagValue(const LDKArgParser *parser, const char *name)
{
for (uint32 i = 0; i < parser->argCount; i++)
{
if (strcmp(parser->args[i].name, name) == 0 && parser->args[i].type == LDK_ARG_TYPE_FLAG)
{
return parser->args[i].flagValue;
}
}
return false;
}


int32 ldkArgGetIntValue(const LDKArgParser *parser, const char *name)
{
for (uint32 i = 0; i < parser->argCount; i++)
{
if (strcmp(parser->args[i].name, name) == 0 && parser->args[i].type == LDK_ARG_TYPE_INT)
{
return parser->args[i].intValue;
}
}
return 0;
}


const char* ldkArgGetStringValue(const LDKArgParser *parser, const char *name)
{
for (uint32 i = 0; i < parser->argCount; i++)
{
if (strcmp(parser->args[i].name, name) == 0 && parser->args[i].type == LDK_ARG_TYPE_STRING)
{
return parser->args[i].stringValue;
}
}
return NULL;
}


void ldkArgForEachArgument(const LDKArgParser *parser, void (*callback)(const LDKArgument *arg))
{
for (uint32 i = 0; i < parser->argCount; i++)
{
if (parser->args[i].isFound)
{
callback(&parser->args[i]);
}
}
}



/*
int32 main(int32 argc, char *argv[])
{
LDKArgParser parser;
ldkArgInitParser(&parser);
ldkArgAddArgument(&parser, "-flag", ARG_TYPE_FLAG, "A simple boolean flag");
ldkArgAddArgument(&parser, "-myIntValue", ARG_TYPE_INT, "An integer value for processing");
ldkArgAddArgument(&parser, "-myStringValue", ARG_TYPE_STRING, "A string input");
ldkArgParseArguments(&parser, argc, argv);
printf("Flag: %s\n", ldkArgGetFlagValue(&parser, "-flag") ? "true" : "false");
printf("Integer Value: %d\n", ldkArgGetIntValue(&parser, "-myIntValue"));
const char *stringValue = ldkArgGetStringValue(&parser, "-myStringValue");
printf("String Value: %s\n", stringValue ? stringValue : "(none)");
printf("\n--- Found Arguments ---\n");
ldkArgForEachArgument(&parser, printFoundArgument); // Print32each found argument
// Print32usage if no arguments were found
if (argc == 1)
{
ldkArgPrintUsage(&parser);
}
ldkArgFreeParser(&parser);
return 0;
}
*/
Loading

0 comments on commit 788b1c4

Please sign in to comment.