Initial commit
This commit is contained in:
		
							
								
								
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | # Ground Libraries | ||||||
|  |  | ||||||
|  | These are some libraries coded in C++ for Ground. All are avaliable for anyone to use. | ||||||
							
								
								
									
										15
									
								
								compileall.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								compileall.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | echo "This script is designed for Linux systems" | ||||||
|  | echo "Please ensure CPR is installed on your system before continuing" | ||||||
|  | echo "On Arch Linux: sudo pacman -S cpr" | ||||||
|  |  | ||||||
|  | echo "Compiling exec library" | ||||||
|  | g++ -shared -fPIC -o exec.so exec/exec.cpp | ||||||
|  | echo "Compiling file library" | ||||||
|  | g++ -shared -fPIC -o file.so file/file.cpp | ||||||
|  | echo "Compiling math library" | ||||||
|  | g++ -shared -fPIC -o math.so math/math.cpp | ||||||
|  | echo "Compiling request library" | ||||||
|  | g++ -shared -fPIC -lcpr -o request.so request/request.cpp | ||||||
|  | echo "Done" | ||||||
							
								
								
									
										9
									
								
								compiling.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								compiling.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | ## Compiling External Libraries | ||||||
|  |  | ||||||
|  | On Linux: | ||||||
|  |  | ||||||
|  | `g++ -shared -fPIC -o filename.so filename.cpp` | ||||||
|  |  | ||||||
|  | On macOS: | ||||||
|  |  | ||||||
|  | `g++ -shared -fPIC -o filename.dylib filename.cpp` | ||||||
							
								
								
									
										9
									
								
								exec/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								exec/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | # exec library | ||||||
|  |  | ||||||
|  | This library allows executing third party executables via the C++ "system" command. | ||||||
|  |  | ||||||
|  | ## Functions | ||||||
|  |  | ||||||
|  | ### fun -int !exec -string &command | ||||||
|  |  | ||||||
|  | Runs a command on a system. Returns the status code of that command. | ||||||
							
								
								
									
										16
									
								
								exec/exec.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								exec/exec.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | #include "ground_lib.h" | ||||||
|  |  | ||||||
|  | GroundValue exec(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_STRING); | ||||||
|  |     int exec = system(GET_STRING(args[0])); | ||||||
|  |     return GROUND_INT_VAL(exec); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INTERFACE() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INIT() | ||||||
|  |     REGISTER_GROUND_FUNCTION(exec); | ||||||
|  | GROUND_LIBRARY_INIT_END() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_CLEANUP() | ||||||
|  | GROUND_LIBRARY_CLEANUP_END() | ||||||
							
								
								
									
										193
									
								
								exec/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								exec/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 | ||||||
							
								
								
									
										13
									
								
								file/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								file/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | # file library | ||||||
|  |  | ||||||
|  | This library allows reading from and writing to files on the system. | ||||||
|  |  | ||||||
|  | ## Functions | ||||||
|  |  | ||||||
|  | ### fun -string !readFile -string &fileName | ||||||
|  |  | ||||||
|  | This function reads all content from a file and returns it. | ||||||
|  |  | ||||||
|  | ### fun -bool !writeFile -string &fileName -string &content | ||||||
|  |  | ||||||
|  | This function overwrites a file with specified content. If successful, returns true. If not successful, returns false, and prints out a reason why it didn't work. | ||||||
							
								
								
									
										43
									
								
								file/file.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								file/file.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | #include "ground_lib.h" | ||||||
