57ce37e678ecb6d4b1b73e40091b9c5f98f5d645
[raydungeon] / libs / imago / src / ftmodule.c
1 /*
2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010-2021 John Tsiombikas <nuclear@member.fsf.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include "ftmodule.h"
22
23 static struct list_node {
24         struct ftype_module *module;
25         struct list_node *next;
26 } *modules;
27
28 /* defined in modules.c which is generated by configure */
29 void img_modules_init();
30
31 static int done_init;
32
33 int img_register_module(struct ftype_module *mod)
34 {
35         struct list_node *node;
36
37         if(!(node = malloc(sizeof *node))) {
38                 return -1;
39         }
40
41         node->module = mod;
42         node->next = modules;
43         modules = node;
44         return 0;
45 }
46
47 struct ftype_module *img_find_format_module(struct img_io *io, const char *fname)
48 {
49         struct list_node *node;
50
51         if(!done_init) {
52                 img_modules_init();
53                 done_init = 1;
54         }
55
56         /* first attempt magic format detection */
57         node = modules;
58         while(node) {
59                 if(node->module->check(io) != -1) {
60                         return node->module;
61                 }
62                 node = node->next;
63         }
64
65         /* fallback to detecting by suffix if possible */
66         return fname ? img_guess_format(fname) : 0;
67 }
68
69 struct ftype_module *img_guess_format(const char *fname)
70 {
71         struct list_node *node;
72         char *suffix;
73         int suffix_len;
74
75         if(!done_init) {
76                 img_modules_init();
77                 done_init = 1;
78         }
79
80         if(!(suffix = strrchr(fname, '.'))) {
81                 return 0;       /* no suffix, can't guess ... */
82         }
83         suffix_len = (int)strlen(suffix);
84
85         node = modules;
86         while(node) {
87                 char *suflist = node->module->suffix;
88                 char *start, *end;
89
90                 while(*suflist) {
91                         if(!(start = strstr(suflist, suffix))) {
92                                 break;
93                         }
94                         end = start + suffix_len;
95
96                         if(*end == ':' || *end == 0) {
97                                 return node->module;    /* found it */
98                         }
99                         suflist = end;
100                 }
101
102                 node = node->next;
103         }
104         return 0;
105 }
106
107 struct ftype_module *img_get_module(int idx)
108 {
109         struct list_node *node;
110
111         if(!done_init) {
112                 img_modules_init();
113                 done_init = 1;
114         }
115
116         node = modules;
117         while(node && idx--) {
118                 node = node->next;
119         }
120         return node ? node->module : 0;
121 }