star-stl

Load STereo Lithography (StL) file format
git clone git://git.meso-star.fr/star-stl.git
Log | Files | Refs | README | LICENSE

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 }