source: branches/profile/CONVERTALN/util.cxx

Last change on this file was 11844, checked in by westram, 10 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1#include <BufferedFileReader.h>
2#include "fun.h"
3#include "defs.h"
4#include "global.h"
5#include "reader.h"
6
7#include <cstdarg>
8#include <cerrno>
9
10bool scan_token(char *to, const char *from) { // __ATTR__USERESULT
11    return sscanf(from, "%s", to) == 1;
12}
13
14void scan_token_or_die(char *to, const char *from) {
15    if (!scan_token(to, from)) {
16        throw_error(88, "expected to see a token here");
17    }
18}
19void scan_token_or_die(char *to, Reader& reader, int offset) {
20    scan_token_or_die(to, reader.line()+offset);
21}
22
23void throw_error(int error_num, const char *error_message) { // __ATTR__NORETURN
24    throw Convaln_exception(error_num, error_message);
25}
26
27char *strf(const char *format, ...) { // __ATTR__FORMAT(1)
28    va_list parg;
29    va_start(parg, format);
30    char    buffer[LINESIZE];
31    int     printed = vsprintf(buffer, format, parg);
32    ca_assert(printed <= LINESIZE);
33    va_end(parg);
34
35    return strndup(buffer, printed);
36}
37
38void throw_errorf(int error_num, const char *error_messagef, ...) { // __ATTR__FORMAT(2) __ATTR__NORETURN
39    va_list parg;
40    va_start(parg, error_messagef);
41
42    const int   BUFSIZE = 1000;
43    static char buffer[BUFSIZE];
44    int         printed = vsprintf(buffer, error_messagef, parg);
45
46    va_end(parg);
47
48    if (printed >= BUFSIZE) {
49        throw_errorf(998, "Internal buffer overflow (while formatting error #%i '%s')", error_num, error_messagef);
50    }
51    throw_error(error_num, buffer);
52}
53
54// --------------------------------------------------------------------------------
55
56bool Warnings::show_warnings = true;
57
58void warning(int warning_num, const char *warning_message) {
59    // print out warning_message and continue execution.
60    if (Warnings::shown())
61        fprintf(stderr, "WARNING(%d): %s\n", warning_num, warning_message);
62}
63void warningf(int warning_num, const char *warning_messagef, ...) { // __ATTR__FORMAT(2)
64    if (Warnings::shown()) {
65        va_list parg;
66        va_start(parg, warning_messagef);
67
68        const int   BUFSIZE = 1000;
69        static char buffer[BUFSIZE];
70        int         printed = vsprintf(buffer, warning_messagef, parg);
71
72        va_end(parg);
73
74        if (printed >= BUFSIZE) {
75            throw_errorf(997, "Internal buffer overflow (while formatting warning #%i '%s')", warning_num, warning_messagef);
76        }
77        warning(warning_num, buffer);
78    }
79}
80
81char *Reallocspace(void *block, unsigned int size) {
82    // Realloc a continue space, expand or shrink the original space.
83    char *temp;
84
85    if (size <= 0) {
86        free(block);
87        return NULL;
88    }
89
90    if (block == NULL) {
91        temp = (char *)calloc(1, size);
92    }
93    else {
94        temp = (char *)realloc(block, size);
95    }
96    if (!temp) throw_error(999, "Run out of memory (Reallocspace)");
97    return temp;
98}
99
100int Skip_white_space(const char *line, int index) {
101    // Skip white space from (index)th char of Str line.
102
103    while (line[index] == ' ' || line[index] == '\t')
104        ++index;
105    return (index);
106}
107
108void Getstr(char *line, int linenum) {
109    // Get input Str from terminal.
110    char c;
111    int  indi = 0;
112
113    for (; (c = getchar()) != '\n' && indi < (linenum - 1); line[indi++] = c) {}
114
115    line[indi] = '\0';
116}
117
118inline void append_known_len(char*& string1, int len1, const char *string2, int len2) {
119    ca_assert(len2); // else no need to call, string1 already correct
120    int newlen      = len1+len2;
121    string1         = Reallocspace(string1, newlen+1);
122    memcpy(string1+len1, string2, len2);
123    string1[newlen] = 0;
124}
125
126void terminate_with(char*& str, char ch) {
127    // append 'ch' to end of 'str' (before \n)
128    // - if it's not already there and
129    // - 'str' contains more than just '\n'
130
131    int len = str0len(str);
132    if (!len) return;
133    ca_assert(str[len-1] == '\n');
134    if (len == 1) return;
135    if (str[len-2] == ch) return;
136
137    char temp[] = { ch, '\n' };
138    append_known_len(str, len-1, temp, 2);
139}
140
141void skip_eolnl_and_append(char*& string1, const char *string2) {
142    int len1 = str0len(string1);
143    if (len1 && string1[len1-1] == '\n') len1--;
144    int len2 = str0len(string2);
145    if (len2) append_known_len(string1, len1, string2, len2);
146    else { string1[len1] = 0; }
147}
148
149void skip_eolnl_and_append_spaced(char*& string1, const char *string2) {
150    int len1 = str0len(string1);
151    if (len1 && string1[len1-1] == '\n') string1[len1-1] = ' ';
152    append_known_len(string1, len1, string2, str0len(string2));
153}
154
155void Append(char*& string1, const char *string2) {
156    int len2 = str0len(string2);
157    if (len2) append_known_len(string1, str0len(string1), string2, len2);
158}
159void Append(char*& string1, char ch) {
160    append_known_len(string1, str0len(string1), &ch, 1);
161}
162
163void upcase(char *str) {
164    // Capitalize all char in the str.
165    if (!str) return;
166    for (int i = 0; str[i]; ++i) str[i] = toupper(str[i]);
167}
168
169int fputs_len(const char *str, int len, Writer& write) {
170    // like fputs(), but does not print more than 'len' characters
171    // returns number of chars written or throws write error
172    for (int i = 0; i<len; ++i) {
173        if (!str[i]) return i;
174        write.out(str[i]);
175    }
176    return len;
177}
178
179// -------------------------
180//      pattern matching
181
182enum FindMode { FIND_START, FIND_SKIP_OVER };
183
184static int findPattern(const char *text, const char *pattern, FindMode mode) {
185    // Return offset of 'pattern' in 'text' or -1
186    // (compares case insensitive)
187    // return position after found 'pattern' in 'endPtr'
188
189    if (text && pattern) {
190        for (int t = 0; text[t]; ++t) {
191            bool mismatch = false;
192
193            int p = 0;
194            for (; !mismatch && pattern[p]; ++p) {
195                mismatch = tolower(text[t+p]) != tolower(pattern[p]);
196            }
197            if (!mismatch) {
198                switch (mode) {
199                    case FIND_START: return t;
200                    case FIND_SKIP_OVER: return t+p;
201                }
202                ca_assert(0);
203            }
204        }
205    }
206    return -1;
207}
208
209static int findMultipattern(const char *str, const char** const& pattern, char expect_behind, FindMode mode) {
210    // search 'str' for the occurrence of any 'pattern'
211    // if 'expect_behind' != 0 -> expect that char behind the found pattern
212
213    int offset = -1;
214
215    if (str) {
216        FindMode use = expect_behind ? FIND_SKIP_OVER : mode;
217
218        int p;
219        for (p = 0; offset == -1 && pattern[p]; ++p) {
220            offset = findPattern(str, pattern[p], use);
221        }
222
223        if (offset != -1) {
224            if (expect_behind) {
225                if (str[offset] != expect_behind) { // mismatch
226                    offset = findMultipattern(str+offset, pattern, expect_behind, mode);
227                }
228                else {
229                    switch (mode) {
230                        case FIND_START:
231                            offset -= str0len(pattern[p]);
232                            ca_assert(offset >= 0);
233                            break;
234                        case FIND_SKIP_OVER:
235                            offset++;
236                            break;
237                    }
238                }
239            }
240        }
241    }
242    return offset;
243}
244
245static int findSubspecies(const char *str, char expect_behind, FindMode mode) {
246    const char *subspecies_pattern[] = { "subspecies", "sub-species", "subsp.", NULL };
247    return findMultipattern(str, subspecies_pattern, expect_behind, mode);
248}
249
250static int findStrain(const char *str, char expect_behind, FindMode mode) {
251    const char *strain_pattern[] = { "strain", "str.", NULL };
252    return findMultipattern(str, strain_pattern, expect_behind, mode);
253}
254
255int find_pattern(const char *text, const char *pattern) { return findPattern(text, pattern, FIND_START); }
256int skip_pattern(const char *text, const char *pattern) { return findPattern(text, pattern, FIND_SKIP_OVER); }
257
258int find_subspecies(const char *str, char expect_behind) { return findSubspecies(str, expect_behind, FIND_START); }
259int skip_subspecies(const char *str, char expect_behind) { return findSubspecies(str, expect_behind, FIND_SKIP_OVER); }
260
261int find_strain(const char *str, char expect_behind) { return findStrain(str, expect_behind, FIND_START); }
262int skip_strain(const char *str, char expect_behind) { return findStrain(str, expect_behind, FIND_SKIP_OVER); }
263
264const char *stristr(const char *str, const char *substring) {
265    int offset = find_pattern(str, substring);
266    return offset >= 0 ? str+offset : NULL;
267}
268
269int ___lookup_keyword(const char *keyword, const char * const *lookup_table, int lookup_table_size) {
270    // returns the index [0..n-1] of 'keyword' in lookup_table
271    // or -1 if not found.
272
273    for (int i = 0; i<lookup_table_size; ++i) {
274        if (str_equal(keyword, lookup_table[i])) return i;
275    }
276    return -1;
277}
278
279int parse_key_word(const char *line, char *key, const char *separator) {
280    // Copy keyword starting at position 'index' of 'line' delimited by 'separator' into 'key'.
281    // Do not copy more than 'TOKENSIZE-1' characters.
282    // Returns length of keyword.
283
284    int k = 0;
285    if (line) {
286        while (k<(TOKENSIZE-1) && line[k] && !occurs_in(line[k], separator)) {
287            key[k] = line[k];
288            ++k;
289        }
290    }
291    key[k] = 0;
292    return k;
293}
294
295// ----------------------
296//      FormattedFile
297
298FormattedFile::FormattedFile(const char *Name, Format Type)
299    : name_(strdup(Name)),
300      type_(Type)
301{}
302FormattedFile::~FormattedFile() {
303    free(name_);
304}
305
306void FormattedFile::init(const char *Name, Format Type) {
307    ca_assert(!name_); // do not init twice
308    ca_assert(Name);
309    ca_assert(Type != UNKNOWN);
310
311    name_ = nulldup(Name);
312    type_ = Type;
313}
314
Note: See TracBrowser for help on using the repository browser.