Browse Source

Temporary release without license

Smoolak 1 year ago
parent
commit
4711257585
4 changed files with 814 additions and 0 deletions
  1. 3
    0
      .gitignore
  2. 20
    0
      CMakeLists.txt
  3. 40
    0
      include/readbop.h
  4. 751
    0
      src/readbop.c.in

+ 3
- 0
.gitignore View File

@@ -1,3 +1,6 @@
1
+# File generated by CMake configure
2
+src/readbop.c
3
+
1 4
 # ---> CMake
2 5
 CMakeCache.txt
3 6
 CMakeFiles

+ 20
- 0
CMakeLists.txt View File

@@ -0,0 +1,20 @@
1
+cmake_minimum_required(VERSION 3.9)
2
+project(readbop VERSION 1.0 DESCRIPTION "A library for reading and manipulating Parrot's drones pud and black box files")
3
+include(GNUInstallDirs)
4
+add_library(readbop SHARED src/readbop.c)
5
+set_target_properties(readbop PROPERTIES PUBLIC_HEADER include/readbop.h)
6
+target_include_directories(readbop PRIVATE include)
7
+target_include_directories(readbop PRIVATE src)
8
+install(TARGETS readbop
9
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
10
+    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
11
+
12
+include(CheckIncludeFiles)
13
+check_include_files("fcntl.h;errno.h;sys/types.h;sys/stat.h;unistd.h" POSIX_READ_FILE)
14
+configure_file(src/readbop.c.in src/readbop.c @ONLY)
15
+
16
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "Intel" OR CMAKE_C_COMPILER_ID STREQUAL "XL")
17
+	set(CMAKE_C_FLAGS "-Ofast ${CMAKE_C_FLAGS}")
18
+elseif(MSVC)
19
+	set(CMAKE_C_FLAGS "/Ox ${CMAKE_C_FLAGS}")
20
+endif()

+ 40
- 0
include/readbop.h View File

@@ -0,0 +1,40 @@
1
+#ifndef READBOP_H
2
+#define READBOP_H
3
+	#include <stdlib.h>
4
+	#include <stdio.h>
5
+	#include <string.h>
6
+	#include <stdint.h>
7
+	#include <inttypes.h>
8
+	#include <float.h>
9
+	#include <errno.h>
10
+
11
+	#define BUFFER_SIZE 2097152 //Default 2M
12
+
13
+	_Thread_local int rb_errno = 0;
14
+
15
+	typedef enum {BOOL, UINT8, UINT16, UINT32, UINT64, INT8, INT16, INT32, INT64, FLOAT, DOUBLE, UNKNOWN} type_t;
16
+	const int8_t type_sizes[] = {1, 1, 2, 4, 8, 1, 2, 4, 8, 4, 8, -1};
17
+	char const *type_names[] = {"bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float", "double", "unknown"};
18
+
19
+	#ifdef __cplusplus
20
+	extern "C" {
21
+	#endif
22
+		void rb_perror(const char*);
23
+
24
+		int bb2csv_buf(const char* buffer, size_t buffer_size, char **output);
25
+		int bb2csv(const char* filename, char **output);
26
+		int bb2arr_buf(const char* buffer, size_t buffer_size, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output);
27
+		int bb2arr(const char* filename, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output);
28
+
29
+		int pud2csv_buf(const char* buffer, size_t buffer_size, char **output);
30
+		int pud2csv(const char* filename, char **output);
31
+		int pud2arr_buf(const char* buffer, size_t buffer_size, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output);
32
+		int pud2arr(const char* filename, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output);
33
+
34
+		int arr2csv(const char* arr, size_t rows, size_t row_length, size_t cols, const type_t *types, char **headers, char **output);
35
+		int print_data(const char *ptr, type_t t);
36
+
37
+	#ifdef __cplusplus
38
+	}
39
+	#endif
40
+#endif

+ 751
- 0
src/readbop.c.in View File

