{"id":13494698,"url":"https://github.com/metayeti/mINI","last_synced_at":"2025-03-28T14:31:40.958Z","repository":{"id":45837802,"uuid":"132079467","full_name":"metayeti/mINI","owner":"metayeti","description":"INI file reader and writer","archived":false,"fork":false,"pushed_at":"2024-09-30T20:34:03.000Z","size":122,"stargazers_count":531,"open_issues_count":3,"forks_count":114,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-10-31T09:37:09.687Z","etag":null,"topics":["ini","ini-config","ini-file","ini-generator","ini-parser","ini-reader","ini-writer"],"latest_commit_sha":null,"homepage":"","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/metayeti.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-04T03:11:15.000Z","updated_at":"2024-10-31T02:21:58.000Z","dependencies_parsed_at":"2022-08-12T12:21:16.074Z","dependency_job_id":"a6cef70b-769a-4e58-ae75-b3174f590c60","html_url":"https://github.com/metayeti/mINI","commit_stats":null,"previous_names":["metayeti/mini","pulzed/mini"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metayeti%2FmINI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metayeti%2FmINI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metayeti%2FmINI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metayeti%2FmINI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/metayeti","download_url":"https://codeload.github.com/metayeti/mINI/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246046053,"owners_count":20714893,"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":["ini","ini-config","ini-file","ini-generator","ini-parser","ini-reader","ini-writer"],"created_at":"2024-07-31T19:01:27.338Z","updated_at":"2025-03-28T14:31:40.576Z","avatar_url":"https://github.com/metayeti.png","language":"C++","funding_links":[],"categories":["Configuration","C++"],"sub_categories":[],"readme":"# mINI \u003cimg align=\"left\" src=\"icon.png?raw=true\" height=\"96\"\u003e\n\nv0.9.17\n\n## Info\n\nThis is a tiny, header only C++ library for manipulating INI files.\n\nIt conforms to the following format:\n- section and key names are case insensitive by default\n- whitespace around sections, keys and values is ignored\n- empty section and key names are allowed\n- keys that do not belong to a section are ignored\n- comments are lines where the first non-whitespace character is a semicolon (`;`)\n- trailing comments are allowed on section lines, but not key/value lines\n- every entry exists on a single line and multiline is not supported\n\n\n```INI\n; comment\n[section]\nkey = value\n```\n\n\nFiles are read on demand in one go, after which the data is kept in memory and is ready to be manipulated. Files are closed after read or write operations. This utility supports lazy writing, which only writes changes and updates and preserves custom formatting and comments. A lazy write invoked by a `write()` call will read the output file, find which changes have been made, and update the file accordingly. If you only need to generate files, use `generate()` instead.\n\nSection and key order is preserved on read and write operations. Iterating through data will take the same order as the original file or the order in which keys were added to the structure.\n\nThis library operates with the `std::string` type to hold values and relies on your host environment for encoding. It should play nicely with UTF-8 but your mileage may vary.\n\n## Installation\n\nThis is a header-only library. To install it, just copy everything in `/src/` into your own project's source code folder, or use a custom location and just make sure your compiler sees the additional include directory. Then include the file somewhere in your code:\n\n```C++\n#include \"mini/ini.h\"\n```\n\nYou're good to go!\n\n## Basic examples\n\n### Reading / writing\n\nStart with an INI file named `myfile.ini`:\n```INI\n; amounts of fruits\n[fruits]\napples=20\noranges=30\n```\n\nOur code:\n```C++\n// first, create a file instance\nmINI::INIFile file(\"myfile.ini\");\n\n// next, create a structure that will hold data\nmINI::INIStructure ini;\n\n// now we can read the file\nfile.read(ini);\n\n// read a value\nstd::string\u0026 amountOfApples = ini[\"fruits\"][\"apples\"];\n\n// update a value\nini[\"fruits\"][\"oranges\"] = \"50\";\n\n// add a new entry\nini[\"fruits\"][\"bananas\"] = \"100\";\n\n// write updates to file\nfile.write(ini);\n```\n\nAfter running the code, our INI file now looks like this:\n```INI\n; amounts of fruits\n[fruits]\napples=20\noranges=50\nbananas=100\n```\n\n### Generating a file\n\n```C++\n// create a file instance\nmINI::INIFile file(\"myfile.ini\");\n\n// create a data structure\nmINI::INIStructure ini;\n\n// populate the structure\nini[\"things\"][\"chairs\"] = \"20\";\nini[\"things\"][\"balloons\"] = \"100\";\n\n// generate an INI file (overwrites any previous file)\nfile.generate(ini);\n```\n\n## Manipulating files\n\nThe `INIFile` class holds the filename and exposes functions for reading, writing and generating INI files. It does not keep the file open but merely provides an abstraction you can use to access physical files.\n\nTo create a file instance:\n```C++\nmINI::INIFile file(\"myfile.ini\");\n```\n\nYou will also need a structure you can operate on:\n```C++\nmINI::INIStructure ini;\n```\n\nTo read from a file:\n```C++\nbool readSuccess = file.read(ini);\n```\n\nTo write back to a file while preserving comments and custom formatting:\n```C++\nbool writeSuccess = file.write(ini);\n```\n\nYou can set the second parameter to `write()` to `true` if you want the file to be written with pretty-print. Pretty-print adds spaces between key-value pairs and blank lines between sections in the output file:\n```C++\nbool writeSuccess = file.write(ini, true);\n```\n\nA `write()` call will attempt to preserve any custom formatting the original INI file uses and will only use pretty-print for creation of new keys and sections.\n\nTo generate a file:\n```C++\nfile.generate(ini);\n```\n\nNote that `generate()` will overwrite any custom formatting and comments from the original file!\n\nYou can use pretty-print with `generate()` as well:\n```C++\nfile.generate(ini, true);\n```\n\nExample output for a generated INI file *without* pretty-print:\n```INI\n[section1]\nkey1=value1\nkey2=value2\n[section2]\nkey1=value1\n```\n\nExample output for a generated INI file *with* pretty-print:\n```INI\n[section1]\nkey1 = value1\nkey2 = value2\n\n[section2]\nkey1 = value1\n```\n\n## Manipulating data\n\n### Reading data\n\nThere are two ways to read data from the INI structure. You can either use the `[]` operator or the `get()` function:\n\n```C++\n// read value - if key or section don't exist, they will be created\n// returns reference to real value\nstd::string\u0026 value = ini[\"section\"][\"key\"];\n\n// read value safely - if key or section don't exist they will NOT be created\n// returns a copy\nstd::string value = ini.get(\"section\").get(\"key\");\n```\n\nThe difference between `[]` and `get()` operations is that `[]` returns a reference to **real** data (that you may modify) and creates a new item automatically if one does not already exist, whereas `get()` returns a **copy** of the data and doesn't create new items in the structure. Use `has()` before doing any operations with `[]` if you wish to avoid altering the structure.\n\nYou may combine usage of `[]` and `get()`.\n\nSection and key names are case insensitive and are stripped of leading and trailing whitespace. `ini[\"section\"]` is the same as `ini[\"SECTION\"]` is the same as `ini[\"   sEcTiOn   \"]` and so on, and same for keys. Generated files always use lower case for section and key names. Writing to an existing file will preserve letter cases of the original file whenever those keys or sections already exists.\n\n### Updating data\n\nTo set or update a value:\n```C++\nini[\"section\"][\"key\"] = \"value\";\n```\n\nNote that when writing to a file, values will be stripped of leading and trailing whitespace . For example, the following value will be converted to just `\"c\"` when reading back from a file: `ini[\"a\"][\"b\"] = \"   c   \";`\n\nYou can set multiple values at once by using `set()`:\n```C++\nini[\"section\"].set({\n\t{\"key1\", \"value1\"},\n\t{\"key2\", \"value2\"}\n});\n```\n\nTo create an empty section, simply do:\n```C++\nini[\"section\"];\n```\n\nSimilarly, to create an empty key:\n```C++\nini[\"section\"][\"key\"];\n```\n\nTo remove a single key from a section:\n```C++\nbool removeSuccess = ini[\"section\"].remove(\"key\");\n```\n\nTo remove a section:\n```C++\nbool removeSuccess = ini.remove(\"section\");\n```\n\nTo remove all keys from a section:\n```C++\nini[\"section\"].clear();\n```\n\nTo remove all data in structure:\n```C++\nini.clear();\n```\n\n### Other functions\n\nTo check if a section is present:\n```C++\nbool hasSection = ini.has(\"section\");\n```\n\nTo check if a key within a section is present:\n```C++\nbool hasKey = ini[\"section\"].has(\"key\");\n```\n\nTo get the number of keys in a section:\n```C++\nsize_t n_keys = ini[\"section\"].size();\n```\n\nTo get the number of sections in the structure:\n```C++\nsize_t n_sections = ini.size();\n```\n\n### Nitty-gritty\n\nKeep in mind that `[]` will always create a new item if the item does not already exist! You can use `has()` to check if an item exists before performing further operations. Remember that `get()` will return a copy of data, so you should **not** be doing removes or updates to data with it!\n\nUsage of the `[]` operator shouldn't be a problem in most real-world cases where you're doing lookups on known keys and you may not care if empty keys or sections get created. However - if you have a situation where you do not want new items to be added to the structure, either use `get()` to retreive items, or if you don't want to be working with copies of data, use `has()` before using the `[]` operator if you want to be on the safe side.\n\nShort example that demonstrates safe manipulation of data:\n```C++\nif (ini.has(\"section\"))\n{\n\t// we have section, we can access it safely without creating a new one\n\tauto\u0026 collection = ini[\"section\"];\n\tif (collection.has(\"key\"))\n\t{\n\t\t// we have key, we can access it safely without creating a new one\n\t\tauto\u0026 value = collection[\"key\"];\n\t}\n}\n```\n\n## Iteration\n\nYou can traverse the structure in order of insertion. The following example loops through the structure and displays results in a familiar format:\n```C++\nfor (auto const\u0026 it : ini)\n{\n\tauto const\u0026 section = it.first;\n\tauto const\u0026 collection = it.second;\n\tstd::cout \u003c\u003c \"[\" \u003c\u003c section \u003c\u003c \"]\" \u003c\u003c std::endl;\n\tfor (auto const\u0026 it2 : collection)\n\t{\n\t\tauto const\u0026 key = it2.first;\n\t\tauto const\u0026 value = it2.second;\n\t\tstd::cout \u003c\u003c key \u003c\u003c \"=\" \u003c\u003c value \u003c\u003c std::endl;\n\t}\n}\n```\n\n`it.first` is always `std::string` type.\n\n`it.second` is an object which is either a `mINI::INIMap` type on the first level or `std::string` type on the second level.\n\nThe API only exposes a `const_iterator`, so you can't use iterators to manipulate data directly. You can however access the structure as normal while iterating:\n\n```C++\n// change all values in the structure to \"banana\"\nfor (auto const\u0026 it : ini)\n{\n\tauto const\u0026 section = it.first;\n\tauto const\u0026 collection = it.second;\n\tfor (auto const\u0026 it2 : collection)\n\t{\n\t\tauto const\u0026 key = it2.first;\n\t\tini[section][key] = \"banana\"; // O(1) because hashmaps\n\t}\n}\n```\n\n## Case sensitivity\n\nIf you wish to make the library not ignore letter case, add the directive `#define MINI_CASE_SENSITIVE` **before** including the library:\n```C++\n#define MINI_CASE_SENSITIVE\n#include \"mini/ini.h\"\n```\n\nThis will affect reading and writing from files and access to the structure.\n\n## Thanks\n\n- [lest](https://github.com/martinmoene/lest) - testing framework\n\n## License\n\nCopyright \u0026copy; 2018 Danijel Durakovic\n\nLicensed under the terms of the [MIT license](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetayeti%2FmINI","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmetayeti%2FmINI","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetayeti%2FmINI/lists"}