QUOTE: Life is tough, but so are you.

main.c - aoc - Advent of Code challenges

aoc

Advent of Code challenges
git clone git@soophie.de:/srv/git/aoc
log | files | refs

main.c (2767B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <dlfcn.h>
      5 #include <time.h>
      6 #include <wchar.h>
      7 
      8 typedef struct {
      9   char *uid;
     10   void *handle;
     11   long (*perform)(char *data);
     12 } task_t;
     13 
     14 char *load_data(char *task_uid) {
     15   // convert YEAR_MT_ST to YEAR_MT
     16   int task_uid_len = strlen(task_uid);
     17   int idx = 0;
     18   for (int i = 0; i < task_uid_len; i++) {
     19     char c = task_uid[i];
     20     if (c == '_') {
     21       idx = i;
     22     }
     23   }
     24   char task_uid_base[idx + 1];
     25   snprintf(task_uid_base, idx + 1, "%s", task_uid);
     26   char filename[100];
     27   snprintf(filename, 100, "txt/%s.txt", task_uid_base);
     28   FILE *fp = fopen(filename, "r");
     29   if (fp == NULL) {
     30     return NULL;
     31   }
     32   fseek(fp, 0, SEEK_END);
     33   int len = ftell(fp);
     34   fseek(fp, 0, SEEK_SET);
     35   char *data = calloc(len + 1, sizeof(char));
     36   fread(data, sizeof(char), len, fp);
     37   data[len] = '\0';
     38   return data;
     39 }
     40 
     41 void load_task(task_t *task, char *task_uid) {
     42   task->uid = task_uid;
     43   char cmd[100];
     44   snprintf(cmd, 100, "cc -shared -fPIC -o %s.so -Werror -Wextra -Wall -lm -pedantic src/tasks/aoc_%s.c", task_uid, task_uid);
     45   FILE *fp = popen(cmd, "r");
     46   if (fp == NULL) {
     47     return;
     48   }
     49   pclose(fp);
     50   char filename[100];
     51   snprintf(filename, 100, "./%s.so", task_uid);
     52   task->handle = dlopen(filename, RTLD_LAZY);
     53   if (task->handle == NULL) {
     54     printf("Error: failed to load task %s!\n%s\n", task_uid, dlerror());
     55     return;
     56   }
     57   task->perform = dlsym(task->handle, "perform");
     58   char *err = dlerror();
     59   if (err != 0) {
     60     printf("Error: failed to link task function %s!\n%s\n", task_uid, err);
     61     return;
     62   }
     63 }
     64 
     65 void unload_task(task_t *task) {
     66   if (task == NULL || task->handle == NULL) {
     67     return;
     68   }
     69   dlclose(task->handle);
     70   char cmd[100];
     71   snprintf(cmd, 100, "rm %s.so", task->uid);
     72   FILE *fp = popen(cmd, "r");
     73   if (fp == NULL) {
     74     return;
     75   }
     76   pclose(fp);
     77 }
     78 
     79 int main(int argc, char **argv) {
     80   if (argc < 2) {
     81     printf("Error: Usage: aoc <task-id>\n");
     82     return 1;
     83   }
     84   char *task_uid = argv[1];
     85   task_t task = { NULL, NULL, NULL };
     86   load_task(&task, task_uid);
     87   if (task.handle == NULL) {
     88     return 1;
     89   }
     90   char *data = load_data(task_uid);
     91   printf("task_uid: %s\n", task_uid);
     92   struct timespec time_set;
     93   clock_gettime(CLOCK_MONOTONIC, &time_set);
     94   long result = task.perform(data);
     95   struct timespec time_end;
     96   clock_gettime(CLOCK_MONOTONIC, &time_end);
     97   unload_task(&task);
     98   if (data != NULL) {
     99     free(data);
    100   }
    101   long dur_sec = time_end.tv_sec - time_set.tv_sec;
    102   long dur_ns = time_end.tv_nsec - time_set.tv_nsec;
    103   long dur_ms = dur_ns / 1000000;
    104   long dur_ys = (dur_ns / 1000) % 1000;
    105   dur_ns = dur_ns % 1000;
    106   printf("time: %lds %ldms %ldµs %ldns\n", dur_sec, dur_ms, dur_ys, dur_ns);
    107   printf("result: %ld\n", result);
    108   return 0;
    109 }