Skip to content

guillermocalvo/resultlib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

336bac0 Β· Feb 26, 2025

History

34 Commits
Feb 26, 2025
Feb 26, 2025
Feb 26, 2025
Feb 26, 2025
Feb 26, 2025
Dec 16, 2024
Dec 16, 2024
Dec 16, 2024
Feb 26, 2025
Feb 26, 2025
Dec 16, 2024
Feb 26, 2025
Feb 24, 2025
Feb 26, 2025
Feb 26, 2025
Feb 26, 2025
Feb 26, 2025
Feb 26, 2025

Repository files navigation

Build Status Quality Gate Status Docs Status Latest Release

Result Library

A header-only C library to handle errors elegantly

Wave goodbye to output parameters, sentinel values, and endless null checking! Embrace clean, efficient error handling today by encapsulating operations that may succeed or fail in a type-safe way.

Main Features

  • Boost Performance: Fewer pointer dereferences; rely on optimized single return values
  • Simple API: Handle success and failure scenarios with just a handful of C macros
  • Streamlined Error Handling: Reduce the chances of incorrect or inconsistent error handling
  • Safe Execution: Enforce valid states, eliminating risks like dangling pointers or stale data
  • Enhanced Readability: Reduce boilerplate code to make your code easier to understand
  • Functional Style: Avoid side effects and encourage pure, composable functions
  • Lightweight: Keep your project slim with no extra dependencies
  • Open Source: Enjoy transparent, permissive Apache 2 licensing
  • Header-Only C Library: Compatible with C23 standard and modern compilers

Tip

This library provides a cleaner, safer, and more modern approach to error handling by combining function result and error into a unified return value. It enforces correct usage at the call site, reduces the risk of bugs, and leads to more maintainable and extensible code.

Results in a Nutshell

Result objects represent the outcome of an operation, removing the need for output parameters, sentinel values, and null checking. Operations that succeed produce results encapsulating a success value; operations that fail produce results with a failure value. Success and failure can be represented by whatever types make the most sense for each operation.

Let's use a pet store example to show how this library can simplify your code.

Start by defining some data types to represent pets.

// Pet status in the store
typedef enum pet_status { AVAILABLE, PENDING, SOLD } pet_status;

// Represents a pet
typedef struct pet { int id; const char * name; pet_status status; } * Pet;

// Convenience macros
#define PET_ID(pet) pet->id
#define PET_NAME(pet) pet->name
#define PET_STATUS(pet) pet->status

// Pet error codes
typedef enum pet_error { OK, PET_NOT_FOUND, PET_NOT_AVAILABLE, PET_ALREADY_SOLD } pet_error;

Next, let's say you have an array of pets acting as your "database".

// Available pets in the store
static struct pet pets[] = {
  { .id = 0, .name = "Rocky", .status = AVAILABLE },
  { .id = 1, .name = "Garfield", .status = PENDING },
  { .id = 2, .name = "Rantanplan", .status = SOLD }
};

Note

You'll use a function, find_pet(id), to retrieve pets by their ID. We'll skip its implementation for now.

Suppose you need to write a function to get a pet's status.

Warning

This works... until someone passes an invalid ID. If find_pet returns NULL, your code could crash unexpectedly.

To fix this, you refactor the function to return an error code and use an output parameter to "return" the pet status.

It's safer, but also clunky.

Warning

What if the output pointer is NULL? Should you return a new error code? Use assert? It's starting to feel messy.

Instead of juggling pointers and error codes, you should return a Result object.

Tip

The result encapsulates both success (pet status) and failure (error code) in one clean package. The caller immediately knows the function can fail, and you've eliminated the need for an output pointer. This is simpler, safer, and much easier to read.

Encouraged, you refactor find_pet to return a failed result instead of NULL when a pet isn't found. Now, get_pet_status can rely on find_pet to handle errors and focus on the happy path.

Note

And just like that, your code becomes robust and maintainable. No more mysterious crashes, no awkward pointer checks. Just clean, elegant error handling.

With Results, handling success and failure feels natural, leaving you free to focus on the fun parts of coding.

Author

Copyright 2025 Guillermo Calvo.

License

This library is licensed under the Apache License, Version 2.0 (the "License"); you may not use it except in compliance with the License.

You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and limitations under the License.

Permitted:

  • Commercial Use: You may use this library and derivatives for commercial purposes.
  • Modification: You may modify this library.
  • Distribution: You may distribute this library.
  • Patent Use: This license provides an express grant of patent rights from contributors.
  • Private Use: You may use and modify this library without distributing it.

Required:

  • License and Copyright Notice: If you distribute this library you must include a copy of the license and copyright notice.
  • State Changes: If you modify and distribute this library you must document changes made to this library.

Forbidden:

  • Trademark use: This license does not grant any trademark rights.
  • Liability: The library author cannot be held liable for damages.
  • Warranty: This library is provided without any warranty.