{"id":18077423,"url":"https://github.com/parisneo/cfg","last_synced_at":"2025-04-05T20:13:21.308Z","repository":{"id":40784998,"uuid":"504835517","full_name":"ParisNeo/cfg","owner":"ParisNeo","description":"Simple Linux C configuration library to help using simplified configuration files in your projects.","archived":false,"fork":false,"pushed_at":"2022-06-27T20:55:26.000Z","size":39,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-18T19:46:56.562Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ParisNeo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-18T12:18:04.000Z","updated_at":"2022-06-27T23:09:42.000Z","dependencies_parsed_at":"2022-09-09T12:41:31.691Z","dependency_job_id":null,"html_url":"https://github.com/ParisNeo/cfg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ParisNeo%2Fcfg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ParisNeo%2Fcfg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ParisNeo%2Fcfg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ParisNeo%2Fcfg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ParisNeo","download_url":"https://codeload.github.com/ParisNeo/cfg/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393572,"owners_count":20931813,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-31T11:24:52.553Z","updated_at":"2025-04-05T20:13:21.253Z","avatar_url":"https://github.com/ParisNeo.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cfg\nSimple Linux C configuration library to help using simplified configuration files in your projects.\n\n# Build\nTo build and install the library on your system, just use:\n```console\nfoo@bar:~$ make clean;make; sudo make install\n```\nYou can skip the make install part and copy the .a output file as well as the header file to your project to link it statically with your code\n# Usage\nOnce the library is installed on your system or after adding the header file and the .a file to your project, you can use it like this.\n\nFirst import the header files\n```c\n#include\u003ccfg.h\u003e\n```\nif you are using c++, make sure you add extern \"C\" protection\n```cpp\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n    // udp library\n    #include \u003ccfg.h\u003e\n#ifdef __cplusplus\n}\n#endif\n```\n\nLet's define the configuration file path. For example:\n```c\n// The path of the file to load\nconst char *cfg_file_path = \"/etc/myconfig\"\n\n```\n\nThe library is very lightweight and is very simple to use. You need to provide a function that parses a single line from your configuration file. Then the library searches through the the file, ignores the comments (comments use # as escape character), then sports key value pairs.\nA key value pair is defined by typing the key (no spaces allowed for its key), then space, then the value which can be any thing from string, integer, floating point etc. \n\nEach key value entry is separated by a space.\nFor example:\n```python\n# parameter 1 is a string\nparameter1 this is a string\n# parameter 2 is an integer\nparameter2 100\n# parameter 4 is a more complex combination of subparameters sepatated by [:]. For example here is a complex parameter that has two subparameters\nparameter3 100:string value\n```\n\nNow we define the function to parse these lines. This function is going to be called by the library for each valid line it finds\n\n```c\n/**\n * \\fn void cfg_parser(char* key, char* val)\n * \\brief Parses one entry from the configuration file\n *\n * \\param key      The configuration parameter name\n * \\param val      The configuration value (as string)\n * \n * \\return nothing.\n */\nvoid cfg_parser(char* key, char* val)\n{\n    // Simple key value configuration\n    // a string parameter   ex : parameter1 some text\n    if(strcmp(key,\"parameter1\")==0)\n    {\n        strcpy(parameter1,val); // Copy the parameter value to the variable\n    }\n    // an integer parameter ex : parameter2 100\n    else if (strcmp(key,\"parameter2\")==0)\n    {\n        parameter2 = atoi(val); // Convert the value to an integer\n    }\n    else if(strcmp(key,\"parameter3\")==0) // A more complex parameter for example parameter3 100:hello\n    {\n        char subparam1[UDP_MAXADDR_SIZE];\n        char subparam2[UDP_MAXPORT_SIZE];\n        \n        if(sscanf(val,\"%[^:]:%s\", subparam1, subparam2)==2) // Use regular expression to decompose the value into sub parameters here the \n        {\n            parameter3.subparam1 = atoi(subparam1);\n            strcpy(parameter3.subparam2, subparam2);\n        }\n    }     \n}\n\n```\n\nNow in our main (or another function), we call the cfg_read function that will read the entire file and fill the parameters by calling the cfg_parser function.\n```c\n    // Read the configuration file\n    if(cfg_read(cfg_file_path, cfg_parser)==false)\n    {\n        printf(\"Error loading configuration file. Make sure the file exists in %s\\n\", cfg_file_path);\n    }\n```\nIn C++, you may want to cast your cfg_file_path to (char*).\n\nNow, you are ready and your parameters are loaded\n\n# Complete example\n\n```c\n#include\u003cstdio.h\u003e\n#include\u003ccfg.h\u003e\n\n// We define few parameters to fill\nchar parameter1[256]; // a string parameter\nint parameter2; // an integer parameter\n\n// The path of the file to load\nconst char *cfg_file_path = \"/etc/myconfig\"\n\n// A more complex parameter\nstruct paramtype{\n    int subparam1;\n    char subparam2[256];\n}\nstruct paramtype parameter3;\n\n/**\n * \\fn void cfg_parser(char* key, char* val)\n * \\brief Parses one entry from the configuration file\n *\n * \\param key      The configuration parameter name\n * \\param val      The configuration value (as string)\n * \n * \\return nothing.\n */\nvoid cfg_parser(char* key, char* val)\n{\n    // Simple key value configuration\n    // a string parameter   ex : parameter1 some text\n    if(strcmp(key,\"parameter1\")==0)\n    {\n        strcpy(parameter1,val); // Copy the parameter value to the variable\n    }\n    // an integer parameter ex : parameter2 100\n    else if (strcmp(key,\"parameter2\")==0)\n    {\n        parameter2 = atoi(val); // Convert the value to an integer\n    }\n    else if(strcmp(key,\"parameter3\")==0) // A more complex parameter for example parameter3 100:hello\n    {\n        char subparam1[UDP_MAXADDR_SIZE];\n        char subparam2[UDP_MAXPORT_SIZE];\n        \n        if(sscanf(val,\"%[^:]:%s\", subparam1, subparam2)==2) // Use regular expression to decompose the value into sub parameters here the \n        {\n            parameter3.subparam1 = atoi(subparam1);\n            strcpy(parameter3.subparam2, subparam2);\n        }\n    }     \n}\n\nint main(int argc, char ** argv)\n{\n    // Read the configuration file\n    if(cfg_read(cfg_file_path, cfg_parser)==false)\n    {\n        printf(\"Error loading configuration file. Make sure the file exists in %s\\n\", cfg_file_path);\n    }\n    // Now our parameters are all loaded successfully, time to play\n}\n```\n# Information\nThis is one of multiple libraries I have developed to simplify some tasks we do with C on linux. The objective is for it to be open source, eazy to use and compatible with both c and cpp. The build system is make and is compatible with gcc building system. It is very eazy to use this with cmake or other build systems. All these libraries have been tested on raspberry pi with raspbian. They help starting a new application that requires configuration, communication with arduino tools and spreading information between multiple services on the raspberry pi.\n\nThe licence is MIT, so you can use this code in your projects without worrying about licence contamination that could happen when using GPL licences. So you still can use it for free in commercial applications.\n\nTests and bugfixes are welcome. Just clone it, repare it and send a pull request. I want to keep this code as clean and simple as possible so please avoid feature creaping.\n\n# Useful links\nCheck out my [uart library](https://github.com/ParisNeo/uart) built in the same spirit as this library.\nCheck out my [udp library](https://github.com/ParisNeo/udp) built in the same spirit as this library.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparisneo%2Fcfg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparisneo%2Fcfg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparisneo%2Fcfg/lists"}