# par: single-file C libraries where the header is the whole library

> The par repository collects standalone C headers from Philip Allan Rideout, mostly graphics related, each documented at the top of the file and each meant to be copied into a project rather than installed. The engineering discipline is visible in the details: a vertical density rule, a 100 column limit enforced by a Python script on top of uncrustify, and a README that marks one library as unmaintained and says do not use.

**prideout/par** — single-file C libraries from Philip Allan Rideout

- Repository: https://github.com/prideout/par
- Stars: 1,023 · Forks: 77
- Language: C
- License: not declared
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/prideout-par

## Twelve headers at the top level, and nothing else

The repository description is single-file C libraries from Philip Allan Rideout, and the README says the same thing in one line: single-file C libraries under the MIT license, mostly graphics related.

The layout is the whole architecture. The top level of the repository is the headers themselves, par_camera_control.h, par_octasphere.h, par_streamlines.h, par_string_blocks.h, par_shapes.h and the rest, plus a test directory and a tools directory. There is no build system for the library, because there is no library to build. You copy the header you want into your project and include it.

That design has one large advantage and one large cost, and both are worth naming. The advantage is that a single header with no dependencies cannot conflict with anything else in your build, and it is trivially auditable, since you can read the entire implementation before including it. The cost is that you now own a copy, and when the upstream fixes a bug, your copy does not get it.

The documentation arrangement is the part that makes this workable. Documentation can be found at the top of each header file, and some libraries have an accompanying blog post. There is no manual, no doc directory, no generated API reference. The header is the manual, which works because the library is small enough that the interface and its explanation fit in the first hundred lines of a file you have already opened to use it.

The audience is a developer working in C on graphics or tooling, who wants to read and adapt the code rather than consume a package.

## The five the README puts first

The README lists the most useful libraries in a table, and the descriptions are terse enough to be worth quoting in full, because they tell you what each header is for.

par_camera_control.h is an orbit controller, or pan-and-zoom like Google Maps, and it is the only one in the table with a demo project rather than a blog post. par_octasphere.h is malloc-free mesh gen for spheres and rounded cuboids, and the malloc-free part is the interesting detail, since a mesh generator that allocates is a mesh generator you cannot easily put in a frame loop.

par_streamlines.h triangulates wide lines and curves, which is the problem of turning a stroked path into geometry that a GPU can render with the right thickness. par_shapes.h generates parametric surfaces and other simple shapes, which is the building block for the sphere and cuboid generator above rather than a competitor to it. And par_string_blocks.h is a string manager for snippets of Lua or GLSL, which is a narrower and stranger tool than the rest, aimed at people who generate code as data.

The README is honest about the rest of the collection. There are more libraries too but they are probably less useful, and it points you to the bottom of the file.

The longer list has the same character. par_bluenoise.h generates progressive 2D point sequences, which is the sampling side of a renderer. par_bubbles.h packs circles into hierarchical diagrams, which is a layout algorithm with a demo. par_easings.h is Robert Penner's easing functions, a well-known set with a well-known licence history. par_easycurl.h is simple HTTP requests using libcurl, which makes it the one header in the list with an external dependency. par_filecache.h is LRU caching on the device's filesystem. And par_sprune.h is efficient broad-phase collision detection in 2D.

## The tests are programs you run by hand

There is no test runner in the usual sense, because there is no library to link against. The tests are small programs in the test directory, and the README explains how to build and run them.

You need CMake and pkg-config, and on macOS the README suggests homebrew:

```bash
$ brew install cmake pkg-config
```

Then you point CMake at the CMakeLists in the test folder, placing all the messy stuff in a new folder called build:

```bash
$ cmake test -Bbuild   # Create makefiles
$ cmake --build build  # Invoke the build
```

And the tests are executed by simply running the programs:

```bash
$ build/test_bubbles
$ build/test_shapes
$ build/test_octasphere
```

That last part is the interesting choice. These are not assertions in a harness, they are executables that produce output, which means they are also the demos, and a bug in a mesh generator shows up as visibly wrong geometry rather than as a failed assertion. The price is that there is no automated pass or fail signal, so a regression has to be noticed by a human or by comparing output.

The arrangement fits the single-file model. The library is used by including a header, so the test for that library is a program that includes the header and exercises it, and the build is a normal CMake project over the test directory rather than a test runner wired into the library's own build.