|  |  | ||||||
|  | #include <fstream> | ||||||
|  | #include <filesystem> | ||||||
|  |  | ||||||
|  | GroundValue readFile(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_STRING); | ||||||
|  |  | ||||||
|  |     std::ifstream ffile(GET_STRING(args[0])); | ||||||
|  |  | ||||||
|  |     std::string tmp; | ||||||
|  |     std::string out; | ||||||
|  |  | ||||||
|  |     while (std::getline(ffile, tmp)) { | ||||||
|  |         out += tmp + "\n"; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     return ground_string_val(out); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue writeFile(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_2(GROUND_STRING, GROUND_STRING); | ||||||
|  |  | ||||||
|  |     std::ofstream file(GET_STRING(args[0])); | ||||||
|  |     if (file.good()) { | ||||||
|  |         file << GET_STRING(args[1]); | ||||||
|  |     } else { | ||||||
|  |         std::cout << "File isn't good for writing in" << std::endl; | ||||||
|  |         return GROUND_BOOL_VAL(false); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     return GROUND_BOOL_VAL(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INTERFACE() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INIT() | ||||||
|  |     REGISTER_GROUND_FUNCTION(readFile); | ||||||
|  |     REGISTER_GROUND_FUNCTION(writeFile); | ||||||
|  | GROUND_LIBRARY_INIT_END() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_CLEANUP() | ||||||
|  | GROUND_LIBRARY_CLEANUP_END() | ||||||
							
								
								
									
										193
									
								
								file/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								file/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 | ||||||
							
								
								
									
										193
									
								
								ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								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 | ||||||
							
								
								
									
										193
									
								
								httpserver/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								httpserver/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 | ||||||
							
								
								
									
										17
									
								
								httpserver/httpserver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								httpserver/httpserver.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | #define CPPHTTPLIB_OPENSSL_SUPPORT | ||||||
|  | #include "ground_lib.h" | ||||||
|  | #include "libraries/httplib.h" | ||||||
|  |  | ||||||
|  | GroundValue startHttpServer(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_INT);   | ||||||
|  |      | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INTERFACE() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INIT() | ||||||
|  |     REGISTER_GROUND_FUNCTION(startHttpServer); | ||||||
|  | GROUND_LIBRARY_INIT_END() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_CLEANUP() | ||||||
|  | GROUND_LIBRARY_CLEANUP_END() | ||||||
							
								
								
									
										
											BIN
										
									
								
								httpserver/httpserver.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								httpserver/httpserver.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										0
									
								
								httpserver/libraries/httplib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								httpserver/libraries/httplib.h
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										45
									
								
								math/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								math/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | # math library | ||||||
|  |  | ||||||
|  | This library adds extra math functions to Ground. | ||||||
|  |  | ||||||
|  | ## Functions | ||||||
|  |  | ||||||
|  | ### fun -double !sinVal -double &input | ||||||
|  |  | ||||||
|  | Gets the sin of input. | ||||||
|  |  | ||||||
|  | ### fun -double !cosVal -double &input | ||||||
|  |  | ||||||
|  | Gets the cos of input. | ||||||
|  |  | ||||||
|  | ### fun -double !tanVal -double &input | ||||||
|  |  | ||||||
|  | Gets the tan of input. | ||||||
|  |  | ||||||
|  | ### fun -double !sqrtVal -double &input | ||||||
|  |  | ||||||
|  | Gets the square root of input. | ||||||
|  |  | ||||||
|  | ### fun -int !modVal -int &a -int &b | ||||||
|  |  | ||||||
|  | Gets the remainder of a divided by b. | ||||||
|  |  | ||||||
|  | ### fun -double !floorVal -double &input | ||||||
|  |  | ||||||
|  | Gets the floor of input. | ||||||
|  |  | ||||||
|  | ### fun -double !ceilVal -double &input | ||||||
|  |  | ||||||
|  | Gets the ceil of input. | ||||||
|  |  | ||||||
|  | ### fun -double !roundVal -double &input | ||||||
|  |  | ||||||
|  | Rounds the input to the nearest integer. | ||||||
|  |  | ||||||
|  | ### fun -int !randomInt -int &min -int &max | ||||||
|  |  | ||||||
|  | Gets a random integer between min and max (inclusive). | ||||||
|  |  | ||||||
|  | ### fun -double !randomDouble -double &min -double &max | ||||||
|  |  | ||||||
|  | Gets a random double between min and max (inclusive). | ||||||
							
								
								
									
										193
									
								
								math/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								math/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 | ||||||
							
								
								
									
										79
									
								
								math/math.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								math/math.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | |||||||
|  | #include "ground_lib.h" | ||||||
|  | #include <cmath> | ||||||
|  | #include <random> | ||||||
|  |  | ||||||
|  | // Math functions | ||||||
|  | GroundValue sinVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(sin(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue cosVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(cos(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue tanVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(tan(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue sqrtVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(sqrt(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue modVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_2(GROUND_INT, GROUND_INT); | ||||||
|  |     return GROUND_INT_VAL(GET_INT(args[0]) % GET_INT(args[1])); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue floorVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(floor(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue ceilVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(ceil(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue roundVal(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_DOUBLE); | ||||||
|  |     return GROUND_DOUBLE_VAL(round(GET_DOUBLE(args[0]))); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue randomInt(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_2(GROUND_INT, GROUND_INT); | ||||||
|  |     std::random_device rd; | ||||||
|  |     std::mt19937 gen(rd()); | ||||||
|  |     std::uniform_int_distribution<> distrib(GET_INT(args[0]), GET_INT(args[1])); | ||||||
|  |     return GROUND_INT_VAL(distrib(gen)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue randomDouble(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_2(GROUND_DOUBLE, GROUND_DOUBLE); | ||||||
|  |     std::random_device rd; | ||||||
|  |     std::mt19937 gen(rd()); | ||||||
|  |     std::uniform_real_distribution<> distrib(GET_DOUBLE(args[0]), GET_DOUBLE(args[1])); | ||||||
|  |     return GROUND_DOUBLE_VAL(distrib(gen)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Library setup | ||||||
|  | GROUND_LIBRARY_INTERFACE() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INIT() | ||||||
|  |     REGISTER_GROUND_FUNCTION(sinVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(cosVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(tanVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(sqrtVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(modVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(floorVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(ceilVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(roundVal); | ||||||
|  |     REGISTER_GROUND_FUNCTION(randomInt); | ||||||
|  |     REGISTER_GROUND_FUNCTION(randomDouble); | ||||||
|  | GROUND_LIBRARY_INIT_END() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_CLEANUP() | ||||||
|  | GROUND_LIBRARY_CLEANUP_END() | ||||||
							
								
								
									
										
											BIN
										
									
								
								request.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								request.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										13
									
								
								request/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								request/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | # request library | ||||||
|  |  | ||||||
|  | This library allows various web requests from within Ground. | ||||||
|  |  | ||||||
|  | ## Functions | ||||||
|  |  | ||||||
|  | ### fun -string !simpleRequest -string &url | ||||||
|  |  | ||||||
|  | Makes a web request to a URL, and returns the contents. If the request is not successful, returns a response beginning with "Error code", and prints it to the console. | ||||||
|  |  | ||||||
|  | ### fun -bool !saveContents -string &url -string &location | ||||||
|  |  | ||||||
|  | Makes a web request to a URL, and saves the contents to a file. If successful, returns true. If not, returns false. | ||||||
							
								
								
									
										193
									
								
								request/ground_lib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								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 | ||||||
							
								
								
									
										52
									
								
								request/request.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								request/request.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | #include "ground_lib.h" | ||||||
|  |  | ||||||
|  | #include <cpr/cpr.h> | ||||||
|  | #include <cpr/interface.h> | ||||||
|  | #include <fstream> | ||||||
|  |  | ||||||
|  | void error(std::string status) { | ||||||
|  |     std::cout << "Request error: " << status << std::endl; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue simpleRequest(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_1(GROUND_STRING); | ||||||
|  |  | ||||||
|  |     cpr::Response r = cpr::Get(cpr::Url(GET_STRING(args[0]))); | ||||||
|  |  | ||||||
|  |     if (!(r.status_code >= 200 && r.status_code < 300)) { | ||||||
|  |         error("Non zero HTTP code " + std::to_string(r.status_code)); | ||||||
|  |         return ground_string_val("Error code " + std::to_string(r.status_code));     | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     return ground_string_val(r.text); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GroundValue saveContents(GroundValue* args, int arg_count) { | ||||||
|  |     VALIDATE_ARGS_2(GROUND_STRING, GROUND_STRING); | ||||||
|  |  | ||||||
|  |     std::ofstream file(GET_STRING(args[1]), std::ios::binary); | ||||||
|  |  | ||||||
|  |     if (file.good()) { | ||||||
|  |         cpr::Response r = cpr::Download(file, cpr::Url{GET_STRING(args[0])}); | ||||||
|  |  | ||||||
|  |         if (!(r.status_code >= 200 && r.status_code < 300)) { | ||||||
|  |             error("Non zero HTTP code " + std::to_string(r.status_code)); | ||||||
|  |             return GROUND_BOOL_VAL(false); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         error(std::string("Cannot open file ") + GET_STRING(args[1]) + " for writing"); | ||||||
|  |         return GROUND_BOOL_VAL(false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return GROUND_BOOL_VAL(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INTERFACE() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_INIT() | ||||||
|  |     REGISTER_GROUND_FUNCTION(simpleRequest); | ||||||
|  |     REGISTER_GROUND_FUNCTION(saveContents); | ||||||
|  | GROUND_LIBRARY_INIT_END() | ||||||
|  |  | ||||||
|  | GROUND_LIBRARY_CLEANUP() | ||||||
|  | GROUND_LIBRARY_CLEANUP_END() | ||||||
		Reference in New Issue
	
	Block a user