main
xs_mime.h
1/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */
2
3#ifndef _XS_MIME_H
4
5#define _XS_MIME_H
6
7#include "xs.h"
8
9const char *xs_mime_by_ext(const char *file);
10
11extern const char *xs_mime_types[];
12
13#ifdef XS_IMPLEMENTATION
14
15/* intentionally brain-dead simple */
16/* CAUTION: sorted by extension */
17
18const char *xs_mime_types[] = {
19 "3gp", "video/3gpp",
20 "aac", "audio/aac",
21 "apng", "image/apng",
22 "avif", "image/avif",
23 "css", "text/css",
24 "flac", "audio/flac",
25 "flv", "video/flv",
26 "gif", "image/gif",
27 "gmi", "text/gemini",
28 "html", "text/html",
29 "jpeg", "image/jpeg",
30 "jpg", "image/jpeg",
31 "json", "application/json",
32 "m4a", "audio/aac",
33 "m4v", "video/mp4",
34 "md", "text/markdown",
35 "mov", "video/quicktime",
36 "mp3", "audio/mp3",
37 "mp4", "video/mp4",
38 "mpg4", "video/mp4",
39 "oga", "audio/ogg",
40 "ogg", "audio/ogg",
41 "ogv", "video/ogg",
42 "opus", "audio/ogg",
43 "png", "image/png",
44 "svg", "image/svg+xml",
45 "svgz", "image/svg+xml",
46 "txt", "text/plain",
47 "wav", "audio/wav",
48 "webm", "video/webm",
49 "webp", "image/webp",
50 "wma", "audio/wma",
51 "xml", "text/xml",
52 NULL, NULL,
53};
54
55
56const char *xs_mime_by_ext(const char *file)
57/* returns the MIME type by file extension */
58{
59 const char *ext = strrchr(file, '.');
60
61 if (ext) {
62 xs *uext = xs_tolower_i(xs_dup(ext + 1));
63 int b = 0;
64 int t = xs_countof(xs_mime_types) / 2 - 2;
65
66 while (t >= b) {
67 int n = (b + t) / 2;
68 const char *p = xs_mime_types[n * 2];
69
70 int c = strcmp(uext, p);
71
72 if (c < 0)
73 t = n - 1;
74 else
75 if (c > 0)
76 b = n + 1;
77 else
78 return xs_mime_types[(n * 2) + 1];
79 }
80 }
81
82 return "application/octet-stream";
83}
84
85
86#endif /* XS_IMPLEMENTATION */
87
88#endif /* XS_MIME_H */