Skip to content

Commit e543b32

Browse files
authored
Switch to the release version of rds2cpp (#74)
1 parent cb8a00b commit e543b32

3 files changed

Lines changed: 48 additions & 28 deletions

File tree

lib/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ include(FetchContent)
1111
FetchContent_Declare(
1212
rds2cpp
1313
GIT_REPOSITORY https://github.com/LTLA/rds2cpp
14-
GIT_TAG master
14+
GIT_TAG v1.3.1
1515
)
1616

1717
FetchContent_Declare(
1818
byteme
1919
GIT_REPOSITORY https://github.com/LTLA/byteme
20-
GIT_TAG master
20+
GIT_TAG v2.1.3
2121
)
2222

2323
FetchContent_Declare(
2424
sanisizer
2525
GIT_REPOSITORY https://github.com/LTLA/sanisizer
26-
GIT_TAG master
26+
GIT_TAG v0.2.2
2727
)
2828

2929
FetchContent_MakeAvailable(byteme)

lib/src/rdswrapper.cpp

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ namespace py = pybind11;
1010
class RdsReader {
1111
private:
1212
const rds2cpp::RObject* ptr;
13+
const std::vector<rds2cpp::Symbol>* symbols_ptr;
1314

1415
public:
15-
RdsReader(const rds2cpp::RObject* p) : ptr(p) {
16+
RdsReader(const rds2cpp::RObject* p, const std::vector<rds2cpp::Symbol>* syms) : ptr(p), symbols_ptr(syms) {
1617
if (!p) throw std::runtime_error("Null pointer passed to 'RdsReader'.");
18+
if (!syms) throw std::runtime_error("Null symbols pointer passed to 'RdsReader'.");
1719
}
1820

1921
std::string get_rtype() const {
@@ -69,23 +71,36 @@ class RdsReader {
6971
throw std::runtime_error("Invalid type for 'string_arr'");
7072
}
7173
const auto& data = static_cast<const rds2cpp::StringVector*>(ptr)->data;
72-
return py::cast(data);
74+
py::list result;
75+
for (const auto& s : data) {
76+
if (s.value.has_value()) {
77+
result.append(s.value.value());
78+
} else {
79+
result.append(py::none());
80+
}
81+
}
82+
return result;
7383
}
7484

7585
py::list get_attribute_names() const {
7686
if (!ptr) throw std::runtime_error("Null pointer in 'get_attribute_names'");
77-
return py::cast(get_attributes().names);
87+
const auto& attrs = get_attributes();
88+
py::list names;
89+
for (const auto& attr : attrs) {
90+
names.append(resolve_symbol(attr.name));
91+
}
92+
return names;
7893
}
7994

8095
py::object load_attribute_by_name(const std::string& name) const {
8196
if (!ptr) throw std::runtime_error("Null pointer in 'load_attribute_by_name'");
82-
const auto& attributes = get_attributes();
83-
auto it = std::find(attributes.names.begin(), attributes.names.end(), name);
84-
if (it == attributes.names.end()) {
85-
throw std::runtime_error("Attribute not found: " + name);
97+
const auto& attrs = get_attributes();
98+
for (const auto& attr : attrs) {
99+
if (resolve_symbol(attr.name) == name) {
100+
return py::cast(new RdsReader(attr.value.get(), symbols_ptr));
101+
}
86102
}
87-
size_t index = std::distance(attributes.names.begin(), it);
88-
return py::cast(new RdsReader(attributes.values[index].get()));
103+
throw std::runtime_error("Attribute not found: " + name);
89104
}
90105

91106
py::object load_vec_element(int index) const {
@@ -97,7 +112,7 @@ class RdsReader {
97112
if (index < 0 || static_cast<size_t>(index) >= data.size()) {
98113
throw std::out_of_range("Vector index out of range");
99114
}
100-
return py::cast(new RdsReader(data[index].get()));
115+
return py::cast(new RdsReader(data[index].get(), symbols_ptr));
101116
}
102117

103118
std::string get_package_name() const {
@@ -126,7 +141,14 @@ class RdsReader {
126141
}
127142

128143
private:
129-
const rds2cpp::Attributes& get_attributes() const {
144+
std::string resolve_symbol(const rds2cpp::SymbolIndex& sym) const {
145+
if (sym.index >= symbols_ptr->size()) {
146+
throw std::runtime_error("Symbol index out of range");
147+
}
148+
return (*symbols_ptr)[sym.index].name;
149+
}
150+
151+
const std::vector<rds2cpp::Attribute>& get_attributes() const {
130152
if (!ptr) throw std::runtime_error("Null pointer in get_attributes");
131153
switch (ptr->type()) {
132154
case rds2cpp::SEXPType::INT: return static_cast<const rds2cpp::IntegerVector*>(ptr)->attributes;
@@ -153,7 +175,7 @@ class RdsObject {
153175
if (!parsed || !parsed->object) {
154176
throw std::runtime_error("Failed to parse RDS file");
155177
}
156-
reader = std::make_unique<RdsReader>(parsed->object.get());
178+
reader = std::make_unique<RdsReader>(parsed->object.get(), &parsed->symbols);
157179
} catch (const std::exception& e) {
158180
throw std::runtime_error(std::string("Error in 'RdsObject' constructor: ") + e.what());
159181
}
@@ -181,11 +203,10 @@ class RdaObject {
181203

182204
py::list get_object_names() const {
183205
if (!parsed) throw std::runtime_error("Null parsed in 'get_object_names'");
184-
const auto& pairlist = parsed->contents;
185206
py::list names;
186-
for (size_t i = 0; i < pairlist.tag_names.size(); ++i) {
187-
if (pairlist.has_tag[i]) {
188-
names.append(pairlist.tag_names[i]);
207+
for (const auto& obj : parsed->objects) {
208+
if (obj.name.index < parsed->symbols.size()) {
209+
names.append(parsed->symbols[obj.name.index].name);
189210
} else {
190211
names.append(py::none());
191212
}
@@ -195,24 +216,23 @@ class RdaObject {
195216

196217
int get_object_count() const {
197218
if (!parsed) throw std::runtime_error("Null parsed in 'get_object_count'");
198-
return static_cast<int>(parsed->contents.data.size());
219+
return static_cast<int>(parsed->objects.size());
199220
}
200221

201222
RdsReader* get_object_by_index(int index) const {
202223
if (!parsed) throw std::runtime_error("Null parsed in 'get_object_by_index'");
203-
const auto& data = parsed->contents.data;
204-
if (index < 0 || static_cast<size_t>(index) >= data.size()) {
224+
if (index < 0 || static_cast<size_t>(index) >= parsed->objects.size()) {
205225
throw std::out_of_range("Object index out of range");
206226
}
207-
return new RdsReader(data[index].get());
227+
return new RdsReader(parsed->objects[index].value.get(), &parsed->symbols);
208228
}
209229

210230
RdsReader* get_object_by_name(const std::string& name) const {
211231
if (!parsed) throw std::runtime_error("Null parsed in 'get_object_by_name'");
212-
const auto& pairlist = parsed->contents;
213-
for (size_t i = 0; i < pairlist.tag_names.size(); ++i) {
214-
if (pairlist.has_tag[i] && pairlist.tag_names[i] == name) {
215-
return new RdsReader(pairlist.data[i].get());
232+
for (const auto& obj : parsed->objects) {
233+
if (obj.name.index < parsed->symbols.size() &&
234+
parsed->symbols[obj.name.index].name == name) {
235+
return new RdsReader(obj.value.get(), &parsed->symbols);
216236
}
217237
}
218238
throw std::runtime_error("Object not found: " + name);
@@ -234,7 +254,6 @@ PYBIND11_MODULE(lib_rds_parser, m) {
234254
.def("get_object_by_name", &RdaObject::get_object_by_name, py::return_value_policy::take_ownership, py::keep_alive<0, 1>());
235255

236256
py::class_<RdsReader>(m, "RdsReader")
237-
.def(py::init<const rds2cpp::RObject*>())
238257
.def("get_rtype", &RdsReader::get_rtype)
239258
.def("get_rsize", &RdsReader::get_rsize)
240259
.def("get_numeric_data", &RdsReader::get_numeric_data)

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ optional =
7272
compressed_lists>=0.4.4
7373
biocutils>=0.3.4
7474
compressed_lists
75+
iranges
7576

7677
# Add here test requirements (semicolon/line-separated)
7778
testing =

0 commit comments

Comments
 (0)