smsh-desc.c (5305B)
1 /* Copyright (C) 2020-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 General Public License for more details. 12 * 13 * You should have received a copy of the GNU 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 "smsh.h" 19 20 #include <rsys/cstr.h> 21 #include <rsys/mem_allocator.h> 22 #include <rsys/str.h> 23 24 #include <errno.h> 25 #include <unistd.h> /* getopt */ 26 27 enum query_flag { 28 QUERY_DCELL = BIT(0), 29 QUERY_DNODE = BIT(1), 30 QUERY_NCELLS = BIT(2), 31 QUERY_NNODES = BIT(3), 32 QUERY_PAGESIZE = BIT(4), 33 QUERY_ALL = ~0 34 }; 35 36 /* Input arguments */ 37 struct args { 38 const char* mesh; 39 int query_mask; /* Cmbination of query flag */ 40 }; 41 static const struct args ARGS_DEFAULT = {0}; 42 43 /* Command data */ 44 struct cmd { 45 struct args args; 46 struct smsh* mesh; /* Tetrahedral mesh */ 47 uint64_t pagesize; 48 }; 49 static const struct cmd CMD_NULL = {0}; 50 51 /******************************************************************************* 52 * Helper functions 53 ******************************************************************************/ 54 static INLINE void 55 usage(FILE* stream) 56 { 57 fprintf(stream, "usage: smsh-desc [-cdnpt] mesh\n"); 58 } 59 60 static res_T 61 args_init(struct args* args, const int argc, char** argv) 62 { 63 int opt = 0; 64 res_T res = RES_OK; 65 66 *args = ARGS_DEFAULT; 67 68 while((opt = getopt(argc, argv, "cdnpqt")) != -1) { 69 switch(opt) { 70 case 'c': args->query_mask |= QUERY_NCELLS; break; 71 case 'd': args->query_mask |= QUERY_DNODE; break; 72 case 'n': args->query_mask |= QUERY_NNODES; break; 73 case 'p': args->query_mask |= QUERY_PAGESIZE; break; 74 case 't': args->query_mask |= QUERY_DCELL; break; 75 default: res = RES_BAD_ARG; 76 } 77 if(res != RES_OK) goto error; 78 } 79 80 if(optind < argc) args->mesh = argv[optind]; 81 82 /* By default, query all */ 83 if(!args->query_mask) args->query_mask = QUERY_ALL; 84 85 if(!args->mesh) { 86 fprintf(stderr, "mesh is missing\n"); 87 res = RES_BAD_ARG; 88 goto error; 89 } 90 91 exit: 92 return res; 93 error: 94 usage(stderr); 95 goto exit; 96 } 97 98 static res_T 99 setup_mesh(struct cmd* cmd, const struct args* args) 100 { 101 struct smsh_create_args create_args = SMSH_CREATE_ARGS_DEFAULT; 102 struct smsh_load_args load_args = SMSH_LOAD_ARGS_NULL; 103 FILE* fp = NULL; 104 res_T res = RES_OK; 105 ASSERT(cmd && args); 106 107 if(!(fp = fopen(args->mesh, "r"))) { 108 fprintf(stderr, "%s: %s\n", args->mesh, strerror(errno)); 109 res = RES_IO_ERR; 110 goto error; 111 } 112 if(fread(&cmd->pagesize, sizeof(uint64_t), 1, fp) != 1) { 113 fprintf(stderr, "%s: %s\n", args->mesh, strerror(errno)); 114 res = RES_IO_ERR; 115 goto error; 116 } 117 118 create_args.verbose = 1; 119 if((res = smsh_create(&create_args, &cmd->mesh)) != RES_OK) goto error; 120 121 load_args.path = args->mesh; 122 if((res = smsh_load(cmd->mesh, &load_args)) != RES_OK) goto error; 123 124 exit: 125 if(fp) CHK(fclose(fp) == 0); 126 return res; 127 error: 128 if(cmd->mesh) { SMSH(ref_put(cmd->mesh)); cmd->mesh = NULL; } 129 goto exit; 130 } 131 132 static void 133 cmd_release(struct cmd* cmd) 134 { 135 ASSERT(cmd); 136 if(cmd->mesh) SMSH(ref_put(cmd->mesh)); 137 } 138 139 static res_T 140 cmd_init(struct cmd* cmd, const struct args* args) 141 { 142 res_T res = RES_OK; 143 ASSERT(cmd && args && args->query_mask); 144 145 if((res = setup_mesh(cmd, args)) != RES_OK) goto error; 146 cmd->args = *args; 147 148 exit: 149 return res; 150 error: 151 cmd_release(cmd); 152 goto exit; 153 } 154 155 static res_T 156 cmd_run(struct cmd* cmd) 157 { 158 struct smsh_desc desc = SMSH_DESC_NULL; 159 struct str str; 160 res_T res = RES_OK; 161 ASSERT(cmd); 162 163 str_init(NULL, &str); 164 SMSH(get_desc(cmd->mesh, &desc)); 165 166 #define APPEND(Fmt, Val) { \ 167 if((res = str_append_printf(&str, Fmt, (Val))) != RES_OK) goto error; \ 168 } (void)0 169 if(cmd->args.query_mask & QUERY_PAGESIZE) APPEND("%zu ", cmd->pagesize); 170 if(cmd->args.query_mask & QUERY_NNODES) APPEND("%zu ", desc.nnodes); 171 if(cmd->args.query_mask & QUERY_NCELLS) APPEND("%zu ", desc.ncells); 172 if(cmd->args.query_mask & QUERY_DNODE) APPEND("%u ", desc.dnode); 173 if(cmd->args.query_mask & QUERY_DCELL) APPEND("%u ", desc.dcell); 174 APPEND("%s", cmd->args.mesh); 175 #undef APPEND 176 177 printf("%s\n", str_cget(&str)); 178 179 exit: 180 str_release(&str); 181 return res; 182 error: 183 fprintf(stderr, "error: %s\n", res_to_cstr(res)); 184 goto exit; 185 } 186 187 /******************************************************************************* 188 * The program 189 ******************************************************************************/ 190 int 191 main(int argc, char** argv) 192 { 193 struct args args = ARGS_DEFAULT; 194 struct cmd cmd = CMD_NULL; 195 int err = 0; 196 res_T res = RES_OK; 197 198 if((res = args_init(&args, argc, argv)) != RES_OK) goto error; 199 if((res = cmd_init(&cmd, &args)) != RES_OK) goto error; 200 if((res = cmd_run(&cmd)) != RES_OK) goto error; 201 202 exit: 203 cmd_release(&cmd); 204 CHK(mem_allocated_size() == 0); 205 return err; 206 error: 207 err = 1; 208 goto exit; 209 }