rds2cpp
C++ library for parsing RDS files
Loading...
Searching...
No Matches
parse_rds.hpp
Go to the documentation of this file.
1#ifndef RDS2CPP_PARSE_HPP
2#define RDS2CPP_PARSE_HPP
3
4#include <memory>
5#include <algorithm>
6#include <cstdint>
7
8#include "RdsFile.hpp"
9#include "utils_parse.hpp"
10#include "SharedParseInfo.hpp"
11#include "parse_object.hpp"
12
13#include "byteme/byteme.hpp"
14
21namespace rds2cpp {
22
38
49template<class Reader_>
50RdsFile parse_rds(Reader_& reader, const ParseRdsOptions& options) {
51 std::unique_ptr<byteme::PerByteInterface<unsigned char> > srcptr;
52 if (options.parallel) {
53 srcptr.reset(new byteme::PerByteParallel<unsigned char, Reader_*>(&reader));
54 } else {
55 srcptr.reset(new byteme::PerByteSerial<unsigned char, Reader_*>(&reader));
56 }
57 auto& src = *srcptr;
58 RdsFile output(false);
59
60 // Reading the header first. This is the first and only time that
61 // we need to do a src.valid() check, as we're using the current
62 // position of the source; in all other cases, it can be assumed
63 // that the source needs to be advance()'d before get().
64 {
65 try {
66 if (!src.valid()) {
67 throw empty_error();
68 }
69 if (src.get() != 'X') {
70 throw std::runtime_error("only RDS files in XDR format are currently supported");
71 }
72
73 if (!src.advance()) {
74 throw empty_error();
75 }
76 if (src.get() != '\n') {
77 throw std::runtime_error("only RDS files in XDR format are currently supported");
78 }
79 } catch (std::exception& e) {
80 throw traceback("failed to read the header from the RDS preamble", e);
81 }
82
83 output.format_version = 0;
84 try {
85 for (int i = 0; i < 4; ++i) {
86 if (!src.advance()) {
87 throw empty_error();
88 }
89 output.format_version <<= 8;
90 output.format_version += src.get();
91 }
92 } catch (std::exception& e) {
93 throw traceback("failed to read the format version number from the RDS preamble", e);
94 }
95
96 // Just skipping the first byte for the R reader/writer versions...
97 // unless we get up to a major version > 255, then we're in trouble.
98 try {
99 if (!src.advance()) {
100 throw empty_error();
101 }
102 quick_extract(src, output.writer_version.size(), output.writer_version.data());
103 } catch (std::exception& e) {
104 throw traceback("failed to read the writer version number from the RDS preamble", e);
105 }
106
107 try {
108 if (!src.advance()) {
109 throw empty_error();
110 }
111 quick_extract(src, output.reader_version.size(), output.reader_version.data());
112 } catch (std::exception& e) {
113 throw traceback("failed to read the reader version number from the RDS preamble", e);
114 }
115 }
116
117 // Reading this undocumented section about the string encoding.
118 {
119 size_t encoding_length = 0;
120 try {
121 for (int b = 0; b < 4; ++b) {
122 if (!src.advance()) {
123 throw empty_error();
124 }
125 encoding_length <<= 8;
126 encoding_length += src.get();
127 }
128 } catch (std::exception& e) {
129 throw traceback("failed to read the encoding length from the RDS preamble", e);
130 }
131
132 try {
133 output.encoding.reserve(encoding_length); // don't resize and use extract() on string::data, as that pointer is read-only AFAICT.
134 for (size_t b = 0; b < encoding_length; ++b) {
135 if (!src.advance()) {
136 throw empty_error();
137 }
138 output.encoding.push_back(as_char(src.get()));
139 }
140 } catch (std::exception& e) {
141 throw traceback("failed to read the encoding string from the RDS preamble", e);
142 }
143 }
144
145 // Now we can finally read the damn object.
146 SharedParseInfo shared;
147 output.object = parse_object(src, shared);
148 output.environments = std::move(shared.environments);
149 output.symbols = std::move(shared.symbols);
150 output.external_pointers = std::move(shared.external_pointers);
151
152 return output;
153}
154
163inline RdsFile parse_rds(std::string file, const ParseRdsOptions& options) {
164 byteme::SomeFileReader reader(file.c_str(), options.file_options);
165 return parse_rds(reader, options);
166}
167
172
173}
174
175#endif
Information about an RDS file.
Parse an RDS file in C++.
Definition StringEncoding.hpp:10
RdsFile parse_rds(Reader_ &reader, const ParseRdsOptions &options)
Definition parse_rds.hpp:50
RdsFile Parsed
Definition parse_rds.hpp:171
Options for parse_rds().
Definition parse_rds.hpp:26
bool parallel
Definition parse_rds.hpp:30
byteme::SomeFileReaderOptions file_options
Definition parse_rds.hpp:36
Contents of the parsed RDS file.
Definition RdsFile.hpp:21
std::array< unsigned char, 3 > writer_version
Definition RdsFile.hpp:53
std::unique_ptr< RObject > object
Definition RdsFile.hpp:68
std::vector< Symbol > symbols
Definition RdsFile.hpp:80
std::vector< ExternalPointer > external_pointers
Definition RdsFile.hpp:86
std::string encoding
Definition RdsFile.hpp:63
uint32_t format_version
Definition RdsFile.hpp:48
std::vector< Environment > environments
Definition RdsFile.hpp:74
std::array< unsigned char, 3 > reader_version
Definition RdsFile.hpp:58