source: trunk/PROBE/PT_etc.cxx

Last change on this file was 19339, checked in by westram, 2 years ago
  • reintegrates 'refactor' into 'trunk'
    • eliminates old interface of GBS_strstruct
    • add a few new unittests (editor-config string + some PT-SERVER-functions)
  • adds: log:branches/refactor@19300:19338
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : PT_etc.cxx                                        //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "probe.h"
12
13#include <PT_server_prototypes.h>
14#include "pt_prototypes.h"
15
16#include <struct_man.h>
17#include <arb_strbuf.h>
18
19void pt_export_error(PT_local *locs, const char *error) {
20    freedup(locs->ls_error, error);
21}
22void pt_export_error_if(PT_local *locs, ARB_ERROR& error) {
23    if (error) pt_export_error(locs, error.deliver());
24    else error.expect_no_error();
25}
26
27static const gene_struct *get_gene_struct_by_internal_gene_name(const char *gene_name) {
28    gene_struct to_search(gene_name, "", "");
29
30    gene_struct_index_internal::const_iterator found = gene_struct_internal2arb.find(&to_search);
31    return (found == gene_struct_internal2arb.end()) ? NULp : *found;
32}
33static const gene_struct *get_gene_struct_by_arb_species_gene_name(const char *species_gene_name) {
34    const char *slash = strchr(species_gene_name, '/');
35    if (!slash) {
36        fprintf(stderr, "Internal error: '%s' should be in format 'organism/gene'\n", species_gene_name);
37        return NULp;
38    }
39
40    int   slashpos     = slash-species_gene_name;
41    char *organism     = ARB_strdup(species_gene_name);
42    organism[slashpos] = 0;
43
44    gene_struct to_search("", organism, species_gene_name+slashpos+1);
45    free(organism);
46
47    gene_struct_index_arb::const_iterator found = gene_struct_arb2internal.find(&to_search);
48    return (found == gene_struct_arb2internal.end()) ? NULp : *found;
49}
50
51static const char *arb2internal_name(const char *name) {
52    // convert arb name ('species/gene') into internal shortname
53    const gene_struct *found = get_gene_struct_by_arb_species_gene_name(name);
54    return found ? found->get_internal_gene_name() : NULp;
55}
56
57const char *virt_name(const PT_probematch *ml) {
58    // get the name with a virtual function
59    if (gene_flag) {
60        const gene_struct *gs = get_gene_struct_by_internal_gene_name(psg.data[ml->name].get_shortname());
61        return gs ? gs->get_arb_species_name() : "<cantResolveName>";
62    }
63    else {
64        pt_assert(psg.data[ml->name].get_shortname());
65        return psg.data[ml->name].get_shortname();
66    }
67}
68
69const char *virt_fullname(const PT_probematch * ml) {
70    if (gene_flag) {
71        const gene_struct *gs = get_gene_struct_by_internal_gene_name(psg.data[ml->name].get_shortname());
72        return gs ? gs->get_arb_gene_name() : "<cantResolveGeneFullname>";
73    }
74    else {
75        return psg.data[ml->name].get_fullname() ?  psg.data[ml->name].get_fullname() : "<undefinedFullname>";
76    }
77}
78
79#define MAX_LIST_PART_SIZE 50
80
81static const char *get_list_part(const char *list, int& offset) {
82    // scans strings with format "xxxx#yyyy#zzzz"
83    // your first call should be with offset == 0
84    //
85    // returns : static copy of each part or 0 when done
86    // offset is incremented by this function and set to -1 when all parts were returned
87
88    static char buffer[2][MAX_LIST_PART_SIZE+1];
89    static int  curr_buff = 0;  // toggle buffer to allow 2 parallel gets w/o invalidation
90
91    if (offset<0) return NULp; // already done
92    curr_buff ^= 1; // toggle buffer
93
94    const char *numsign = strchr(list+offset, '#');
95    int         num_offset;
96    if (numsign) {
97        num_offset = numsign-list;
98        pt_assert(list[num_offset] == '#');
99    }
100    else { // last list part
101        num_offset = offset+strlen(list+offset);
102        pt_assert(list[num_offset] == 0);
103    }
104
105    // now num_offset points to next '#' or to end-of-string
106
107    int len = num_offset-offset;
108    pt_assert(len <= MAX_LIST_PART_SIZE);
109
110    memcpy(buffer[curr_buff], list+offset, len);
111    buffer[curr_buff][len] = 0; // EOS
112
113    offset = (list[num_offset] == '#') ? num_offset+1 : -1; // set offset for next part
114
115    return buffer[curr_buff];
116}
117
118#undef MAX_LIST_PART_SIZE
119
120char *ptpd_read_names(PT_local *locs, const char *names_list, const char *checksums, ARB_ERROR& error) {
121    /* read the name list separated by '#' and set the flag for the group members,
122     + returns a list of names which have not been found
123     */
124
125    // clear 'is_group'
126    for (int i = 0; i < psg.data_count; i++) {
127        psg.data[i].set_group_state(0); // Note: probes are designed for species with is_group == 1
128    }
129    locs->group_count = 0;
130
131    error = NULp;
132
133    if (!names_list) {
134        error = "Can't design probes for no species (species list is empty)";
135        return NULp;
136    }
137
138    int noff = 0;
139    int coff = 0;
140
141    GBS_strstruct *not_found = NULp;
142
143    while (noff >= 0) {
144        pt_assert(coff >= 0);   // otherwise 'checksums' contains less elements than 'names_list'
145        const char *arb_name      = get_list_part(names_list, noff);
146        const char *internal_name = arb_name; // differs only for gene pt server
147
148        if (arb_name[0] == 0) {
149            pt_assert(names_list[0] == 0);
150            break; // nothing marked
151        }
152
153        if (gene_flag) {
154            const char *slash = strchr(arb_name, '/');
155
156            if (!slash) {
157                // ARB has to send 'species/gene'.
158                // If it did not, user did not mark 'Gene probes ?' flag
159
160                error = GBS_global_string("Expected '/' in '%s' (this PT-server can only design probes for genes)", arb_name);
161                break;
162            }
163
164            internal_name = arb2internal_name(arb_name);
165            pt_assert(internal_name);
166        }
167
168        int  idx   = GBS_read_hash(psg.namehash, internal_name);
169        bool found = false;
170
171        if (idx) {
172            --idx;              // because 0 means not found!
173
174            if (checksums) {
175                const char *checksum = get_list_part(checksums, coff);
176                // if sequence checksum changed since pt server was updated -> not found
177                found                = atol(checksum) == psg.data[idx].get_checksum();
178            }
179            else {
180                found = true;
181            }
182
183            if (found) {
184                psg.data[idx].set_group_state(1); // mark
185                locs->group_count++;
186            }
187        }
188
189        if (!found) { // name not found -> put into result
190            if (!not_found) not_found = new GBS_strstruct(1000);
191            else not_found->put('#');
192            not_found->cat(arb_name);
193        }
194    }
195
196    char *result = NULp;
197    if (not_found && !error) {
198        result = not_found->release();
199    }
200    delete not_found;
201    return result;
202}
203
204bytestring *PT_unknown_names(const PT_pdc *pdc) {
205    PT_local *locs = (PT_local*)pdc->mh.parent->parent;
206    static bytestring unknown = { NULp, 0 };
207    delete unknown.data;
208
209    ARB_ERROR error;
210    unknown.data = ptpd_read_names(locs, pdc->names.data, pdc->checksums.data, error);
211    if (unknown.data) {
212        unknown.size = strlen(unknown.data) + 1;
213        pt_assert(!error);
214    }
215    else {
216        unknown.data = ARB_strdup("");
217        unknown.size = 1;
218    }
219    pt_export_error_if(locs, error);
220    return &unknown;
221}
222
Note: See TracBrowser for help on using the repository browser.