main xs_po.h
 1/* copyright (c) 2025 - 2026 grunfink et al. / MIT license */
 2
 3#ifndef _XS_PO_H
 4
 5#define _XS_PO_H
 6
 7#include "xs.h"
 8#include "xs_io.h"
 9
10xs_dict *xs_po_to_dict(const char *fn);
11
12#ifdef XS_IMPLEMENTATION
13
14xs_dict *xs_po_to_dict(const char *fn)
15/* converts a PO file to a dict */
16{
17    xs_dict *d = NULL;
18    FILE *f;
19
20    if ((f = fopen(fn, "r")) != NULL) {
21        d = xs_dict_new();
22
23        xs *k = NULL;
24        xs *v = NULL;
25        enum { IN_NONE, IN_K, IN_V } mode = IN_NONE;
26
27        while (!feof(f)) {
28            xs *l = xs_strip_i(xs_readline(f));
29
30            /* discard empty lines and comments */
31            if (*l == '\0' || *l == '#')
32                continue;
33
34            if (xs_startswith(l, "msgid ")) {
35                if (mode == IN_V) {
36                    /* flush */
37                    if (xs_is_string(k) && xs_is_string(v) && *v)
38                        d = xs_dict_set(d, k, v);
39
40                    k = xs_free(k);
41                    v = xs_free(v);
42                }
43
44                l = xs_replace_i(l, "msgid ", "");
45                mode = IN_K;
46
47                k = xs_str_new(NULL);
48            }
49            else
50            if (xs_startswith(l, "msgstr ")) {
51                if (mode != IN_K)
52                    break;
53
54                l = xs_replace_i(l, "msgstr ", "");
55                mode = IN_V;
56
57                v = xs_str_new(NULL);
58            }
59
60            l = xs_replace_i(l, "\\n", "\n");
61            l = xs_strip_chars_i(l, "\"");
62
63            switch (mode) {
64            case IN_K:
65                k = xs_str_cat(k, l);
66                break;
67
68            case IN_V:
69                v = xs_str_cat(v, l);
70                break;
71
72            case IN_NONE:
73                break;
74            }
75        }
76
77        /* final flush */
78        if (xs_is_string(k) && xs_is_string(v) && *v)
79            d = xs_dict_set(d, k, v);
80
81        fclose(f);
82    }
83
84    return d;
85}
86
87#endif /* XS_IMPLEMENTATION */
88
89#endif /* XS_PO_H */