Advertisement
mdgaziur001

kv_parser

Apr 15th, 2024 (edited)
685
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.24 KB | None | 0 0
  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. struct Config {
  7.   bool  show_welcome;
  8.   bool  kill_yourself;
  9.   char* last_message;
  10. };
  11.  
  12. char *get_key(const char **buf) {
  13.   char *key = (char*)malloc(sizeof(char) * 12 + 1);
  14.   if (key == NULL) {
  15.     printf("Failed to allocate buffer for key\n");
  16.     return NULL;
  17.   }
  18.  
  19.   unsigned int key_size = 0;
  20.   unsigned int key_cap = 12;
  21.  
  22.   while (**buf != '\0' && **buf != '\n' && **buf != '=') {
  23.     if (**buf == ' ' || **buf == '\t') {
  24.       *buf = *buf + 1;
  25.       continue;
  26.     }
  27.  
  28.     if (key_size >= key_cap) {
  29.       key_cap *= 2;
  30.       key = realloc(key, sizeof(char) * key_cap + 1);
  31.       if (key == NULL) {
  32.         printf("Failed to reallocate buffer for key\n");
  33.         return NULL;
  34.       }
  35.     }
  36.  
  37.     key[key_size] = **buf;
  38.     key_size++;
  39.     *buf = *buf + 1;
  40.   }
  41.   key[key_size] = '\0';
  42.   return key;
  43. }
  44.  
  45. char *get_val(const char **buf) {
  46.   char *key = (char*)malloc(sizeof(char) * 12 + 1);
  47.   if (key == NULL) {
  48.     printf("Failed to allocate buffer for key\n");
  49.     return NULL;
  50.   }
  51.  
  52.   // eat whitespaces till we reach a valid character
  53.   while (**buf != '\0' && (**buf == ' '  || **buf == '\t')) {
  54.     *buf = *buf + 1;
  55.   }
  56.  
  57.   bool is_string = **buf == '"' ? true : false;
  58.   if (is_string) *buf = *buf + 1;
  59.  
  60.   unsigned int key_size = 0;
  61.   unsigned int key_cap = 12;
  62.  
  63.   while (**buf != '\0') {
  64.     if (is_string && **buf == '"') {
  65.       *buf = *buf + 1;
  66.       break;
  67.     } else if (**buf == '\n' || **buf == '=') {
  68.       break;
  69.     } else if (!is_string && (**buf == ' ' || **buf == '\t')) {
  70.       *buf = *buf + 1;
  71.       continue;
  72.     }
  73.  
  74.     if (key_size >= key_cap) {
  75.       key_cap *= 2;
  76.       key = realloc(key, sizeof(char) * key_cap + 1);
  77.       if (key == NULL) {
  78.         printf("Failed to reallocate buffer for key\n");
  79.         return NULL;
  80.       }
  81.     }
  82.  
  83.     key[key_size] = **buf;
  84.     key_size++;
  85.     *buf = *buf + 1;
  86.   }
  87.   key[key_size] = '\0';
  88.   return key;
  89. }
  90.  
  91. int parse_input(const char *buf, struct Config* cfg) {
  92.   while (*buf != '\0') {
  93.     char *key = get_key(&buf);
  94.     if (key == NULL) return 1;
  95.     buf++;
  96.  
  97.     char *val = get_val(&buf);
  98.     if (val == NULL) return 1;
  99.     buf++;
  100.  
  101.     if (strcmp(key, "show_welcome") == 0) {
  102.       if (strcmp(val, "true") == 0) {
  103.         cfg->show_welcome = true;
  104.       } else if (strcmp(val, "false") != 0) {
  105.         printf("WARNING: wrong type of value for `show_welcome`, defaulting to `false`\n");
  106.       }
  107.  
  108.       free(key);
  109.       free(val);
  110.     } else if (strcmp(key, "kill_yourself") == 0) {
  111.       if (strcmp(val, "true") == 0) {
  112.         cfg->kill_yourself = true;
  113.       } else if (strcmp(val, "false") != 0) {
  114.         printf("WARNING: wrong type of value for `kill_yourself`, defaulting to `false`\n");
  115.       }
  116.  
  117.       free(key);
  118.       free(val);
  119.     } else if (strcmp(key, "last_message") == 0) {
  120.       free(cfg->last_message);
  121.       cfg->last_message = val;
  122.      
  123.       free(key);
  124.     } else {
  125.       printf("WARNING: unknown key '%s'\n", key);
  126.       free(key);
  127.       free(val);
  128.     }
  129.   }
  130.   return 0;
  131. }
  132.  
  133. int main(int argc, const char** argv) {
  134.   if (argc < 2) {
  135.     printf("Usage: %s [FILE]\n", argv[0]);
  136.     return 0;
  137.   };
  138.  
  139.   FILE *fp = fopen(argv[1], "r");
  140.   if (fp == NULL) {
  141.     printf("Failed to open file: %s\n", argv[1]);
  142.     return 1;
  143.   }
  144.  
  145.   fseek(fp, 0L, SEEK_END);
  146.   unsigned int sz = ftell(fp);
  147.   rewind(fp);
  148.  
  149.   char *buf = (char*)malloc(sizeof(char) * sz + 1);
  150.   if (!buf) {
  151.     printf("Failed to create buffer\n");
  152.     return 1;
  153.   }
  154.  
  155.   fread(buf, sz, sizeof(char), fp);
  156.   buf[sz] = '\0';
  157.  
  158.   fflush(fp);
  159.   fclose(fp);
  160.  
  161.   struct Config *cfg = (struct Config*)malloc(sizeof(struct Config));
  162.   cfg->show_welcome = false;
  163.   cfg->kill_yourself = false;
  164.   cfg->last_message = (char*)malloc(sizeof(char));
  165.   cfg->last_message[0] = '\0';
  166.  
  167.   int ret = parse_input(buf, cfg);
  168.  
  169.   printf("Config {\n"
  170.          "\tshow_welcome: %s,\n"
  171.          "\tkill_yourself: %s,\n"
  172.          "\tlast_message: \"%s\"\n"
  173.          "}\n",
  174.          cfg->show_welcome ? "true" : "false",
  175.          cfg->kill_yourself ? "true" : "false",
  176.          cfg->last_message
  177.   );
  178.  
  179.   free(buf);
  180.   free(cfg->last_message);
  181.   free(cfg);
  182.  
  183.   return ret;
  184. }
  185.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement