cg_catalog.c (9586B)
1 /* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA 2 * Copyright (C) 2022 CNRS 3 * Copyright (C) 2022 Sorbonne Université 4 * Copyright (C) 2022 Université Paul Sabatier 5 * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "cg.h" 21 #include "cg_building.h" 22 #include "cg_catalog.h" 23 #include "cg_catalog_parsing.h" 24 #include "cg_construction_mode_0.h" 25 #include "cg_construction_mode_1.h" 26 #include "cg_construction_mode_2.h" 27 #include "cg_construction_mode_0_parsing_schemas.h" 28 #include "cg_construction_mode_1_parsing_schemas.h" 29 #include "cg_construction_mode_2_parsing_schemas.h" 30 31 #include <rsys/rsys.h> 32 #include <rsys/mem_allocator.h> 33 #include <rsys/logger.h> 34 #include <rsys/str.h> 35 36 static const char* 37 find_first_filename 38 (const char* dataset_name, 39 const enum parsed_cmode_type dataset_cmode, 40 const struct parsed_catalog_items* items, 41 size_t count) 42 { 43 size_t i, j; 44 45 ASSERT(dataset_name && items && count > 0); 46 47 for(i = 0; i < count; i++) { 48 if(items[i].construction_mode != dataset_cmode) continue; 49 switch(items[i].construction_mode) { 50 case mode_0: { 51 const struct parsed_catalog_cmode_0* prsd_0 = items[i].parsed_data; 52 for(j = 0; j < prsd_0->datasets_count; j++) { 53 const struct parsed_dataset_cmode_0* prsd_item = prsd_0->datasets + j; 54 if(0 == strcmp(prsd_item->name, dataset_name)) { 55 return items[i].filename; 56 } 57 } 58 break; 59 } 60 case mode_1: { 61 const struct parsed_catalog_cmode_1* prsd_1 = items[i].parsed_data; 62 for(j = 0; j < prsd_1->datasets_count; j++) { 63 const struct parsed_dataset_cmode_1* prsd_item = prsd_1->datasets + j; 64 if(0 == strcmp(prsd_item->name, dataset_name)) { 65 return items[i].filename; 66 } 67 } 68 break; 69 } 70 case mode_2: { 71 const struct parsed_catalog_cmode_2* prsd_2 = items[i].parsed_data; 72 for(j = 0; j < prsd_2->datasets_count; j++) { 73 const struct parsed_dataset_cmode_2* prsd_item = prsd_2->datasets + j; 74 if(0 == strcmp(prsd_item->name, dataset_name)) { 75 return items[i].filename; 76 } 77 } 78 break; 79 } 80 default: FATAL("Invalid enum value."); 81 } 82 } 83 CHK(0); /* Should not be there */ 84 } 85 86 res_T 87 create_catalog 88 (struct mem_allocator* allocator, 89 struct logger* logger, 90 struct parsed_catalog* parsed_catalog, 91 struct catalog** out_catalog) 92 { 93 res_T res = RES_OK; 94 size_t i, j, count; 95 const struct parsed_catalog_items* items; 96 struct catalog* catalog; 97 struct str name; 98 int name_initialized = 0; 99 100 ASSERT(allocator && logger && parsed_catalog && out_catalog); 101 102 catalog = MEM_ALLOC(allocator, sizeof(*catalog)); 103 if(!catalog) { 104 res = RES_MEM_ERR; 105 goto error; 106 } 107 108 str_init(allocator, &name); 109 name_initialized = 0; 110 111 catalog->allocator = allocator; 112 catalog->logger = logger; 113 htable_dataset_cmode_0_init(allocator, &catalog->catalog_0); 114 htable_dataset_cmode_1_init(allocator, &catalog->catalog_1); 115 htable_dataset_cmode_2_init(allocator, &catalog->catalog_2); 116 count = darray_parsed_catalog_items_size_get(&parsed_catalog->catalog); 117 items = darray_parsed_catalog_items_cdata_get(&parsed_catalog->catalog); 118 119 for(i = 0; i < count; i++) { 120 switch(items[i].construction_mode) { 121 case mode_0: { 122 const struct parsed_catalog_cmode_0* parsed_0 = items[i].parsed_data; 123 for(j = 0; j < parsed_0->datasets_count; j++) { 124 const struct parsed_dataset_cmode_0* parsed_item 125 = parsed_0->datasets + j; 126 struct dataset_cmode_0 item; 127 ERR(str_set(&name, parsed_item->name)); 128 /* test name unicity */ 129 if(htable_dataset_cmode_0_find(&catalog->catalog_0, &name)) { 130 const char* first_filename 131 = find_first_filename(parsed_item->name, PARSED_CMODE_0, items, count); 132 logger_print(logger, LOG_ERROR, 133 "Duplicate dataset name: '%s' (in files '%s' and '%s').\n", 134 parsed_item->name, first_filename, items[i].filename); 135 res = RES_BAD_ARG; 136 goto error; 137 } 138 /* Setup item */ 139 item.wall_thickness = parsed_item->wall_thickness; 140 item.floor_thickness = parsed_item->floor_thickness; 141 ERR(htable_dataset_cmode_0_set(&catalog->catalog_0, &name, &item)); 142 } 143 break; 144 } 145 case mode_1: { 146 const struct parsed_catalog_cmode_1* parsed_1 = items[i].parsed_data; 147 for(j = 0; j < parsed_1->datasets_count; j++) { 148 const struct parsed_dataset_cmode_1* parsed_item 149 = parsed_1->datasets + j; 150 struct dataset_cmode_1 item; 151 ERR(str_set(&name, parsed_item->name)); 152 /* test name unicity */ 153 if(htable_dataset_cmode_1_find(&catalog->catalog_1, &name)) { 154 const char* first_filename 155 = find_first_filename(parsed_item->name, PARSED_CMODE_1, items, count); 156 logger_print(logger, LOG_ERROR, 157 "Duplicate dataset name: '%s' (in files '%s' and '%s').\n", 158 parsed_item->name, first_filename, items[i].filename); 159 res = RES_BAD_ARG; 160 goto error; 161 } 162 /* Setup item */ 163 item.inter_floor_count = parsed_item->inter_floor_count; 164 item.wall_thickness = parsed_item->wall_thickness; 165 item.floor_thickness = parsed_item->floor_thickness; 166 item.inter_floor_thickness = parsed_item->inter_floor_thickness; 167 item.roof_thickness = parsed_item->roof_thickness; 168 item.internal_insulation_thickness 169 = parsed_item->internal_insulation_thickness; 170 item.external_insulation_thickness 171 = parsed_item->external_insulation_thickness; 172 item.floor_insulation_thickness = parsed_item->floor_insulation_thickness; 173 item.roof_insulation_thickness = parsed_item->roof_insulation_thickness; 174 item.foundation_depth = parsed_item->foundation_depth; 175 item.crawl_height = parsed_item->crawl_height; 176 item.attic_height = parsed_item->attic_height; 177 item.glass_ratio = parsed_item->glass_ratio; 178 ERR(htable_dataset_cmode_1_set(&catalog->catalog_1, &name, &item)); 179 } 180 break; 181 } 182 case mode_2: { 183 const struct parsed_catalog_cmode_2* parsed_2 = items[i].parsed_data; 184 for(j = 0; j < parsed_2->datasets_count; j++) { 185 const struct parsed_dataset_cmode_2* parsed_item 186 = parsed_2->datasets + j; 187 struct dataset_cmode_2 item; 188 ERR(str_set(&name, parsed_item->name)); 189 /* test name unicity */ 190 if(htable_dataset_cmode_2_find(&catalog->catalog_2, &name)) { 191 const char* first_filename 192 = find_first_filename(parsed_item->name, PARSED_CMODE_2, items, count); 193 logger_print(logger, LOG_ERROR, 194 "Duplicate dataset name: '%s' (in files '%s' and '%s').\n", 195 parsed_item->name, first_filename, items[i].filename); 196 res = RES_BAD_ARG; 197 goto error; 198 } 199 /* Setup item */ 200 item.wall_thickness = parsed_item->wall_thickness; 201 item.floor_thickness = parsed_item->floor_thickness; 202 item.inter_floor_thickness = parsed_item->inter_floor_thickness; 203 item.roof_thickness = parsed_item->roof_thickness; 204 item.internal_insulation_thickness 205 = parsed_item->internal_insulation_thickness; 206 item.external_insulation_thickness 207 = parsed_item->external_insulation_thickness; 208 item.floor_insulation_thickness = parsed_item->floor_insulation_thickness; 209 item.roof_insulation_thickness = parsed_item->roof_insulation_thickness; 210 item.foundation_depth = parsed_item->foundation_depth; 211 item.crawl_height = parsed_item->crawl_height; 212 item.has_attic = parsed_item->has_attic; 213 item.glass_ratio = parsed_item->glass_ratio; 214 item.windows_min_width = parsed_item->windows_min_width; 215 item.windows_max_width = parsed_item->windows_max_width; 216 item.windows_min_spacing = parsed_item->windows_min_spacing; 217 item.windows_height_ratio = parsed_item->windows_height_ratio; 218 ERR(htable_dataset_cmode_2_set(&catalog->catalog_2, &name, &item)); 219 } 220 break; 221 } 222 default: FATAL("Invalid enum value."); 223 } 224 } 225 exit: 226 if(name_initialized) str_release(&name); 227 *out_catalog = catalog; 228 return res; 229 error: 230 release_catalog(catalog); 231 catalog = NULL; 232 goto exit; 233 } 234 235 void 236 release_catalog 237 (struct catalog* catalog) 238 { 239 if(!catalog) return; 240 241 htable_dataset_cmode_0_release(&catalog->catalog_0); 242 htable_dataset_cmode_1_release(&catalog->catalog_1); 243 htable_dataset_cmode_2_release(&catalog->catalog_2); 244 MEM_RM(catalog->allocator, catalog); 245 } 246