source: tags/ms_ra2q56/ARBDB/ad_config.cxx

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