278 lines
8.8 KiB
C
278 lines
8.8 KiB
C
/* Copyright (c) 2024-2026, CK Tan.
|
|
* https://github.com/cktan/tomlc17/blob/main/LICENSE
|
|
*/
|
|
|
|
/**
|
|
* @file tomlc17.h
|
|
* @brief A TOML parser for C17.
|
|
*
|
|
* This library provides a simple and efficient way to parse TOML documents
|
|
* in C. It supports standard TOML features and provides an easy-to-use API
|
|
* for traversing the parsed data.
|
|
*/
|
|
|
|
#ifndef TOMLC17_H
|
|
#define TOMLC17_H
|
|
|
|
// A crude way to determine version. Manually changed.
|
|
#define TOMLC17_RELEASE_AFTER "260618"
|
|
|
|
/*
|
|
* USAGE:
|
|
*
|
|
* 1. Call toml_parse(), toml_parse_file(), or toml_parse_file_ex()
|
|
* 2. Check result.ok
|
|
* 3. Use toml_get() or toml_seek() to query and traverse the
|
|
* result.toptab
|
|
* 4. Call toml_free() to release resources.
|
|
*
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef __cplusplus
|
|
#define TOML_EXTERN extern "C"
|
|
#else
|
|
#define TOML_EXTERN extern
|
|
#endif
|
|
|
|
/**
|
|
* @brief Enumeration of TOML data types.
|
|
*/
|
|
enum toml_type_t {
|
|
TOML_UNKNOWN = 0, /**< Unknown or invalid type */
|
|
TOML_STRING, /**< String type */
|
|
TOML_INT64, /**< 64-bit integer type */
|
|
TOML_FP64, /**< 64-bit floating point type */
|
|
TOML_BOOLEAN, /**< Boolean type */
|
|
TOML_DATE, /**< Local date type */
|
|
TOML_TIME, /**< Local time type */
|
|
TOML_DATETIME, /**< Local datetime type */
|
|
TOML_DATETIMETZ, /**< Offset datetime type */
|
|
TOML_ARRAY, /**< Array type */
|
|
TOML_TABLE, /**< Table type */
|
|
};
|
|
typedef enum toml_type_t toml_type_t;
|
|
|
|
/**
|
|
* @brief Represents a single piece of TOML data.
|
|
*
|
|
* This structure is a node in a tree that represents a TOML document.
|
|
* The `u` union contains the actual value based on the `type` field.
|
|
*/
|
|
typedef struct toml_datum_t toml_datum_t;
|
|
struct toml_datum_t {
|
|
toml_type_t type; /**< Type of the datum */
|
|
uint32_t flag; /**< Internal flag, do not use */
|
|
int lineno; /**< 1-based source line number, 0 if synthesized */
|
|
int colno; /**< 1-based source column number, 0 if synthesized */
|
|
const char *source; /**< Source name (e.g. filename), NULL if not provided.
|
|
Owned by the result; valid until toml_free(). */
|
|
union {
|
|
const char *s; /**< Shorthand for str.ptr */
|
|
struct {
|
|
const char *ptr; /**< NUL terminated string pointer */
|
|
int len; /**< Length of the string excluding the terminating NUL */
|
|
} str;
|
|
int64_t int64; /**< 64-bit integer value */
|
|
double fp64; /**< 64-bit floating point value */
|
|
bool boolean; /**< Boolean value */
|
|
struct { /**< Date and time components */
|
|
int16_t year, month, day;
|
|
int16_t hour, minute, second;
|
|
int32_t usec;
|
|
int16_t tz; /**< Timezone offset in minutes */
|
|
} ts;
|
|
struct { /**< Array data */
|
|
int32_t size; /**< Number of elements in the array */
|
|
toml_datum_t *elem; /**< Array of elements */
|
|
} arr;
|
|
struct { /**< Table data */
|
|
int32_t size; /**< Number of keys in the table */
|
|
const char **key; /**< Array of keys */
|
|
int *len; /**< Array of key lengths */
|
|
toml_datum_t *value; /**< Array of values corresponding to keys */
|
|
} tab;
|
|
} u;
|
|
};
|
|
|
|
/**
|
|
* @brief Result of a TOML parsing operation.
|
|
*/
|
|
typedef struct toml_result_t toml_result_t;
|
|
struct toml_result_t {
|
|
bool ok; /**< True if parsing was successful */
|
|
toml_datum_t toptab; /**< The top-level table (valid if ok is true) */
|
|
char errmsg[200]; /**< Error message (valid if ok is false) */
|
|
void *__internal; /**< Internal state, do not use */
|
|
};
|
|
|
|
/**
|
|
* @brief Parse a TOML document from a string.
|
|
*
|
|
* @param src A NUL-terminated string containing the TOML document.
|
|
* @param len The length of the string (excluding the NUL terminator).
|
|
* @return A toml_result_t structure. Must be freed with toml_free().
|
|
*
|
|
* IMPORTANT: src[] must be a NUL terminated string! The len parameter
|
|
* does not include the NUL terminator.
|
|
*/
|
|
TOML_EXTERN toml_result_t toml_parse(const char *src, int len);
|
|
|
|
/**
|
|
* @brief Parse a TOML document, tagging every datum with a source name.
|
|
*
|
|
* @param src A NUL-terminated string containing the TOML document.
|
|
* @param len The length of the string (excluding the NUL terminator).
|
|
* @param name A source name (e.g. filename) copied into the result, or NULL.
|
|
* Every parsed datum's `source` is set to this name (or NULL).
|
|
* @return A toml_result_t structure. Must be freed with toml_free().
|
|
*
|
|
* IMPORTANT: src[] must be a NUL terminated string! The len parameter
|
|
* does not include the NUL terminator.
|
|
*/
|
|
TOML_EXTERN toml_result_t toml_parse_named(const char *src, int len,
|
|
const char *name);
|
|
|
|
/**
|
|
* @brief Parse a TOML document from a file pointer.
|
|
*
|
|
* @param fp A pointer to the open file. The caller is responsible for closing
|
|
* it.
|
|
* @return A toml_result_t structure. Must be freed with toml_free().
|
|
*
|
|
* IMPORTANT: you are still responsible to fclose(fp).
|
|
*/
|
|
TOML_EXTERN toml_result_t toml_parse_file(FILE *fp);
|
|
|
|
/**
|
|
* @brief Parse a TOML document from a file pointer, tagging datums with a name.
|
|
*
|
|
* @param fp A pointer to the open file. The caller is responsible for closing
|
|
* it.
|
|
* @param name A source name copied into the result, or NULL.
|
|
* @return A toml_result_t structure. Must be freed with toml_free().
|
|
*
|
|
* IMPORTANT: you are still responsible to fclose(fp).
|
|
*/
|
|
TOML_EXTERN toml_result_t toml_parse_file_named(FILE *fp, const char *name);
|
|
|
|
/**
|
|
* @brief Parse a TOML document from a file path.
|
|
*
|
|
* @param fname The path to the TOML file.
|
|
* @return A toml_result_t structure. Must be freed with toml_free().
|
|
*/
|
|
TOML_EXTERN toml_result_t toml_parse_file_ex(const char *fname);
|
|
|
|
/**
|
|
* @brief Release resources allocated for a TOML result.
|
|
*
|
|
* @param result The TOML result to free.
|
|
*/
|
|
TOML_EXTERN void toml_free(toml_result_t result);
|
|
|
|
/**
|
|
* @brief Find a value for a specific key in a TOML table.
|
|
*
|
|
* @param table The TOML table to search in.
|
|
* @param key The key to look for.
|
|
* @return The value associated with the key, or a datum with type TOML_UNKNOWN
|
|
* if not found.
|
|
*/
|
|
TOML_EXTERN toml_datum_t toml_get(toml_datum_t table, const char *key);
|
|
|
|
/**
|
|
* @brief Locate a value using a multipart-key (e.g., "a.b.c").
|
|
*
|
|
* @param table The TOML table to start the search from.
|
|
* @param multipart_key A dot-separated key string. No escape characters
|
|
* allowed. Maximum length is 255 bytes.
|
|
* @return The value found, or a datum with type TOML_UNKNOWN if not found.
|
|
*/
|
|
TOML_EXTERN toml_datum_t toml_seek(toml_datum_t table,
|
|
const char *multipart_key);
|
|
|
|
/**
|
|
* @brief OBSOLETE: use toml_get() instead.
|
|
* Find a key in a toml_table. Return the value of the key if found,
|
|
* or a TOML_UNKNOWN otherwise.
|
|
*/
|
|
static inline toml_datum_t toml_table_find(toml_datum_t table,
|
|
const char *key) {
|
|
return toml_get(table, key);
|
|
}
|
|
|
|
/**
|
|
* @brief Merge two TOML results.
|
|
*
|
|
* All results (r1, r2, and the returned result) must be freed independently.
|
|
*
|
|
* @param r1 The base TOML result.
|
|
* @param r2 The TOML result containing overrides.
|
|
* @return A new toml_result_t representing the merged document.
|
|
*
|
|
* LOGIC:
|
|
* ret = copy of r1
|
|
* for each item x in r2:
|
|
* if x is not in ret:
|
|
* set x in ret
|
|
* elif x in ret is NOT of the same type:
|
|
* override
|
|
* elif x in ret is an array of tables:
|
|
* append r2.x to ret.x
|
|
* elif x in ret is a table:
|
|
* merge r2.x to ret.x
|
|
* else:
|
|
* override
|
|
*/
|
|
TOML_EXTERN toml_result_t toml_merge(const toml_result_t *r1,
|
|
const toml_result_t *r2);
|
|
|
|
/**
|
|
* @brief Compare two TOML results for equality.
|
|
*
|
|
* Comparison is sensitive to the order of elements in arrays and tables.
|
|
*
|
|
* @param r1 The first TOML result.
|
|
* @param r2 The second TOML result.
|
|
* @return True if they are equivalent, false otherwise.
|
|
*/
|
|
TOML_EXTERN bool toml_equiv(const toml_result_t *r1, const toml_result_t *r2);
|
|
|
|
/**
|
|
* @brief Global options for the TOML parser.
|
|
*/
|
|
typedef struct toml_option_t toml_option_t;
|
|
struct toml_option_t {
|
|
bool check_utf8; /**< If true, check if all characters are valid UTF-8.
|
|
Default: false. */
|
|
void *(*mem_realloc)(
|
|
void *ptr,
|
|
size_t size); /**< Custom realloc function. Default: realloc(). */
|
|
void (*mem_free)(void *ptr); /**< Custom free function. Default: free(). */
|
|
};
|
|
|
|
/**
|
|
* @brief Get the default parser options.
|
|
*
|
|
* Use this to obtain and initialize a toml_option_t structure before
|
|
* customizing it.
|
|
*
|
|
* @return A toml_option_t with default values.
|
|
*/
|
|
TOML_EXTERN toml_option_t toml_default_option(void);
|
|
|
|
/**
|
|
* @brief Set the global parser options.
|
|
*
|
|
* Call this only if you need to override the default behavior.
|
|
*
|
|
* @param opt The options to set.
|
|
*/
|
|
TOML_EXTERN void toml_set_option(toml_option_t opt);
|
|
|
|
#endif // TOMLC17_H
|