1 /*
2 * Copyright (c) 2012-2021, The OSKAR Developers.
3 * See the LICENSE file at the top-level directory of this distribution.
4 */
5
6 #include "settings/oskar_option_parser.h"
7 #include "binary/oskar_binary.h"
8 #include "binary/private_binary.h"
9 #include "log/oskar_log.h"
10 #include "mem/oskar_binary_read_mem.h"
11 #include "utility/oskar_get_binary_tag_string.h"
12 #include "utility/oskar_get_error_string.h"
13 #include "utility/oskar_version_string.h"
14
15 #include <cmath>
16 #include <cstdio>
17 #include <cstdlib>
18 #include <string>
19
print_log(const char * filename,oskar_Log * log,int * status)20 static void print_log(const char* filename, oskar_Log* log, int* status)
21 {
22 int tag_not_present = 0;
23 oskar_Binary* h = oskar_binary_create(filename, 'r', status);
24 if (*status)
25 {
26 oskar_binary_free(h);
27 return;
28 }
29 oskar_Mem* temp = oskar_mem_create(OSKAR_CHAR, OSKAR_CPU, 0, status);
30 oskar_binary_read_mem(h, temp, OSKAR_TAG_GROUP_RUN,
31 OSKAR_TAG_RUN_LOG, 0, &tag_not_present);
32 oskar_mem_realloc(temp, oskar_mem_length(temp) + 1, status);
33 oskar_mem_char(temp)[oskar_mem_length(temp) - 1] = 0; /* Null-terminate. */
34 if (tag_not_present)
35 {
36 oskar_log_error(log, "Run log not found");
37 }
38 else
39 {
40 printf("%s\n", oskar_mem_char(temp));
41 }
42 oskar_mem_free(temp, status);
43 oskar_binary_free(h);
44 }
45
print_settings(const char * filename,oskar_Log * log,int * status)46 static void print_settings(const char* filename, oskar_Log* log, int* status)
47 {
48 int tag_not_present = 0;
49 oskar_Binary* h = oskar_binary_create(filename, 'r', status);
50 if (*status)
51 {
52 oskar_binary_free(h);
53 return;
54 }
55 oskar_Mem* temp = oskar_mem_create(OSKAR_CHAR, OSKAR_CPU, 0, status);
56 oskar_binary_read_mem(h, temp, OSKAR_TAG_GROUP_SETTINGS,
57 OSKAR_TAG_SETTINGS, 0, &tag_not_present);
58 oskar_mem_realloc(temp, oskar_mem_length(temp) + 1, status);
59 oskar_mem_char(temp)[oskar_mem_length(temp) - 1] = 0; /* Null-terminate. */
60 if (tag_not_present)
61 {
62 oskar_log_error(log, "Settings data not found");
63 }
64 else
65 {
66 printf("%s\n", oskar_mem_char(temp));
67 }
68 oskar_mem_free(temp, status);
69 oskar_binary_free(h);
70 }
71
scan_file(const char * filename,oskar_Log * log,int * status)72 static void scan_file(const char* filename, oskar_Log* log, int* status)
73 {
74 int extended_tags = 0, depth = -4, i = 0;
75 const char p = 'M';
76 oskar_Mem* temp = 0;
77 oskar_Binary* h = oskar_binary_create(filename, 'r', status);
78 if (*status)
79 {
80 oskar_binary_free(h);
81 return;
82 }
83
84 /* Log file header data. */
85 const int num_chunks = oskar_binary_num_tags(h);
86 oskar_log_section(log, p, "File header in '%s'", filename);
87 oskar_log_message(log, p, 0, "File contains %d chunks.", num_chunks);
88
89 /* Iterate all tags in index. */
90 oskar_log_section(log, p, "Standard tags:");
91 oskar_log_message(log, p, -1, "[%3s] %-23s %5s.%-3s : %-10s (%s)",
92 "ID", "TYPE", "GROUP", "TAG", "INDEX", "BYTES");
93 oskar_log_message(log, p, depth, "CONTENTS");
94 oskar_log_line(log, p, '-');
95 for (i = 0; i < num_chunks; ++i)
96 {
97 size_t num_items = 0;
98 if (h->extended[i])
99 {
100 extended_tags++;
101 continue;
102 }
103 const char group = (char) (h->id_group[i]);
104 const char tag = (char) (h->id_tag[i]);
105 const char type = (char) (h->data_type[i]);
106 const int idx = h->user_index[i];
107 const size_t bytes = h->payload_size_bytes[i];
108
109 /* Display tag data. */
110 oskar_log_message(log, p, -1,
111 "[%3d] %-23s %5d.%-3d : %-10d (%ld bytes)",
112 i, oskar_mem_data_type_string(type), group, tag, idx, bytes);
113
114 /* Display more info if available. */
115 const char* label = oskar_get_binary_tag_string(group, tag);
116 temp = oskar_mem_create(type, OSKAR_CPU, 0, status);
117 if (bytes <= 512 || type == OSKAR_CHAR)
118 {
119 oskar_binary_read_mem(h, temp, group, tag, idx, status);
120 }
121 const int precision = oskar_type_precision((int)type);
122 num_items = oskar_mem_length(temp);
123 if (oskar_type_is_complex(type)) num_items *= 2;
124 if (oskar_type_is_matrix(type)) num_items *= 4;
125 switch (precision)
126 {
127 case OSKAR_CHAR:
128 {
129 size_t c = 0;
130 char* data = oskar_mem_char(temp);
131 const int max_string_length = 40;
132 const char* fmt = "%s: %.*s";
133 for (c = 0; c < bytes && c < oskar_mem_length(temp); ++c)
134 {
135 if (data[c] < 32 && data[c] != 0) data[c] = ' ';
136 }
137 if (bytes > max_string_length) fmt = "%s: %.*s ...";
138 oskar_log_message(log, p, depth, fmt, label,
139 max_string_length, oskar_mem_char(temp));
140 break;
141 }
142 case OSKAR_INT:
143 {
144 const int* data = oskar_mem_int_const(temp, status);
145 switch (num_items)
146 {
147 case 0:
148 oskar_log_message(log, p, depth, "%s", label);
149 break;
150 case 1:
151 oskar_log_message(log, p, depth, "%s: %d", label, data[0]);
152 break;
153 case 2:
154 oskar_log_message(log, p, depth, "%s: [%d, %d]",
155 label, data[0], data[1]);
156 break;
157 case 3:
158 oskar_log_message(log, p, depth, "%s: [%d, %d, %d]",
159 label, data[0], data[1], data[2]);
160 break;
161 case 4:
162 oskar_log_message(log, p, depth, "%s: [%d, %d, %d, %d]",
163 label, data[0], data[1], data[2], data[3]);
164 break;
165 case 5:
166 oskar_log_message(log, p, depth, "%s: [%d, %d, %d, %d, %d]",
167 label, data[0], data[1], data[2], data[3], data[4]);
168 break;
169 case 6:
170 oskar_log_message(log, p, depth, "%s: [%d, %d, %d, %d, %d, %d]",
171 label, data[0], data[1], data[2], data[3], data[4],
172 data[5]);
173 break;
174 default:
175 oskar_log_message(log, p, depth,
176 "%s: [%d, %d, %d, %d, %d, %d ...]",
177 label, data[0], data[1], data[2], data[3], data[4],
178 data[5]);
179 }
180 break;
181 }
182 case OSKAR_SINGLE:
183 {
184 const float* data = oskar_mem_float_const(temp, status);
185 switch (num_items)
186 {
187 case 1:
188 if ((fabs(data[0]) < 1e3 && fabs(data[0]) > 1e-3) ||
189 data[0] == 0.0)
190 {
191 oskar_log_message(log, p, depth, "%s: %.3f",
192 label, data[0]);
193 }
194 else
195 {
196 oskar_log_message(log, p, depth, "%s: %.3e",
197 label, data[0]);
198 }
199 break;
200 case 2:
201 oskar_log_message(log, p, depth, "%s: [%.3e, %.3e]",
202 label, data[0], data[1]);
203 break;
204 default:
205 if (num_items > 2)
206 {
207 oskar_log_message(log, p, depth,
208 "%s: [%.3e, %.3e ...]", label, data[0], data[1]);
209 }
210 else
211 {
212 oskar_log_message(log, p, depth, "%s", label);
213 }
214 }
215 break;
216 }
217 case OSKAR_DOUBLE:
218 {
219 const double* data = oskar_mem_double_const(temp, status);
220 switch (num_items)
221 {
222 case 1:
223 if ((fabs(data[0]) < 1e3 && fabs(data[0]) > 1e-3) ||
224 data[0] == 0.0)
225 {
226 oskar_log_message(log, p, depth, "%s: %.3f",
227 label, data[0]);
228 }
229 else
230 {
231 oskar_log_message(log, p, depth, "%s: %.3e",
232 label, data[0]);
233 }
234 break;
235 case 2:
236 oskar_log_message(log, p, depth, "%s: [%.3e, %.3e]",
237 label, data[0], data[1]);
238 break;
239 default:
240 if (num_items > 2)
241 {
242 oskar_log_message(log, p, depth,
243 "%s: [%.3e, %.3e ...]", label, data[0], data[1]);
244 }
245 else
246 {
247 oskar_log_message(log, p, depth, "%s", label);
248 }
249 }
250 break;
251 }
252 default:
253 break;
254 }
255 oskar_mem_free(temp, status);
256 }
257
258 /* Iterate extended tags in index. */
259 if (extended_tags)
260 {
261 oskar_log_section(log, p, "Extended tags:");
262 oskar_log_message(log, p, -1, "[%3s] %-23s (%s)",
263 "ID", "TYPE", "BYTES");
264 oskar_log_message(log, p, depth, "%s.%s : %s", "GROUP", "TAG", "INDEX");
265 oskar_log_line(log, p, '-');
266 for (i = 0; i < num_chunks; ++i)
267 {
268 if (!h->extended[i]) continue;
269 const char* group = h->name_group[i];
270 const char* tag = h->name_tag[i];
271 const char type = (char) (h->data_type[i]);
272 const int idx = h->user_index[i];
273 const size_t bytes = h->payload_size_bytes[i];
274
275 /* Display tag data. */
276 oskar_log_message(log, p, -1, "[%3d] %-23s (%d bytes)",
277 i, oskar_mem_data_type_string(type), bytes);
278 oskar_log_message(log, p, depth, "%s.%s : %d", group, tag, idx);
279 }
280 }
281 oskar_binary_free(h);
282 }
283
284
main(int argc,char ** argv)285 int main(int argc, char** argv)
286 {
287 oskar::OptionParser opt("oskar_binary_file_query", oskar_version_string());
288 opt.set_description("List a summary of the contents of an OSKAR binary file.");
289 opt.add_required("binary file", "Path to an OSKAR binary file.");
290 opt.add_flag("-l", "Display the log.", false, "--log");
291 opt.add_flag("-s", "Display the settings file.", false, "--opts");
292 if (!opt.check_options(argc, argv)) return EXIT_FAILURE;
293 const char* filename = opt.get_arg();
294
295 int error = 0;
296 bool display_log = opt.is_set("-l") ? true : false;
297 bool display_settings = opt.is_set("-s") ? true : false;
298
299 oskar_Log* log = 0;
300 oskar_log_set_file_priority(log, OSKAR_LOG_NONE);
301 oskar_log_set_term_priority(log, OSKAR_LOG_STATUS);
302
303 if (display_log)
304 {
305 print_log(filename, log, &error);
306 }
307 else if (display_settings)
308 {
309 print_settings(filename, log, &error);
310 }
311 else
312 {
313 scan_file(filename, log, &error);
314 }
315
316 if (error)
317 {
318 oskar_log_error(log, oskar_get_error_string(error));
319 }
320
321 return error ? EXIT_FAILURE : EXIT_SUCCESS;
322 }
323