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