sstl_main.c (5274B)
1 /* Copyright (C) 2015, 2016, 2019, 2021, 2023, 2025 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #define _POSIX_C_SOURCE 200112L /* getopt support */ 17 18 #include "sstl.h" 19 20 #include <rsys/mem_allocator.h> 21 #include <unistd.h> /* getopt */ 22 23 struct args { 24 /* List of input meshes. 25 * Empty list means that a mesh is read from standard */ 26 char* const* meshes; 27 unsigned nmeshes; 28 29 enum sstl_type type; /* Type of input meshes */ 30 int verbose; /* Verbosity level */ 31 int quit; 32 }; 33 static const struct args ARGS_DEFAULT = {NULL, 0, SSTL_NONE__, 0, 0}; 34 35 struct cmd { 36 struct args args; 37 struct sstl* sstl; 38 }; 39 static const struct cmd CMD_NULL = {0}; 40 41 /******************************************************************************* 42 * Helper functions 43 ******************************************************************************/ 44 static INLINE void 45 usage(FILE* stream) 46 { 47 fprintf(stream, "usage: sstl [-abhv] [file ...]\n"); 48 } 49 50 static res_T 51 args_init(struct args* args, int argc, char** argv) 52 { 53 int opt = 0; 54 res_T res = RES_OK; 55 56 *args = ARGS_DEFAULT; 57 58 while((opt = getopt(argc, argv, "abhv")) != -1) { 59 switch(opt) { 60 case 'a': args->type = SSTL_ASCII; break; 61 case 'b': args->type = SSTL_BINARY; break; 62 case 'h': 63 usage(stdout); 64 args->quit = 1; 65 goto exit; 66 case 'v': args->verbose += (args->verbose < 3); break; 67 default: res = RES_BAD_ARG; break; 68 } 69 if(res != RES_OK) goto error; 70 } 71 72 /* Setup the list of meshes */ 73 args->meshes = argv + optind; 74 args->nmeshes = (unsigned)(argc - optind); 75 76 if(!args->nmeshes && args->type == SSTL_NONE__) { 77 fprintf(stderr, 78 "StL type must be defined for reading on stdin " 79 "-- options '-a' or -b'\n"); 80 res = RES_BAD_ARG; 81 goto error; 82 } 83 84 exit: 85 return res; 86 error: 87 usage(stderr); 88 goto exit; 89 } 90 91 static INLINE void 92 cmd_release(struct cmd* cmd) 93 { 94 if(cmd->sstl) SSTL(ref_put(cmd->sstl)); 95 } 96 97 static INLINE res_T 98 cmd_init(struct cmd* cmd, const struct args* args) 99 { 100 res_T res = RES_OK; 101 ASSERT(cmd && args); 102 103 cmd->args = *args; 104 105 res = sstl_create(NULL, NULL, args->verbose, &cmd->sstl); 106 if(res != RES_OK) goto error; 107 108 exit: 109 return res; 110 error: 111 cmd_release(cmd); 112 goto exit; 113 } 114 115 static INLINE const char* 116 type_to_cstr(const enum sstl_type type) 117 { 118 const char* cstr = NULL; 119 switch(type) { 120 case SSTL_ASCII: cstr = "ascii"; break; 121 case SSTL_BINARY: cstr = "binary"; break; 122 default: FATAL("Unreachable code"); break; 123 } 124 return cstr; 125 } 126 127 static INLINE void 128 print_info(const struct cmd* cmd) 129 { 130 struct sstl_desc desc = SSTL_DESC_NULL; 131 ASSERT(cmd); 132 133 SSTL(get_desc(cmd->sstl, &desc)); 134 printf("%s\t%s\t%lu\t%lu\t%s\n", 135 type_to_cstr(desc.type), 136 desc.solid_name ? desc.solid_name : "null", 137 (unsigned long)desc.triangles_count, 138 (unsigned long)desc.vertices_count, 139 desc.filename); 140 } 141 142 static INLINE res_T 143 cmd_run(const struct cmd* cmd) 144 { 145 res_T res = RES_OK; 146 ASSERT(cmd); 147 148 /* Read from the standard input */ 149 if(!cmd->args.nmeshes) { 150 switch(cmd->args.type) { 151 case SSTL_ASCII: 152 res = sstl_load_stream_ascii(cmd->sstl, stdin, "stdin (ASCII)"); 153 break; 154 case SSTL_BINARY: 155 res = sstl_load_stream_binary(cmd->sstl, stdin, "stdin (binary)"); 156 break; 157 default: FATAL("Unreachable code"); break; 158 } 159 if(res != RES_OK) goto error; 160 print_info(cmd); 161 162 /* Load files */ 163 } else { 164 unsigned i; 165 FOR_EACH(i, 0, cmd->args.nmeshes) { 166 switch(cmd->args.type) { 167 case SSTL_ASCII: 168 res = sstl_load_ascii(cmd->sstl, cmd->args.meshes[i]); 169 break; 170 case SSTL_BINARY: 171 res = sstl_load_binary(cmd->sstl, cmd->args.meshes[i]); 172 break; 173 case SSTL_NONE__: 174 res = sstl_load(cmd->sstl, cmd->args.meshes[i]); 175 break; 176 default: FATAL("Unreachable code"); break; 177 } 178 if(res != RES_OK) goto error; 179 print_info(cmd); 180 } 181 } 182 183 exit: 184 return res; 185 error: 186 goto exit; 187 } 188 189 /******************************************************************************* 190 * The program 191 ******************************************************************************/ 192 int 193 main(int argc, char** argv) 194 { 195 struct args args = ARGS_DEFAULT; 196 struct cmd cmd = CMD_NULL; 197 int err = 0; 198 res_T res = RES_OK; 199 200 if((res = args_init(&args, argc, argv)) != RES_OK) goto error; 201 if(args.quit) goto exit; 202 203 if((res = cmd_init(&cmd, &args)) != RES_OK) goto error; 204 if((res = cmd_run(&cmd)) != RES_OK) goto error; 205 206 exit: 207 cmd_release(&cmd); 208 CHK(mem_allocated_size() == 0); 209 return err; 210 error: 211 err = 1; 212 goto exit; 213 }