{"id":16991655,"url":"https://github.com/pstolarz/sprops","last_synced_at":"2026-05-16T18:04:06.739Z","repository":{"id":98196964,"uuid":"38916929","full_name":"pstolarz/sprops","owner":"pstolarz","description":"C library for parsing configuration files built of properties (key/value pairs) which may reside inside \"scopes\", that is blocks of configuration with assigned name and an optional type. Scopes may constitute hierarchical nesting tree of an arbitrary depth.","archived":false,"fork":false,"pushed_at":"2022-05-20T23:48:13.000Z","size":331,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-22T04:11:30.739Z","etag":null,"topics":["api","bison","c","configuration","cpp","library","parser","properties","yacc"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pstolarz.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-07-11T06:47:29.000Z","updated_at":"2021-12-27T14:57:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"6795a40b-5f92-4e55-801e-bd283371944d","html_url":"https://github.com/pstolarz/sprops","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pstolarz/sprops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pstolarz%2Fsprops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pstolarz%2Fsprops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pstolarz%2Fsprops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pstolarz%2Fsprops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pstolarz","download_url":"https://codeload.github.com/pstolarz/sprops/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pstolarz%2Fsprops/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274821733,"owners_count":25356357,"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","status":"online","status_checked_at":"2025-09-12T02:00:09.324Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["api","bison","c","configuration","cpp","library","parser","properties","yacc"],"created_at":"2024-10-14T03:26:47.463Z","updated_at":"2026-05-16T18:04:06.688Z","avatar_url":"https://github.com/pstolarz.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"Scoped properties configuration library\n=======================================\n\nThis project provides a lightweight and flexible library for parsing\nconfiguration files built of properties (key/value pairs) which may reside\ninside \"scopes\", that is blocks of configuration with assigned name and an\noptional type. Scopes may constitute hierarchical nesting tree of an arbitrary\n(configurable) depth.\n\nThe library API consists of small but powerful set of C functions for read/write\naccess of configuration file elements (properties/scopes). There is possible to\naccess an element located inside a specific scope when its location (expressed\nby a path) is known, or to discover a configuration file structure by iterating\nover its elements located in some scope (or the global scope).\n\nThe library provides unique functionality to parse only a specific scope (block\nof configuration), therefore highly reducing an overhead needed by frequent\naccess to some limited configuration block inside a larger configuration file.\n\nThe library is inspired by:\n\n - Microsoft INI files API: `GetPrivateProfileXXX()`, `WritePrivateProfileXXX()`\n   family of functions with their simplicity of usage, sections and basic\n   iteration functionality.\n - C language grammar as a base for scopes and properties definition syntax.\n - C++ namespace notion, as a sum of sets identified by the same name.\n\nNotes\n-----\n\n - Full support for UNIX (LF), Windows (CR/LF) and Legacy Mac (CR) end-of-line\n   markers.\n - The library uses ONLY standard C library API (mainly `stdio.h`) and shall be\n   ported with a little effort for any conforming platforms.\n - The library works purely on text stream tokens and doesn't interpret the read\n   information in any way (e.g. no serialization of the read configuration).\n - Memory allocation is performed ONLY by the generated grammar parser code\n   for grammar reductions. Bison parser allows a flexible way for configuring\n   such allocations e.g. via stack `alloca(3)` (used by the library) or heap\n   `malloc(3)`. This may be useful for porting to some constrained embedded\n   platforms. See the Bison parser generator documentation for more details.\n - The API is fully re-entrant. No global variables are used during the parsing\n   process.\n - The library is thread safe in terms of all library objects except API passed\n   file-objects (that is file handles for read access and physical files for\n   write access). Since there is no effective way to ensure such file-objects\n   synchronization on the library level, the application is responsible to handle\n   this issue. This may be done via standard thread synchronization approach or\n   by other means, e.g. if many threads read a single configuration file, each\n   of them may use its own read-only file handle to access the file in a thread\n   safe way (such approach is much more effective than the classical mutext\n   usage).\n\nQuick start\n-----------\n\nRefer to [`examples`](examples) for some simple examples presenting usage of the\nlibrary in typical cases. Thorough API specification is contained in C headers\nlocated in [`src/inc/sprops`](src/inc/sprops).\n\nCompilation\n-----------\n\nPrerequisites:\n\n - Standard building tool-set as part of the `build-essential` packet: `gcc`,\n   GNU Make etc.,\n - Bison parser generator of version 3 or higher (only in case of regenerating\n   `src/parser.c` grammar definition file).\n\nCompilation:\n\n    make\n\nproduces static library `src/libsprops.a` which may be linked into an application.\n\n    make examples\n\nwill compile examples.\n\nUnit tests are contained in [`tests`](tests) directory and are launched by\n\n    make test\n\nThere is possible to cross-compile the library by setting `CROSS_COMPILE` (for\nthe project `Makefile`) to the tool-chain prefix:\n\n    CROSS_COMPILE=\u003ctool-chain-prefix\u003e make\n\nConfiguration file format\n-------------------------\n\n\"One word from Chairman Mao is worth ten thousand from others\" --Lin Biao\n\nThe same is true with a good example:\n\n    # A comment starts with '#' up to the end of a line.\n    # This property is located in the global scope.\n    prop1 = value\n\n    # Quotation marks required in the property name to avoid parsing problems.\n    # A property value finishes at the end of a line or at a semicolon (unless\n    # the library is configured with CONFIG_NO_SEMICOL_ENDS_VAL).\n    \"property 2\" = some other value;\n\n    # Scope with a type and name.\n    scope_type scope_name\n    {\n        # 2 properties w/o their values (defined in the same line).\n        a; b=;\n\n        # Scope w/o a type. If no quotation marks had been used, the scope name\n        # would be \"name\" with type \"scope\".\n        \"scope name\"\n        {\n            c = property \"c\" value \\\n                with line \\\n                continuation;\n\n            # Property contains escaped characters: semicolon (\\;), LF (\\n),\n            # space (\\ ) and backslash (\\\\).\n            d = \\;abc\\n\\ \\\\\n        }\n\n        # Property names may contain arbitrary characters. In this example\n        # quotation marks are required since '{', '}' are parser's reserved\n        # tokens. Additionally tab characters are escaped by \\t.\n        \"{\\tprop name w/o a value\\t}\";\n    }\n\n    # This scope is a continuation of the scope above (with the same name and\n    # type). The library allows to sum (concatenate) all scopes with the same\n    # name and type as a single compound scope (so called split scope). This\n    # functionality is similar to the C++ namespaces.\n    scope_type scope_name\n    {\n        # These 2 properties duplicate the ones defined above.\n        a=val;\n        b=val;\n\n        c;\n\n        # Scope with \"type\" and \"name\" and an empty body.\n        type name {}\n    }\n\nPath-based addressing\n---------------------\n\nThe library provides path-based method of scope addressing to reach for a\nspecific element inside it (similarly to path and file analogous).\n\nBasing on the previous example:\n\n    global scope\n        -\u003e \"/\"\n\n    1st compound (split) scope in /\n        -\u003e \"/scope_type:scope_name\"\n             or\n           \"/scope_type:scope_name@*\"\n\n    1st part of the split scope above\n        -\u003e \"/scope_type:scope_name@0\"\n\n    2nd (and the last) part of the split scope above\n        -\u003e \"/scope_type:scope_name@1\"\n             or\n           \"/scope_type:scope_name@$\"\n\n    1st scope in split /scope_type:scope_name\n        -\u003e \"/scope_type:scope_name/:scope name\"\n\n    2nd scope in split /scope_type:scope_name\n        -\u003e \"/scope_type:scope_name/type:name\"\n            which is a scope with an empty body\n\nAPI specification\n-----------------\n\nThe library provides two sets of API:\n\n - Low level parser API with header: [`src/inc/sprops/parser.h`](src/inc/sprops/parser.h),\n - High level functional API with header: [`src/inc/sprops/props.h`](src/inc/sprops/props.h).\n\nThe first set of API defines low level, parser specific functionality and is\nnot intended to be used unless, for some reason, there is a need for direct\ncooperation with the parser. The interface defines set of callbacks which allow\nan application to be informed about grammar reductions.\n\nThe second set of API constitutes the proper read/write access interface (its\nimplementation bases on the low level parser API). The API allows addressing\nelements inside their scopes as well as discovering a configuration structure\nby iterating over its content.\n\nNOTE: Basically, the API treats properties values as strings built of arbitrary\ncharacters which are not interpreted. For user convenience there have been\nprovided three simple functions to interpret strings as integers, floats and\nenumerations, namely:\n\n    sp_get_prop_int()\n    sp_get_prop_float()\n    sp_get_prop_enum()\n\nLists may be easily emulated by iterating over dedicated scopes content.\n\nRefer to the mentioned header files for complete API specification.\n\nTransactional support\n---------------------\n\nTo handle wrong-state of the modified data issue, there has been provided\na simple transactional support with an API specified in the header\n[`src/inc/sprops/trans.h`](src/inc/sprops/trans.h), implemented as a wrapper\naround the write access API.\n\nApart from the transactions, the API provides a handy way for modification of\na specific scope (block of configuration) inside a larger configuration file.\nThis may be useful in terms of performance (in case of really huge files) or\nif a modifying caller is interested only in a specific block of configuration\n(which is managed by it) and doesn't care about the rest.\n\nLicense\n-------\n\n2 clause BSD license. See [`LICENSE`](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpstolarz%2Fsprops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpstolarz%2Fsprops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpstolarz%2Fsprops/lists"}