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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
#include <algorithm>
#include "Alignment/Geners/interface/AbsArchive.hh"
#include "Alignment/Geners/interface/AbsReference.hh"
#include "Alignment/Geners/interface/CatalogEntry.hh"
#include "Alignment/Geners/interface/IOException.hh"
// Notes on implementation
//
// The following invariants should be preserved:
//
// 0 items: must have itemId_ == 0 && idList_.empty()
// 1 item: must have itemId_ != 0 && idList_.empty()
// more items: must have itemId_ == 0 && !idList_.empty()
//
namespace gs {
std::istream &AbsReference::positionInputStream(const unsigned long long id) const {
return archive_.inputStream(id, nullptr);
}
void AbsReference::initialize() const {
AbsReference *modifiable = const_cast<AbsReference *>(this);
if (searchId_) {
// Make sure that the searchId_ item id is going to produce
// a valid item
std::shared_ptr<const CatalogEntry> record = archive_.catalogEntry(searchId_);
const unsigned long long idFound = record->id();
// Check for valid id in the archive
if (idFound && this->isIOCompatible(*record)) {
if (idFound != searchId_)
throw IOInvalidData("In AbsReference::initialize: catalog is corrupted");
modifiable->itemId_ = searchId_;
}
} else {
// Search for matching items in the archive
archive_.search(*modifiable);
if (!idList_.empty()) {
// Check if the list is sorted.
// Sort if it is not.
const unsigned long nFound = idList_.size();
const unsigned long long *ids = &idList_[0];
bool sorted = true;
for (unsigned long i = 1; i < nFound; ++i)
if (ids[i - 1] >= ids[i]) {
sorted = false;
break;
}
if (!sorted)
std::sort(modifiable->idList_.begin(), modifiable->idList_.end());
}
}
modifiable->initialized_ = true;
}
bool AbsReference::isIOCompatible(const CatalogEntry &r) const {
return !classId_.name().empty() && classId_.name() == r.type().name() && ioProto_ == r.ioPrototype();
}
bool AbsReference::empty() const {
if (!initialized_)
initialize();
return itemId_ == 0 && idList_.empty();
}
bool AbsReference::unique() const {
if (!initialized_)
initialize();
return itemId_ && idList_.empty();
}
unsigned long AbsReference::size() const {
if (!initialized_)
initialize();
return itemId_ ? 1UL : idList_.size();
}
unsigned long long AbsReference::id(const unsigned long index) const {
if (!initialized_)
initialize();
if (itemId_ && index == 0UL)
return itemId_;
else if (index < idList_.size())
return idList_[index];
else
throw gs::IOOutOfRange(
"In gs::AbsReference::id: "
"index out of range");
}
std::shared_ptr<const CatalogEntry> AbsReference::indexedCatalogEntry(const unsigned long index) const {
return archive_.catalogEntry(id(index));
}
bool AbsReference::isSameIOPrototype(const CatalogEntry &r) const { return ioProto_ == r.ioPrototype(); }
void AbsReference::addItemId(const unsigned long long idIn) {
if (!idIn)
throw gs::IOInvalidArgument("In AbsReference::addItemId: invalid item id");
const unsigned long mySize = itemId_ ? 1UL : idList_.size();
switch (mySize) {
case 0UL:
itemId_ = idIn;
break;
case 1UL:
idList_.reserve(2);
idList_.push_back(itemId_);
idList_.push_back(idIn);
itemId_ = 0ULL;
break;
default:
idList_.push_back(idIn);
break;
}
}
AbsReference::AbsReference(AbsArchive &ar,
const ClassId &classId,
const char *ioPrototype,
const unsigned long long itemId)
: archive_(ar),
classId_(classId),
ioProto_(ioPrototype ? ioPrototype : ""),
searchId_(itemId),
namePattern_(nullptr),
categoryPattern_(nullptr),
itemId_(0),
initialized_(false) {
if (!itemId)
throw gs::IOInvalidArgument("In AbsReference constructor: invalid item id");
}
AbsReference::AbsReference(AbsArchive &ar,
const ClassId &classId,
const char *ioPrototype,
const SearchSpecifier &namePattern,
const SearchSpecifier &categoryPattern)
: archive_(ar),
classId_(classId),
ioProto_(ioPrototype ? ioPrototype : ""),
searchId_(0),
namePattern_(namePattern),
categoryPattern_(categoryPattern),
itemId_(0),
initialized_(false) {}
} // namespace gs
|