-
Notifications
You must be signed in to change notification settings - Fork 1
/
Table.h
98 lines (85 loc) · 2.32 KB
/
Table.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef __Table_h__
#define __Table_h__ 1
#include <iostream>
#include <cstdio>
#include <string>
using std::string;
#include "DynVector.h"
template<class B>
class EntryBase {
protected:
const char *key;
public:
virtual ~EntryBase() {}
const char *Key() {return key;}
virtual B* New()=0;
};
template<class B>
class Table {
const char *name;
Compare_t *Compare;
KeyCompare_t *KeyCompare;
size_t n;
DynVector<EntryBase<B> *>list;
public:
static int DefaultCompare(const void *a, const void *b) {
return strcasecmp((*(EntryBase<B> **)a)->Key(),
(*(EntryBase<B> **)b)->Key());
}
static int DefaultKeyCompare(const void *key, const void *p,
const size_t n) {
return strcasecmpn((char *) key, (*(EntryBase<B> **)p)->Key(), n);
}
Table(const char *name, Compare_t Compare, KeyCompare_t KeyCompare) :
name(name), Compare(Compare), KeyCompare(KeyCompare), n(0) {}
Table(const char *name) : name(name), Compare(DefaultCompare),
KeyCompare(DefaultKeyCompare), n(0) {}
void Add(EntryBase<B> *ptr) {list[n++]=ptr;}
size_t Size() {return n;}
EntryBase<B> **Base() {return list;}
EntryBase<B> *Entry(size_t i) {return list[i];}
void List(ostream& os) {
for(size_t i=0; i < Size(); i++) os << Entry(i)->Key() << newl;
os << flush;
}
B *Locate (const char *& key) {
int match_type;
EntryBase<B> *e;
B *p;
qsort(Base(),Size(),sizeof(*Base()),Compare);
for(;;) {
e=*(EntryBase<B> **) bsearch2(key,Base(),Size(),sizeof(*Base()),
KeyCompare,&match_type);
if(check_match(match_type,name,key,2)) break;
cout << "Recognized " << name << " values:" << endl << endl;
List(cout);
cout << newl << name << "=";
string s;
getline(cin,s);
if(s.c_str()) key=strdup(s.c_str());
}
p=e->New();
if(*p->Name()) {
key=e->Key();
cout << newl << upcase(name) << ": " << p->Name() << endl;
}
return p;
}
B *New() {return NULL;}
};
template<class T, class B>
class Entry : public EntryBase<B> {
public:
Entry(const char *key0, Table<B> *t) {this->key=key0; t->Add(this);}
B *New() {return new T;}
};
template<class T, class B, class P>
class entry : public EntryBase<B> {
P *p;
public:
entry(const char *key0, Table<B> *t, P *p) : p(p) {
this->key=key0; t->Add(this);
}
B *New() {return new T(p);}
};
#endif