| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- //
- // Copyright 2026 Aarav Ravindra Kharade
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file 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.
- //
- #include "ark_parser.h"
- static void strip_newline(char *str) {
- int len = strlen(str);
- while (len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r')) {
- str[len - 1] = '\0';
- len--;
- }
- }
- static char *trim_whitespace(char *str) {
- while (*str == ' ' || *str == '\t')
- str++;
- int len = strlen(str);
- while (len > 0 && (str[len - 1] == ' ' || str[len - 1] == '\t')) {
- str[len - 1] = '\0';
- len--;
- }
- return str;
- }
- ArkConfig *ark_parse(const char *filepath) {
- ArkConfig *config = (ArkConfig *)malloc(sizeof(ArkConfig));
- memset(config, 0, sizeof(ArkConfig));
- strncpy(config->filepath, filepath, sizeof(config->filepath) - 1);
- FILE *f = fopen(filepath, "r");
- if (!f)
- return config;
- char line[MAX_LINE_LEN];
- ArkSection *curr_sec = NULL;
- while (fgets(line, sizeof(line), f)) {
- strip_newline(line);
- char *trimmed = trim_whitespace(line);
- if (strlen(trimmed) == 0 || trimmed[0] == '#')
- continue;
- // Check for section
- if (strncmp(trimmed, "---", 3) == 0) {
- char *end = strstr(trimmed + 3, "---");
- if (end && config->section_count < MAX_SECTIONS) {
- *end = '\0';
- curr_sec = &config->sections[config->section_count++];
- strncpy(curr_sec->name, trim_whitespace(trimmed + 3), 255);
- }
- continue;
- }
- // Check for Key=Value or Key:Value
- char *sep = strchr(trimmed, '=');
- if (!sep)
- sep = strchr(trimmed, ':');
- if (sep) {
- *sep = '\0';
- char *key = trim_whitespace(trimmed);
- char *val = trim_whitespace(sep + 1);
- if (curr_sec) {
- if (curr_sec->pair_count < MAX_KEYS) {
- strncpy(curr_sec->pairs[curr_sec->pair_count].key, key, 255);
- strncpy(curr_sec->pairs[curr_sec->pair_count].value, val, 511);
- curr_sec->pair_count++;
- }
- } else {
- if (config->global_count < MAX_KEYS) {
- strncpy(config->global_pairs[config->global_count].key, key, 255);
- strncpy(config->global_pairs[config->global_count].value, val, 511);
- config->global_count++;
- }
- }
- } else {
- if (config->standalone_count < MAX_STANDALONE) {
- strncpy(config->standalone[config->standalone_count++], trimmed, 511);
- }
- }
- }
- fclose(f);
- return config;
- }
- const char *ark_get_global(ArkConfig *config, const char *key) {
- for (int i = 0; i < config->global_count; i++) {
- if (strcmp(config->global_pairs[i].key, key) == 0) {
- return config->global_pairs[i].value;
- }
- }
- return NULL;
- }
- const char *ark_get_section_val(ArkConfig *config, const char *section,
- const char *key) {
- for (int i = 0; i < config->section_count; i++) {
- if (strcmp(config->sections[i].name, section) == 0) {
- for (int j = 0; j < config->sections[i].pair_count; j++) {
- if (strcmp(config->sections[i].pairs[j].key, key) == 0) {
- return config->sections[i].pairs[j].value;
- }
- }
- }
- }
- return NULL;
- }
- void ark_set_global(ArkConfig *config, const char *key, const char *value) {
- for (int i = 0; i < config->global_count; i++) {
- if (strcmp(config->global_pairs[i].key, key) == 0) {
- strncpy(config->global_pairs[i].value, value, 511);
- return;
- }
- }
- if (config->global_count < MAX_KEYS) {
- strncpy(config->global_pairs[config->global_count].key, key, 255);
- strncpy(config->global_pairs[config->global_count].value, value, 511);
- config->global_count++;
- }
- }
- void ark_dump(ArkConfig *config, const char *filepath) {
- FILE *f = fopen(filepath, "w");
- if (!f)
- return;
- for (int i = 0; i < config->global_count; i++) {
- fprintf(f, "%s = %s\n", config->global_pairs[i].key,
- config->global_pairs[i].value);
- }
- for (int i = 0; i < config->section_count; i++) {
- fprintf(f, "\n--- %s ---\n\n", config->sections[i].name);
- for (int j = 0; j < config->sections[i].pair_count; j++) {
- fprintf(f, "%s = %s\n", config->sections[i].pairs[j].key,
- config->sections[i].pairs[j].value);
- }
- }
- if (config->standalone_count > 0) {
- fprintf(f, "\n");
- for (int i = 0; i < config->standalone_count; i++) {
- fprintf(f, "%s\n", config->standalone[i]);
- }
- }
- fclose(f);
- }
- void ark_free(ArkConfig *config) {
- if (config)
- free(config);
- }
- /* ── List Value Support ────────────────────────────────────────── */
- static ArkList parse_csv(const char *value) {
- ArkList list;
- memset(&list, 0, sizeof(ArkList));
- if (!value)
- return list;
- char buf[512];
- strncpy(buf, value, sizeof(buf) - 1);
- buf[sizeof(buf) - 1] = '\0';
- char *token = strtok(buf, ",");
- while (token && list.count < MAX_LIST_ITEMS) {
- char *trimmed = trim_whitespace(token);
- if (strlen(trimmed) > 0) {
- strncpy(list.items[list.count], trimmed, 255);
- list.count++;
- }
- token = strtok(NULL, ",");
- }
- return list;
- }
- ArkList ark_get_list(ArkConfig *config, const char *key) {
- const char *val = ark_get_global(config, key);
- return parse_csv(val);
- }
- ArkList ark_get_section_list(ArkConfig *config, const char *section,
- const char *key) {
- const char *val = ark_get_section_val(config, section, key);
- return parse_csv(val);
- }
- /* ── Boolean Value Support ─────────────────────────────────────── */
- static int parse_bool(const char *value, int default_val) {
- if (!value)
- return default_val;
- if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 ||
- strcmp(value, "1") == 0 || strcmp(value, "on") == 0)
- return 1;
- if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 ||
- strcmp(value, "0") == 0 || strcmp(value, "off") == 0)
- return 0;
- return default_val;
- }
- int ark_get_bool(ArkConfig *config, const char *key, int default_val) {
- const char *val = ark_get_global(config, key);
- return parse_bool(val, default_val);
- }
- int ark_get_section_bool(ArkConfig *config, const char *section,
- const char *key, int default_val) {
- const char *val = ark_get_section_val(config, section, key);
- return parse_bool(val, default_val);
- }
|