forked from ground/ground
		
	Organisation, documentation, mathlib
This commit is contained in:
		
							
								
								
									
										193
									
								
								extlibs/request/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								extlibs/request/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
#ifndef GROUND_LIB_H
 | 
			
		||||
#define GROUND_LIB_H
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
// Ground types - must match the interpreter
 | 
			
		||||
typedef enum {
 | 
			
		||||
    GROUND_INT,
 | 
			
		||||
    GROUND_DOUBLE, 
 | 
			
		||||
    GROUND_BOOL,
 | 
			
		||||
    GROUND_STRING,
 | 
			
		||||
    GROUND_CHAR
 | 
			
		||||
} GroundType;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    GroundType type;
 | 
			
		||||
    union {
 | 
			
		||||
        int int_val;
 | 
			
		||||
        double double_val;
 | 
			
		||||
        int bool_val;
 | 
			
		||||
        char* string_val;
 | 
			
		||||
        char char_val;
 | 
			
		||||
    } data;
 | 
			
		||||
} GroundValue;
 | 
			
		||||
 | 
			
		||||
// Helper macros for creating GroundValue objects
 | 
			
		||||
#define GROUND_INT_VAL(x) ({ GroundValue v; v.type = GROUND_INT; v.data.int_val = (x); v; })
 | 
			
		||||
#define GROUND_DOUBLE_VAL(x) ({ GroundValue v; v.type = GROUND_DOUBLE; v.data.double_val = (x); v; })
 | 
			
		||||
#define GROUND_BOOL_VAL(x) ({ GroundValue v; v.type = GROUND_BOOL; v.data.bool_val = (x) ? 1 : 0; v; })
 | 
			
		||||
#define GROUND_CHAR_VAL(x) ({ GroundValue v; v.type = GROUND_CHAR; v.data.char_val = (x); v; })
 | 
			
		||||
 | 
			
		||||
// Helper function for creating string values
 | 
			
		||||
