Coverage Report

Created: 2023-12-08 06:59

/src/aspell/common/info.cpp
Line
Count
Source (jump to first uncovered line)
1
// This file is part of The New Aspell
2
// Copyright (C) 2001 by Kevin Atkinson under the GNU LGPL license
3
// version 2.0 or 2.1.  You should have received a copy of the LGPL
4
// license along with this library if you did not you can find
5
// it at http://www.gnu.org/.
6
7
#include <stdlib.h>
8
#include <assert.h>
9
#include <string.h>
10
#include <ctype.h>
11
#include <dirent.h>
12
13
// POSIX includes
14
#ifdef __bsdi__
15
 /* BSDi defines u_intXX_t types in machine/types.h */
16
#include <machine/types.h>
17
#endif
18
#ifdef WIN32
19
#  include <windows.h>
20
#  include <winbase.h>
21
#endif
22
23
#include "iostream.hpp"
24
25
#include "asc_ctype.hpp"
26
#include "config.hpp"
27
#include "errors.hpp"
28
#include "fstream.hpp"
29
#include "getdata.hpp"
30
#include "info.hpp"
31
#include "itemize.hpp"
32
#include "string.hpp"
33
#include "string_list.hpp"
34
#include "vector.hpp"
35
#include "stack_ptr.hpp"
36
#include "strtonum.hpp"
37
#include "lock.hpp"
38
#include "string_map.hpp"
39
40
#include "gettext.h"
41
42
namespace acommon {
43
44
  class Dir {
45
    DIR * d_;
46
    Dir(const Dir &);
47
    Dir & operator=(const Dir &);
48
  public:
49
51.7k
    operator DIR * () {return d_;}
50
306
    Dir(DIR * d) : d_(d) {}
51
306
    ~Dir() {if (d_) closedir(d_);}
52
  };
53
54
  /////////////////////////////////////////////////////////////////
55
  //
56
  // Lists of Info Lists
57
  //
58
59
  static void get_data_dirs (Config *,
60
           StringList &);
61
62
  struct DictExt
63
  {
64
    static const size_t max_ext_size = 15;
65
    const ModuleInfo * module;
66
    size_t ext_size;
67
    char ext[max_ext_size + 1];
68
    DictExt(ModuleInfo * m, const char * e);
69
  };
70
71
  typedef Vector<DictExt> DictExtList;
72
73
  struct MDInfoListAll
74
  // this is in an invalid state if some of the lists
75
  // has data but others don't
76
  {
77
    StringList key;
78
    StringList for_dirs;
79
    ModuleInfoList module_info_list;
80
    StringList dict_dirs;
81
    DictExtList    dict_exts;
82
    DictInfoList   dict_info_list;
83
    StringMap      dict_aliases;
84
    void clear();
85
    PosibErr<void> fill(Config *, StringList &);
86
2.25k
    bool has_data() const {return module_info_list.head_ != 0;}
87
    void fill_helper_lists(const StringList &);
88
    PosibErr<void> fill_dict_aliases(Config *);
89
  };
90
91
  class MDInfoListofLists
92
  {
93
    Mutex lock;
94
95
    MDInfoListAll * data;
96
  
97
    int       offset;
98
    int       size;
99
  
100
4.50k
    int valid_pos(int pos) {return offset <= pos && pos < size + offset;}
101
102
    void clear(Config * c);
103
    int find(const StringList &);
104
105
  public:
106
107
    MDInfoListofLists();
108
    ~MDInfoListofLists();
109
110
    PosibErr<const MDInfoListAll *> get_lists(Config * c);
111
112
0
    void flush() {} // unimplemented
113
  };
114
115
  static MDInfoListofLists md_info_list_of_lists;
116
117
  /////////////////////////////////////////////////////////////////
118
  //
119
  // Utility functions declaration
120
  //
121
122
  static const char * strnchr(const char * i, char c, unsigned int size);
123
  static const char * strnrchr(const char * stop, char c, unsigned int size);
124
125
  /////////////////////////////////////////////////////////////////
126
  //
127
  // Built in modules
128
  //
129
130
  struct ModuleInfoDefItem {
131
    const char * name;
132
    const char * data;
133
  };
134
135
  static const ModuleInfoDefItem module_info_list_def_list[] = {
136
    {"default", 
137
     "order-num 0.50;" 
138
     "dict-exts .multi,.alias"}
139
  };
140
  
141
  /////////////////////////////////////////////////////////////////
142
  //
143
  // ModuleInfoList Impl
144
  //
145
146
  struct ModuleInfoNode
147
  {
148
    ModuleInfo c_struct;
149
    ModuleInfoNode * next;
150
153
    ModuleInfoNode(ModuleInfoNode * n = 0) : next(n) {}
151
    String name;
152
    String lib_dir;
153
    StringList dict_exts;
154
    StringList dict_dirs;
155
  };
156
157
  void ModuleInfoList::clear() 
158
2
  {
159
2
    while (head_ != 0) {
160
0
      ModuleInfoNode * to_del = head_;
161
0
      head_ = head_->next;
162
0
      delete to_del;
163
0
    }
164
2
  }
165
166
  PosibErr<void> ModuleInfoList::fill(MDInfoListAll & list_all,
167
              Config * config)
168
153
  {
169
153
    const ModuleInfoDefItem * i   = module_info_list_def_list;
170
153
    const ModuleInfoDefItem * end = module_info_list_def_list
171
153
      + sizeof(module_info_list_def_list)/sizeof(ModuleInfoDefItem);
172
306
    for (; i != end; ++i)
173
153
    {
174
153
      StringIStream in(i->data);
175
153
      proc_info(list_all, config, i->name, strlen(i->name), in);
176
153
    }
177
178
153
    StringListEnumeration els = list_all.for_dirs.elements_obj();
179
153
    const char * dir;
180
306
    while ( (dir = els.next()) != 0) {
181
153
      Dir d(opendir(dir));
182
153
      if (d==0) continue;
183
    
184
153
      struct dirent * entry;
185
25.7k
      while ( (entry = readdir(d)) != 0) {
186
25.5k
  const char * name = entry->d_name;
187
25.5k
  const char * dot_loc = strrchr(name, '.');
188
25.5k
  unsigned int name_size = dot_loc == 0 ? strlen(name) :  dot_loc - name;
189
      
190
  // check if it ends in suffix
191
25.5k
  if (strcmp(name + name_size, ".asmi") != 0)
192
25.5k
    continue;
193
      
194
0
  String path;
195
0
  path += dir;
196
0
  path += '/';
197
0
  path += name;
198
0
  FStream in;
199
0
  RET_ON_ERR(in.open(path, "r"));
200
0
  RET_ON_ERR(proc_info(list_all, config, name, name_size, in));
201
0
      }
202
153
    }
203
153
    return no_err;
204
153
  }
205
206
  PosibErr<void> ModuleInfoList::proc_info(MDInfoListAll &,
207
             Config * config,
208
             const char * name,
209
             unsigned int name_size,
210
             IStream & in)
211
153
  {
212
153
    ModuleInfoNode * * prev = &head_;
213
153
    ModuleInfoNode * to_add = new ModuleInfoNode();
214
153
    to_add->c_struct.name = 0;
215
153
    to_add->c_struct.order_num = -1;
216
153
    to_add->c_struct.lib_dir = 0;
217
153
    to_add->c_struct.dict_dirs = 0;
218
219
153
    to_add->name.assign(name, name_size);
220
153
    to_add->c_struct.name = to_add->name.c_str();
221
    
222
153
    PosibErr<void> err;
223
224
153
    String buf; DataPair d;
225
459
    while (getdata_pair(in, d, buf)) {
226
306
      if (d.key == "order-num") {
227
153
  to_add->c_struct.order_num = strtod_c(d.value.str, NULL);
228
153
  if (!(0 < to_add->c_struct.order_num && 
229
153
        to_add->c_struct.order_num < 1)) 
230
0
    {
231
0
      err.prim_err(bad_value, d.key, d.value,
232
0
       _("a number between 0 and 1"));
233
0
      goto RETURN_ERROR;
234
0
    }
235
153
      } else if (d.key == "lib-dir") {
236
0
  to_add->lib_dir = d.value.str;
237
0
  to_add->c_struct.lib_dir = to_add->lib_dir.c_str();
238
153
      } else if (d.key == "dict-dir" || d.key == "dict-dirs") {
239
0
  to_add->c_struct.dict_dirs = &(to_add->dict_dirs);
240
0
  itemize(d.value, to_add->dict_dirs);
241
153
      } else if (d.key == "dict-exts") {
242
153
  to_add->c_struct.dict_dirs = &(to_add->dict_exts);
243
153
  itemize(d.value, to_add->dict_exts);
244
153
      } else {
245
0
  err.prim_err(unknown_key, d.key);
246
0
  goto RETURN_ERROR;
247
0
      }
248
306
    }
249
  
250
153
    while (*prev != 0 && 
251
153
     (*prev)->c_struct.order_num < to_add->c_struct.order_num)
252
0
      prev = &(*prev)->next;
253
153
    to_add->next = *prev;
254
153
    *prev = to_add;
255
153
    return err;
256
257
0
  RETURN_ERROR:
258
0
    delete to_add;
259
0
    return err;
260
153
  }
261
262
  ModuleInfoNode * ModuleInfoList::find(const char * to_find, 
263
          unsigned int to_find_len)
264
0
  {
265
0
    for (ModuleInfoNode * n = head_; 
266
0
   n != 0; 
267
0
   n = n->next)
268
0
    {
269
0
      if (n->name.size() == to_find_len 
270
0
    && strncmp(n->name.c_str(), to_find, to_find_len) == 0) return n;
271
0
    }
272
0
    return 0;
273
0
  }
274
275
  /////////////////////////////////////////////////////////////////
276
  //
277
  // DictInfoList Impl
278
  //
279
280
  struct DictInfoNode
281
  {
282
    DictInfo c_struct;
283
    DictInfoNode * next;
284
34.7k
    DictInfoNode(DictInfoNode * n = 0) : next(n) {}
285
    String name;
286
    String code;
287
    String variety;
288
    String size_str;
289
    String info_file;
290
    bool direct;
291
  };
292
293
  bool operator< (const DictInfoNode & r, const DictInfoNode & l);
294
295
  void DictInfoList::clear() 
296
2
  {
297
2
    while (head_ != 0) {
298
0
      DictInfoNode * to_del = head_;
299
0
      head_ = head_->next;
300
0
      delete to_del;
301
0
    }
302
2
  }
303
304
  const DictExt * find_dict_ext(const DictExtList & l, ParmStr name)
305
50.0k
  {
306
50.0k
    DictExtList::const_iterator   i = l.begin();
307
50.0k
    DictExtList::const_iterator end = l.end();
308
160k
    for (; i != end; ++i) 
309
145k
    {
310
145k
      if (i->ext_size <= name.size() 
311
145k
          && strncmp(name + (name.size() - i->ext_size),
312
143k
                     i->ext, i->ext_size) == 0)
313
34.7k
        break;
314
145k
    }
315
    
316
50.0k
    if (i == end) // does not end in one of the extensions in list
317
15.3k
      return 0;
318
34.7k
    else
319
34.7k
      return &*i;
320
50.0k
  }
321
322
323
  PosibErr<void> DictInfoList::fill(MDInfoListAll & list_all,
324
            Config * config)
325
153
  {
326
153
    StringList aliases;
327
153
    config->retrieve_list("dict-alias", &aliases);
328
153
    StringListEnumeration els = aliases.elements_obj();
329
153
    const char * str;
330
24.6k
    while ( (str = els.next()) != 0) {
331
24.5k
      const char * end = strchr(str, ' ');
332
24.5k
      assert(end != 0); // FIXME: Return error
333
0
      String name(str, end - str);
334
24.5k
      RET_ON_ERR(proc_file(list_all, config,
335
24.5k
                           0, name.str(), name.size(), 
336
24.5k
                           find_dict_ext(list_all.dict_exts, ".alias")->module));
337
24.5k
    }
338
339
153
    els = list_all.dict_dirs.elements_obj();
340
153
    const char * dir;
341
306
    while ( (dir = els.next()) != 0) {
342
153
      Dir d(opendir(dir));
343
153
      if (d==0) continue;
344
    
345
153
      struct dirent * entry;
346
25.7k
      while ( (entry = readdir(d)) != 0) {
347
25.5k
  const char * name = entry->d_name;
348
25.5k
  unsigned int name_size = strlen(name);
349
350
25.5k
  const DictExt * i = find_dict_ext(list_all.dict_exts, 
351
25.5k
                                          ParmString(name, name_size));
352
25.5k
  if (i == 0) // does not end in one of the extensions in list
353
15.3k
    continue;
354
355
10.2k
  name_size -= i->ext_size;
356
      
357
10.2k
  RET_ON_ERR(proc_file(list_all, config, 
358
10.2k
           dir, name, name_size, i->module));
359
10.2k
      }
360
153
    }
361
153
    return no_err;
362
153
  }
363
364
  PosibErr<void> DictInfoList::proc_file(MDInfoListAll & list_all,
365
           Config * config,
366
           const char * dir,
367
           const char * name,
368
           unsigned int name_size,
369
           const ModuleInfo * module)
370
34.7k
  {
371
34.7k
    DictInfoNode * * prev = &head_;
372
34.7k
    StackPtr<DictInfoNode> to_add(new DictInfoNode());
373
34.7k
    const char * p0;
374
34.7k
    const char * p1;
375
34.7k
    const char * p2;
376
34.7k
    p0 = strnchr(name, '-', name_size);
377
34.7k
    if (!module)
378
0
      p2 = strnrchr(name, '-', name_size);
379
34.7k
    else
380
34.7k
      p2 = name + name_size;
381
34.7k
    if (p0 == 0)
382
25.6k
      p0 = p2;
383
34.7k
    p1 = p2;
384
34.7k
    if (p0 + 2 < p1 && asc_isdigit(p1[-1]) && asc_isdigit(p1[-2]) && p1[-3] == '-')
385
21
      p1 -= 2;
386
387
34.7k
    to_add->name.assign(name, p2-name);
388
34.7k
    to_add->c_struct.name = to_add->name.c_str();
389
  
390
34.7k
    to_add->code.assign(name, p0-name);
391
34.7k
    to_add->c_struct.code = to_add->code.c_str();
392
393
    // check if the code is in a valid form and normalize entry.  
394
    // If its not in a valid form, then ignore this entry
395
396
34.7k
    if (to_add->code.size() >= 2 
397
34.7k
  && asc_isalpha(to_add->code[0]) && asc_isalpha(to_add->code[1])) 
398
28.7k
    {
399
28.7k
      unsigned s = strcspn(to_add->code.str(), "_");
400
28.7k
      if (s > 3) return no_err;
401
22.1k
      unsigned i = 0;
402
70.7k
      for (; i != s; ++i)
403
48.6k
        to_add->name[i] = to_add->code[i] = asc_tolower(to_add->code[i]);
404
22.1k
      i++;
405
32.4k
      for (; i < to_add->code.size(); ++i)
406
10.3k
        to_add->name[i] = to_add->code[i] = asc_toupper(to_add->code[i]);
407
22.1k
    } else {
408
6.04k
      return no_err;
409
6.04k
    }
410
    
411
    // Need to do it here as module is about to get a value
412
    // if it is null
413
22.1k
    to_add->direct = module == 0 ? false : true;
414
415
22.1k
    if (!module) {
416
0
      assert(p2 != 0); //FIXME: return error
417
0
      ModuleInfoNode * mod 
418
0
  = list_all.module_info_list.find(p2+1, name_size - (p2+1-name));
419
      //FIXME: Check for null and return an error on an unknown module
420
0
      module = &(mod->c_struct);
421
0
    }
422
0
    to_add->c_struct.module = module;
423
  
424
22.1k
    if (p0 + 1 < p1)
425
4.56k
      to_add->variety.assign(p0+1, p1 - p0 - 1);
426
22.1k
    to_add->c_struct.variety = to_add->variety.c_str();
427
  
428
22.1k
    if (p1 != p2) 
429
21
      to_add->size_str.assign(p1, 2);
430
22.0k
    else
431
22.0k
      to_add->size_str = "60";
432
22.1k
    to_add->c_struct.size_str = to_add->size_str.c_str();
433
22.1k
    to_add->c_struct.size = atoi(to_add->c_struct.size_str);
434
435
22.1k
    if (dir) {
436
5.04k
      to_add->info_file  = dir;
437
5.04k
      to_add->info_file += '/';
438
5.04k
    }
439
22.1k
    to_add->info_file += name;
440
  
441
891k
    while (*prev != 0 && *(DictInfoNode *)*prev < *to_add)
442
869k
      prev = &(*prev)->next;
443
22.1k
    to_add->next = *prev;
444
22.1k
    *prev = to_add.release();
445
446
22.1k
    return no_err;
447
34.7k
  }
448
449
  bool operator< (const DictInfoNode & r, const DictInfoNode & l)
450
890k
  {
451
890k
    const DictInfo & rhs = r.c_struct;
452
890k
    const DictInfo & lhs = l.c_struct;
453
890k
    int res = strcmp(rhs.code, lhs.code);
454
890k
    if (res < 0) return true;
455
81.2k
    if (res > 0) return false;
456
75.7k
    res = strcmp(rhs.variety,lhs.variety);
457
75.7k
    if (res < 0) return true;
458
15.7k
    if (res > 0) return false;
459
12.8k
    if (rhs.size < lhs.size) return true;
460
12.8k
    if (rhs.size > lhs.size) return false;
461
12.8k
    res = strcmp(rhs.module->name,lhs.module->name);
462
12.8k
    if (res < 0) return true;
463
12.8k
    return false;
464
12.8k
  }
465
466
  PosibErr<void> get_dict_file_name(const DictInfo * mi, 
467
            String & main_wl, String & flags)
468
737
  {
469
737
    const DictInfoNode * node = reinterpret_cast<const DictInfoNode *>(mi);
470
737
    if (node->direct) {
471
737
      main_wl = node->info_file;
472
737
      flags   = "";
473
737
      return no_err;
474
737
    } else {
475
0
      FStream f;
476
0
      RET_ON_ERR(f.open(node->info_file, "r"));
477
0
      String buf; DataPair dp;
478
0
      bool res = getdata_pair(f, dp, buf);
479
0
      main_wl = dp.key; flags = dp.value;
480
0
      f.close();
481
0
      if (!res)
482
0
  return make_err(bad_file_format,  node->info_file, "");
483
0
      return no_err;
484
0
    }
485
737
  }
486
487
  /////////////////////////////////////////////////////////////////
488
  //
489
  // Lists of Info Lists Impl
490
  //
491
492
  void get_data_dirs (Config * config,
493
          StringList & lst)
494
760
  {
495
760
    lst.clear();
496
760
    lst.add(config->retrieve("data-dir"));
497
760
    lst.add(config->retrieve("dict-dir"));
498
760
  }
499
500
  DictExt::DictExt(ModuleInfo * m, const char * e)
501
459
  {
502
459
    module = m;
503
459
    ext_size = strlen(e);
504
459
    assert(ext_size <= max_ext_size);
505
0
    memcpy(ext, e, ext_size + 1);
506
459
  }
507
508
  void MDInfoListAll::clear()
509
2
  {
510
2
    module_info_list.clear();
511
2
    dict_dirs.clear();
512
2
    dict_exts.clear();
513
2
    dict_info_list.clear();
514
2
  }
515
516
  PosibErr<void> MDInfoListAll::fill(Config * c, 
517
                                     StringList & dirs)
518
155
  {
519
155
    PosibErr<void> err;
520
521
155
    err = fill_dict_aliases(c);
522
155
    if (err.has_err()) goto RETURN_ERROR;
523
524
153
    for_dirs = dirs;
525
153
    err = module_info_list.fill(*this, c);
526
153
    if (err.has_err()) goto RETURN_ERROR;
527
528
153
    fill_helper_lists(dirs);
529
153
    err = dict_info_list.fill(*this, c);
530
153
    if (err.has_err()) goto RETURN_ERROR;
531
532
153
    return err;
533
534
2
  RETURN_ERROR:
535
2
    clear();
536
2
    return err;
537
153
  }
538
539
  void MDInfoListAll::fill_helper_lists(const StringList & def_dirs)
540
153
  {
541
153
    dict_dirs = def_dirs;
542
153
    dict_exts.append(DictExt(0, ".awli"));
543
544
306
    for (ModuleInfoNode * n = module_info_list.head_; n != 0; n = n->next) 
545
153
    {
546
153
      {
547
153
  StringListEnumeration e = n->dict_dirs.elements_obj();
548
153
  const char * item;
549
153
  while ( (item = e.next()) != 0 )
550
0
    dict_dirs.add(item);
551
153
      }{
552
153
  StringListEnumeration e = n->dict_exts.elements_obj();
553
153
  const char * item;
554
459
  while ( (item = e.next()) != 0 )
555
306
    dict_exts.append(DictExt(&n->c_struct, item));
556
153
      }
557
153
    }
558
153
  }
559
560
  PosibErr<void> MDInfoListAll::fill_dict_aliases(Config * c)
561
155
  {
562
155
    StringList aliases;
563
155
    c->retrieve_list("dict-alias", &aliases);
564
155
    StringListEnumeration els = aliases.elements_obj();
565
155
    const char * str;
566
24.6k
    while ( (str = els.next()) != 0) {
567
24.5k
      const char * end = strchr(str, ' ');
568
24.5k
      if (!end) return make_err(bad_value, "dict-alias", str, 
569
2
                                _("in the form \"<name> <value>\""));
570
24.5k
      String name(str, end - str);
571
50.9k
      while (asc_isspace(*end)) ++end;
572
24.5k
      dict_aliases.insert(name.str(), end);
573
24.5k
    }
574
153
    return no_err;
575
155
  }
576
577
578
  MDInfoListofLists::MDInfoListofLists()
579
    : data(0), offset(0), size(0)
580
2
  {
581
2
  }
582
583
0
  MDInfoListofLists::~MDInfoListofLists() {
584
0
    for (int i = offset; i != offset + size; ++i)
585
0
      data[i].clear();
586
0
    delete[] data;
587
0
  }
588
589
  void MDInfoListofLists::clear(Config * c)
590
0
  {
591
0
    StringList dirs;
592
0
    get_data_dirs(c, dirs);
593
0
    int pos = find(dirs);
594
0
    if (pos == -1) {
595
0
      data[pos - offset].clear();
596
0
    }
597
0
  }
598
599
  int MDInfoListofLists::find(const StringList & key)
600
760
  {
601
12.6k
    for (int i = 0; i != size; ++i) {
602
12.5k
      if (data[i].key == key)
603
605
  return i + offset;
604
12.5k
    }
605
155
    return -1;
606
760
  }
607
608
  PosibErr<const MDInfoListAll *>
609
  MDInfoListofLists::get_lists(Config * c)
610
2.25k
  {
611
2.25k
    LOCK(&lock);
612
2.25k
    Config * config = (Config *)c; // FIXME: WHY?
613
2.25k
    int & pos = config->md_info_list_index;
614
2.25k
    StringList dirs;
615
2.25k
    StringList key;
616
2.25k
    if (!valid_pos(pos)) {
617
760
      get_data_dirs(config, dirs);
618
760
      key = dirs;
619
760
      key.add("////////");
620
760
      config->retrieve_list("dict-alias", &key);
621
760
      pos = find(key);
622
760
    }
623
2.25k
    if (!valid_pos(pos)) {
624
155
      MDInfoListAll * new_data = new MDInfoListAll[size + 1];
625
12.0k
      for (int i = 0; i != size; ++i) {
626
11.9k
  new_data[i] = data[i];
627
11.9k
      }
628
155
      ++size;
629
155
      delete[] data;
630
155
      data = new_data;
631
155
      pos = size - 1 + offset;
632
155
    }
633
2.25k
    MDInfoListAll & list_all = data[pos - offset];
634
2.25k
    if (list_all.has_data())
635
2.09k
      return &list_all;
636
637
155
    list_all.key = key;
638
155
    RET_ON_ERR(list_all.fill(config, dirs));
639
640
153
    return &list_all;
641
155
  }
642
643
  /////////////////////////////////////////////////////////////////
644
  //
645
  // utility functions
646
  //
647
648
  static const char * strnchr(const char * i, char c, unsigned int size)
649
34.7k
  {
650
34.7k
    const char * stop = i + size;
651
177k
    while (i != stop) {
652
151k
      if (*i == c)
653
9.11k
  return i;
654
142k
      ++i;
655
142k
    }
656
25.6k
    return 0;
657
34.7k
  }
658
659
  static const char * strnrchr(const char * stop, char c, unsigned int size)
660
0
  {
661
0
    const char * i = stop + size - 1;
662
0
    --stop;
663
0
    while (i != stop) {
664
0
      if (*i == c)
665
0
  return i;
666
0
      --i;
667
0
    }
668
0
    return 0;
669
0
  }
670
671
  /////////////////////////////////////////////////////////////////
672
  //
673
  // user visible functions and enumeration impl
674
  //
675
676
  //
677
  // ModuleInfo
678
  //
679
680
  PosibErr<const ModuleInfoList *> get_module_info_list(Config * c)
681
758
  {
682
758
    RET_ON_ERR_SET(md_info_list_of_lists.get_lists(c), const MDInfoListAll *, la);
683
756
    return &la->module_info_list;
684
758
  }
685
686
  ModuleInfoEnumeration * ModuleInfoList::elements() const
687
756
  {
688
756
    return new ModuleInfoEnumeration((ModuleInfoNode *)head_);
689
756
  }
690
691
  unsigned int ModuleInfoList::size() const
692
0
  {
693
0
    return size_;
694
0
  }
695
696
  bool ModuleInfoList::empty() const
697
0
  {
698
0
    return size_ != 0;
699
0
  }
700
701
  ModuleInfoEnumeration * ModuleInfoEnumeration::clone () const
702
0
  {
703
0
    return new ModuleInfoEnumeration(*this);
704
0
  }
705
706
  void ModuleInfoEnumeration::assign(const ModuleInfoEnumeration * other)
707
0
  {
708
0
    *this = *other;
709
0
  }
710
  
711
  bool ModuleInfoEnumeration::at_end () const
712
0
  {
713
0
    return node_ == 0;
714
0
  }
715
716
  const ModuleInfo * ModuleInfoEnumeration::next ()
717
1.51k
  {
718
1.51k
    if (node_ == 0) return 0;
719
756
    const ModuleInfo * data = &(node_->c_struct);
720
756
    node_ = (ModuleInfoNode *)(node_->next);
721
756
    return data;
722
1.51k
  }
723
724
  //
725
  // DictInfo
726
  //
727
728
  PosibErr<const DictInfoList *> get_dict_info_list(Config * c)
729
756
  {
730
756
    RET_ON_ERR_SET(md_info_list_of_lists.get_lists(c), const MDInfoListAll *, la);
731
756
    return &la->dict_info_list;
732
756
  }
733
734
  PosibErr<const StringMap *> get_dict_aliases(Config * c)
735
739
  {
736
739
    RET_ON_ERR_SET(md_info_list_of_lists.get_lists(c), const MDInfoListAll *, la);
737
739
    return &la->dict_aliases;
738
739
  }
739
740
  DictInfoEnumeration * DictInfoList::elements() const
741
756
  {
742
756
    return new DictInfoEnumeration(static_cast<DictInfoNode *>(head_));
743
756
  }
744
745
  unsigned int DictInfoList::size() const
746
0
  {
747
0
    return size_;
748
0
  }
749
750
  bool DictInfoList::empty() const
751
0
  {
752
0
    return size_ != 0;
753
0
  }
754
755
  DictInfoEnumeration * DictInfoEnumeration::clone() const
756
0
  {
757
0
    return new DictInfoEnumeration(*this);
758
0
  }
759
760
  void DictInfoEnumeration::assign(const DictInfoEnumeration * other)
761
0
  {
762
0
    *this = *other;
763
0
  }
764
765
  bool DictInfoEnumeration::at_end() const
766
0
  {
767
0
    return node_ == 0;
768
0
  }
769
770
  const DictInfo * DictInfoEnumeration::next ()
771
42.7k
  {
772
42.7k
    if (node_ == 0) return 0;
773
41.9k
    const DictInfo * data = &(node_->c_struct);
774
41.9k
    node_ = (DictInfoNode *)(node_->next);
775
41.9k
    return data;
776
42.7k
  }
777
778
}