| 1 | // =============================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : ad_config.cxx // |
|---|
| 4 | // Purpose : editor configurations (aka species selections) // |
|---|
| 5 | // // |
|---|
| 6 | // Coded by Ralf Westram (coder@reallysoft.de) in May 2005 // |
|---|
| 7 | // Institute of Microbiology (Technical University Munich) // |
|---|
| 8 | // http://www.arb-home.de/ // |
|---|
| 9 | // // |
|---|
| 10 | // =============================================================== // |
|---|
| 11 | |
|---|
| 12 | #include "gb_local.h" |
|---|
| 13 | |
|---|
| 14 | #include <ad_config.h> |
|---|
| 15 | #include <arbdbt.h> |
|---|
| 16 | |
|---|
| 17 | #include <arb_defs.h> |
|---|
| 18 | #include <arb_strarray.h> |
|---|
| 19 | |
|---|
| 20 | void GBT_get_configuration_names(ConstStrArray& configNames, GBDATA *gb_main) { |
|---|
| 21 | /* returns existing configurations in 'configNames' |
|---|
| 22 | * Note: automatically generates names for configs w/o legal name. |
|---|
| 23 | */ |
|---|
| 24 | |
|---|
| 25 | GB_transaction ta(gb_main); |
|---|
| 26 | GBDATA *gb_config_data = GB_search(gb_main, CONFIG_DATA_PATH, GB_CREATE_CONTAINER); |
|---|
| 27 | |
|---|
| 28 | if (gb_config_data) { |
|---|
| 29 | int unnamed_count = 0; |
|---|
| 30 | |
|---|
| 31 | configNames.reserve(GB_number_of_subentries(gb_config_data)); |
|---|
| 32 | |
|---|
| 33 | for (GBDATA *gb_config = GB_entry(gb_config_data, CONFIG_ITEM); |
|---|
| 34 | gb_config; |
|---|
| 35 | gb_config = GB_nextEntry(gb_config)) |
|---|
| 36 | { |
|---|
| 37 | const char *name = GBT_read_char_pntr(gb_config, "name"); |
|---|
| 38 | |
|---|
| 39 | if (!name || name[0] == 0) { // no name or empty name |
|---|
| 40 | char *new_name = GBS_global_string_copy("<unnamed%i>", ++unnamed_count); |
|---|
| 41 | GB_ERROR error = GBT_write_string(gb_config, "name", new_name); |
|---|
| 42 | |
|---|
| 43 | if (error) { |
|---|
| 44 | GB_warningf("Failed to rename unnamed configuration to '%s'", new_name); |
|---|
| 45 | freenull(new_name); |
|---|
| 46 | name = NULp; |
|---|
| 47 | } |
|---|
| 48 | else { |
|---|
| 49 | name = GBT_read_char_pntr(gb_config, "name"); |
|---|
| 50 | } |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | if (name) configNames.put(name); |
|---|
| 54 | } |
|---|
| 55 | } |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | GBDATA *GBT_find_configuration(GBDATA *gb_main, const char *name) { |
|---|
| 59 | GBDATA *gb_config_data = GB_search(gb_main, CONFIG_DATA_PATH, GB_DB); |
|---|
| 60 | GBDATA *gb_config_name = GB_find_string(gb_config_data, "name", name, GB_IGNORE_CASE, SEARCH_GRANDCHILD); |
|---|
| 61 | return gb_config_name ? GB_get_father(gb_config_name) : NULp; |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | static GBDATA *findOrCreate_configuration(GBDATA *gb_main, const char *name) { |
|---|
| 65 | GBDATA *gb_config = GBT_find_configuration(gb_main, name); |
|---|
| 66 | if (!gb_config) { |
|---|
| 67 | GBDATA *gb_config_data = GB_search(gb_main, CONFIG_DATA_PATH, GB_DB); |
|---|
| 68 | |
|---|
| 69 | gb_config = GB_create_container(gb_config_data, CONFIG_ITEM); // create new container |
|---|
| 70 | if (gb_config) { |
|---|
| 71 | GB_ERROR error = GBT_write_string(gb_config, "name", name); |
|---|
| 72 | if (error) GB_export_error(error); |
|---|
| 73 | } |
|---|
| 74 | } |
|---|
| 75 | return gb_config; |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | GBT_config::GBT_config(GBDATA *gb_main, const char *name, GB_ERROR& error) { |
|---|
| 79 | GB_transaction ta(gb_main); |
|---|
| 80 | GBDATA *gb_config = GBT_find_configuration(gb_main, name); |
|---|
| 81 | |
|---|
| 82 | error = NULp; |
|---|
| 83 | if (!gb_config) { |
|---|
| 84 | error = GBS_global_string("No such configuration '%s'", name); |
|---|
| 85 | top_area = NULp; |
|---|
| 86 | middle_area = NULp; |
|---|
| 87 | comment = NULp; |
|---|
| 88 | } |
|---|
| 89 | else { |
|---|
| 90 | top_area = GBT_read_string(gb_config, "top_area"); |
|---|
| 91 | middle_area = GBT_read_string(gb_config, "middle_area"); |
|---|
| 92 | |
|---|
| 93 | if (!top_area || !middle_area) { |
|---|
| 94 | error = GBS_global_string("Configuration '%s' is corrupted (Reason: %s)", name, GB_await_error()); |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | comment = GBT_read_string(gb_config, "comment"); |
|---|
| 98 | } |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | GB_ERROR GBT_config::saveAsOver(GBDATA *gb_main, const char *name, const char *oldName, bool warnIfSavingDefault) const { |
|---|
| 102 | /*! save config as 'name' (overwriting config 'oldName') |
|---|
| 103 | * if 'warnIfSavingDefault' is true, saving DEFAULT_CONFIGURATION raises a warning |
|---|
| 104 | */ |
|---|
| 105 | GB_ERROR error = NULp; |
|---|
| 106 | |
|---|
| 107 | GB_push_transaction(gb_main); |
|---|
| 108 | |
|---|
| 109 | GBDATA *gb_config = findOrCreate_configuration(gb_main, oldName); |
|---|
| 110 | if (!gb_config) { |
|---|
| 111 | error = GBS_global_string("Can't create configuration '%s' (Reason: %s)", oldName, GB_await_error()); |
|---|
| 112 | } |
|---|
| 113 | else { |
|---|
| 114 | if (strcmp(name, oldName) != 0) error = GBT_write_string(gb_config, "name", name); |
|---|
| 115 | |
|---|
| 116 | error = GBT_write_string(gb_config, "top_area", top_area); |
|---|
| 117 | if (!error) error = GBT_write_string(gb_config, "middle_area", middle_area); |
|---|
| 118 | |
|---|
| 119 | if (!error) { |
|---|
| 120 | if (comment && comment[0]) { // non-empty |
|---|
| 121 | error = GBT_write_string(gb_config, "comment", comment); |
|---|
| 122 | } |
|---|
| 123 | else { |
|---|
| 124 | GBDATA *gb_comment = GB_entry(gb_config, "comment"); |
|---|
| 125 | if (gb_comment) error = GB_delete(gb_comment); // delete field if comment empty |
|---|
| 126 | } |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | if (error) error = GBS_global_string("%s (in configuration '%s')", error, name); |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | if (warnIfSavingDefault && strcmp(name, DEFAULT_CONFIGURATION) == 0) { |
|---|
| 133 | GBT_message(gb_main, "Note: You saved the '" DEFAULT_CONFIGURATION "'.\nStarting ARB_EDIT4 will probably overwrite it!"); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | return GB_end_transaction(gb_main, error); |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | const GBT_config_item& GBT_config_parser::nextItem(GB_ERROR& error) { |
|---|
| 140 | // see als similar code in ../PERL_SCRIPTS/DB/databaseReport.pl@PARSE_SELECTION |
|---|
| 141 | |
|---|
| 142 | error = NULp; |
|---|
| 143 | |
|---|
| 144 | freenull(item.name); |
|---|
| 145 | item.type = CI_END_OF_CONFIG; |
|---|
| 146 | |
|---|
| 147 | if (config_string[parse_pos]) { // if not at 0-byte |
|---|
| 148 | char label = config_string[parse_pos+1]; |
|---|
| 149 | item.type = CI_UNKNOWN; |
|---|
| 150 | |
|---|
| 151 | switch (label) { |
|---|
| 152 | case 'L': item.type = CI_SPECIES; break; |
|---|
| 153 | case 'S': item.type = CI_SAI; break; |
|---|
| 154 | case 'F': item.type = CI_FOLDED_GROUP; break; |
|---|
| 155 | case 'G': item.type = CI_GROUP; break; |
|---|
| 156 | case 'E': item.type = CI_CLOSE_GROUP; break; |
|---|
| 157 | default: item.type = CI_UNKNOWN; break; |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | if (item.type == CI_CLOSE_GROUP) { |
|---|
| 161 | parse_pos += 2; |
|---|
| 162 | } |
|---|
| 163 | else { |
|---|
| 164 | const char *start_of_name = config_string+parse_pos+2; |
|---|
| 165 | const char *behind_name = strchr(start_of_name, '\1'); |
|---|
| 166 | |
|---|
| 167 | if (!behind_name) behind_name = strchr(start_of_name, '\0'); // eos |
|---|
| 168 | gb_assert(behind_name); |
|---|
| 169 | |
|---|
| 170 | char *data = ARB_strpartdup(start_of_name, behind_name-1); |
|---|
| 171 | if (item.type == CI_UNKNOWN) { |
|---|
| 172 | error = GBS_global_string_copy("Unknown flag '%c' (followed by '%s')", label, data); |
|---|
| 173 | free(data); |
|---|
| 174 | } |
|---|
| 175 | else { |
|---|
| 176 | item.name = data; |
|---|
| 177 | parse_pos = behind_name-config_string; |
|---|
| 178 | } |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | if (error) { // stop parser |
|---|
| 182 | const char *end_of_config = strchr(config_string+parse_pos, '\0'); |
|---|
| 183 | parse_pos = end_of_config-config_string; |
|---|
| 184 | gb_assert(config_string[parse_pos] == 0); |
|---|
| 185 | } |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | return item; |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | void GBT_config_item::append_to_config_string(GBS_strstruct& out) const { |
|---|
| 192 | gb_assert((type & (CI_UNKNOWN|CI_END_OF_CONFIG)) == 0); |
|---|
| 193 | |
|---|
| 194 | char prefix[] = "\1?"; |
|---|
| 195 | if (type == CI_CLOSE_GROUP) { |
|---|
| 196 | prefix[1] = 'E'; |
|---|
| 197 | out.cat(prefix); |
|---|
| 198 | } |
|---|
| 199 | else { |
|---|
| 200 | char label = 0; |
|---|
| 201 | switch (type) { |
|---|
| 202 | case CI_SPECIES: label = 'L'; break; |
|---|
| 203 | case CI_SAI: label = 'S'; break; |
|---|
| 204 | case CI_GROUP: label = 'G'; break; |
|---|
| 205 | case CI_FOLDED_GROUP: label = 'F'; break; |
|---|
| 206 | |
|---|
| 207 | default: gb_assert(0); break; |
|---|
| 208 | } |
|---|
| 209 | prefix[1] = label; |
|---|
| 210 | out.cat(prefix); |
|---|
| 211 | out.cat(name); |
|---|
| 212 | } |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | // -------------------------------------------------------------------------------- |
|---|
| 216 | |
|---|
| 217 | #ifdef UNIT_TESTS |
|---|
| 218 | #include <test_unit.h> |
|---|
| 219 | |
|---|
| 220 | void TEST_GBT_get_configuration_names() { |
|---|
| 221 | GB_shell shell; |
|---|
| 222 | GBDATA *gb_main = GB_open("nosuch.arb", "c"); |
|---|
| 223 | |
|---|
| 224 | { |
|---|
| 225 | GB_transaction ta(gb_main); |
|---|
| 226 | |
|---|
| 227 | const char *configs[] = { "arb", "BASIC", "Check it", "dummy" }; |
|---|
| 228 | for (size_t i = 0; i<ARRAY_ELEMS(configs); ++i) { |
|---|
| 229 | TEST_EXPECT_RESULT__NOERROREXPORTED(findOrCreate_configuration(gb_main, configs[i])); |
|---|
| 230 | } |
|---|
| 231 | |
|---|
| 232 | ConstStrArray cnames; |
|---|
| 233 | GBT_get_configuration_names(cnames, gb_main); |
|---|
| 234 | |
|---|
| 235 | TEST_EXPECT_EQUAL(cnames.size(), 4U); |
|---|
| 236 | TEST_EXPECT_STRARRAY_CONTAINS(cnames, '*', "arb*BASIC*Check it*dummy"); |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | GB_close(gb_main); |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | #endif // UNIT_TESTS |
|---|
| 243 | |
|---|
| 244 | |
|---|