inline GroundValue ground_string_val(const std::string& str) {
 | 
			
		||||
    GroundValue v;
 | 
			
		||||
    v.type = GROUND_STRING;
 | 
			
		||||
    char* result_str = new char[str.length() + 1];
 | 
			
		||||
    std::strcpy(result_str, str.c_str());
 | 
			
		||||
    v.data.string_val = result_str;
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function for creating string values from C strings
 | 
			
		||||
inline GroundValue ground_cstring_val(const char* str) {
 | 
			
		||||
    GroundValue v;
 | 
			
		||||
    v.type = GROUND_STRING;
 | 
			
		||||
    if (str) {
 | 
			
		||||
        size_t len = std::strlen(str);
 | 
			
		||||
        char* result_str = new char[len + 1];
 | 
			
		||||
        std::strcpy(result_str, str);
 | 
			
		||||
        v.data.string_val = result_str;
 | 
			
		||||
    } else {
 | 
			
		||||
        v.data.string_val = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper macros for type checking
 | 
			
		||||
#define IS_INT(v) ((v).type == GROUND_INT)
 | 
			
		||||
#define IS_DOUBLE(v) ((v).type == GROUND_DOUBLE)
 | 
			
		||||
#define IS_BOOL(v) ((v).type == GROUND_BOOL)
 | 
			
		||||
#define IS_STRING(v) ((v).type == GROUND_STRING)
 | 
			
		||||
#define IS_CHAR(v) ((v).type == GROUND_CHAR)
 | 
			
		||||
 | 
			
		||||
// Helper macros for extracting values
 | 
			
		||||
#define GET_INT(v) ((v).data.int_val)
 | 
			
		||||
#define GET_DOUBLE(v) ((v).data.double_val)
 | 
			
		||||
#define GET_BOOL(v) ((v).data.bool_val != 0)
 | 
			
		||||
#define GET_STRING(v) ((v).data.string_val)
 | 
			
		||||
#define GET_CHAR(v) ((v).data.char_val)
 | 
			
		||||
 | 
			
		||||
// Helper macros for argument validation
 | 
			
		||||
#define REQUIRE_ARGS(count) \
 | 
			
		||||
    if (arg_count < (count)) { \
 | 
			
		||||
        std::cerr << "Error: Expected at least " << (count) << " arguments, got " << arg_count << std::endl; \
 | 
			
		||||
        return GROUND_BOOL_VAL(false); \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define REQUIRE_TYPE(arg_index, expected_type) \
 | 
			
		||||
    if (args[arg_index].type != expected_type) { \
 | 
			
		||||
        std::cerr << "Error: Argument " << (arg_index + 1) << " must be of type " << #expected_type << std::endl; \
 | 
			
		||||
        return GROUND_BOOL_VAL(false); \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// Convenience macro for checking both arg count and types
 | 
			
		||||
#define VALIDATE_ARGS_1(type1) \
 | 
			
		||||
    REQUIRE_ARGS(1); \
 | 
			
		||||
    REQUIRE_TYPE(0, type1);
 | 
			
		||||
 | 
			
		||||
#define VALIDATE_ARGS_2(type1, type2) \
 | 
			
		||||
    REQUIRE_ARGS(2); \
 | 
			
		||||
    REQUIRE_TYPE(0, type1); \
 | 
			
		||||
    REQUIRE_TYPE(1, type2);
 | 
			
		||||
 | 
			
		||||
#define VALIDATE_ARGS_3(type1, type2, type3) \
 | 
			
		||||
    REQUIRE_ARGS(3); \
 | 
			
		||||
    REQUIRE_TYPE(0, type1); \
 | 
			
		||||
    REQUIRE_TYPE(1, type2); \
 | 
			
		||||
    REQUIRE_TYPE(2, type3);
 | 
			
		||||
 | 
			
		||||
// Function registration helpers
 | 
			
		||||
class GroundLibrary {
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<std::string> function_names;
 | 
			
		||||
    std::vector<void*> function_pointers;
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
    void register_function(const std::string& name, void* ptr) {
 | 
			
		||||
        function_names.push_back(name);
 | 
			
		||||
        function_pointers.push_back(ptr);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    const char** get_function_names() {
 | 
			
		||||
        static std::vector<const char*> names;
 | 
			
		||||
        names.clear();
 | 
			
		||||
        for (const auto& name : function_names) {
 | 
			
		||||
            names.push_back(name.c_str());
 | 
			
		||||
        }
 | 
			
		||||
        names.push_back(nullptr);  // Null terminator
 | 
			
		||||
        return names.data();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void* get_function(const char* name) {
 | 
			
		||||
        for (size_t i = 0; i < function_names.size(); i++) {
 | 
			
		||||
            if (function_names[i] == name) {
 | 
			
		||||
                return function_pointers[i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Global library instance
 | 
			
		||||
extern GroundLibrary ground_lib_registry;
 | 
			
		||||
 | 
			
		||||
// Macro to register functions easily
 | 
			
		||||
#define REGISTER_GROUND_FUNCTION(func_name) \
 | 
			
		||||
    ground_lib_registry.register_function(#func_name, (void*)func_name)
 | 
			
		||||
 | 
			
		||||
// Macro to define the library interface
 | 
			
		||||
#define GROUND_LIBRARY_INTERFACE() \
 | 
			
		||||
    GroundLibrary ground_lib_registry; \
 | 
			
		||||
    extern "C" { \
 | 
			
		||||
        const char** ground_get_functions() { \
 | 
			
		||||
            return ground_lib_registry.get_function_names(); \
 | 
			
		||||
        } \
 | 
			
		||||
        void* ground_get_function(const char* name) { \
 | 
			
		||||
            return ground_lib_registry.get_function(name); \
 | 
			
		||||
        } \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// Optional initialization macro
 | 
			
		||||
#define GROUND_LIBRARY_INIT() \
 | 
			
		||||
    extern "C" { \
 | 
			
		||||
        void ground_lib_init() {
 | 
			
		||||
 | 
			
		||||
#define GROUND_LIBRARY_INIT_END() \
 | 
			
		||||
        } \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// Optional cleanup macro
 | 
			
		||||
#define GROUND_LIBRARY_CLEANUP() \
 | 
			
		||||
    extern "C" { \
 | 
			
		||||
        void ground_lib_cleanup() {
 | 
			
		||||
 | 
			
		||||
#define GROUND_LIBRARY_CLEANUP_END() \
 | 
			
		||||
        } \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// Utility function to print GroundValue for debugging
 | 
			
		||||
inline void debug_print_ground_value(const GroundValue& v) {
 | 
			
		||||
    switch (v.type) {
 | 
			
		||||
        case GROUND_INT:
 | 
			
		||||
            std::cout << "INT: " << v.data.int_val << std::endl;
 | 
			
		||||
            break;
 | 
			
		||||
        case GROUND_DOUBLE:
 | 
			
		||||
            std::cout << "DOUBLE: " << v.data.double_val << std::endl;
 | 
			
		||||
            break;
 | 
			
		||||
        case GROUND_BOOL:
 | 
			
		||||
            std::cout << "BOOL: " << (v.data.bool_val ? "true" : "false") << std::endl;
 | 
			
		||||
            break;
 | 
			
		||||
        case GROUND_STRING:
 | 
			
		||||
            std::cout << "STRING: " << (v.data.string_val ? v.data.string_val : "(null)") << std::endl;
 | 
			
		||||
            break;
 | 
			
		||||
        case GROUND_CHAR:
 | 
			
		||||
            std::cout << "CHAR: '" << v.data.char_val << "'" << std::endl;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // GROUND_LIB_H
 | 
			
		||||
		Reference in New Issue
	
	Block a user