{"id":16154422,"url":"https://github.com/vtnerd/prima","last_synced_at":"2025-04-06T23:44:46.988Z","repository":{"id":35684076,"uuid":"39960173","full_name":"vtnerd/prima","owner":"vtnerd","description":"A C++11 compile-time printf library","archived":false,"fork":false,"pushed_at":"2016-05-14T04:08:38.000Z","size":93,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-13T05:43:51.442Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vtnerd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-30T16:18:24.000Z","updated_at":"2018-02-04T12:41:39.000Z","dependencies_parsed_at":"2022-09-04T03:10:26.009Z","dependency_job_id":null,"html_url":"https://github.com/vtnerd/prima","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/vtnerd%2Fprima","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtnerd%2Fprima/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtnerd%2Fprima/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vtnerd%2Fprima/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vtnerd","download_url":"https://codeload.github.com/vtnerd/prima/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247569130,"owners_count":20959758,"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-10T01:17:19.678Z","updated_at":"2025-04-06T23:44:46.968Z","avatar_url":"https://github.com/vtnerd.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# prima #\nPrima is an implementation of the C I/O functions that parses the format string at compile time using [boost::metaparse](https://github.com/boostorg/metaparse), and then generates input/output formatting code at _compile time_ instead of runtime. This results in [faster](#performance-benchmarks) and safer (type-checked) I/O. Prima supports multiple [backends](#backends) that do the actual I/O, making Prima a flexible C format string compiler.\n\n\u003e This library is a work in-progress.\n\n## Dependencies ##\nPrima currently requires Boost 1.61.\n\n## Supported Formatting ##\n#### Input ####\nNot yet-implemented. Will support `boost::spirit::qi` and default to `boost::spirit::x3`.\n\n#### Output ####\nPrima output I/O matches the behavior of the standard C behavior. Some flags are compile-time errors if they have no effect or are conflicting (i.e. ' ' and '+' is a compile-time error). If a flag is _not_ supported for a type, it is a compile-time error if used.\n\n   Format Flag   |                              Valid Argument Types                              | Supported Flags\n:---------------:|--------------------------------------------------------------------------------|-----------------\n       d, i      |         Any built-in signed integer type (char, short, int, etc.)              | Width, Precision, '-', '0', ' ', and '+'.\ne, E, f, F, g, G |                               float, and double                                | Width, Precision, '-', '0', ' ', '+', and '#'\n        u        | Any unsigned integer type (unsigned char, unsigned short, unsigned int, etc.)  | Width, Precision, '-', and '0'.\n   o, x, X       |  Any unsigned integer type (unsigned char, unsigned short, unsigned int, etc.) | Width, Precision, '-', and '0'.\n       s         |                           const char*, std::string                             | Width, Precision, and '-'\n      \n\u003e * The length modifiers ('hh', 'll', etc.) are _not_ supported, because variadic templates are used instead of the type opaque C variadic arguments (so they are not needed).\n\u003e * Pointers can be output by converting to `std::uintptr_t` and using any of the format flags that support an unsigned integer type (\"%p\" is not needed).\n\u003e * A zero length width is a compile-time error.\n\u003e * The '0' flag with no specified width is a compile-time error.\n\u003e * The combination of flags '+' and ' ' is a compile-time error.\n\u003e * The combination of flags '0' and '-' is a compile-time error.\n\u003e * The combination of the '0' flag and usage of the precision field with an integer format flag (d, i, u, o, x, X) is a compile-time error.\n      \n## Usage ##\nThe prima I/O functions require a variadic compile-time string as input. A macro `PRIMA_FMT` can convert a string literal to the compile-time string in a C++11 compatible compiler. The user-literal `prima::literals::_fmt` can be used in compilers that support [literal operator templates for strings](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3599.html):\n\n```c++\n{\n    prima::printf(PRIMA_FMT(\"%s\"), \"world\");\n}\n{\n    using prima::literals;\n    prima::printf(\"hello %s\"_fmt, \"world\");\n}\n```\nThe user string literal `_fmt` is the preferred method, because it will have more efficient _compile_-times.\n\n#### Output ####\n##### printf #####\nBehaves just like `std::printf`:\n\n```c++\nprima::printf(PRIMA_FMT(\"hello %s\"), \"world\");\n```\n\n##### sprintf #####\n`prima::sprintf` differs slightly from `std::sprintf`; the first argument is templated and must meet [output iterator](http://en.cppreference.com/w/cpp/concept/OutputIterator) requirements, and the output is _never_ null-terminated. Since `char*` is a valid output iterator, `prima::sprintf` can be used in place of std::sprintf or other scenarios:\n\n```c++\n{\n    char buffer[100] = {0};\n    // Never checks for buffer size. Does not null-terminate.\n    prima::sprintf(std::begin(buffer), PRIMA_FMT(\"hello %s\"), \"world\");\n}\n{\n    std::string buffer{};\n    // Throws if std::bad_alloc. Implicitly null-terminated due to std::string.\n    prima::sprintf(std::back_inserter(buffer), PRIMA_FMT(\"hello %s\"), \"world\");\n}\n```\n`prima::sprintf` will also update the output iterator to one-past the last write location, iff the argument is passed as a mutable l-value.\n\n##### snprintf #####\n`prima::snprintf` differs slightly from `std::snprintf`; the first argument is templated and must meet [output iterator](http://en.cppreference.com/w/cpp/concept/OutputIterator) requirements, and the function does not stop until `size` bytes have been output. Since `char*` is a valid output iterator, `prima::sprintf` can be used in place of std::sprintf or other scenarios:\n\n```c++\n{\n    char buffer[100] = {0};\n    // Does not null-terminate. Stops after sizeof(buffer) bytes (not sizeof(buffer) - 1).\n    prima::snprintf(std::begin(buffer), PRIMA_FMT(\"hello %s\"), sizeof(buffer), \"world\");\n}\n{\n    std::string buffer{};\n    buffer.resize(100);\n    // Implicitly null-terminated due to std::string. Stops after buffer.size() bytes.\n    prima::snprintf(\u0026buffer[0], PRIMA_FMT(\"hello %s\"), buffer.size(), \"world\");\n}\n```\n`prima::snprintf` will also update the output iterator to one-past the last write location, iff the argument is passed as a mutable l-value.\n\n## Backends ##\n#### Input ####\nNot yet-implemented. Will support `boost::spirit::qi` and default to `boost::spirit::x3`.\n\n#### Output ####\n##### Karma #####\n`boost::spirit::karma` is the only backend for output, so it is the current default. Explicit usage example:\n\n```c++\nusing prima::literals;\nprima::printf.call\u003cprima::backend::karma\u003e()(\"hello %s\"_fmt, \"world\");\n```\n\n## Performance Benchmarks ##\n#### OSX (libc++) - Clang 3.5 - Intel i5-3210M (2.5 GHz 3MB Cache) ####\n```\nRunning \"%f\" with input -100.000000 benchmark 1000000 times for each implementation...\n        std::sprintf :0.231175 microseconds per run {checksum: 3dfd240}\n       std::snprintf :0.230521 microseconds per run {checksum: 3dfd240}\n      prima::sprintf :0.082181 microseconds per run {checksum: 3dfd240}\n     prima::snprintf :0.080238 microseconds per run {checksum: 3dfd240}\nRunning \"%f\" with input 0.000000 benchmark 1000000 times for each implementation...\n        std::sprintf :0.174141 microseconds per run {checksum: 40d9900}\n       std::snprintf :0.171285 microseconds per run {checksum: 40d9900}\n      prima::sprintf :0.062569 microseconds per run {checksum: 40d9900}\n     prima::snprintf :0.068810 microseconds per run {checksum: 40d9900}\nRunning \"%f\" with input 100.000000 benchmark 1000000 times for each implementation...\n        std::sprintf :0.227993 microseconds per run {checksum: 41cdb40}\n       std::snprintf :0.226350 microseconds per run {checksum: 41cdb40}\n      prima::sprintf :0.072780 microseconds per run {checksum: 41cdb40}\n     prima::snprintf :0.072128 microseconds per run {checksum: 41cdb40}\nRunning \"%f\" with input 1234.123413 benchmark 1000000 times for each implementation...\n        std::sprintf :0.257176 microseconds per run {checksum: 41cdb40}\n       std::snprintf :0.256577 microseconds per run {checksum: 41cdb40}\n      prima::sprintf :0.096077 microseconds per run {checksum: 41cdb40}\n     prima::snprintf :0.095936 microseconds per run {checksum: 41cdb40}\n\nBenchmark averages:\n        std::sprintf :0.222621 microseconds per run {checksum: 102721c0}\n       std::snprintf :0.221183 microseconds per run {checksum: 102721c0}\n      prima::sprintf :0.078402 microseconds per run {checksum: 102721c0}\n     prima::snprintf :0.079278 microseconds per run {checksum: 102721c0}\n```\n\u003e **Note:** This is from latest master branch, but not C++11 branch\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvtnerd%2Fprima","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvtnerd%2Fprima","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvtnerd%2Fprima/lists"}