source: branches/stable/ARBDB/gb_aci.h

Last change on this file was 18186, checked in by westram, 4 years ago
File size: 8.6 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : gb_aci.h                                          //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#ifndef GB_ACI_H
12#define GB_ACI_H
13
14#ifndef ARB_STR_H
15#include <arb_str.h>
16#endif
17#ifndef ARBDBT_H
18#include "arbdbt.h"
19#endif
20#ifndef _GLIBCXX_VECTOR
21#include <vector>
22#endif
23#ifndef _GLIBCXX_MAP
24#include <map>
25#endif
26
27#define gb_assert(cond) arb_assert(cond)
28
29typedef SmartMallocPtr(char) GBL;
30
31class GBL_streams {
32    std::vector<GBL> content;
33
34public:
35    void insert(char *copy) { content.push_back(copy); }
36    void insert(GBL smartie) { content.push_back(smartie); }
37    const char *get(int idx) const { gb_assert(idx<size()); return &*content[idx]; }
38    GBL get_smart(int idx) const { gb_assert(idx<size()); return content[idx]; }
39    int size() const { return content.size(); }
40    bool empty() const { return content.empty(); }
41
42    void erase() { content.clear(); }
43
44    char *concatenated() const;
45    void swap(GBL_streams& other) { std::swap(content, other.content); }
46};
47
48class GBL_command_arguments;
49typedef GB_ERROR (*GBL_COMMAND)(GBL_command_arguments *args);
50
51struct GBL_command_definition {
52    const char  *identifier; // command identifier (alphanumeric)
53    GBL_COMMAND  function;   // function to execute
54
55    bool is_defined() const { return identifier && function; }
56    bool is_sentinel() const { return !identifier && !function; }
57};
58
59// ------------------------
60//      command lookup
61
62class GBL_command_lookup_table : virtual Noncopyable {
63    struct ccp_less {
64        bool operator()(const char *s1, const char *s2) const {
65            return ARB_stricmp(s1, s2) < 0;
66        }
67    };
68
69    typedef std::map<const char*,GBL_COMMAND,ccp_less> CmdMap;
70
71    CmdMap defined;
72
73public:
74    GBL_command_lookup_table(const GBL_command_definition *table, unsigned size);
75    virtual ~GBL_command_lookup_table() {}
76
77    virtual GBL_COMMAND lookup(const char *identifier) const {
78        CmdMap::const_iterator found = defined.find(identifier);
79        return found == defined.end() ? NULp : found->second;
80    }
81};
82
83const GBL_command_lookup_table& ACI_get_standard_commands(); // provides access to commands defined in adlang1.cxx
84
85enum GBL_customization_mode {
86    DENY_SUBSTITUTION,
87    PERMIT_SUBSTITUTION,
88};
89
90class GBL_custom_command_lookup_table : public GBL_command_lookup_table {
91    const GBL_command_lookup_table& base_table;
92
93    void warn_about_overwritten_commands(const GBL_command_definition *custom_table, unsigned custom_size) const;
94public:
95    GBL_custom_command_lookup_table(const GBL_command_definition    *custom_table,
96                                    unsigned                         custom_size,
97                                    const GBL_command_lookup_table&  extending_this,
98                                    GBL_customization_mode           cmode = DENY_SUBSTITUTION) :
99        GBL_command_lookup_table(custom_table, custom_size),
100        base_table(extending_this)
101    {
102        if (cmode == DENY_SUBSTITUTION) {
103            warn_about_overwritten_commands(custom_table, custom_size);
104        }
105    }
106    ~GBL_custom_command_lookup_table() OVERRIDE {}
107
108    GBL_COMMAND lookup(const char *identifier) const OVERRIDE {
109        GBL_COMMAND cmd = GBL_command_lookup_table::lookup(identifier);
110        if (!cmd) cmd   = base_table.lookup(identifier);
111        return cmd;
112    }
113};
114
115// -------------------------------
116//      execution environment
117
118class GBL_env : virtual Noncopyable {
119    // provides an environment for running ACI commands
120
121    GBDATA *gb_main;               // database to use
122    char   *default_tree_name;     // if we have a default tree, its name is specified here (NULp otherwise)
123
124    const GBL_command_lookup_table& std_cmds;
125
126public:
127    GBL_env(GBDATA *gbMain, const char *treeName, const GBL_command_lookup_table& cmds = ACI_get_standard_commands()) :
128        gb_main(gbMain),
129        default_tree_name(nulldup(treeName)),
130        std_cmds(cmds)
131    {}
132
133    ~GBL_env() { free(default_tree_name); }
134
135    GBDATA *get_gb_main() const { return gb_main; }
136    const char *get_treename() const { return default_tree_name; }
137
138    GBL_COMMAND lookup_command(const char *identifier) const { return std_cmds.lookup(identifier); }
139};
140
141
142class FieldTracker {
143public:
144    virtual ~FieldTracker() {}
145    virtual void track_field(const char *fieldname) = 0;
146};
147
148class GBL_call_env : virtual Noncopyable {
149    // provides a specific call environment (for one item)
150
151    GBDATA         *gb_ref; // the database entry on which the command is applied (may be species, gene, experiment, group and maybe more)
152    const GBL_env&  env;
153
154    mutable RefPtr<FieldTracker> tracker;
155
156public:
157    GBL_call_env(GBDATA *gbd, const GBL_env& env_) : gb_ref(gbd), env(env_), tracker(NULp) {}
158    virtual ~GBL_call_env() {}
159
160    GBDATA *get_item_ref() const { return gb_ref; } // Warning: may return NULp (see also: EXPECT_ITEM_REFERENCED)
161    const GBL_env& get_env() const { return env; }
162
163    void useFieldTracker(FieldTracker *tracker_) { tracker = tracker_; }
164    const char *track_field_access(const char *fieldname) const {
165        if (tracker) tracker->track_field(fieldname); // track access to itemfield
166        return fieldname;
167    }
168
169    GBDATA *get_gb_main() const { return env.get_gb_main(); }
170    const char *get_treename() const { return env.get_treename(); }
171
172    char *interpret_subcommand(const char *input, const char *command) const { // @@@ should take command in pre-parsed format
173        return GB_command_interpreter_in_env(input, command, *this); // @@@ swap this function with GB_command_interpreter_in_env!
174    }
175};
176
177class GBL_maybe_itemless_call_env : public GBL_call_env {
178    GBL_env env;
179public:
180    GBL_maybe_itemless_call_env(GBDATA *gb_main, GBDATA *gb_item) :
181        GBL_call_env(gb_item, env),
182        env(gb_main, NULp)
183    {
184        gb_assert(gb_main);
185        gb_assert(get_gb_main());
186    }
187};
188
189struct GBL_simple_call_env : public GBL_maybe_itemless_call_env { // only useable if gb_item always exists (i.e. never is NULp)
190    GBL_simple_call_env(GBDATA *gb_item) :
191        GBL_maybe_itemless_call_env(GB_get_root(gb_item), gb_item)
192    {}
193};
194
195// -------------------------
196//      execution state
197
198class GBL_command_arguments : virtual Noncopyable {
199    // provides arguments, input, output + environment
200
201    const GBL_call_env&  callEnv;
202    const char          *cmdName; // the name of the current command (used for error messages)
203
204    GBL_streams &param;
205#if defined(ASSERTION_USED)
206    bool params_checked;
207#endif
208
209public:
210
211    GBL_streams &input;
212    GBL_streams &output;
213
214    GBL_command_arguments(const GBL_call_env& cenv_,
215                          const char *command_,
216                          GBL_streams& input_,
217                          GBL_streams& param_,
218                          GBL_streams& output_)
219        : callEnv(cenv_),
220          cmdName(command_),
221          param(param_),
222          input(input_),
223          output(output_)
224    {
225#if defined(ASSERTION_USED)
226        params_checked = false;
227#endif
228    }
229    ~GBL_command_arguments() {
230        gb_assert(params_checked);
231    }
232
233    GBDATA *get_item_ref() const { return callEnv.get_item_ref(); } // Warning: may return NULp (see also: EXPECT_ITEM_REFERENCED)
234    const GBL_call_env& get_callEnv() const { return callEnv; }
235    const GBL_env& get_env() const { return callEnv.get_env(); }
236
237    const char *track_field_access(const char *fieldname) const { return get_callEnv().track_field_access(fieldname ); }
238
239    GBDATA *get_gb_main() const { return callEnv.get_gb_main(); }
240    const char *get_treename() const { return callEnv.get_treename(); }
241    const char *get_cmdName() const { return cmdName; }
242
243    const GBL_streams& get_param_streams() const { return param; }
244    int param_count() const { return param.size(); }
245    const char *get_param(int idx) const { return param.get(idx); }
246    const char *get_optional_param(int idx, const char *defaultValue) const { return idx>=0 && idx<param.size() ? param.get(idx) : defaultValue; }
247    GBL get_param_smart(int idx) const { return param.get_smart(idx); }
248
249#if defined(ASSERTION_USED)
250    bool set_params_checked() {
251        if (params_checked) return false;
252        params_checked = true;
253        return true;
254    }
255#endif
256};
257
258#else
259#error gb_aci.h included twice
260#endif // GB_ACI_H
261
262
Note: See TracBrowser for help on using the repository browser.