@@ -0,0 +1,751 @@
1
+#include "readbop.h"
2
+
3
+#define STD_ERR_FN_NAME_SIZE 7
4
+
5
+_Thread_local uint8_t rb_std_errno = 0;
6
+_Thread_local char rb_std_err_fn_name[STD_ERR_FN_NAME_SIZE];
7
+enum {NONE, ALLOC, SNPRINTF, PRINTF};
8
+char const *rb_err_msgs[] = {
9
+	"No errors",
10
+	"Memory allocation failed",
11
+	"snprintf: encoding error",
12
+	"printf: writing error"
13
+};
14
+
15
+#define set_error(e) do { rb_errno = e; rb_std_errno = 0; return -1; } while(0)
16
+#define set_error_std(str) do { _Static_assert(sizeof(str)/sizeof(str[0]) < STD_ERR_FN_NAME_SIZE, "STD_ERR_FN_NAME_SIZE is too small"); strcpy(rb_std_err_fn_name, str); rb_std_errno = 1; return -1; } while(0)
17
+
18
+void rb_perror(const char *str) {
19
+	if(rb_std_errno) {
20
+		fprintf(stderr, "%s: ", str);
21
+		perror(rb_std_err_fn_name);
22
+	}
23
+	else
24
+		fprintf(stderr, "%s: %s\n", str, rb_err_msgs[errno]);
25
+}
26
+
27
+#cmakedefine POSIX_READ_FILE
28
+#ifdef POSIX_READ_FILE
29
+	#include <fcntl.h>
30
+	#include <sys/types.h>
31
+	#include <sys/stat.h>
32
+	#include <unistd.h>
33
+
34
+	int read_file(const char* filename, char** buffer, size_t *size) {
35
+		int fd;
36
+		if((fd = open(filename, O_RDONLY)) < 0)
37
+			set_error_std("open");
38
+
39
+		struct stat sb;
40
+		if(fstat(fd, &sb) < 0)
41
+			set_error_std("fstat");
42
+		*size = sb.st_size;
43
+
44
+		if((*buffer = malloc(*size)) == NULL)
45
+			set_error(ALLOC);
46
+
47
+		if(read(fd, *buffer, *size) < 0)
48
+			set_error_std("read");
49
+
50
+		if(close(fd) < 0)
51
+			set_error_std("close");
52
+
53
+		return 0;
54
+	}
55
+#else
56
+	int read_file(const char* filename, char** buffer, size_t *size) {
57
+		FILE *f;
58
+		if((f = fopen(filename, "rb")) == NULL)
59
+			set_error_std("fopen");
60
+
61
+		if(fseek(f, 0, SEEK_END) < 0)
62
+			set_error_std("fseek");
63
+
64
+		long s;
65
+		if((s = ftell(f)) < 0)
66
+			set_error_std("ftell");
67
+		*size = s;
68
+
69
+		if(fseek(f, 0, SEEK_SET) < 0)
70
+			set_error_std("fseek");
71
+
72
+		if((*buffer = malloc(*size)) == NULL)
73
+			set_error(ALLOC);
74
+
75
+		if(fread(*buffer, *size, 1, f) != 1)
76
+			set_error_std("fread");
77
+
78
+		if(fclose(f) < 0)
79
+			set_error_std("fclose");
80
+
81
+		return 0;
82
+	}
83
+#endif
84
+
85
+type_t get_type_bb(const char* s) {
86
+	switch(*s) {
87
+		case 'B':
88
+			return BOOL;
89
+		case 'H':
90
+			return BOOL;
91
+		case 'U':
92
+			switch(*(s+4)) {
93
+				case '8':
94
+					return UINT8;
95
+				case '1':
96
+					return UINT16;
97
+				case '3':
98
+					return UINT32;
99
+				case '6':
100
+					return UINT64;
101
+			}
102
+		case 'I':
103
+			switch(*(s+3)) {
104
+				case '3':
105
+					return INT32;
106
+				case '6':
107
+					return INT64;
108
+			}
109
+		case 'F':
110
+			return FLOAT;
111
+		case 'D':
112
+			return DOUBLE;
113
+	}
114
+
115
+	return UNKNOWN;
116
+}
117
+
118
+int append_data_bb(double *ptr, type_t t, char **output, size_t *output_size, size_t *output_offset) {
119
+	int n;
120
+	if(t == BOOL || t == UINT8)
121
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu8, (uint8_t)*ptr);
122
+	else if(t == UINT16)
123
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu16, (uint16_t)*ptr);
124
+	else if(t == UINT32)
125
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu32, (uint32_t)*ptr);
126
+	else if(t == UINT64)
127
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu64, (uint64_t)*ptr);
128
+	else if(t == INT32)
129
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi32, (int32_t)*ptr);
130
+	else if(t == INT64)
131
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi64, (int64_t)*ptr);
132
+	else if(t == FLOAT)
133
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%.*e", FLT_DECIMAL_DIG-1, (float)*ptr);
134
+	else if(t == DOUBLE)
135
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%.*e", DBL_DECIMAL_DIG-1, (double)*ptr);
136
+
137
+	if(n < 0) 
138
+		set_error(SNPRINTF);
139
+
140
+	if((size_t)n >= (*output_size)-(*output_offset)) {
141
+		*output_size += BUFFER_SIZE;
142
+		if((*output = realloc(*output, (*output_size)*sizeof(char))) == NULL)
143
+			set_error(ALLOC);
144
+
145
+		return append_data_bb(ptr, t, output, output_size, output_offset);
146
+	}
147
+
148
+	*output_offset += n;
149
+
150
+	return 0;
151
+}
152
+
153
+int bb2csv_buf(const char* buffer, size_t buffer_size, char **output) {
154
+	size_t output_size = buffer_size*1.75; //Factor obtained empirically
155
+	size_t output_offset = 0;
156
+	if((*output = malloc(output_size*sizeof(char))) == NULL)
157
+		set_error(ALLOC);
158
+
159
+	size_t cols;
160
+	const char *s = buffer;
161
+	const char *it;
162
+	type_t *types;
163
+	for(it = buffer; it < buffer+buffer_size; ++it) {
164
+		if(*it == '\n') {
165
+			if(memcmp(s, "nentries: ", 10) == 0) {
166
+				char *end;
167
+				cols = strtoull(s+10, &end, 10);
168
+			} else if(memcmp(s, "types: ", 7) == 0) {
169
+				if((types = malloc(cols*sizeof(type_t))) == NULL)
170
+					set_error(ALLOC);
171
+
172
+				const char *tmp_s = s+7;
173
+				size_t i = 0;
174
+				for(const char *tmp = s+7; tmp < it-7; ++tmp) {
175
+					if(*tmp == ',') {
176
+						types[i++] = get_type_bb(tmp_s+6);
177
+						tmp_s = tmp+2;
178
+					}
179
+				} 
180
+				types[i] = get_type_bb(tmp_s+6);
181
+			} else if(memcmp(s, "titles: ", 8) == 0) {
182
+				if(output_offset+(it-s-8) >= output_size) {
183
+					output_size += BUFFER_SIZE;
184
+					if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
185
+						set_error(ALLOC);
186
+				}
187
+
188
+				memcpy((*output)+output_offset, s+8, it-s-8);
189
+				output_offset += it-s-8;
190
+			} else if(memcmp(s, "-- Data", 7) == 0) {
191
+				++it;
192
+				break;
193
+			}
194
+
195
+			s = it+1;
196
+		}
197
+	}
198
+
199
+	for(double *tmp = (double*)it; tmp < (double*)(buffer+buffer_size-1); ++tmp) {
200
+		if(((char*)tmp-it)%(8*cols) == 0) {
201
+			if(output_offset+1 >= output_size) {
202
+				output_size += BUFFER_SIZE;
203
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
204
+					set_error(ALLOC);
205
+			}
206
+
207
+			*((*output)+(output_offset++)) = '\n';
208
+		}
209
+		else {
210
+			if(output_offset+2 >= output_size) {
211
+				output_size += BUFFER_SIZE;
212
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
213
+					set_error(ALLOC);
214
+			}
215
+
216
+			*((*output)+output_offset) = ',';
217
+			*((*output)+output_offset+1) = ' ';
218
+			output_offset += 2;
219
+		}
220
+
221
+		if(append_data_bb(tmp, types[(tmp-(double*)it)%cols], output, &output_size, &output_offset) < 0)
222
+			return -1;
223
+	}
224
+
225
+	free(types);
226
+
227
+	if(output_offset+1 >= output_size) {
228
+		++output_size;
229
+		if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
230
+			set_error(ALLOC);
231
+	}
232
+	*((*output)+output_offset++) = '\0';
233
+	if((*output = realloc(*output, output_offset*sizeof(char))) == NULL)
234
+		set_error(ALLOC);
235
+
236
+	return 0;
237
+}
238
+
239
+int bb2csv(const char* filename, char **output) {
240
+	char *buffer;
241
+	size_t buffer_size;
242
+	if(read_file(filename, &buffer, &buffer_size) < 0)
243
+		return -1;
244
+
245
+	int e = bb2csv_buf(buffer, buffer_size, output);
246
+	free(buffer);
247
+
248
+	return e;
249
+}
250
+
251
+int append_raw_data_bb(double *ptr, type_t t, char **output, size_t *output_size, size_t *output_offset) {
252
+	if((size_t)type_sizes[t] > (*output_size)-(*output_offset)) {
253
+		*output_size += BUFFER_SIZE;
254
+		if((*output = realloc(*output, (*output_size)*sizeof(char))) == NULL)
255
+			set_error(ALLOC);
256
+	}
257
+
258
+	if(t == BOOL || t == UINT8)
259
+		*((uint8_t*)((*output)+(*output_offset))) = (uint8_t)*ptr;
260
+	else if(t == UINT16)
261
+		*((uint16_t*)((*output)+(*output_offset))) = (uint16_t)*ptr;
262
+	else if(t == UINT32)
263
+		*((uint32_t*)((*output)+(*output_offset))) = (uint32_t)*ptr;
264
+	else if(t == UINT64)
265
+		*((uint64_t*)((*output)+(*output_offset))) = (uint64_t)*ptr;
266
+	else if(t == INT32)
267
+		*((int32_t*)((*output)+(*output_offset))) = (int32_t)*ptr;
268
+	else if(t == INT64)
269
+		*((int64_t*)((*output)+(*output_offset))) = (int64_t)*ptr;
270
+	else if(t == FLOAT)
271
+		*((float*)((*output)+(*output_offset))) = (float)*ptr;
272
+	else if(t == DOUBLE)
273
+		*((double*)((*output)+(*output_offset))) = (double)*ptr;
274
+
275
+	*output_offset += type_sizes[t];
276
+
277
+	return 0;
278
+}
279
+
280
+int bb2arr_buf(const char* buffer, size_t buffer_size, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output) {
281
+	const char *s = buffer;
282
+	const char *it;
283
+	for(it = buffer; it < buffer+buffer_size; ++it) {
284
+		if(*it == '\n') {
285
+			if(memcmp(s, "nentries: ", 10) == 0) {
286
+				char *end;
287
+				*cols = strtoull(s+10, &end, 10);
288
+			} else if(memcmp(s, "types: ", 7) == 0) {
289
+				if((*types = malloc((*cols)*sizeof(type_t))) == NULL)
290
+					set_error(ALLOC);
291
+
292
+				const char *tmp_s = s+7;
293
+				size_t i = 0;
294
+				for(const char *tmp = s+7; tmp < it-7; ++tmp) {
295
+					if(*tmp == ',') {
296
+						(*types)[i++] = get_type_bb(tmp_s+6);
297
+						tmp_s = tmp+2;
298
+					}
299
+				} 
300
+				(*types)[i] = get_type_bb(tmp_s+6);
301
+			} else if(memcmp(s, "titles: ", 8) == 0) {
302
+				if((*headers = malloc((*cols)*sizeof(char*))) == NULL)
303
+					set_error(ALLOC);
304
+
305
+				size_t i = 0;
306
+				const char *tmp_s = s+8;
307
+				for(const char *tmp = s+8; tmp < it-8; ++tmp) {
308
+					if(*tmp == ',') {
309
+						if(((*headers)[i] = malloc((tmp-tmp_s+1)*sizeof(char))) == NULL)
310
+							set_error(ALLOC);
311
+						memcpy((*headers)[i], tmp_s, tmp-tmp_s);
312
+						(*headers)[i++][tmp-tmp_s] = '\0';
313
+
314
+						tmp_s = tmp+2;
315
+					}
316
+				} 
317
+
318
+				if(((*headers)[i] = malloc((it-tmp_s+1)*sizeof(char))) == NULL)
319
+					set_error(ALLOC);
320
+				memcpy((*headers)[i], tmp_s, it-tmp_s);
321
+				(*headers)[i][it-tmp_s] = '\0';
322
+			} else if(memcmp(s, "-- Data", 7) == 0) {
323
+				++it;
324
+				break;
325
+			}
326
+
327
+			s = it+1;
328
+		}
329
+	}
330
+
331
+	*rows = ((buffer+buffer_size)-it)/(8*(*cols));
332
+	*row_length = 0;
333
+	for(size_t i = 0; i < *cols; ++i)
334
+		*row_length += type_sizes[(*types)[i]];
335
+
336
+	size_t output_size = buffer_size*0.47; //Factor obtained empirically
337
+	size_t output_offset = 0;
338
+	if((*output = malloc(output_size*sizeof(char))) == NULL)
339
+		set_error(ALLOC);
340
+
341
+	for(double *tmp = (double*)it; tmp < (double*)(buffer+buffer_size-1); ++tmp)
342
+		if(append_raw_data_bb(tmp, (*types)[(tmp-(double*)it)%(*cols)], output, &output_size, &output_offset) < 0)
343
+			return -1;
344
+
345
+	if((*output = realloc(*output, output_offset*sizeof(char))) == NULL)
346
+		set_error(ALLOC);
347
+
348
+	return 0;
349
+}
350
+
351
+int bb2arr(const char* filename, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output) {
352
+	char *buffer;
353
+	size_t buffer_size;
354
+	if(read_file(filename, &buffer, &buffer_size) < 0)
355
+		return -1;
356
+
357
+	int e = bb2arr_buf(buffer, buffer_size, rows, row_length, cols, types, headers, output);
358
+	free(buffer);
359
+
360
+	return e;
361
+}
362
+
363
+type_t get_type_pud(char c, char n) {
364
+	switch(c) {
365
+		case 'b':
366
+			return BOOL;
367
+		case 'i':
368
+			switch(n) {
369
+				case '1':
370
+					return INT8;
371
+				case '2':
372
+					return INT16;
373
+				case '4':
374
+					return INT32;
375
+			}
376
+		case 'f':
377
+			return FLOAT;
378
+		case 'd':
379
+			return DOUBLE;
380
+	}
381
+
382
+	return UNKNOWN;
383
+}
384
+
385
+int append_data_pud(const char *ptr, type_t t, char **output, size_t *output_size, size_t *output_offset) {
386
+	int n;
387
+	if(t == BOOL)
388
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu8, *((uint8_t*)ptr));
389
+	else if(t == INT8)
390
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi8, *((int8_t*)ptr));
391
+	else if(t == INT16)
392
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi16, *((int16_t*)ptr));
393
+	else if(t == INT32)
394
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi32, *((int32_t*)ptr));
395
+	else if(t == FLOAT)
396
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%.*e", FLT_DECIMAL_DIG-1, *((float*)ptr));
397
+	else if(t == DOUBLE)
398
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%.*e", DBL_DECIMAL_DIG-1, *((double*)ptr));
399
+
400
+	if(n < 0)
401
+		set_error(SNPRINTF);
402
+
403
+	if((size_t)n >= (*output_size)-(*output_offset)) {
404
+		*output_size += BUFFER_SIZE;
405
+		if((*output = realloc(*output, (*output_size)*sizeof(char))) == NULL)
406
+			set_error(ALLOC);
407
+
408
+		return append_data_pud(ptr, t, output, output_size, output_offset);
409
+	}
410
+
411
+	*output_offset += n;
412
+
413
+	return 0;
414
+}
415
+
416
+int pud2csv_buf(const char* buffer, size_t buffer_size, char **output) {
417
+	size_t output_size = buffer_size*1.4; //Factor obtained empirically
418
+	size_t output_offset = 0;
419
+	if((*output = malloc(output_size*sizeof(char))) == NULL)
420
+		set_error(ALLOC);
421
+
422
+	const char *it;
423
+	for(it = buffer; it < buffer+buffer_size && memcmp("details_headers", it, 15) != 0; ++it);
424
+	it += 31;
425
+
426
+	size_t rsize = 27;
427
+	type_t *types;
428
+	if((types = malloc(rsize*sizeof(type_t))) == NULL)
429
+		set_error(ALLOC);
430
+
431
+	size_t packet_size = 0;
432
+	const char *s = it++;
433
+	size_t i;
434
+	for(i = 0;; ++i) {
435
+		if(i == rsize) {
436
+			rsize += 2;
437
+			if((types = realloc(types, rsize*sizeof(type_t))) == NULL)
438
+				set_error(ALLOC);
439
+		}
440
+
441
+		for(; it < buffer+buffer_size && *it != '"'; ++it);
442
+
443
+		if(output_offset+(it-s) >= output_size) {
444
+			output_size += BUFFER_SIZE;
445
+			if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
446
+				set_error(ALLOC);
447
+		}
448
+
449
+		memcpy((*output)+output_offset, s, it-s);
450
+		output_offset += it-s;
451
+
452
+		s = it+12;
453
+
454
+		for(it+=12; it < buffer+buffer_size && *it != '"'; ++it);
455
+
456
+		packet_size += *(it+11)-48;
457
+		types[i] = get_type_pud(*s, *(it+11));
458
+		s = it+11;
459
+
460
+		if(*(s+4) == ']') {
461
+			if(output_offset+1 >= output_size) {
462
+				output_size += BUFFER_SIZE;
463
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
464
+					set_error(ALLOC);
465
+			}
466
+
467
+			*((*output)+(output_offset++)) = '\n';
468
+
469
+			it = s+32;
470
+			break;
471
+		} else {
472
+			if(output_offset+2 >= output_size) {
473
+				output_size += BUFFER_SIZE;
474
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
475
+					set_error(ALLOC);
476
+			}
477
+
478
+			*((*output)+output_offset) = ',';
479
+			*((*output)+output_offset+1) = ' ';
480
+			output_offset += 2;
481
+
482
+			s += 16;
483
+			it = s+2;
484
+		}
485
+	}
486
+
487
+	for(; it+packet_size-1 < buffer+buffer_size; it += packet_size) {
488
+		if(append_data_pud(it, types[0], output, &output_size, &output_offset) < 0)
489
+			return -1;
490
+
491
+		size_t acc = type_sizes[types[0]];
492
+		for(size_t j = 1; j <= i; ++j) {
493
+			if(output_offset+2 >= output_size) {
494
+				output_size += BUFFER_SIZE;
495
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
496
+					set_error(ALLOC);
497
+			}
498
+
499
+			*((*output)+output_offset) = ',';
500
+			*((*output)+output_offset+1) = ' ';
501
+			output_offset += 2;
502
+
503
+			if(append_data_pud(it+acc, types[j], output, &output_size, &output_offset) < 0)
504
+				return -1;
505
+
506
+			acc += type_sizes[types[j]];
507
+		}		
508
+
509
+		if(output_offset+1 >= output_size) {
510
+			output_size += BUFFER_SIZE;
511
+			if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
512
+				set_error(ALLOC);
513
+		}
514
+
515
+		*((*output)+(output_offset++)) = '\n';
516
+	}
517
+
518
+	free(types);
519
+
520
+	return 0;
521
+}
522
+
523
+int pud2csv(const char* filename, char **output) {
524
+	char *buffer;
525
+	size_t buffer_size;
526
+	if(read_file(filename, &buffer, &buffer_size) < 0)
527
+		return -1;
528
+
529
+	int e = pud2csv_buf(buffer, buffer_size, output);
530
+	free(buffer);
531
+
532
+	return e;
533
+}
534
+
535
+int pud2arr_buf(const char* buffer, size_t buffer_size, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output) {
536
+	const char *it;
537
+	for(it = buffer; it < buffer+buffer_size && memcmp("details_headers", it, 15) != 0; ++it);
538
+	it += 31;
539
+
540
+	*cols = 27;
541
+	if((*types = malloc((*cols)*sizeof(type_t))) == NULL)
542
+		set_error(ALLOC);
543
+	if((*headers = malloc((*cols)*sizeof(char*))) == NULL)
544
+		set_error(ALLOC);
545
+
546
+	*row_length = 0;
547
+	const char *s = it++;
548
+	size_t i;
549
+	for(i = 0;; ++i) {
550
+		for(; it < buffer+buffer_size && *it != '"'; ++it);
551
+
552
+		if(i == *cols) {
553
+			*cols += 2;
554
+			if((*types = realloc(*types, (*cols)*sizeof(type_t))) == NULL)
555
+				set_error(ALLOC);
556
+			if((*headers = realloc(*headers, (*cols)*sizeof(char*))) == NULL)
557
+				set_error(ALLOC);
558
+		}
559
+
560
+		if(((*headers)[i] = malloc((it-s+1)*sizeof(char))) == NULL)
561
+			set_error(ALLOC);
562
+		memcpy((*headers)[i], s, it-s);
563
+		(*headers)[i][it-s] = '\0';
564
+
565
+		s = it+12;
566
+
567
+		for(it+=12; it < buffer+buffer_size && *it != '"'; ++it);
568
+
569
+		*row_length += *(it+11)-48;
570
+		(*types)[i] = get_type_pud(*s, *(it+11));
571
+		s = it+11;
572
+
573
+		if(*(s+4) == ']') {
574
+			it = s+32;
575
+			break;
576
+		} else {
577
+			s += 16;
578
+			it = s+2;
579
+		}
580
+	}
581
+
582
+	*cols = i+1;
583
+	if((*types = realloc(*types, (*cols)*sizeof(type_t))) == NULL)
584
+		set_error(ALLOC);
585
+    if((*headers = realloc(*headers, (*cols)*sizeof(char*))) == NULL)
586
+		set_error(ALLOC);
587
+
588
+	if((*output = malloc((buffer_size-(it-buffer))*sizeof(char))) == NULL)
589
+		set_error(ALLOC);
590
+	memcpy(*output, it, buffer_size-(it-buffer));
591
+	*rows = (buffer_size-(it-buffer))/(*row_length);
592
+
593
+	return 0;
594
+}
595
+
596
+int pud2arr(const char* filename, size_t *rows, size_t *row_length, size_t *cols, type_t **types, char ***headers, char **output) {
597
+	char *buffer;
598
+	size_t buffer_size;
599
+	if(read_file(filename, &buffer, &buffer_size) < 0)
600
+		return -1;
601
+
602
+	int e = pud2arr_buf(buffer, buffer_size, rows, row_length, cols, types, headers, output);
603
+	free(buffer);
604
+
605
+	return e;
606
+}
607
+
608
+int append_data(const char *ptr, type_t t, char **output, size_t *output_size, size_t *output_offset) {
609
+	int n;
610
+	if(t == BOOL || t == UINT8)
611
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu8, *((uint8_t*)ptr));
612
+	else if(t == UINT16)
613
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu16, *((uint16_t*)ptr));
614
+	else if(t == UINT32)
615
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu32, *((uint32_t*)ptr));
616
+	else if(t == UINT64)
617
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIu64, *((uint64_t*)ptr));
618
+	else if(t == INT8)
619
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi8, *((int8_t*)ptr));
620
+	else if(t == INT16)
621
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi16, *((int16_t*)ptr));
622
+	else if(t == INT32)
623
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi32, *((int32_t*)ptr));
624
+	else if(t == INT64)
625
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%"PRIi64, *((int64_t*)ptr));
626
+	else if(t == FLOAT)
627
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%.*e", FLT_DECIMAL_DIG-1, *((float*)ptr));
628
+	else if(t == DOUBLE)
629
+		n = snprintf((*output)+(*output_offset), (*output_size)-(*output_offset), "%.*e", DBL_DECIMAL_DIG-1, *((double*)ptr));
630
+
631
+	if(n < 0)
632
+		set_error(SNPRINTF);
633
+
634
+	if((size_t)n >= (*output_size)-(*output_offset)) {
635
+		*output_size += BUFFER_SIZE;
636
+		if((*output = realloc(*output, (*output_size)*sizeof(char))) == NULL)
637
+			set_error(ALLOC);
638
+
639
+		return append_data(ptr, t, output, output_size, output_offset);
640
+	}
641
+
642
+	*output_offset += n;
643
+
644
+	return 0;
645
+}
646
+
647
+int arr2csv(const char* arr, size_t rows, size_t row_length, size_t cols, const type_t *types, char **headers, char **output) {
648
+	size_t output_size = rows*row_length*3.71; //Factor obtained empirically
649
+	size_t output_offset = 0;
650
+	if((*output = malloc(output_size*sizeof(char))) == NULL)
651
+		set_error(ALLOC);
652
+
653
+	for(size_t i = 0; i < cols; ++i) {
654
+		size_t len = strlen(headers[i]);
655
+
656
+		if(i == cols-1) {
657
+			if(output_offset+len+1 >= output_size) {
658
+				output_size += BUFFER_SIZE;
659
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
660
+					set_error(ALLOC);
661
+			}
662
+
663
+			memcpy((*output)+output_offset, headers[i], len);
664
+			*((*output)+output_offset+len) = '\n';
665
+			output_offset += len+1;
666
+		} else {
667
+			if(output_offset+len+2 >= output_size) {
668
+				output_size += BUFFER_SIZE;
669
+				if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
670
+					set_error(ALLOC);
671
+			}
672
+
673
+			memcpy((*output)+output_offset, headers[i], len);
674
+			*((*output)+output_offset+len) = ',';
675
+			*((*output)+output_offset+len+1) = ' ';
676
+			output_offset += len+2;
677
+		}
678
+	}
679
+
680
+	const char *tmp = arr;
681
+	for(size_t i = 0; i < rows; ++i) {
682
+		for(size_t j = 0; j < cols; ++j) {
683
+			if(append_data(tmp, types[j], output, &output_size, &output_offset) < 0)
684
+				return -1;
685
+
686
+			if(j != cols-1) {
687
+				if(output_offset+2 >= output_size) {
688
+					output_size += BUFFER_SIZE;
689
+					if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
690
+						set_error(ALLOC);
691
+				}
692
+
693
+				*((*output)+output_offset) = ',';
694
+				*((*output)+output_offset+1) = ' ';
695
+				output_offset += 2;
696
+			}
697
+			tmp += type_sizes[types[j]];
698
+		}
699
+
700
+		if(output_offset+1 >= output_size) {
701
+			output_size += BUFFER_SIZE;
702
+			if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
703
+				set_error(ALLOC);
704
+		}
705
+
706
+		*((*output)+output_offset) = '\n';
707
+		++output_offset;
708
+	}
709
+
710
+	if(output_offset+1 >= output_size) {
711
+		++output_size;
712
+		if((*output = realloc(*output, output_size*sizeof(char))) == NULL)
713
+			set_error(ALLOC);
714
+	}
715
+
716
+	*((*output)+output_offset) = '\0';
717
+	++output_offset;
718
+	if((*output = realloc(*output, output_offset*sizeof(char))) == NULL)
719
+		set_error(ALLOC);
720
+
721
+	return 0;
722
+}
723
+
724
+int print_data(const char *ptr, type_t t) {
725
+	int n;
726
+	if(t == BOOL || t == UINT8)
727
+		n = printf("%"PRIu8, *((uint8_t*)ptr));
728
+	else if(t == UINT16)
729
+		n = printf("%"PRIu16, *((uint16_t*)ptr));
730
+	else if(t == UINT32)
731
+		n = printf("%"PRIu32, *((uint32_t*)ptr));
732
+	else if(t == UINT64)
733
+		n = printf("%"PRIu64, *((uint64_t*)ptr));
734
+	else if(t == INT8)
735
+		n = printf("%"PRIi8, *((int8_t*)ptr));
736
+	else if(t == INT16)
737
+		n = printf("%"PRIi16, *((int16_t*)ptr));
738
+	else if(t == INT32)
739
+		n = printf("%"PRIi32, *((int32_t*)ptr));
740
+	else if(t == INT64)
741
+		n = printf("%"PRIi64, *((int64_t*)ptr));
742
+	else if(t == FLOAT)
743
+		n = printf("%.*e", FLT_DECIMAL_DIG-1, *((float*)ptr));
744
+	else if(t == DOUBLE)
745
+		n = printf("%.*e", DBL_DECIMAL_DIG-1, *((double*)ptr));
746
+
747
+	if(n < 0)
748
+		set_error(PRINTF);
749
+
750
+	return 0;
751
+}

Loading…
Cancel
Save