@@ -10,10 +10,12 @@ namespace py = pybind11;
1010class RdsReader {
1111private:
1212 const rds2cpp::RObject* ptr;
13+ const std::vector<rds2cpp::Symbol>* symbols_ptr;
1314
1415public:
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
128143private:
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)
0 commit comments