## Vertical density and a 100 column limit, enforced by a script

The code formatting section is the most unusual thing in the README, and it tells you something about how the project is maintained.

This library's code style is strictly enforced to be vertically dense, with no consecutive newlines, and 100 columns or less. The tools/format.py script invokes a two-step code formatting process: it runs uncrustify with the project's custom configuration, which auto-formats all code in the root folder up to a point, and then it checks for violations that are not otherwise enforced with uncrustify.

The script is also invoked from Travis, but using the --check option, which checks for conformance without editing the code. Beyond what the uncrustify configuration enforces, the Python script checks that no lines are more than 100 chars, and checks for extra newlines before an end brace.

So the rule is not just a preference in a style guide, it is a build-time gate. The two checks that survive past uncrustify are the two that a general purpose formatter cannot express, a hard column limit and a rule about blank lines before a closing brace. The combination of a formatter and a script that catches what the formatter misses is the standard way to keep a style rule from decaying, and here the style rule is deliberately unusual.

Vertical density is worth understanding as a choice rather than a quirk. In a header that a person reads before including, every blank line is a line of scrolling, and the rule removes them.

The CI side of this is Travis, with the badge in the README and a .travis.yml in the repository. The test workflow is therefore the same mechanism that enforces the formatting, which means a formatting violation fails the same run as a test failure.

## One library is marked do not use, and that is the honest move

The second table of libraries ends with an entry that is worth reading as a policy statement rather than a feature list: par_msquares.h, an unmaintained marching squares library, with the note do not use, and a blog post link beside it.

Every other entry in that table is described by what it does. This one is described by its status, and the status is that it should not be used. The blog post is still linked, so the write-up about the technique has value, but the code does not, and the README says so.

That is a small thing that says a lot about the repository. The list is a shelf of things the author found useful, and a shelf that quietly keeps a broken item on it, hoping nobody picks it up, is a shelf that eventually bites somebody. Marking it is nearly free, and it moves the decision to the person who would otherwise have to discover the problem themselves.

It also sets the expectation for the rest of the collection. The libraries here are the ones the author reached for, not a curated package with a compatibility matrix and a support policy, and the do not use marker is how the project says where its own confidence ends.

For an adopter, the practical reading is that these headers are code to read and adapt. Where a header documents its own limits, take them seriously, because the author has already taken the trouble to write them down.

## Conclusion

par fits a graphics or tools developer who wants one algorithm, such as a camera controller or a parametric surface generator, without taking on a dependency graph, and who is willing to own the copy of the header afterwards. It does not fit a project that needs versioned upgrades of its dependencies, and it does not fit someone who wants a coherent library rather than a shelf of unrelated pieces. Before you take one, read the documentation block at the top of the header, because that is where the whole interface is described, and check whether the piece you want needs an external library, since most do not and par_easycurl does.

## FAQ

### How do I use a library from the par repository?

You copy the header you want into your project and include it. The repository has no build step for the library itself, because each library is a single self-contained header with its documentation at the top of the file.

### How do I run the par tests?

You need CMake and pkg-config, then run cmake test -Bbuild to create the makefiles and cmake --build build to build, and finally run the test programs directly, for example build/test_bubbles, build/test_shapes and build/test_octasphere.

### Which par libraries are the most useful?

The README lists par_camera_control.h, an orbit or pan-and-zoom controller, par_octasphere.h, a malloc-free mesh generator for spheres and rounded cuboids, par_streamlines.h for triangulating wide lines and curves, par_string_blocks.h, a string manager for Lua or GLSL snippets, and par_shapes.h for parametric surfaces and other simple shapes.

### Does any par library need an external dependency?

Most do not, but par_easycurl.h is for simple HTTP requests using libcurl, so it needs libcurl present. The README's formatting section also assumes the uncrustify tool and a Python script for the checks that uncrustify does not cover.

### How is code style enforced in the par repository?

The style is strictly vertically dense, with no consecutive newlines and 100 columns or less. The tools/format.py script runs uncrustify with a custom configuration and then checks the rules uncrustify does not enforce, and it is also invoked from Travis with the --check option so violations fail the build.

## Sources

- [Issues](https://github.com/prideout/par/issues)
- [prideout/par on GitHub](https://github.com/prideout/par)
- [README](https://github.com/prideout/par/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/prideout-par
