Complete API documentation for the VIBE C parser library.
- Parser Management
- Parsing Functions
- Value Creation
- Value Access
- Object Operations
- Array Operations
- Memory Management
- Error Handling
- Type System
- Usage Examples
Creates a new parser instance.
VibeParser* vibe_parser_new(void);Returns:
- Pointer to a new
VibeParserinstance NULLif memory allocation fails
Example:
VibeParser* parser = vibe_parser_new();
if (!parser) {
fprintf(stderr, "Failed to create parser\n");
return 1;
}Notes:
- Must be freed with
vibe_parser_free()when done - Parser can be reused for multiple parse operations
- Not thread-safe (use one parser per thread)
Frees a parser instance and its resources.
void vibe_parser_free(VibeParser* parser);Parameters:
parser- Parser instance to free (can beNULL)
Example:
vibe_parser_free(parser);Notes:
- Safe to call with
NULL - Does not free parsed values (use
vibe_value_free()for those) - Frees error messages if any
Parses a VIBE string into a value tree.
VibeValue* vibe_parse_string(VibeParser* parser, const char* input);Parameters:
parser- Parser instanceinput- Null-terminated VIBE string to parse
Returns:
- Root
VibeValueobject containing parsed configuration NULLon parse error (check withvibe_get_last_error())
Example:
const char* config =
"app {\n"
" name \"My App\"\n"
" port 8080\n"
"}\n";
VibeValue* root = vibe_parse_string(parser, config);
if (!root) {
VibeError error = vibe_get_last_error(parser);
fprintf(stderr, "Error at line %d: %s\n", error.line, error.message);
return 1;
}Notes:
- Input must be valid UTF-8
- Parser keeps first error encountered
- Returned value must be freed with
vibe_value_free()
Parses a VIBE file into a value tree.
VibeValue* vibe_parse_file(VibeParser* parser, const char* filename);Parameters:
parser- Parser instancefilename- Path to VIBE file
Returns:
- Root
VibeValueobject containing parsed configuration NULLon error (file not found or parse error)
Example:
VibeValue* config = vibe_parse_file(parser, "config.vibe");
if (!config) {
VibeError error = vibe_get_last_error(parser);
fprintf(stderr, "Error: %s\n", error.message);
return 1;
}Notes:
- Reads entire file into memory
- File must be UTF-8 encoded
- Returns detailed error for both file I/O and parse errors
Creates a new integer value.
VibeValue* vibe_value_new_integer(int64_t value);Parameters:
value- 64-bit signed integer
Returns:
- New
VibeValueof typeVIBE_TYPE_INTEGER NULLif allocation fails
Example:
VibeValue* port = vibe_value_new_integer(8080);Creates a new floating-point value.
VibeValue* vibe_value_new_float(double value);Parameters:
value- Double-precision floating-point number
Returns:
- New
VibeValueof typeVIBE_TYPE_FLOAT NULLif allocation fails
Example:
VibeValue* version = vibe_value_new_float(1.5);Creates a new boolean value.
VibeValue* vibe_value_new_boolean(bool value);Parameters:
value- Boolean (trueorfalse)
Returns:
- New
VibeValueof typeVIBE_TYPE_BOOLEAN NULLif allocation fails
Example:
VibeValue* debug = vibe_value_new_boolean(true);Creates a new string value.
VibeValue* vibe_value_new_string(const char* value);Parameters:
value- Null-terminated UTF-8 string (copied internally)
Returns:
- New
VibeValueof typeVIBE_TYPE_STRING NULLif allocation fails
Example:
VibeValue* name = vibe_value_new_string("My Application");Notes:
- String is copied (caller retains ownership of input)
- Supports full UTF-8
Creates a new empty array.
VibeValue* vibe_value_new_array(void);Returns:
- New
VibeValueof typeVIBE_TYPE_ARRAY NULLif allocation fails
Example:
VibeValue* servers = vibe_value_new_array();
vibe_array_push(servers->as_array, vibe_value_new_string("server1.com"));
vibe_array_push(servers->as_array, vibe_value_new_string("server2.com"));Creates a new empty object.
VibeValue* vibe_value_new_object(void);Returns:
- New
VibeValueof typeVIBE_TYPE_OBJECT NULLif allocation fails
Example:
VibeValue* config = vibe_value_new_object();
vibe_object_set(config->as_object, "port", vibe_value_new_integer(8080));
vibe_object_set(config->as_object, "host", vibe_value_new_string("localhost"));Accesses a value using dot notation path.
VibeValue* vibe_get(VibeValue* root, const char* path);Parameters:
root- Root value to search frompath- Dot-separated path (e.g.,"server.ssl.enabled")
Returns:
- Pointer to the value at the path
NULLif path not found
Example:
VibeValue* ssl_enabled = vibe_get(config, "server.ssl.enabled");
if (ssl_enabled && ssl_enabled->type == VIBE_TYPE_BOOLEAN) {
printf("SSL: %s\n", ssl_enabled->as_boolean ? "enabled" : "disabled");
}Notes:
- Path is case-sensitive
- Returns borrowed reference (don't free)
NULLpath returns the root value itself
Gets a string value from a path.
const char* vibe_get_string(VibeValue* value, const char* path);Parameters:
value- Root value to search frompath- Dot-separated path (orNULLfor direct access)
Returns:
- String value at the path
NULLif not found or not a string
Example:
const char* app_name = vibe_get_string(config, "app.name");
if (app_name) {
printf("Application: %s\n", app_name);
}
// Direct access (no path)
VibeValue* val = vibe_get(config, "app.name");
const char* name = vibe_get_string(val, NULL);Notes:
- Returns borrowed pointer (don't free)
- Returns
NULLif value is not a string - Path can be
NULLto access value directly
Gets an integer value from a path.
int64_t vibe_get_int(VibeValue* value, const char* path);Parameters:
value- Root value to search frompath- Dot-separated path (orNULLfor direct access)
Returns:
- Integer value at the path
0if not found or not an integer
Example:
int64_t port = vibe_get_int(config, "server.port");
printf("Port: %lld\n", (long long)port);
// Check if value exists and is correct type
VibeValue* port_val = vibe_get(config, "server.port");
if (port_val && port_val->type == VIBE_TYPE_INTEGER) {
printf("Port: %lld\n", (long long)port_val->as_integer);
} else {
printf("Port not configured or wrong type\n");
}Notes:
- Returns
0on error (check type if0is a valid value) - Use
vibe_get()first if you need to distinguish missing vs. zero
Gets a float value from a path.
double vibe_get_float(VibeValue* value, const char* path);Parameters:
value- Root value to search frompath- Dot-separated path (orNULLfor direct access)
Returns:
- Float value at the path
0.0if not found or not a float
Example:
double timeout = vibe_get_float(config, "server.timeout");
printf("Timeout: %.2f seconds\n", timeout);Gets a boolean value from a path.
bool vibe_get_bool(VibeValue* value, const char* path);Parameters:
value- Root value to search frompath- Dot-separated path (orNULLfor direct access)
Returns:
- Boolean value at the path
falseif not found or not a boolean
Example:
bool debug = vibe_get_bool(config, "app.debug");
if (debug) {
printf("Debug mode enabled\n");
}Notes:
- Returns
falseon error - Check type if
falseis a meaningful value
Gets an array from a path.
VibeArray* vibe_get_array(VibeValue* value, const char* path);Parameters:
value- Root value to search frompath- Dot-separated path (orNULLfor direct access)
Returns:
- Pointer to
VibeArraystructure NULLif not found or not an array
Example:
VibeArray* servers = vibe_get_array(config, "servers");
if (servers) {
for (size_t i = 0; i < servers->count; i++) {
VibeValue* server = servers->values[i];
if (server->type == VIBE_TYPE_STRING) {
printf("Server %zu: %s\n", i, server->as_string);
}
}
}Gets an object from a path.
VibeObject* vibe_get_object(VibeValue* value, const char* path);Parameters:
value- Root value to search frompath- Dot-separated path (orNULLfor direct access)
Returns:
- Pointer to
VibeObjectstructure NULLif not found or not an object
Example:
VibeObject* ssl = vibe_get_object(config, "server.ssl");
if (ssl) {
for (size_t i = 0; i < ssl->count; i++) {
printf("%s: ", ssl->entries[i].key);
vibe_value_print(ssl->entries[i].value, 0);
printf("\n");
}
}Sets a key-value pair in an object.
void vibe_object_set(VibeObject* obj, const char* key, VibeValue* value);Parameters:
obj- Object to modifykey- Key name (will be copied)value- Value to set (ownership transferred)
Example:
VibeObject* config = vibe_value_new_object()->as_object;
vibe_object_set(config, "port", vibe_value_new_integer(8080));
vibe_object_set(config, "host", vibe_value_new_string("localhost"));Notes:
- If key exists, replaces old value (old value is freed)
- Key is copied (caller retains ownership)
- Value ownership transfers to object
Gets a value from an object by key.
VibeValue* vibe_object_get(VibeObject* obj, const char* key);Parameters:
obj- Object to searchkey- Key name
Returns:
- Value associated with key
NULLif key not found
Example:
VibeValue* port = vibe_object_get(config->as_object, "port");
if (port && port->type == VIBE_TYPE_INTEGER) {
printf("Port: %lld\n", (long long)port->as_integer);
}Appends a value to an array.
void vibe_array_push(VibeArray* arr, VibeValue* value);Parameters:
arr- Array to modifyvalue- Value to append (ownership transferred)
Example:
VibeArray* servers = vibe_value_new_array()->as_array;
vibe_array_push(servers, vibe_value_new_string("server1.com"));
vibe_array_push(servers, vibe_value_new_string("server2.com"));
vibe_array_push(servers, vibe_value_new_string("server3.com"));Gets a value from an array by index.
VibeValue* vibe_array_get(VibeArray* arr, size_t index);Parameters:
arr- Array to accessindex- Zero-based index
Returns:
- Value at index
NULLif index out of bounds
Example:
VibeArray* servers = vibe_get_array(config, "servers");
if (servers) {
VibeValue* first = vibe_array_get(servers, 0);
if (first && first->type == VIBE_TYPE_STRING) {
printf("First server: %s\n", first->as_string);
}
}Recursively frees a value and all its children.
void vibe_value_free(VibeValue* value);Parameters:
value- Value to free (can beNULL)
Example:
VibeValue* config = vibe_parse_file(parser, "config.vibe");
// Use config...
vibe_value_free(config); // Frees entire treeNotes:
- Recursively frees nested objects and arrays
- Safe to call with
NULL - Frees all strings, arrays, and objects in the tree
Gets the last error from a parser.
VibeError vibe_get_last_error(VibeParser* parser);Parameters:
parser- Parser instance
Returns:
VibeErrorstructure with error information
Example:
VibeValue* config = vibe_parse_file(parser, "config.vibe");
if (!config) {
VibeError error = vibe_get_last_error(parser);
if (error.has_error) {
fprintf(stderr, "Parse error at line %d, column %d:\n",
error.line, error.column);
fprintf(stderr, " %s\n", error.message);
}
}VibeError Structure:
typedef struct {
bool has_error; // True if error occurred
char* message; // Error message (owned by parser)
int line; // Line number (1-indexed)
int column; // Column number (1-indexed)
} VibeError;Frees error message memory.
void vibe_error_free(VibeError* error);Parameters:
error- Error structure to free
Example:
// Usually not needed - errors are freed with parser
VibeError error = vibe_get_last_error(parser);
// Use error...
vibe_error_free(&error); // Only if you need to free earlyNotes:
- Usually not needed - errors freed with parser
- Only use if you need to free error before parser
typedef enum {
VIBE_TYPE_NULL = 0,
VIBE_TYPE_INTEGER,
VIBE_TYPE_FLOAT,
VIBE_TYPE_BOOLEAN,
VIBE_TYPE_STRING,
VIBE_TYPE_ARRAY,
VIBE_TYPE_OBJECT
} VibeType;struct VibeValue {
VibeType type;
union {
int64_t as_integer;
double as_float;
bool as_boolean;
char* as_string;
VibeArray* as_array;
VibeObject* as_object;
};
};Usage:
VibeValue* val = vibe_get(config, "server.port");
switch (val->type) {
case VIBE_TYPE_INTEGER:
printf("Port: %lld\n", (long long)val->as_integer);
break;
case VIBE_TYPE_STRING:
printf("Port: %s\n", val->as_string);
break;
default:
printf("Port has unexpected type\n");
}#include "vibe.h"
#include <stdio.h>
int main() {
// 1. Create parser
VibeParser* parser = vibe_parser_new();
if (!parser) {
fprintf(stderr, "Failed to create parser\n");
return 1;
}
// 2. Parse file
VibeValue* config = vibe_parse_file(parser, "config.vibe");
if (!config) {
VibeError error = vibe_get_last_error(parser);
fprintf(stderr, "Error at line %d: %s\n",
error.line, error.message);
vibe_parser_free(parser);
return 1;
}
// 3. Access values using dot notation
const char* app_name = vibe_get_string(config, "app.name");
int64_t port = vibe_get_int(config, "server.port");
bool debug = vibe_get_bool(config, "app.debug");
printf("Application: %s\n", app_name ? app_name : "Unknown");
printf("Port: %lld\n", (long long)port);
printf("Debug: %s\n", debug ? "enabled" : "disabled");
// 4. Access arrays
VibeArray* servers = vibe_get_array(config, "servers");
if (servers) {
printf("Servers:\n");
for (size_t i = 0; i < servers->count; i++) {
VibeValue* server = servers->values[i];
if (server->type == VIBE_TYPE_STRING) {
printf(" - %s\n", server->as_string);
}
}
}
// 5. Access nested objects
VibeObject* ssl = vibe_get_object(config, "server.ssl");
if (ssl) {
printf("SSL Configuration:\n");
for (size_t i = 0; i < ssl->count; i++) {
printf(" %s = ", ssl->entries[i].key);
vibe_value_print(ssl->entries[i].value, 0);
printf("\n");
}
}
// 6. Cleanup
vibe_value_free(config);
vibe_parser_free(parser);
return 0;
}// Create a config from scratch
VibeValue* config = vibe_value_new_object();
// Add simple values
vibe_object_set(config->as_object, "port", vibe_value_new_integer(8080));
vibe_object_set(config->as_object, "host", vibe_value_new_string("localhost"));
vibe_object_set(config->as_object, "debug", vibe_value_new_boolean(true));
// Add nested object
VibeValue* ssl = vibe_value_new_object();
vibe_object_set(ssl->as_object, "enabled", vibe_value_new_boolean(true));
vibe_object_set(ssl->as_object, "cert", vibe_value_new_string("/etc/ssl/cert.pem"));
vibe_object_set(config->as_object, "ssl", ssl);
// Add array
VibeValue* servers = vibe_value_new_array();
vibe_array_push(servers->as_array, vibe_value_new_string("server1.com"));
vibe_array_push(servers->as_array, vibe_value_new_string("server2.com"));
vibe_object_set(config->as_object, "servers", servers);
// Use config...
vibe_value_free(config);Prints a value tree (for debugging).
void vibe_value_print(VibeValue* value, int indent);Parameters:
value- Value to printindent- Indentation level (use 0 for root)
Example:
VibeValue* config = vibe_parse_file(parser, "config.vibe");
printf("Configuration:\n");
vibe_value_print(config, 0);-
Always check return values:
VibeValue* config = vibe_parse_file(parser, "config.vibe"); if (!config) { // Handle error }
-
Check types before accessing:
VibeValue* port = vibe_get(config, "server.port"); if (port && port->type == VIBE_TYPE_INTEGER) { use_port(port->as_integer); }
-
Always free resources:
vibe_value_free(config); vibe_parser_free(parser);
-
Use dot notation for clarity:
// Good const char* name = vibe_get_string(config, "app.name"); // Also works but more verbose VibeObject* app = vibe_get_object(config, "app"); VibeValue* name_val = vibe_object_get(app, "name");
For more examples, see the examples/ directory.