Veritable Lasagna
An Allocator & Data Structure Library for C.
Loading...
Searching...
No Matches
Conventions
  1. Function Naming
  2. Instantiation and Destruction
  3. Iterators

Function Naming

For Veritable Lasagna, function names are broken up into three main components.

  • Library Acronym
  • Structure
  • Operation

Modeled after the OpenGL and Vulkan APIs, this naming convention offers the following benefits:

  • Keeps the library safe from overpopulating the global namespace.
  • Plays nicely with IDE autocomplete features.
  • Solves a "rule of three" for function names, which is that they should succinctly describe:
    • Where the function comes from.
    • What the function works with and/or on.
    • What kind of work the function performs.

That is to say, all functions regarding lists are of the form vlList..., all functions for queues are of the form vlQueue..., and so on.

Naming Diagram

Instantiation and Destruction

Instantiating and destroying any data structure (aside from those provided by the vl_memory.h header) is accomplished with two primary methods, being Init / Free and New / Delete.

  • Init / Free
    • Used when a memory location for the structure already exists (usually, on the stack).
    • Avoids a separate heap allocation just for the structure metadata.
      • Just don't forget to free it.
  • New / Delete
    • Used when a new memory location is needed for the structure metadata to exist in.
      • Most useful when stack allocation is not an option (e.g, returning a pointer to a data structure from a function).
    • No stack-related lifetime restrictions.
      • Just don't forget to delete it.
    • Just a wrapper over Init / Free wherein the structure is allocated on the heap.
      Details

      vlStructureNew(...)

      vl_structure* struct = malloc(sizeof(vl_structure));

      vlStructInit(struct, ...);

      vlStructureDelete(...)

      vlStructFree(struct);

      free(struct);

Instantiation
Details
#include <vl/vl_list.h>
int main(int argc, const char** argv){
//Start with a vl_list variable on the stack.
vl_list list;
//Initialize the list at its known location.
vlListInit(&list, sizeof(int));
//Use the list...
//Then free the list.
vlListFree(&list);
return 0;
}
void vlListInit(vl_linked_list *list, vl_memsize_t elementSize)
Initializes the specified list instance.
Definition vl_linked_list.c:16
#define vlListFree(listPtr)
Frees the specified list instance.
Definition vl_linked_list.h:77
#include <vl/vl_list.h>
int main(int argc, const char** argv){
//Initialize the list at a new location.
vl_list* list = vlListNew(sizeof(int));
//Use the list...
//Then delete the list.
vlListDelete(list);
return 0;
}
void vlListDelete(vl_linked_list *list)
Deletes the specified list instance.
Definition vl_linked_list.c:29
vl_linked_list * vlListNew(vl_memsize_t elementSize)
Allocates on the heap, initializes, and returns a list instance.
Definition vl_linked_list.c:23

Iterators

Conventional data structures offered by this library offer the ability to iterate their elements. They come equipped with their own VL_XXX_FOREACH macros, and also VL_XXX_FOREACH_REVERSE in most cases. Iterator types are never anything more than some integer, however the specific type used is dependent on which kind of structure it is associated with. Meaning, the iterator types for Hash Tables and Linked Lists (as examples) are not guaranteed to be the same type of integer.