aboutsummaryrefslogtreecommitdiff
path: root/xs_po.h
diff options
context:
space:
mode:
Diffstat (limited to 'xs_po.h')
-rw-r--r--xs_po.h86
1 files changed, 86 insertions, 0 deletions
diff --git a/xs_po.h b/xs_po.h
new file mode 100644
index 0000000..c6feec9
--- /dev/null
+++ b/xs_po.h
@@ -0,0 +1,86 @@
+/* copyright (c) 2025 grunfink et al. / MIT license */
+
+#ifndef _XS_PO_H
+
+#define _XS_PO_H
+
+xs_dict *xs_po_to_dict(const char *fn);
+
+#ifdef XS_IMPLEMENTATION
+
+xs_dict *xs_po_to_dict(const char *fn)
+/* converts a PO file to a dict */
+{
+ xs_dict *d = NULL;
+ FILE *f;
+
+ if ((f = fopen(fn, "r")) != NULL) {
+ d = xs_dict_new();
+
+ xs *k = NULL;
+ xs *v = NULL;
+ enum { IN_NONE, IN_K, IN_V } mode = IN_NONE;
+
+ while (!feof(f)) {
+ xs *l = xs_strip_i(xs_readline(f));
+
+ /* discard empty lines and comments */
+ if (*l == '\0' || *l == '#')
+ continue;
+
+ if (xs_startswith(l, "msgid ")) {
+ if (mode == IN_V) {
+ /* flush */
+ if (xs_is_string(k) && xs_is_string(v) && *v)
+ d = xs_dict_set(d, k, v);
+
+ k = xs_free(k);
+ v = xs_free(v);
+ }
+
+ l = xs_replace_i(l, "msgid ", "");
+ mode = IN_K;
+
+ k = xs_str_new(NULL);
+ }
+ else
+ if (xs_startswith(l, "msgstr ")) {
+ if (mode != IN_K)
+ break;
+
+ l = xs_replace_i(l, "msgstr ", "");
+ mode = IN_V;
+
+ v = xs_str_new(NULL);
+ }
+
+ l = xs_replace_i(l, "\\n", "\n");
+ l = xs_strip_chars_i(l, "\"");
+
+ switch (mode) {
+ case IN_K:
+ k = xs_str_cat(k, l);
+ break;
+
+ case IN_V:
+ v = xs_str_cat(v, l);
+ break;
+
+ case IN_NONE:
+ break;
+ }
+ }
+
+ /* final flush */
+ if (xs_is_string(k) && xs_is_string(v) && *v)
+ d = xs_dict_set(d, k, v);
+
+ fclose(f);
+ }
+
+ return d;
+}
+
+#endif /* XS_IMPLEMENTATION */
+
+#endif /* XS_PO_H */