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 for (int pos = 0; pos < 3; ++pos) {
103 if (!src.advance()) {
104 throw empty_error();
105 }
106 output.writer_version[pos] = src.get();
107 }
108 } catch (std::exception& e) {
109 throw traceback("failed to read the writer version number from the RDS preamble", e);
110 }
111
112 try {
113 if (!src.advance()) {
114 throw empty_error();
115 }
116 for (int pos = 0; pos < 3; ++pos) {
117 if (!src.advance()) {
118 throw empty_error();
119 }
120 output.reader_version[pos] = src.get();
121 }
122 } catch (std::exception& e) {
123 throw traceback("failed to read the reader version number from the RDS preamble", e);
124 }
125 }
126
127 // Reading this undocumented section about the string encoding.
128 {
129 size_t encoding_length = 0;
130 try {
131 for (int b = 0; b < 4; ++b) {
132 if (!src.advance()) {
133 throw empty_error();
134 }
135 encoding_length <<= 8;
136 encoding_length += src.get();
137 }
138 } catch (std::exception& e) {
139 throw traceback("failed to read the encoding length from the RDS preamble", e);
140 }
141
142 try {
143 output.encoding.reserve(encoding_length);
144 for (size_t b = 0; b < encoding_length; ++b) {
145 if (!src.advance()) {
146 throw empty_error();
147 }
148 output.encoding.push_back(src.get());
149 }
150 } catch (std::exception& e) {
151 throw traceback("failed to read the encoding string from the RDS preamble", e);
152 }
153 }
154
155 // Now we can finally read the damn object.
156 SharedParseInfo shared;
157 output.object = parse_object(src, shared);
158 output.environments = std::move(shared.environments);
159 output.symbols = std::move(shared.symbols);
160 output.external_pointers = std::move(shared.external_pointers);
161
162 return output;
163}
164
173inline RdsFile parse_rds(std::string file, const ParseRdsOptions& options) {
174 byteme::SomeFileReader reader(file.c_str(), options.file_options);
175 return parse_rds(reader, options);
176}
177
182
183}
184
185#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:181
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